aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpennae <[email protected]>2023-07-31 20:02:06 +0200
committerpennae <[email protected]>2023-07-31 20:02:06 +0200
commitf3ad0c6adeb4212af52f4ff974a488765551e81e (patch)
tree2beac7c10b274fe7ed9a6fda868e6ba7b229f80f
parentdca1777a2f3659b1acaa87aba31caf9afb09eae4 (diff)
rp: fix qspi gpio interrupts
so far only bank0 interrupts were processed and configured, even if a qspi pin was given. this is obviously not the right thing to do, so let's rectify that. the fact that no problems have shown up so far does suggest that most, if not all, applications don't use this functionality at all.
-rw-r--r--embassy-rp/src/gpio.rs45
1 files changed, 36 insertions, 9 deletions
diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs
index 9861429f3..73e893523 100644
--- a/embassy-rp/src/gpio.rs
+++ b/embassy-rp/src/gpio.rs
@@ -11,9 +11,13 @@ use crate::pac::common::{Reg, RW};
11use crate::pac::SIO; 11use crate::pac::SIO;
12use crate::{interrupt, pac, peripherals, Peripheral, RegExt}; 12use crate::{interrupt, pac, peripherals, Peripheral, RegExt};
13 13
14const PIN_COUNT: usize = 30;
15const NEW_AW: AtomicWaker = AtomicWaker::new(); 14const NEW_AW: AtomicWaker = AtomicWaker::new();
16static INTERRUPT_WAKERS: [AtomicWaker; PIN_COUNT] = [NEW_AW; PIN_COUNT]; 15const BANK0_PIN_COUNT: usize = 30;
16static BANK0_WAKERS: [AtomicWaker; BANK0_PIN_COUNT] = [NEW_AW; BANK0_PIN_COUNT];
17#[cfg(feature = "qspi-as-gpio")]
18const QSPI_PIN_COUNT: usize = 6;
19#[cfg(feature = "qspi-as-gpio")]
20static QSPI_WAKERS: [AtomicWaker; QSPI_PIN_COUNT] = [NEW_AW; QSPI_PIN_COUNT];
17 21
18/// Represents a digital input or output level. 22/// Represents a digital input or output level.
19#[derive(Debug, Eq, PartialEq, Clone, Copy)] 23#[derive(Debug, Eq, PartialEq, Clone, Copy)]
@@ -141,17 +145,23 @@ pub(crate) unsafe fn init() {
141 interrupt::IO_IRQ_BANK0.disable(); 145 interrupt::IO_IRQ_BANK0.disable();
142 interrupt::IO_IRQ_BANK0.set_priority(interrupt::Priority::P3); 146 interrupt::IO_IRQ_BANK0.set_priority(interrupt::Priority::P3);
143 interrupt::IO_IRQ_BANK0.enable(); 147 interrupt::IO_IRQ_BANK0.enable();
148
149 #[cfg(feature = "qspi-as-gpio")]
150 {
151 interrupt::IO_IRQ_QSPI.disable();
152 interrupt::IO_IRQ_QSPI.set_priority(interrupt::Priority::P3);
153 interrupt::IO_IRQ_QSPI.enable();
154 }
144} 155}
145 156
146#[cfg(feature = "rt")] 157#[cfg(feature = "rt")]
147#[interrupt] 158fn irq_handler<const N: usize>(bank: pac::io::Io, wakers: &[AtomicWaker; N]) {
148fn IO_IRQ_BANK0() {
149 let cpu = SIO.cpuid().read() as usize; 159 let cpu = SIO.cpuid().read() as usize;
150 // There are two sets of interrupt registers, one for cpu0 and one for cpu1 160 // There are two sets of interrupt registers, one for cpu0 and one for cpu1
151 // and here we are selecting the set that belongs to the currently executing 161 // and here we are selecting the set that belongs to the currently executing
152 // cpu. 162 // cpu.
153 let proc_intx: pac::io::Int = pac::IO_BANK0.int_proc(cpu); 163 let proc_intx: pac::io::Int = bank.int_proc(cpu);
154 for pin in 0..PIN_COUNT { 164 for pin in 0..N {
155 // There are 4 raw interrupt status registers, PROCx_INTS0, PROCx_INTS1, 165 // There are 4 raw interrupt status registers, PROCx_INTS0, PROCx_INTS1,
156 // PROCx_INTS2, and PROCx_INTS3, and we are selecting the one that the 166 // PROCx_INTS2, and PROCx_INTS3, and we are selecting the one that the
157 // current pin belongs to. 167 // current pin belongs to.
@@ -172,11 +182,23 @@ fn IO_IRQ_BANK0() {
172 w.set_level_high(pin_group, true); 182 w.set_level_high(pin_group, true);
173 w.set_level_low(pin_group, true); 183 w.set_level_low(pin_group, true);
174 }); 184 });
175 INTERRUPT_WAKERS[pin as usize].wake(); 185 wakers[pin as usize].wake();
176 } 186 }
177 } 187 }
178} 188}
179 189
190#[cfg(feature = "rt")]
191#[interrupt]
192fn IO_IRQ_BANK0() {
193 irq_handler(pac::IO_BANK0, &BANK0_WAKERS);
194}
195
196#[cfg(all(feature = "rt", feature = "qspi-as-gpio"))]
197#[interrupt]
198fn IO_IRQ_QSPI() {
199 irq_handler(pac::IO_QSPI, &QSPI_WAKERS);
200}
201
180#[must_use = "futures do nothing unless you `.await` or poll them"] 202#[must_use = "futures do nothing unless you `.await` or poll them"]
181struct InputFuture<'a, T: Pin> { 203struct InputFuture<'a, T: Pin> {
182 pin: PeripheralRef<'a, T>, 204 pin: PeripheralRef<'a, T>,
@@ -195,7 +217,7 @@ impl<'d, T: Pin> InputFuture<'d, T> {
195 // (the alternative being checking the current level and waiting for 217 // (the alternative being checking the current level and waiting for
196 // its inverse, but that requires reading the current level and thus 218 // its inverse, but that requires reading the current level and thus
197 // missing anything that happened before the level was read.) 219 // missing anything that happened before the level was read.)
198 pac::IO_BANK0.intr(pin.pin() as usize / 8).write(|w| { 220 pin.io().intr(pin.pin() as usize / 8).write(|w| {
199 w.set_edge_high(pin_group, true); 221 w.set_edge_high(pin_group, true);
200 w.set_edge_low(pin_group, true); 222 w.set_edge_low(pin_group, true);
201 }); 223 });
@@ -235,7 +257,12 @@ impl<'d, T: Pin> Future for InputFuture<'d, T> {
235 fn poll(self: FuturePin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 257 fn poll(self: FuturePin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
236 // We need to register/re-register the waker for each poll because any 258 // We need to register/re-register the waker for each poll because any
237 // calls to wake will deregister the waker. 259 // calls to wake will deregister the waker.
238 INTERRUPT_WAKERS[self.pin.pin() as usize].register(cx.waker()); 260 let waker = match self.pin.bank() {
261 Bank::Bank0 => &BANK0_WAKERS[self.pin.pin() as usize],
262 #[cfg(feature = "qspi-as-gpio")]
263 Bank::Qspi => &QSPI_WAKERS[self.pin.pin() as usize],
264 };
265 waker.register(cx.waker());
239 266
240 // self.int_proc() will get the register offset for the current cpu, 267 // self.int_proc() will get the register offset for the current cpu,
241 // then we want to access the interrupt enable register for our 268 // then we want to access the interrupt enable register for our