Skip to content

Commit c5c50ad

Browse files
committed
Refactor Edge interrupt handling
1 parent bdcdd8c commit c5c50ad

File tree

1 file changed

+70
-22
lines changed

1 file changed

+70
-22
lines changed

rp2040-hal/src/gpio/pin/non_blocking.rs

Lines changed: 70 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::{
33
sealed::{IrqWaker, Wakeable},
44
AsyncPeripheral, CancellablePollFn as CPFn,
55
},
6-
atomic_register_access::write_bitmask_clear,
6+
atomic_register_access::{write_bitmask_clear, write_bitmask_set},
77
gpio::{
88
func::{FunctionSio, SioConfig},
99
pin::pin_sealed::{PinIdOps, TypeLevelPinId},
@@ -14,6 +14,8 @@ use crate::{
1414
use core::task::Poll;
1515
use embedded_hal_async::digital::Wait;
1616

17+
const EDGE_INTERRUPTS_MASK: u32 = Interrupt::EdgeLow.mask() | Interrupt::EdgeHigh.mask();
18+
1719
impl<I, P, S> AsyncPeripheral for Pin<I, FunctionSio<S>, P>
1820
where
1921
I: PinId + TypeLevelPinId,
@@ -27,9 +29,6 @@ where
2729
| Interrupt::EdgeLow.mask()
2830
| Interrupt::EdgeHigh.mask();
2931

30-
// Level interrupts are not latched and can't be cleared
31-
const CLEAR_INTERRUPTS_MASK: u32 = Interrupt::EdgeLow.mask() | Interrupt::EdgeHigh.mask();
32-
3332
let pin_id = I::ID;
3433

3534
let (ints_reg, ints_offset) = pin_id.proc_ints(Sio::core());
@@ -43,9 +42,8 @@ where
4342
write_bitmask_clear(inte_reg.as_ptr(), INTERRUPTS_MASK << inte_offset);
4443
}
4544

46-
// Clear interrupts for Pin
47-
let (intr_reg, intr_offset) = pin_id.intr();
48-
intr_reg.write(|w| unsafe { w.bits(CLEAR_INTERRUPTS_MASK << intr_offset) });
45+
// Don't need to clear any interrupts here. Level interrupts are not latched,
46+
// Edge interrupts are cleared in the relevant poll functions
4947

5048
Self::waker().wake();
5149
}
@@ -85,6 +83,42 @@ where
8583
}
8684
}
8785

86+
fn poll_rising_edge(&mut self) -> Poll<Result<(), Error>> {
87+
// read raw interrupt status, because interrupt is disabled in on_interrupt(), but is not cleared
88+
if self.raw_interrupt_status(Interrupt::EdgeHigh) {
89+
self.clear_interrupt(Interrupt::EdgeHigh);
90+
91+
Poll::Ready(Ok(()))
92+
} else {
93+
Poll::Pending
94+
}
95+
}
96+
97+
fn poll_falling_edge(&mut self) -> Poll<Result<(), Error>> {
98+
// read raw interrupt status, because interrupt is disabled in on_interrupt(), but is not cleared
99+
if self.raw_interrupt_status(Interrupt::EdgeLow) {
100+
self.clear_interrupt(Interrupt::EdgeLow);
101+
102+
Poll::Ready(Ok(()))
103+
} else {
104+
Poll::Pending
105+
}
106+
}
107+
108+
fn poll_any_edge(&mut self) -> Poll<Result<(), Error>> {
109+
// read raw interrupt status, because interrupt is disabled in on_interrupt(), but is not cleared
110+
let (reg, offset) = self.id.intr();
111+
let bits = reg.read().bits() >> offset;
112+
113+
if bits & EDGE_INTERRUPTS_MASK != 0 {
114+
reg.write(|w| unsafe { w.bits(EDGE_INTERRUPTS_MASK << offset) });
115+
116+
Poll::Ready(Ok(()))
117+
} else {
118+
Poll::Pending
119+
}
120+
}
121+
88122
fn disable_level_high_irq(&mut self) {
89123
self.set_interrupt_enabled(Interrupt::LevelHigh, false);
90124
}
@@ -117,6 +151,26 @@ where
117151
self.set_interrupt_enabled(Interrupt::EdgeLow, true)
118152
}
119153

154+
fn disable_any_edge_irq(&mut self) {
155+
let (reg, offset) = self.id.proc_inte(Sio::core());
156+
unsafe {
157+
write_bitmask_clear(reg.as_ptr(), EDGE_INTERRUPTS_MASK << offset);
158+
}
159+
}
160+
161+
fn enable_any_edge_irq(&mut self) {
162+
let (reg, offset) = self.id.proc_inte(Sio::core());
163+
unsafe {
164+
write_bitmask_set(reg.as_ptr(), EDGE_INTERRUPTS_MASK << offset);
165+
}
166+
}
167+
168+
fn raw_interrupt_status(&self, interrupt: Interrupt) -> bool {
169+
let (reg, offset) = self.id.intr();
170+
let mask = interrupt.mask();
171+
(reg.read().bits() >> offset) & mask == mask
172+
}
173+
120174
async fn _wait_for_high(&mut self) {
121175
let _ = CPFn::new(
122176
self,
@@ -138,39 +192,33 @@ where
138192
}
139193

140194
async fn _wait_for_rising_edge(&mut self) {
141-
if self._is_high() {
142-
self._wait_for_low().await;
143-
}
144-
145195
let _ = CPFn::new(
146196
self,
147-
Self::poll_is_high,
197+
Self::poll_rising_edge,
148198
Self::enable_rising_edge_irq,
149199
Self::disable_rising_edge_irq,
150200
)
151201
.await;
152202
}
153203

154204
async fn _wait_for_falling_edge(&mut self) {
155-
if self._is_low() {
156-
self._wait_for_high().await;
157-
}
158-
159205
let _ = CPFn::new(
160206
self,
161-
Self::poll_is_high,
207+
Self::poll_falling_edge,
162208
Self::enable_falling_edge_irq,
163209
Self::disable_falling_edge_irq,
164210
)
165211
.await;
166212
}
167213

168214
async fn _wait_for_any_edge(&mut self) {
169-
if self._is_high() {
170-
self._wait_for_falling_edge().await;
171-
} else {
172-
self._wait_for_rising_edge().await;
173-
}
215+
let _ = CPFn::new(
216+
self,
217+
Self::poll_any_edge,
218+
Self::enable_any_edge_irq,
219+
Self::disable_any_edge_irq,
220+
)
221+
.await;
174222
}
175223
}
176224

0 commit comments

Comments
 (0)