aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpennae <[email protected]>2023-07-30 02:10:48 +0200
committerpennae <[email protected]>2023-08-03 19:22:47 +0200
commit9dfda46e0c43559a6ca2ed87c0ceb32d19456c62 (patch)
tree42d5a3a165cd54ecc255b354a5e0447b27086161
parent4d60c715e683aaadf25d9f066bde805c725fefb4 (diff)
rp: add dormant-wake functionality for Input
this temporarily takes ownership of pins because we need to clear edge interrupts before waiting for them (otherwise we may wait indefinitely), we want to clean up the dormant-wake bits after a wakeup, and doing anything *else* with the input while we're waiting for a wakeup isn't possible at all. doing it like this lets us not impose any cost on those who don't use dormant wakes without entangling dormant waits too badly with regular interrupt waits.
-rw-r--r--embassy-rp/src/gpio.rs61
1 files changed, 61 insertions, 0 deletions
diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs
index 73e893523..ad9d4262d 100644
--- a/embassy-rp/src/gpio.rs
+++ b/embassy-rp/src/gpio.rs
@@ -75,6 +75,15 @@ pub enum Bank {
75 Qspi = 1, 75 Qspi = 1,
76} 76}
77 77
78#[derive(Debug, Eq, PartialEq, Copy, Clone, Default)]
79#[cfg_attr(feature = "defmt", derive(defmt::Format))]
80pub struct DormantWakeConfig {
81 pub edge_high: bool,
82 pub edge_low: bool,
83 pub level_high: bool,
84 pub level_low: bool,
85}
86
78pub struct Input<'d, T: Pin> { 87pub struct Input<'d, T: Pin> {
79 pin: Flex<'d, T>, 88 pin: Flex<'d, T>,
80} 89}
@@ -128,6 +137,11 @@ impl<'d, T: Pin> Input<'d, T> {
128 pub async fn wait_for_any_edge(&mut self) { 137 pub async fn wait_for_any_edge(&mut self) {
129 self.pin.wait_for_any_edge().await; 138 self.pin.wait_for_any_edge().await;
130 } 139 }
140
141 #[inline]
142 pub fn dormant_wake(&mut self, cfg: DormantWakeConfig) -> DormantWake<T> {
143 self.pin.dormant_wake(cfg)
144 }
131} 145}
132 146
133/// Interrupt trigger levels. 147/// Interrupt trigger levels.
@@ -639,15 +653,62 @@ impl<'d, T: Pin> Flex<'d, T> {
639 pub async fn wait_for_any_edge(&mut self) { 653 pub async fn wait_for_any_edge(&mut self) {
640 InputFuture::new(&mut self.pin, InterruptTrigger::AnyEdge).await; 654 InputFuture::new(&mut self.pin, InterruptTrigger::AnyEdge).await;
641 } 655 }
656
657 #[inline]
658 pub fn dormant_wake(&mut self, cfg: DormantWakeConfig) -> DormantWake<T> {
659 let idx = self.pin._pin() as usize;
660 self.pin.io().intr(idx / 8).write(|w| {
661 w.set_edge_high(idx % 8, cfg.edge_high);
662 w.set_edge_low(idx % 8, cfg.edge_low);
663 });
664 self.pin.io().int_dormant_wake().inte(idx / 8).write_set(|w| {
665 w.set_edge_high(idx % 8, cfg.edge_high);
666 w.set_edge_low(idx % 8, cfg.edge_low);
667 w.set_level_high(idx % 8, cfg.level_high);
668 w.set_level_low(idx % 8, cfg.level_low);
669 });
670 DormantWake {
671 pin: self.pin.reborrow(),
672 cfg,
673 }
674 }
642} 675}
643 676
644impl<'d, T: Pin> Drop for Flex<'d, T> { 677impl<'d, T: Pin> Drop for Flex<'d, T> {
645 #[inline] 678 #[inline]
646 fn drop(&mut self) { 679 fn drop(&mut self) {
680 let idx = self.pin._pin() as usize;
647 self.pin.pad_ctrl().write(|_| {}); 681 self.pin.pad_ctrl().write(|_| {});
648 self.pin.gpio().ctrl().write(|w| { 682 self.pin.gpio().ctrl().write(|w| {
649 w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL as _); 683 w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL as _);
650 }); 684 });
685 self.pin.io().int_dormant_wake().inte(idx / 8).write_clear(|w| {
686 w.set_edge_high(idx % 8, true);
687 w.set_edge_low(idx % 8, true);
688 w.set_level_high(idx % 8, true);
689 w.set_level_low(idx % 8, true);
690 });
691 }
692}
693
694pub struct DormantWake<'w, T: Pin> {
695 pin: PeripheralRef<'w, T>,
696 cfg: DormantWakeConfig,
697}
698
699impl<'w, T: Pin> Drop for DormantWake<'w, T> {
700 fn drop(&mut self) {
701 let idx = self.pin._pin() as usize;
702 self.pin.io().intr(idx / 8).write(|w| {
703 w.set_edge_high(idx % 8, self.cfg.edge_high);
704 w.set_edge_low(idx % 8, self.cfg.edge_low);
705 });
706 self.pin.io().int_dormant_wake().inte(idx / 8).write_clear(|w| {
707 w.set_edge_high(idx % 8, true);
708 w.set_edge_low(idx % 8, true);
709 w.set_level_high(idx % 8, true);
710 w.set_level_low(idx % 8, true);
711 });
651 } 712 }
652} 713}
653 714