aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/config.rs2
-rw-r--r--src/gpio.rs243
-rw-r--r--src/interrupt.rs193
-rw-r--r--src/lib.rs15
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
5use core::convert::Infallible; 5use core::convert::Infallible;
6use core::future::Future;
6use core::marker::PhantomData; 7use core::marker::PhantomData;
8use core::pin::pin;
7 9
8use embassy_hal_internal::{Peri, PeripheralType}; 10use embassy_hal_internal::{Peri, PeripheralType};
11use maitake_sync::WaitMap;
9use paste::paste; 12use paste::paste;
10 13
14use crate::pac::interrupt;
11use crate::pac::port0::pcr0::{Dse, Inv, Mux, Pe, Ps, Sre}; 15use crate::pac::port0::pcr0::{Dse, Inv, Mux, Pe, Ps, Sre};
12 16
17struct BitIter(u32);
18
19impl 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
33const PORT_COUNT: usize = 5;
34
35static PORT_WAIT_MAPS: [WaitMap<usize, ()>; PORT_COUNT] = [
36 WaitMap::new(),
37 WaitMap::new(),
38 WaitMap::new(),
39 WaitMap::new(),
40 WaitMap::new(),
41];
42
43fn 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]
60fn GPIO0() {
61 irq_handler(0, crate::pac::Gpio0::ptr());
62}
63
64#[interrupt]
65fn GPIO1() {
66 irq_handler(1, crate::pac::Gpio1::ptr());
67}
68
69#[interrupt]
70fn GPIO2() {
71 irq_handler(2, crate::pac::Gpio2::ptr());
72}
73
74#[interrupt]
75fn GPIO3() {
76 irq_handler(3, crate::pac::Gpio3::ptr());
77}
78
79#[interrupt]
80fn GPIO4() {
81 irq_handler(4, crate::pac::Gpio4::ptr());
82}
83
84pub(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
685impl<'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.
602pub struct Output<'d> { 756pub 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
855impl<'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
887impl 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
914impl 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.
701impl embedded_hal_02::digital::v2::InputPin for Flex<'_> { 942impl 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
9mod generated { 9mod 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
296pub struct Gpio0;
297pub const GPIO0: Gpio0 = Gpio0;
298
299impl 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
334pub struct Gpio1;
335pub const GPIO1: Gpio1 = Gpio1;
336
337impl 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
372pub struct Gpio2;
373pub const GPIO2: Gpio2 = Gpio2;
374
375impl 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
410pub struct Gpio3;
411pub const GPIO3: Gpio3 = Gpio3;
412
413impl 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
448pub struct Gpio4;
449pub const GPIO4: Gpio4 = Gpio4;
450
451impl 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;
18pub mod ostimer; 18pub mod ostimer;
19pub mod rtc; 19pub mod rtc;
20 20
21#[cfg(feature = "rt")]
22pub use crate::pac::NVIC_PRIO_BITS; 21pub 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);