diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/config.rs | 2 | ||||
| -rw-r--r-- | src/gpio.rs | 243 | ||||
| -rw-r--r-- | src/interrupt.rs | 193 | ||||
| -rw-r--r-- | src/lib.rs | 15 |
4 files changed, 450 insertions, 3 deletions
diff --git a/src/config.rs b/src/config.rs index 9c0d47ecb..8d52a1d44 100644 --- a/src/config.rs +++ b/src/config.rs | |||
| @@ -9,6 +9,7 @@ pub struct Config { | |||
| 9 | pub time_interrupt_priority: Priority, | 9 | pub time_interrupt_priority: Priority, |
| 10 | pub rtc_interrupt_priority: Priority, | 10 | pub rtc_interrupt_priority: Priority, |
| 11 | pub adc_interrupt_priority: Priority, | 11 | pub adc_interrupt_priority: Priority, |
| 12 | pub gpio_interrupt_priority: Priority, | ||
| 12 | pub clock_cfg: ClocksConfig, | 13 | pub clock_cfg: ClocksConfig, |
| 13 | } | 14 | } |
| 14 | 15 | ||
| @@ -19,6 +20,7 @@ impl Default for Config { | |||
| 19 | time_interrupt_priority: Priority::from(0), | 20 | time_interrupt_priority: Priority::from(0), |
| 20 | rtc_interrupt_priority: Priority::from(0), | 21 | rtc_interrupt_priority: Priority::from(0), |
| 21 | adc_interrupt_priority: Priority::from(0), | 22 | adc_interrupt_priority: Priority::from(0), |
| 23 | gpio_interrupt_priority: Priority::from(0), | ||
| 22 | clock_cfg: ClocksConfig::default(), | 24 | clock_cfg: ClocksConfig::default(), |
| 23 | } | 25 | } |
| 24 | } | 26 | } |
diff --git a/src/gpio.rs b/src/gpio.rs index 4f79aff93..332c4c8b2 100644 --- a/src/gpio.rs +++ b/src/gpio.rs | |||
| @@ -3,13 +3,96 @@ | |||
| 3 | //! concrete pin type. | 3 | //! concrete pin type. |
| 4 | 4 | ||
| 5 | use core::convert::Infallible; | 5 | use core::convert::Infallible; |
| 6 | use core::future::Future; | ||
| 6 | use core::marker::PhantomData; | 7 | use core::marker::PhantomData; |
| 8 | use core::pin::pin; | ||
| 7 | 9 | ||
| 8 | use embassy_hal_internal::{Peri, PeripheralType}; | 10 | use embassy_hal_internal::{Peri, PeripheralType}; |
| 11 | use maitake_sync::WaitMap; | ||
| 9 | use paste::paste; | 12 | use paste::paste; |
| 10 | 13 | ||
| 14 | use crate::pac::interrupt; | ||
| 11 | use crate::pac::port0::pcr0::{Dse, Inv, Mux, Pe, Ps, Sre}; | 15 | use crate::pac::port0::pcr0::{Dse, Inv, Mux, Pe, Ps, Sre}; |
| 12 | 16 | ||
| 17 | struct BitIter(u32); | ||
| 18 | |||
| 19 | impl Iterator for BitIter { | ||
| 20 | type Item = usize; | ||
| 21 | |||
| 22 | fn next(&mut self) -> Option<Self::Item> { | ||
| 23 | match self.0.trailing_zeros() { | ||
| 24 | 32 => None, | ||
| 25 | b => { | ||
| 26 | self.0 &= !(1 << b); | ||
| 27 | Some(b as usize) | ||
| 28 | } | ||
| 29 | } | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 33 | const PORT_COUNT: usize = 5; | ||
| 34 | |||
| 35 | static PORT_WAIT_MAPS: [WaitMap<usize, ()>; PORT_COUNT] = [ | ||
| 36 | WaitMap::new(), | ||
| 37 | WaitMap::new(), | ||
| 38 | WaitMap::new(), | ||
| 39 | WaitMap::new(), | ||
| 40 | WaitMap::new(), | ||
| 41 | ]; | ||
| 42 | |||
| 43 | fn irq_handler(port_index: usize, gpio_base: *const crate::pac::gpio0::RegisterBlock) { | ||
| 44 | let gpio = unsafe { &*gpio_base }; | ||
| 45 | let isfr = gpio.isfr0().read().bits(); | ||
| 46 | |||
| 47 | for pin in BitIter(isfr) { | ||
| 48 | // Clear all pending interrupts | ||
| 49 | gpio.isfr0().write(|w| unsafe { w.bits(1 << pin) }); | ||
| 50 | gpio.icr(pin).modify(|_, w| w.irqc().irqc0()); // Disable interrupt | ||
| 51 | |||
| 52 | // Wake the corresponding port waker | ||
| 53 | if let Some(w) = PORT_WAIT_MAPS.get(port_index) { | ||
| 54 | w.wake(&pin, ()); | ||
| 55 | } | ||
| 56 | } | ||
| 57 | } | ||
| 58 | |||
| 59 | #[interrupt] | ||
| 60 | fn GPIO0() { | ||
| 61 | irq_handler(0, crate::pac::Gpio0::ptr()); | ||
| 62 | } | ||
| 63 | |||
| 64 | #[interrupt] | ||
| 65 | fn GPIO1() { | ||
| 66 | irq_handler(1, crate::pac::Gpio1::ptr()); | ||
| 67 | } | ||
| 68 | |||
| 69 | #[interrupt] | ||
| 70 | fn GPIO2() { | ||
| 71 | irq_handler(2, crate::pac::Gpio2::ptr()); | ||
| 72 | } | ||
| 73 | |||
| 74 | #[interrupt] | ||
| 75 | fn GPIO3() { | ||
| 76 | irq_handler(3, crate::pac::Gpio3::ptr()); | ||
| 77 | } | ||
| 78 | |||
| 79 | #[interrupt] | ||
| 80 | fn GPIO4() { | ||
| 81 | irq_handler(4, crate::pac::Gpio4::ptr()); | ||
| 82 | } | ||
| 83 | |||
| 84 | pub(crate) unsafe fn init() { | ||
| 85 | use embassy_hal_internal::interrupt::InterruptExt; | ||
| 86 | |||
| 87 | crate::pac::interrupt::GPIO0.enable(); | ||
| 88 | crate::pac::interrupt::GPIO1.enable(); | ||
| 89 | crate::pac::interrupt::GPIO2.enable(); | ||
| 90 | crate::pac::interrupt::GPIO3.enable(); | ||
| 91 | crate::pac::interrupt::GPIO4.enable(); | ||
| 92 | |||
| 93 | cortex_m::interrupt::enable(); | ||
| 94 | } | ||
| 95 | |||
| 13 | /// Logical level for GPIO pins. | 96 | /// Logical level for GPIO pins. |
| 14 | #[derive(Copy, Clone, Eq, PartialEq, Debug)] | 97 | #[derive(Copy, Clone, Eq, PartialEq, Debug)] |
| 15 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 98 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| @@ -598,6 +681,77 @@ impl<'d> Flex<'d> { | |||
| 598 | } | 681 | } |
| 599 | } | 682 | } |
| 600 | 683 | ||
| 684 | /// Async methods | ||
| 685 | impl<'d> Flex<'d> { | ||
| 686 | /// Helper function that waits for a given interrupt trigger | ||
| 687 | async fn wait_for_inner(&mut self, level: crate::pac::gpio0::icr::Irqc) { | ||
| 688 | // First, ensure that we have a waker that is ready for this port+pin | ||
| 689 | let w = PORT_WAIT_MAPS[self.pin.port].wait(self.pin.pin); | ||
| 690 | let mut w = pin!(w); | ||
| 691 | // Wait for the subscription to occur, which requires polling at least once | ||
| 692 | // | ||
| 693 | // This function returns a result, but can only be an Err if: | ||
| 694 | // | ||
| 695 | // * We call `.close()` on a WaitMap, which we never do | ||
| 696 | // * We have a duplicate key, which can't happen because `wait_for_*` methods | ||
| 697 | // take an &mut ref of their unique port+pin combo | ||
| 698 | // | ||
| 699 | // So we wait for it to complete, but ignore the result. | ||
| 700 | _ = w.as_mut().subscribe().await; | ||
| 701 | |||
| 702 | // Now that our waker is in the map, we can enable the appropriate interrupt | ||
| 703 | // | ||
| 704 | // Clear any existing pending interrupt on this pin | ||
| 705 | self.pin | ||
| 706 | .gpio() | ||
| 707 | .isfr0() | ||
| 708 | .write(|w| unsafe { w.bits(1 << self.pin.pin()) }); | ||
| 709 | self.pin.gpio().icr(self.pin.pin()).write(|w| w.isf().isf1()); | ||
| 710 | |||
| 711 | // Pin interrupt configuration | ||
| 712 | self.pin | ||
| 713 | .gpio() | ||
| 714 | .icr(self.pin.pin()) | ||
| 715 | .modify(|_, w| w.irqc().variant(level)); | ||
| 716 | |||
| 717 | // Finally, we can await the matching call to `.wake()` from the interrupt. | ||
| 718 | // | ||
| 719 | // Again, technically, this could return a result, but for the same reasons | ||
| 720 | // as above, this can't be an error in our case, so just wait for it to complete | ||
| 721 | _ = w.await; | ||
| 722 | } | ||
| 723 | |||
| 724 | /// Wait until the pin is high. If it is already high, return immediately. | ||
| 725 | #[inline] | ||
| 726 | pub fn wait_for_high(&mut self) -> impl Future<Output = ()> + use<'_, 'd> { | ||
| 727 | self.wait_for_inner(crate::pac::gpio0::icr::Irqc::Irqc12) | ||
| 728 | } | ||
| 729 | |||
| 730 | /// Wait until the pin is low. If it is already low, return immediately. | ||
| 731 | #[inline] | ||
| 732 | pub fn wait_for_low(&mut self) -> impl Future<Output = ()> + use<'_, 'd> { | ||
| 733 | self.wait_for_inner(crate::pac::gpio0::icr::Irqc::Irqc8) | ||
| 734 | } | ||
| 735 | |||
| 736 | /// Wait for the pin to undergo a transition from low to high. | ||
| 737 | #[inline] | ||
| 738 | pub fn wait_for_rising_edge(&mut self) -> impl Future<Output = ()> + use<'_, 'd> { | ||
| 739 | self.wait_for_inner(crate::pac::gpio0::icr::Irqc::Irqc9) | ||
| 740 | } | ||
| 741 | |||
| 742 | /// Wait for the pin to undergo a transition from high to low. | ||
| 743 | #[inline] | ||
| 744 | pub fn wait_for_falling_edge(&mut self) -> impl Future<Output = ()> + use<'_, 'd> { | ||
| 745 | self.wait_for_inner(crate::pac::gpio0::icr::Irqc::Irqc10) | ||
| 746 | } | ||
| 747 | |||
| 748 | /// Wait for the pin to undergo any transition, i.e low to high OR high to low. | ||
| 749 | #[inline] | ||
| 750 | pub fn wait_for_any_edge(&mut self) -> impl Future<Output = ()> + use<'_, 'd> { | ||
| 751 | self.wait_for_inner(crate::pac::gpio0::icr::Irqc::Irqc11) | ||
| 752 | } | ||
| 753 | } | ||
| 754 | |||
| 601 | /// GPIO output driver that owns a `Flex` pin. | 755 | /// GPIO output driver that owns a `Flex` pin. |
| 602 | pub struct Output<'d> { | 756 | pub struct Output<'d> { |
| 603 | flex: Flex<'d>, | 757 | flex: Flex<'d>, |
| @@ -691,12 +845,99 @@ impl<'d> Input<'d> { | |||
| 691 | self.flex | 845 | self.flex |
| 692 | } | 846 | } |
| 693 | 847 | ||
| 694 | // Get the pin level. | 848 | /// Get the pin level. |
| 695 | pub fn get_level(&self) -> Level { | 849 | pub fn get_level(&self) -> Level { |
| 696 | self.flex.get_level() | 850 | self.flex.get_level() |
| 697 | } | 851 | } |
| 698 | } | 852 | } |
| 699 | 853 | ||
| 854 | /// Async methods | ||
| 855 | impl<'d> Input<'d> { | ||
| 856 | /// Wait until the pin is high. If it is already high, return immediately. | ||
| 857 | #[inline] | ||
| 858 | pub fn wait_for_high(&mut self) -> impl Future<Output = ()> + use<'_, 'd> { | ||
| 859 | self.flex.wait_for_high() | ||
| 860 | } | ||
| 861 | |||
| 862 | /// Wait until the pin is low. If it is already low, return immediately. | ||
| 863 | #[inline] | ||
| 864 | pub fn wait_for_low(&mut self) -> impl Future<Output = ()> + use<'_, 'd> { | ||
| 865 | self.flex.wait_for_low() | ||
| 866 | } | ||
| 867 | |||
| 868 | /// Wait for the pin to undergo a transition from low to high. | ||
| 869 | #[inline] | ||
| 870 | pub fn wait_for_rising_edge(&mut self) -> impl Future<Output = ()> + use<'_, 'd> { | ||
| 871 | self.flex.wait_for_rising_edge() | ||
| 872 | } | ||
| 873 | |||
| 874 | /// Wait for the pin to undergo a transition from high to low. | ||
| 875 | #[inline] | ||
| 876 | pub fn wait_for_falling_edge(&mut self) -> impl Future<Output = ()> + use<'_, 'd> { | ||
| 877 | self.flex.wait_for_falling_edge() | ||
| 878 | } | ||
| 879 | |||
| 880 | /// Wait for the pin to undergo any transition, i.e low to high OR high to low. | ||
| 881 | #[inline] | ||
| 882 | pub fn wait_for_any_edge(&mut self) -> impl Future<Output = ()> + use<'_, 'd> { | ||
| 883 | self.flex.wait_for_any_edge() | ||
| 884 | } | ||
| 885 | } | ||
| 886 | |||
| 887 | impl embedded_hal_async::digital::Wait for Input<'_> { | ||
| 888 | async fn wait_for_high(&mut self) -> Result<(), Self::Error> { | ||
| 889 | self.wait_for_high().await; | ||
| 890 | Ok(()) | ||
| 891 | } | ||
| 892 | |||
| 893 | async fn wait_for_low(&mut self) -> Result<(), Self::Error> { | ||
| 894 | self.wait_for_low().await; | ||
| 895 | Ok(()) | ||
| 896 | } | ||
| 897 | |||
| 898 | async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> { | ||
| 899 | self.wait_for_rising_edge().await; | ||
| 900 | Ok(()) | ||
| 901 | } | ||
| 902 | |||
| 903 | async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> { | ||
| 904 | self.wait_for_falling_edge().await; | ||
| 905 | Ok(()) | ||
| 906 | } | ||
| 907 | |||
| 908 | async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> { | ||
| 909 | self.wait_for_any_edge().await; | ||
| 910 | Ok(()) | ||
| 911 | } | ||
| 912 | } | ||
| 913 | |||
| 914 | impl embedded_hal_async::digital::Wait for Flex<'_> { | ||
| 915 | async fn wait_for_high(&mut self) -> Result<(), Self::Error> { | ||
| 916 | self.wait_for_high().await; | ||
| 917 | Ok(()) | ||
| 918 | } | ||
| 919 | |||
| 920 | async fn wait_for_low(&mut self) -> Result<(), Self::Error> { | ||
| 921 | self.wait_for_low().await; | ||
| 922 | Ok(()) | ||
| 923 | } | ||
| 924 | |||
| 925 | async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> { | ||
| 926 | self.wait_for_rising_edge().await; | ||
| 927 | Ok(()) | ||
| 928 | } | ||
| 929 | |||
| 930 | async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> { | ||
| 931 | self.wait_for_falling_edge().await; | ||
| 932 | Ok(()) | ||
| 933 | } | ||
| 934 | |||
| 935 | async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> { | ||
| 936 | self.wait_for_any_edge().await; | ||
| 937 | Ok(()) | ||
| 938 | } | ||
| 939 | } | ||
| 940 | |||
| 700 | // Both embedded_hal 0.2 and 1.0 must be supported by embassy HALs. | 941 | // Both embedded_hal 0.2 and 1.0 must be supported by embassy HALs. |
| 701 | impl embedded_hal_02::digital::v2::InputPin for Flex<'_> { | 942 | impl embedded_hal_02::digital::v2::InputPin for Flex<'_> { |
| 702 | // GPIO operations on this block cannot fail, therefor we set the error type | 943 | // GPIO operations on this block cannot fail, therefor we set the error type |
diff --git a/src/interrupt.rs b/src/interrupt.rs index f2f1cccac..0490e3a66 100644 --- a/src/interrupt.rs +++ b/src/interrupt.rs | |||
| @@ -8,7 +8,8 @@ | |||
| 8 | 8 | ||
| 9 | mod generated { | 9 | mod generated { |
| 10 | embassy_hal_internal::interrupt_mod!( | 10 | embassy_hal_internal::interrupt_mod!( |
| 11 | OS_EVENT, LPUART0, LPI2C0, LPI2C1, LPI2C2, LPI2C3, LPUART1, LPUART2, LPUART3, LPUART4, LPUART5, RTC, ADC1, | 11 | OS_EVENT, RTC, ADC1, GPIO0, GPIO1, GPIO2, GPIO3, GPIO4, LPI2C0, LPI2C1, LPI2C2, LPI2C3, LPUART0, LPUART1, |
| 12 | LPUART2, LPUART3, LPUART4, LPUART5, | ||
| 12 | ); | 13 | ); |
| 13 | } | 14 | } |
| 14 | 15 | ||
| @@ -292,6 +293,196 @@ impl InterruptExt for Adc { | |||
| 292 | } | 293 | } |
| 293 | } | 294 | } |
| 294 | 295 | ||
| 296 | pub struct Gpio0; | ||
| 297 | pub const GPIO0: Gpio0 = Gpio0; | ||
| 298 | |||
| 299 | impl InterruptExt for Gpio0 { | ||
| 300 | /// Clear any pending GPIO0 in NVIC. | ||
| 301 | #[inline] | ||
| 302 | fn unpend(&self) { | ||
| 303 | cortex_m::peripheral::NVIC::unpend(Interrupt::GPIO0); | ||
| 304 | } | ||
| 305 | |||
| 306 | /// Set NVIC priority for GPIO0. | ||
| 307 | #[inline] | ||
| 308 | fn set_priority(&self, priority: Priority) { | ||
| 309 | unsafe { | ||
| 310 | let mut nvic = cortex_m::peripheral::Peripherals::steal().NVIC; | ||
| 311 | nvic.set_priority(Interrupt::GPIO0, u8::from(priority)); | ||
| 312 | } | ||
| 313 | } | ||
| 314 | |||
| 315 | /// Enable GPIO0 in NVIC. | ||
| 316 | #[inline] | ||
| 317 | unsafe fn enable(&self) { | ||
| 318 | cortex_m::peripheral::NVIC::unmask(Interrupt::GPIO0); | ||
| 319 | } | ||
| 320 | |||
| 321 | /// Disable GPIO0 in NVIC. | ||
| 322 | #[inline] | ||
| 323 | unsafe fn disable(&self) { | ||
| 324 | cortex_m::peripheral::NVIC::mask(Interrupt::GPIO0); | ||
| 325 | } | ||
| 326 | |||
| 327 | /// Check if GPIO0 is pending in NVIC. | ||
| 328 | #[inline] | ||
| 329 | fn is_pending(&self) -> bool { | ||
| 330 | cortex_m::peripheral::NVIC::is_pending(Interrupt::GPIO0) | ||
| 331 | } | ||
| 332 | } | ||
| 333 | |||
| 334 | pub struct Gpio1; | ||
| 335 | pub const GPIO1: Gpio1 = Gpio1; | ||
| 336 | |||
| 337 | impl InterruptExt for Gpio1 { | ||
| 338 | /// Clear any pending GPIO1 in NVIC. | ||
| 339 | #[inline] | ||
| 340 | fn unpend(&self) { | ||
| 341 | cortex_m::peripheral::NVIC::unpend(Interrupt::GPIO1); | ||
| 342 | } | ||
| 343 | |||
| 344 | /// Set NVIC priority for GPIO1. | ||
| 345 | #[inline] | ||
| 346 | fn set_priority(&self, priority: Priority) { | ||
| 347 | unsafe { | ||
| 348 | let mut nvic = cortex_m::peripheral::Peripherals::steal().NVIC; | ||
| 349 | nvic.set_priority(Interrupt::GPIO1, u8::from(priority)); | ||
| 350 | } | ||
| 351 | } | ||
| 352 | |||
| 353 | /// Enable GPIO1 in NVIC. | ||
| 354 | #[inline] | ||
| 355 | unsafe fn enable(&self) { | ||
| 356 | cortex_m::peripheral::NVIC::unmask(Interrupt::GPIO1); | ||
| 357 | } | ||
| 358 | |||
| 359 | /// Disable GPIO1 in NVIC. | ||
| 360 | #[inline] | ||
| 361 | unsafe fn disable(&self) { | ||
| 362 | cortex_m::peripheral::NVIC::mask(Interrupt::GPIO1); | ||
| 363 | } | ||
| 364 | |||
| 365 | /// Check if GPIO1 is pending in NVIC. | ||
| 366 | #[inline] | ||
| 367 | fn is_pending(&self) -> bool { | ||
| 368 | cortex_m::peripheral::NVIC::is_pending(Interrupt::GPIO1) | ||
| 369 | } | ||
| 370 | } | ||
| 371 | |||
| 372 | pub struct Gpio2; | ||
| 373 | pub const GPIO2: Gpio2 = Gpio2; | ||
| 374 | |||
| 375 | impl InterruptExt for Gpio2 { | ||
| 376 | /// Clear any pending GPIO2 in NVIC. | ||
| 377 | #[inline] | ||
| 378 | fn unpend(&self) { | ||
| 379 | cortex_m::peripheral::NVIC::unpend(Interrupt::GPIO2); | ||
| 380 | } | ||
| 381 | |||
| 382 | /// Set NVIC priority for GPIO2. | ||
| 383 | #[inline] | ||
| 384 | fn set_priority(&self, priority: Priority) { | ||
| 385 | unsafe { | ||
| 386 | let mut nvic = cortex_m::peripheral::Peripherals::steal().NVIC; | ||
| 387 | nvic.set_priority(Interrupt::GPIO2, u8::from(priority)); | ||
| 388 | } | ||
| 389 | } | ||
| 390 | |||
| 391 | /// Enable GPIO2 in NVIC. | ||
| 392 | #[inline] | ||
| 393 | unsafe fn enable(&self) { | ||
| 394 | cortex_m::peripheral::NVIC::unmask(Interrupt::GPIO2); | ||
| 395 | } | ||
| 396 | |||
| 397 | /// Disable GPIO2 in NVIC. | ||
| 398 | #[inline] | ||
| 399 | unsafe fn disable(&self) { | ||
| 400 | cortex_m::peripheral::NVIC::mask(Interrupt::GPIO2); | ||
| 401 | } | ||
| 402 | |||
| 403 | /// Check if GPIO2 is pending in NVIC. | ||
| 404 | #[inline] | ||
| 405 | fn is_pending(&self) -> bool { | ||
| 406 | cortex_m::peripheral::NVIC::is_pending(Interrupt::GPIO2) | ||
| 407 | } | ||
| 408 | } | ||
| 409 | |||
| 410 | pub struct Gpio3; | ||
| 411 | pub const GPIO3: Gpio3 = Gpio3; | ||
| 412 | |||
| 413 | impl InterruptExt for Gpio3 { | ||
| 414 | /// Clear any pending GPIO3 in NVIC. | ||
| 415 | #[inline] | ||
| 416 | fn unpend(&self) { | ||
| 417 | cortex_m::peripheral::NVIC::unpend(Interrupt::GPIO3); | ||
| 418 | } | ||
| 419 | |||
| 420 | /// Set NVIC priority for GPIO3. | ||
| 421 | #[inline] | ||
| 422 | fn set_priority(&self, priority: Priority) { | ||
| 423 | unsafe { | ||
| 424 | let mut nvic = cortex_m::peripheral::Peripherals::steal().NVIC; | ||
| 425 | nvic.set_priority(Interrupt::GPIO3, u8::from(priority)); | ||
| 426 | } | ||
| 427 | } | ||
| 428 | |||
| 429 | /// Enable GPIO3 in NVIC. | ||
| 430 | #[inline] | ||
| 431 | unsafe fn enable(&self) { | ||
| 432 | cortex_m::peripheral::NVIC::unmask(Interrupt::GPIO3); | ||
| 433 | } | ||
| 434 | |||
| 435 | /// Disable GPIO3 in NVIC. | ||
| 436 | #[inline] | ||
| 437 | unsafe fn disable(&self) { | ||
| 438 | cortex_m::peripheral::NVIC::mask(Interrupt::GPIO3); | ||
| 439 | } | ||
| 440 | |||
| 441 | /// Check if GPIO3 is pending in NVIC. | ||
| 442 | #[inline] | ||
| 443 | fn is_pending(&self) -> bool { | ||
| 444 | cortex_m::peripheral::NVIC::is_pending(Interrupt::GPIO3) | ||
| 445 | } | ||
| 446 | } | ||
| 447 | |||
| 448 | pub struct Gpio4; | ||
| 449 | pub const GPIO4: Gpio4 = Gpio4; | ||
| 450 | |||
| 451 | impl InterruptExt for Gpio4 { | ||
| 452 | /// Clear any pending GPIO4 in NVIC. | ||
| 453 | #[inline] | ||
| 454 | fn unpend(&self) { | ||
| 455 | cortex_m::peripheral::NVIC::unpend(Interrupt::GPIO4); | ||
| 456 | } | ||
| 457 | |||
| 458 | /// Set NVIC priority for GPIO4. | ||
| 459 | #[inline] | ||
| 460 | fn set_priority(&self, priority: Priority) { | ||
| 461 | unsafe { | ||
| 462 | let mut nvic = cortex_m::peripheral::Peripherals::steal().NVIC; | ||
| 463 | nvic.set_priority(Interrupt::GPIO4, u8::from(priority)); | ||
| 464 | } | ||
| 465 | } | ||
| 466 | |||
| 467 | /// Enable GPIO4 in NVIC. | ||
| 468 | #[inline] | ||
| 469 | unsafe fn enable(&self) { | ||
| 470 | cortex_m::peripheral::NVIC::unmask(Interrupt::GPIO4); | ||
| 471 | } | ||
| 472 | |||
| 473 | /// Disable GPIO4 in NVIC. | ||
| 474 | #[inline] | ||
| 475 | unsafe fn disable(&self) { | ||
| 476 | cortex_m::peripheral::NVIC::mask(Interrupt::GPIO4); | ||
| 477 | } | ||
| 478 | |||
| 479 | /// Check if GPIO4 is pending in NVIC. | ||
| 480 | #[inline] | ||
| 481 | fn is_pending(&self) -> bool { | ||
| 482 | cortex_m::peripheral::NVIC::is_pending(Interrupt::GPIO4) | ||
| 483 | } | ||
| 484 | } | ||
| 485 | |||
| 295 | /// Set VTOR (Vector Table Offset) to a RAM-based vector table. | 486 | /// Set VTOR (Vector Table Offset) to a RAM-based vector table. |
| 296 | /// Pass a pointer to the first word in the RAM table (stack pointer slot 0). | 487 | /// Pass a pointer to the first word in the RAM table (stack pointer slot 0). |
| 297 | /// Safety: Caller must ensure the RAM table is valid and aligned as required by the core. | 488 | /// Safety: Caller must ensure the RAM table is valid and aligned as required by the core. |
diff --git a/src/lib.rs b/src/lib.rs index 7fccc86c5..fb204d27b 100644 --- a/src/lib.rs +++ b/src/lib.rs | |||
| @@ -18,7 +18,6 @@ pub mod lpuart; | |||
| 18 | pub mod ostimer; | 18 | pub mod ostimer; |
| 19 | pub mod rtc; | 19 | pub mod rtc; |
| 20 | 20 | ||
| 21 | #[cfg(feature = "rt")] | ||
| 22 | pub use crate::pac::NVIC_PRIO_BITS; | 21 | pub use crate::pac::NVIC_PRIO_BITS; |
| 23 | 22 | ||
| 24 | #[rustfmt::skip] | 23 | #[rustfmt::skip] |
| @@ -347,10 +346,24 @@ pub fn init(cfg: crate::config::Config) -> Peripherals { | |||
| 347 | crate::interrupt::RTC.set_priority(cfg.rtc_interrupt_priority); | 346 | crate::interrupt::RTC.set_priority(cfg.rtc_interrupt_priority); |
| 348 | // Apply user-configured priority early; enabling is left to examples/apps | 347 | // Apply user-configured priority early; enabling is left to examples/apps |
| 349 | crate::interrupt::ADC1.set_priority(cfg.adc_interrupt_priority); | 348 | crate::interrupt::ADC1.set_priority(cfg.adc_interrupt_priority); |
| 349 | // Apply user-configured priority early; enabling is left to examples/apps | ||
| 350 | crate::interrupt::GPIO0.set_priority(cfg.gpio_interrupt_priority); | ||
| 351 | // Apply user-configured priority early; enabling is left to examples/apps | ||
| 352 | crate::interrupt::GPIO1.set_priority(cfg.gpio_interrupt_priority); | ||
| 353 | // Apply user-configured priority early; enabling is left to examples/apps | ||
| 354 | crate::interrupt::GPIO2.set_priority(cfg.gpio_interrupt_priority); | ||
| 355 | // Apply user-configured priority early; enabling is left to examples/apps | ||
| 356 | crate::interrupt::GPIO3.set_priority(cfg.gpio_interrupt_priority); | ||
| 357 | // Apply user-configured priority early; enabling is left to examples/apps | ||
| 358 | crate::interrupt::GPIO4.set_priority(cfg.gpio_interrupt_priority); | ||
| 350 | 359 | ||
| 351 | // Configure clocks | 360 | // Configure clocks |
| 352 | crate::clocks::init(cfg.clock_cfg).unwrap(); | 361 | crate::clocks::init(cfg.clock_cfg).unwrap(); |
| 353 | 362 | ||
| 363 | unsafe { | ||
| 364 | crate::gpio::init(); | ||
| 365 | } | ||
| 366 | |||
| 354 | // Initialize embassy-time global driver backed by OSTIMER0 | 367 | // Initialize embassy-time global driver backed by OSTIMER0 |
| 355 | #[cfg(feature = "time")] | 368 | #[cfg(feature = "time")] |
| 356 | crate::ostimer::time_driver::init(crate::config::Config::default().time_interrupt_priority, 1_000_000); | 369 | crate::ostimer::time_driver::init(crate::config::Config::default().time_interrupt_priority, 1_000_000); |
