aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-03-06 00:41:47 +0100
committerGitHub <[email protected]>2023-03-06 00:41:47 +0100
commit18fe398673f55b07159d01a230910bb9689c1525 (patch)
tree85c92ef10298ccaedec58c0582af1bf05753192e
parent403a83e08da67ebb20d04b1675a34c12752a94fc (diff)
parentf5e09a8f4a6d7b1bd6723c60915cb9f29cf352f7 (diff)
Merge pull request #1224 from embassy-rs/interrupt-binding
nrf: new interrupt binding traits/macro
-rw-r--r--embassy-cortex-m/src/interrupt.rs36
-rw-r--r--embassy-macros/src/macros/cortex_m_interrupt_declare.rs4
-rw-r--r--embassy-macros/src/macros/cortex_m_interrupt_take.rs2
-rw-r--r--embassy-nrf/src/buffered_uarte.rs225
-rw-r--r--embassy-nrf/src/chips/nrf52805.rs4
-rw-r--r--embassy-nrf/src/chips/nrf52810.rs6
-rw-r--r--embassy-nrf/src/chips/nrf52811.rs6
-rw-r--r--embassy-nrf/src/chips/nrf52820.rs4
-rw-r--r--embassy-nrf/src/chips/nrf52832.rs9
-rw-r--r--embassy-nrf/src/chips/nrf52833.rs6
-rw-r--r--embassy-nrf/src/chips/nrf52840.rs6
-rw-r--r--embassy-nrf/src/chips/nrf5340_app.rs16
-rw-r--r--embassy-nrf/src/chips/nrf5340_net.rs5
-rw-r--r--embassy-nrf/src/chips/nrf9160.rs2
-rw-r--r--embassy-nrf/src/i2s.rs77
-rw-r--r--embassy-nrf/src/lib.rs41
-rw-r--r--embassy-nrf/src/pdm.rs131
-rw-r--r--embassy-nrf/src/qdec.rs112
-rw-r--r--embassy-nrf/src/qspi.rs65
-rw-r--r--embassy-nrf/src/rng.rs193
-rw-r--r--embassy-nrf/src/saadc.rs62
-rw-r--r--embassy-nrf/src/spim.rs59
-rw-r--r--embassy-nrf/src/spis.rs85
-rw-r--r--embassy-nrf/src/temp.rs35
-rw-r--r--embassy-nrf/src/timer.rs134
-rw-r--r--embassy-nrf/src/twim.rs47
-rw-r--r--embassy-nrf/src/twis.rs55
-rw-r--r--embassy-nrf/src/uarte.rs85
-rw-r--r--embassy-nrf/src/usb/mod.rs (renamed from embassy-nrf/src/usb.rs)234
-rw-r--r--embassy-nrf/src/usb/vbus_detect.rs177
-rw-r--r--examples/nrf52840/Cargo.toml7
-rw-r--r--examples/nrf52840/src/bin/awaitable_timer.rs26
-rw-r--r--examples/nrf52840/src/bin/buffered_uart.rs11
-rw-r--r--examples/nrf52840/src/bin/i2s_effect.rs15
-rw-r--r--examples/nrf52840/src/bin/i2s_monitor.rs9
-rw-r--r--examples/nrf52840/src/bin/i2s_waveform.rs9
-rw-r--r--examples/nrf52840/src/bin/lora_p2p_report.rs9
-rw-r--r--examples/nrf52840/src/bin/lora_p2p_sense.rs9
-rw-r--r--examples/nrf52840/src/bin/pdm.rs10
-rw-r--r--examples/nrf52840/src/bin/qdec.rs9
-rw-r--r--examples/nrf52840/src/bin/qspi.rs9
-rw-r--r--examples/nrf52840/src/bin/qspi_lowpower.rs9
-rw-r--r--examples/nrf52840/src/bin/rng.rs8
-rw-r--r--examples/nrf52840/src/bin/saadc.rs8
-rw-r--r--examples/nrf52840/src/bin/saadc_continuous.rs8
-rw-r--r--examples/nrf52840/src/bin/spim.rs9
-rw-r--r--examples/nrf52840/src/bin/spis.rs9
-rw-r--r--examples/nrf52840/src/bin/temp.rs9
-rw-r--r--examples/nrf52840/src/bin/twim.rs9
-rw-r--r--examples/nrf52840/src/bin/twim_lowpower.rs9
-rw-r--r--examples/nrf52840/src/bin/twis.rs12
-rw-r--r--examples/nrf52840/src/bin/uart.rs9
-rw-r--r--examples/nrf52840/src/bin/uart_idle.rs10
-rw-r--r--examples/nrf52840/src/bin/uart_split.rs9
-rw-r--r--examples/nrf52840/src/bin/usb_ethernet.rs18
-rw-r--r--examples/nrf52840/src/bin/usb_hid_keyboard.rs16
-rw-r--r--examples/nrf52840/src/bin/usb_hid_mouse.rs16
-rw-r--r--examples/nrf52840/src/bin/usb_serial.rs16
-rw-r--r--examples/nrf52840/src/bin/usb_serial_multitask.rs51
-rw-r--r--examples/nrf52840/src/bin/usb_serial_winusb.rs14
-rw-r--r--examples/nrf5340/src/bin/uart.rs10
-rw-r--r--tests/nrf/src/bin/buffered_uart.rs10
-rw-r--r--tests/nrf/src/bin/buffered_uart_spam.rs13
63 files changed, 1311 insertions, 1017 deletions
diff --git a/embassy-cortex-m/src/interrupt.rs b/embassy-cortex-m/src/interrupt.rs
index 1df8671b9..3a82726df 100644
--- a/embassy-cortex-m/src/interrupt.rs
+++ b/embassy-cortex-m/src/interrupt.rs
@@ -13,14 +13,44 @@ pub mod _export {
13 pub use embassy_macros::{cortex_m_interrupt as interrupt, cortex_m_interrupt_declare as declare}; 13 pub use embassy_macros::{cortex_m_interrupt as interrupt, cortex_m_interrupt_declare as declare};
14} 14}
15 15
16/// Interrupt handler trait.
17///
18/// Drivers that need to handle interrupts implement this trait.
19/// The user must ensure `on_interrupt()` is called every time the interrupt fires.
20/// Drivers must use use [`Binding`] to assert at compile time that the user has done so.
21pub trait Handler<I: Interrupt> {
22 /// Interrupt handler function.
23 ///
24 /// Must be called every time the `I` interrupt fires, synchronously from
25 /// the interrupt handler context.
26 ///
27 /// # Safety
28 ///
29 /// This function must ONLY be called from the interrupt handler for `I`.
30 unsafe fn on_interrupt();
31}
32
33/// Compile-time assertion that an interrupt has been bound to a handler.
34///
35/// For the vast majority of cases, you should use the `bind_interrupts!`
36/// macro instead of writing `unsafe impl`s of this trait.
37///
38/// # Safety
39///
40/// By implementing this trait, you are asserting that you have arranged for `H::on_interrupt()`
41/// to be called every time the `I` interrupt fires.
42///
43/// This allows drivers to check bindings at compile-time.
44pub unsafe trait Binding<I: Interrupt, H: Handler<I>> {}
45
16/// Implementation detail, do not use outside embassy crates. 46/// Implementation detail, do not use outside embassy crates.
17#[doc(hidden)] 47#[doc(hidden)]
18pub struct Handler { 48pub struct DynHandler {
19 pub func: AtomicPtr<()>, 49 pub func: AtomicPtr<()>,
20 pub ctx: AtomicPtr<()>, 50 pub ctx: AtomicPtr<()>,
21} 51}
22 52
23impl Handler { 53impl DynHandler {
24 pub const fn new() -> Self { 54 pub const fn new() -> Self {
25 Self { 55 Self {
26 func: AtomicPtr::new(ptr::null_mut()), 56 func: AtomicPtr::new(ptr::null_mut()),
@@ -51,7 +81,7 @@ pub unsafe trait Interrupt: Peripheral<P = Self> {
51 81
52 /// Implementation detail, do not use outside embassy crates. 82 /// Implementation detail, do not use outside embassy crates.
53 #[doc(hidden)] 83 #[doc(hidden)]
54 unsafe fn __handler(&self) -> &'static Handler; 84 unsafe fn __handler(&self) -> &'static DynHandler;
55} 85}
56 86
57/// Represents additional behavior for all interrupts. 87/// Represents additional behavior for all interrupts.
diff --git a/embassy-macros/src/macros/cortex_m_interrupt_declare.rs b/embassy-macros/src/macros/cortex_m_interrupt_declare.rs
index ebbb47cd7..699883efa 100644
--- a/embassy-macros/src/macros/cortex_m_interrupt_declare.rs
+++ b/embassy-macros/src/macros/cortex_m_interrupt_declare.rs
@@ -21,9 +21,9 @@ pub fn run(name: syn::Ident) -> Result<TokenStream, TokenStream> {
21 unsafe fn steal() -> Self { 21 unsafe fn steal() -> Self {
22 Self(()) 22 Self(())
23 } 23 }
24 unsafe fn __handler(&self) -> &'static ::embassy_cortex_m::interrupt::Handler { 24 unsafe fn __handler(&self) -> &'static ::embassy_cortex_m::interrupt::DynHandler {
25 #[export_name = #name_handler] 25 #[export_name = #name_handler]
26 static HANDLER: ::embassy_cortex_m::interrupt::Handler = ::embassy_cortex_m::interrupt::Handler::new(); 26 static HANDLER: ::embassy_cortex_m::interrupt::DynHandler = ::embassy_cortex_m::interrupt::DynHandler::new();
27 &HANDLER 27 &HANDLER
28 } 28 }
29 } 29 }
diff --git a/embassy-macros/src/macros/cortex_m_interrupt_take.rs b/embassy-macros/src/macros/cortex_m_interrupt_take.rs
index d30189ce3..e2ebf98c7 100644
--- a/embassy-macros/src/macros/cortex_m_interrupt_take.rs
+++ b/embassy-macros/src/macros/cortex_m_interrupt_take.rs
@@ -30,7 +30,7 @@ pub fn run(name: syn::Ident) -> Result<TokenStream, TokenStream> {
30 pub unsafe extern "C" fn trampoline() { 30 pub unsafe extern "C" fn trampoline() {
31 extern "C" { 31 extern "C" {
32 #[link_name = #name_handler] 32 #[link_name = #name_handler]
33 static HANDLER: interrupt::Handler; 33 static HANDLER: interrupt::DynHandler;
34 } 34 }
35 35
36 let func = HANDLER.func.load(interrupt::_export::atomic::Ordering::Relaxed); 36 let func = HANDLER.func.load(interrupt::_export::atomic::Ordering::Relaxed);
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs
index ab639aeea..75f93f904 100644
--- a/embassy-nrf/src/buffered_uarte.rs
+++ b/embassy-nrf/src/buffered_uarte.rs
@@ -10,6 +10,7 @@
10 10
11use core::cmp::min; 11use core::cmp::min;
12use core::future::poll_fn; 12use core::future::poll_fn;
13use core::marker::PhantomData;
13use core::slice; 14use core::slice;
14use core::sync::atomic::{compiler_fence, AtomicU8, AtomicUsize, Ordering}; 15use core::sync::atomic::{compiler_fence, AtomicU8, AtomicUsize, Ordering};
15use core::task::Poll; 16use core::task::Poll;
@@ -23,7 +24,7 @@ pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Pari
23 24
24use crate::gpio::sealed::Pin; 25use crate::gpio::sealed::Pin;
25use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; 26use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits};
26use crate::interrupt::InterruptExt; 27use crate::interrupt::{self, InterruptExt};
27use crate::ppi::{ 28use crate::ppi::{
28 self, AnyConfigurableChannel, AnyGroup, Channel, ConfigurableChannel, Event, Group, Ppi, PpiGroup, Task, 29 self, AnyConfigurableChannel, AnyGroup, Channel, ConfigurableChannel, Event, Group, Ppi, PpiGroup, Task,
29}; 30};
@@ -71,6 +72,113 @@ impl State {
71 } 72 }
72} 73}
73 74
75/// Interrupt handler.
76pub struct InterruptHandler<U: UarteInstance> {
77 _phantom: PhantomData<U>,
78}
79
80impl<U: UarteInstance> interrupt::Handler<U::Interrupt> for InterruptHandler<U> {
81 unsafe fn on_interrupt() {
82 //trace!("irq: start");
83 let r = U::regs();
84 let s = U::buffered_state();
85
86 let buf_len = s.rx_buf.len();
87 let half_len = buf_len / 2;
88 let mut tx = unsafe { s.tx_buf.reader() };
89 let mut rx = unsafe { s.rx_buf.writer() };
90
91 if r.events_error.read().bits() != 0 {
92 r.events_error.reset();
93 let errs = r.errorsrc.read();
94 r.errorsrc.write(|w| unsafe { w.bits(errs.bits()) });
95
96 if errs.overrun().bit() {
97 panic!("BufferedUarte overrun");
98 }
99 }
100
101 // Received some bytes, wake task.
102 if r.inten.read().rxdrdy().bit_is_set() && r.events_rxdrdy.read().bits() != 0 {
103 r.intenclr.write(|w| w.rxdrdy().clear());
104 r.events_rxdrdy.reset();
105 s.rx_waker.wake();
106 }
107
108 // If not RXing, start.
109 if s.rx_bufs.load(Ordering::Relaxed) == 0 {
110 let (ptr, len) = rx.push_buf();
111 if len >= half_len {
112 //trace!(" irq_rx: starting {:?}", half_len);
113 s.rx_bufs.store(1, Ordering::Relaxed);
114
115 // Set up the DMA read
116 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
117 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(half_len as _) });
118
119 // Start UARTE Receive transaction
120 r.tasks_startrx.write(|w| unsafe { w.bits(1) });
121 rx.push_done(half_len);
122 r.intenset.write(|w| w.rxstarted().set());
123 }
124 }
125
126 if r.events_rxstarted.read().bits() != 0 {
127 //trace!(" irq_rx: rxstarted");
128 let (ptr, len) = rx.push_buf();
129 if len >= half_len {
130 //trace!(" irq_rx: starting second {:?}", half_len);
131
132 // Set up the DMA read
133 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
134 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(half_len as _) });
135
136 let chn = s.rx_ppi_ch.load(Ordering::Relaxed);
137
138 ppi::regs().chenset.write(|w| unsafe { w.bits(1 << chn) });
139
140 rx.push_done(half_len);
141
142 r.events_rxstarted.reset();
143 } else {
144 //trace!(" irq_rx: rxstarted no buf");
145 r.intenclr.write(|w| w.rxstarted().clear());
146 }
147 }
148
149 // =============================
150
151 // TX end
152 if r.events_endtx.read().bits() != 0 {
153 r.events_endtx.reset();
154
155 let n = s.tx_count.load(Ordering::Relaxed);
156 //trace!(" irq_tx: endtx {:?}", n);
157 tx.pop_done(n);
158 s.tx_waker.wake();
159 s.tx_count.store(0, Ordering::Relaxed);
160 }
161
162 // If not TXing, start.
163 if s.tx_count.load(Ordering::Relaxed) == 0 {
164 let (ptr, len) = tx.pop_buf();
165 if len != 0 {
166 //trace!(" irq_tx: starting {:?}", len);
167 s.tx_count.store(len, Ordering::Relaxed);
168
169 // Set up the DMA write
170 r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
171 r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
172
173 // Start UARTE Transmit transaction
174 r.tasks_starttx.write(|w| unsafe { w.bits(1) });
175 }
176 }
177
178 //trace!("irq: end");
179 }
180}
181
74/// Buffered UARTE driver. 182/// Buffered UARTE driver.
75pub struct BufferedUarte<'d, U: UarteInstance, T: TimerInstance> { 183pub struct BufferedUarte<'d, U: UarteInstance, T: TimerInstance> {
76 _peri: PeripheralRef<'d, U>, 184 _peri: PeripheralRef<'d, U>,
@@ -94,7 +202,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
94 ppi_ch1: impl Peripheral<P = impl ConfigurableChannel> + 'd, 202 ppi_ch1: impl Peripheral<P = impl ConfigurableChannel> + 'd,
95 ppi_ch2: impl Peripheral<P = impl ConfigurableChannel> + 'd, 203 ppi_ch2: impl Peripheral<P = impl ConfigurableChannel> + 'd,
96 ppi_group: impl Peripheral<P = impl Group> + 'd, 204 ppi_group: impl Peripheral<P = impl Group> + 'd,
97 irq: impl Peripheral<P = U::Interrupt> + 'd, 205 _irq: impl interrupt::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
98 rxd: impl Peripheral<P = impl GpioPin> + 'd, 206 rxd: impl Peripheral<P = impl GpioPin> + 'd,
99 txd: impl Peripheral<P = impl GpioPin> + 'd, 207 txd: impl Peripheral<P = impl GpioPin> + 'd,
100 config: Config, 208 config: Config,
@@ -108,7 +216,6 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
108 ppi_ch1.map_into(), 216 ppi_ch1.map_into(),
109 ppi_ch2.map_into(), 217 ppi_ch2.map_into(),
110 ppi_group.map_into(), 218 ppi_group.map_into(),
111 irq,
112 rxd.map_into(), 219 rxd.map_into(),
113 txd.map_into(), 220 txd.map_into(),
114 None, 221 None,
@@ -130,7 +237,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
130 ppi_ch1: impl Peripheral<P = impl ConfigurableChannel> + 'd, 237 ppi_ch1: impl Peripheral<P = impl ConfigurableChannel> + 'd,
131 ppi_ch2: impl Peripheral<P = impl ConfigurableChannel> + 'd, 238 ppi_ch2: impl Peripheral<P = impl ConfigurableChannel> + 'd,
132 ppi_group: impl Peripheral<P = impl Group> + 'd, 239 ppi_group: impl Peripheral<P = impl Group> + 'd,
133 irq: impl Peripheral<P = U::Interrupt> + 'd, 240 _irq: impl interrupt::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
134 rxd: impl Peripheral<P = impl GpioPin> + 'd, 241 rxd: impl Peripheral<P = impl GpioPin> + 'd,
135 txd: impl Peripheral<P = impl GpioPin> + 'd, 242 txd: impl Peripheral<P = impl GpioPin> + 'd,
136 cts: impl Peripheral<P = impl GpioPin> + 'd, 243 cts: impl Peripheral<P = impl GpioPin> + 'd,
@@ -146,7 +253,6 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
146 ppi_ch1.map_into(), 253 ppi_ch1.map_into(),
147 ppi_ch2.map_into(), 254 ppi_ch2.map_into(),
148 ppi_group.map_into(), 255 ppi_group.map_into(),
149 irq,
150 rxd.map_into(), 256 rxd.map_into(),
151 txd.map_into(), 257 txd.map_into(),
152 Some(cts.map_into()), 258 Some(cts.map_into()),
@@ -163,7 +269,6 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
163 ppi_ch1: PeripheralRef<'d, AnyConfigurableChannel>, 269 ppi_ch1: PeripheralRef<'d, AnyConfigurableChannel>,
164 ppi_ch2: PeripheralRef<'d, AnyConfigurableChannel>, 270 ppi_ch2: PeripheralRef<'d, AnyConfigurableChannel>,
165 ppi_group: PeripheralRef<'d, AnyGroup>, 271 ppi_group: PeripheralRef<'d, AnyGroup>,
166 irq: impl Peripheral<P = U::Interrupt> + 'd,
167 rxd: PeripheralRef<'d, AnyPin>, 272 rxd: PeripheralRef<'d, AnyPin>,
168 txd: PeripheralRef<'d, AnyPin>, 273 txd: PeripheralRef<'d, AnyPin>,
169 cts: Option<PeripheralRef<'d, AnyPin>>, 274 cts: Option<PeripheralRef<'d, AnyPin>>,
@@ -172,7 +277,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
172 rx_buffer: &'d mut [u8], 277 rx_buffer: &'d mut [u8],
173 tx_buffer: &'d mut [u8], 278 tx_buffer: &'d mut [u8],
174 ) -> Self { 279 ) -> Self {
175 into_ref!(peri, timer, irq); 280 into_ref!(peri, timer);
176 281
177 assert!(rx_buffer.len() % 2 == 0); 282 assert!(rx_buffer.len() % 2 == 0);
178 283
@@ -257,10 +362,8 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
257 ppi_ch2.disable(); 362 ppi_ch2.disable();
258 ppi_group.add_channel(&ppi_ch2); 363 ppi_group.add_channel(&ppi_ch2);
259 364
260 irq.disable(); 365 unsafe { U::Interrupt::steal() }.pend();
261 irq.set_handler(Self::on_interrupt); 366 unsafe { U::Interrupt::steal() }.enable();
262 irq.pend();
263 irq.enable();
264 367
265 Self { 368 Self {
266 _peri: peri, 369 _peri: peri,
@@ -275,106 +378,6 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
275 unsafe { <U::Interrupt as Interrupt>::steal() }.pend() 378 unsafe { <U::Interrupt as Interrupt>::steal() }.pend()
276 } 379 }
277 380
278 fn on_interrupt(_: *mut ()) {
279 //trace!("irq: start");
280 let r = U::regs();
281 let s = U::buffered_state();
282
283 let buf_len = s.rx_buf.len();
284 let half_len = buf_len / 2;
285 let mut tx = unsafe { s.tx_buf.reader() };
286 let mut rx = unsafe { s.rx_buf.writer() };
287
288 if r.events_error.read().bits() != 0 {
289 r.events_error.reset();
290 let errs = r.errorsrc.read();
291 r.errorsrc.write(|w| unsafe { w.bits(errs.bits()) });
292
293 if errs.overrun().bit() {
294 panic!("BufferedUarte overrun");
295 }
296 }
297
298 // Received some bytes, wake task.
299 if r.inten.read().rxdrdy().bit_is_set() && r.events_rxdrdy.read().bits() != 0 {
300 r.intenclr.write(|w| w.rxdrdy().clear());
301 r.events_rxdrdy.reset();
302 s.rx_waker.wake();
303 }
304
305 // If not RXing, start.
306 if s.rx_bufs.load(Ordering::Relaxed) == 0 {
307 let (ptr, len) = rx.push_buf();
308 if len >= half_len {
309 //trace!(" irq_rx: starting {:?}", half_len);
310 s.rx_bufs.store(1, Ordering::Relaxed);
311
312 // Set up the DMA read
313 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
314 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(half_len as _) });
315
316 // Start UARTE Receive transaction
317 r.tasks_startrx.write(|w| unsafe { w.bits(1) });
318 rx.push_done(half_len);
319 r.intenset.write(|w| w.rxstarted().set());
320 }
321 }
322
323 if r.events_rxstarted.read().bits() != 0 {
324 //trace!(" irq_rx: rxstarted");
325 let (ptr, len) = rx.push_buf();
326 if len >= half_len {
327 //trace!(" irq_rx: starting second {:?}", half_len);
328
329 // Set up the DMA read
330 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
331 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(half_len as _) });
332
333 let chn = s.rx_ppi_ch.load(Ordering::Relaxed);
334
335 ppi::regs().chenset.write(|w| unsafe { w.bits(1 << chn) });
336
337 rx.push_done(half_len);
338
339 r.events_rxstarted.reset();
340 } else {
341 //trace!(" irq_rx: rxstarted no buf");
342 r.intenclr.write(|w| w.rxstarted().clear());
343 }
344 }
345
346 // =============================
347
348 // TX end
349 if r.events_endtx.read().bits() != 0 {
350 r.events_endtx.reset();
351
352 let n = s.tx_count.load(Ordering::Relaxed);
353 //trace!(" irq_tx: endtx {:?}", n);
354 tx.pop_done(n);
355 s.tx_waker.wake();
356 s.tx_count.store(0, Ordering::Relaxed);
357 }
358
359 // If not TXing, start.
360 if s.tx_count.load(Ordering::Relaxed) == 0 {
361 let (ptr, len) = tx.pop_buf();
362 if len != 0 {
363 //trace!(" irq_tx: starting {:?}", len);
364 s.tx_count.store(len, Ordering::Relaxed);
365
366 // Set up the DMA write
367 r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
368 r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
369
370 // Start UARTE Transmit transaction
371 r.tasks_starttx.write(|w| unsafe { w.bits(1) });
372 }
373 }
374
375 //trace!("irq: end");
376 }
377
378 /// Adjust the baud rate to the provided value. 381 /// Adjust the baud rate to the provided value.
379 pub fn set_baudrate(&mut self, baudrate: Baudrate) { 382 pub fn set_baudrate(&mut self, baudrate: Baudrate) {
380 let r = U::regs(); 383 let r = U::regs();
diff --git a/embassy-nrf/src/chips/nrf52805.rs b/embassy-nrf/src/chips/nrf52805.rs
index 3c74a2a63..e406c081b 100644
--- a/embassy-nrf/src/chips/nrf52805.rs
+++ b/embassy-nrf/src/chips/nrf52805.rs
@@ -140,6 +140,10 @@ impl_twim!(TWI0, TWIM0, TWIM0_TWIS0_TWI0);
140 140
141impl_twis!(TWI0, TWIS0, TWIM0_TWIS0_TWI0); 141impl_twis!(TWI0, TWIS0, TWIM0_TWIS0_TWI0);
142 142
143impl_qdec!(QDEC, QDEC, QDEC);
144
145impl_rng!(RNG, RNG, RNG);
146
143impl_timer!(TIMER0, TIMER0, TIMER0); 147impl_timer!(TIMER0, TIMER0, TIMER0);
144impl_timer!(TIMER1, TIMER1, TIMER1); 148impl_timer!(TIMER1, TIMER1, TIMER1);
145impl_timer!(TIMER2, TIMER2, TIMER2); 149impl_timer!(TIMER2, TIMER2, TIMER2);
diff --git a/embassy-nrf/src/chips/nrf52810.rs b/embassy-nrf/src/chips/nrf52810.rs
index 6b5c134b8..153795e54 100644
--- a/embassy-nrf/src/chips/nrf52810.rs
+++ b/embassy-nrf/src/chips/nrf52810.rs
@@ -148,6 +148,12 @@ impl_twis!(TWI0, TWIS0, TWIM0_TWIS0_TWI0);
148 148
149impl_pwm!(PWM0, PWM0, PWM0); 149impl_pwm!(PWM0, PWM0, PWM0);
150 150
151impl_pdm!(PDM, PDM, PDM);
152
153impl_qdec!(QDEC, QDEC, QDEC);
154
155impl_rng!(RNG, RNG, RNG);
156
151impl_timer!(TIMER0, TIMER0, TIMER0); 157impl_timer!(TIMER0, TIMER0, TIMER0);
152impl_timer!(TIMER1, TIMER1, TIMER1); 158impl_timer!(TIMER1, TIMER1, TIMER1);
153impl_timer!(TIMER2, TIMER2, TIMER2); 159impl_timer!(TIMER2, TIMER2, TIMER2);
diff --git a/embassy-nrf/src/chips/nrf52811.rs b/embassy-nrf/src/chips/nrf52811.rs
index c5de9a447..a7a7cf58c 100644
--- a/embassy-nrf/src/chips/nrf52811.rs
+++ b/embassy-nrf/src/chips/nrf52811.rs
@@ -150,6 +150,12 @@ impl_twis!(TWISPI0, TWIS0, TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0);
150 150
151impl_pwm!(PWM0, PWM0, PWM0); 151impl_pwm!(PWM0, PWM0, PWM0);
152 152
153impl_pdm!(PDM, PDM, PDM);
154
155impl_qdec!(QDEC, QDEC, QDEC);
156
157impl_rng!(RNG, RNG, RNG);
158
153impl_timer!(TIMER0, TIMER0, TIMER0); 159impl_timer!(TIMER0, TIMER0, TIMER0);
154impl_timer!(TIMER1, TIMER1, TIMER1); 160impl_timer!(TIMER1, TIMER1, TIMER1);
155impl_timer!(TIMER2, TIMER2, TIMER2); 161impl_timer!(TIMER2, TIMER2, TIMER2);
diff --git a/embassy-nrf/src/chips/nrf52820.rs b/embassy-nrf/src/chips/nrf52820.rs
index 81b07f32c..14a1b8cc9 100644
--- a/embassy-nrf/src/chips/nrf52820.rs
+++ b/embassy-nrf/src/chips/nrf52820.rs
@@ -153,6 +153,10 @@ impl_timer!(TIMER1, TIMER1, TIMER1);
153impl_timer!(TIMER2, TIMER2, TIMER2); 153impl_timer!(TIMER2, TIMER2, TIMER2);
154impl_timer!(TIMER3, TIMER3, TIMER3, extended); 154impl_timer!(TIMER3, TIMER3, TIMER3, extended);
155 155
156impl_qdec!(QDEC, QDEC, QDEC);
157
158impl_rng!(RNG, RNG, RNG);
159
156impl_pin!(P0_00, 0, 0); 160impl_pin!(P0_00, 0, 0);
157impl_pin!(P0_01, 0, 1); 161impl_pin!(P0_01, 0, 1);
158impl_pin!(P0_02, 0, 2); 162impl_pin!(P0_02, 0, 2);
diff --git a/embassy-nrf/src/chips/nrf52832.rs b/embassy-nrf/src/chips/nrf52832.rs
index c2b23fc5b..83ecd0deb 100644
--- a/embassy-nrf/src/chips/nrf52832.rs
+++ b/embassy-nrf/src/chips/nrf52832.rs
@@ -146,6 +146,9 @@ embassy_hal_common::peripherals! {
146 146
147 // I2S 147 // I2S
148 I2S, 148 I2S,
149
150 // PDM
151 PDM,
149} 152}
150 153
151impl_uarte!(UARTE0, UARTE0, UARTE0_UART0); 154impl_uarte!(UARTE0, UARTE0, UARTE0_UART0);
@@ -168,6 +171,12 @@ impl_pwm!(PWM0, PWM0, PWM0);
168impl_pwm!(PWM1, PWM1, PWM1); 171impl_pwm!(PWM1, PWM1, PWM1);
169impl_pwm!(PWM2, PWM2, PWM2); 172impl_pwm!(PWM2, PWM2, PWM2);
170 173
174impl_pdm!(PDM, PDM, PDM);
175
176impl_qdec!(QDEC, QDEC, QDEC);
177
178impl_rng!(RNG, RNG, RNG);
179
171impl_timer!(TIMER0, TIMER0, TIMER0); 180impl_timer!(TIMER0, TIMER0, TIMER0);
172impl_timer!(TIMER1, TIMER1, TIMER1); 181impl_timer!(TIMER1, TIMER1, TIMER1);
173impl_timer!(TIMER2, TIMER2, TIMER2); 182impl_timer!(TIMER2, TIMER2, TIMER2);
diff --git a/embassy-nrf/src/chips/nrf52833.rs b/embassy-nrf/src/chips/nrf52833.rs
index 95f71ade7..5e5db04de 100644
--- a/embassy-nrf/src/chips/nrf52833.rs
+++ b/embassy-nrf/src/chips/nrf52833.rs
@@ -197,6 +197,12 @@ impl_pwm!(PWM1, PWM1, PWM1);
197impl_pwm!(PWM2, PWM2, PWM2); 197impl_pwm!(PWM2, PWM2, PWM2);
198impl_pwm!(PWM3, PWM3, PWM3); 198impl_pwm!(PWM3, PWM3, PWM3);
199 199
200impl_pdm!(PDM, PDM, PDM);
201
202impl_qdec!(QDEC, QDEC, QDEC);
203
204impl_rng!(RNG, RNG, RNG);
205
200impl_timer!(TIMER0, TIMER0, TIMER0); 206impl_timer!(TIMER0, TIMER0, TIMER0);
201impl_timer!(TIMER1, TIMER1, TIMER1); 207impl_timer!(TIMER1, TIMER1, TIMER1);
202impl_timer!(TIMER2, TIMER2, TIMER2); 208impl_timer!(TIMER2, TIMER2, TIMER2);
diff --git a/embassy-nrf/src/chips/nrf52840.rs b/embassy-nrf/src/chips/nrf52840.rs
index 5e7479e88..f6d33f85c 100644
--- a/embassy-nrf/src/chips/nrf52840.rs
+++ b/embassy-nrf/src/chips/nrf52840.rs
@@ -208,6 +208,12 @@ impl_timer!(TIMER4, TIMER4, TIMER4, extended);
208 208
209impl_qspi!(QSPI, QSPI, QSPI); 209impl_qspi!(QSPI, QSPI, QSPI);
210 210
211impl_pdm!(PDM, PDM, PDM);
212
213impl_qdec!(QDEC, QDEC, QDEC);
214
215impl_rng!(RNG, RNG, RNG);
216
211impl_pin!(P0_00, 0, 0); 217impl_pin!(P0_00, 0, 0);
212impl_pin!(P0_01, 0, 1); 218impl_pin!(P0_01, 0, 1);
213impl_pin!(P0_02, 0, 2); 219impl_pin!(P0_02, 0, 2);
diff --git a/embassy-nrf/src/chips/nrf5340_app.rs b/embassy-nrf/src/chips/nrf5340_app.rs
index 9c7b738e6..34f96800f 100644
--- a/embassy-nrf/src/chips/nrf5340_app.rs
+++ b/embassy-nrf/src/chips/nrf5340_app.rs
@@ -34,10 +34,10 @@ pub mod pac {
34 nvmc_ns as nvmc, 34 nvmc_ns as nvmc,
35 oscillators_ns as oscillators, 35 oscillators_ns as oscillators,
36 p0_ns as p0, 36 p0_ns as p0,
37 pdm0_ns as pdm0, 37 pdm0_ns as pdm,
38 power_ns as power, 38 power_ns as power,
39 pwm0_ns as pwm0, 39 pwm0_ns as pwm0,
40 qdec0_ns as qdec0, 40 qdec0_ns as qdec,
41 qspi_ns as qspi, 41 qspi_ns as qspi,
42 regulators_ns as regulators, 42 regulators_ns as regulators,
43 reset_ns as reset, 43 reset_ns as reset,
@@ -253,6 +253,13 @@ embassy_hal_common::peripherals! {
253 // QSPI 253 // QSPI
254 QSPI, 254 QSPI,
255 255
256 // PDM
257 PDM0,
258
259 // QDEC
260 QDEC0,
261 QDEC1,
262
256 // GPIOTE 263 // GPIOTE
257 GPIOTE_CH0, 264 GPIOTE_CH0,
258 GPIOTE_CH1, 265 GPIOTE_CH1,
@@ -398,6 +405,11 @@ impl_timer!(TIMER2, TIMER2, TIMER2);
398 405
399impl_qspi!(QSPI, QSPI, QSPI); 406impl_qspi!(QSPI, QSPI, QSPI);
400 407
408impl_pdm!(PDM0, PDM0, PDM0);
409
410impl_qdec!(QDEC0, QDEC0, QDEC0);
411impl_qdec!(QDEC1, QDEC1, QDEC1);
412
401impl_pin!(P0_00, 0, 0); 413impl_pin!(P0_00, 0, 0);
402impl_pin!(P0_01, 0, 1); 414impl_pin!(P0_01, 0, 1);
403#[cfg(feature = "nfc-pins-as-gpio")] 415#[cfg(feature = "nfc-pins-as-gpio")]
diff --git a/embassy-nrf/src/chips/nrf5340_net.rs b/embassy-nrf/src/chips/nrf5340_net.rs
index d7ba6c16c..1e59528cb 100644
--- a/embassy-nrf/src/chips/nrf5340_net.rs
+++ b/embassy-nrf/src/chips/nrf5340_net.rs
@@ -127,6 +127,9 @@ embassy_hal_common::peripherals! {
127 // SAADC 127 // SAADC
128 SAADC, 128 SAADC,
129 129
130 // RNG
131 RNG,
132
130 // PWM 133 // PWM
131 PWM0, 134 PWM0,
132 PWM1, 135 PWM1,
@@ -252,6 +255,8 @@ impl_timer!(TIMER0, TIMER0, TIMER0);
252impl_timer!(TIMER1, TIMER1, TIMER1); 255impl_timer!(TIMER1, TIMER1, TIMER1);
253impl_timer!(TIMER2, TIMER2, TIMER2); 256impl_timer!(TIMER2, TIMER2, TIMER2);
254 257
258impl_rng!(RNG, RNG, RNG);
259
255impl_pin!(P0_00, 0, 0); 260impl_pin!(P0_00, 0, 0);
256impl_pin!(P0_01, 0, 1); 261impl_pin!(P0_01, 0, 1);
257impl_pin!(P0_02, 0, 2); 262impl_pin!(P0_02, 0, 2);
diff --git a/embassy-nrf/src/chips/nrf9160.rs b/embassy-nrf/src/chips/nrf9160.rs
index 385bd133d..d2b45114f 100644
--- a/embassy-nrf/src/chips/nrf9160.rs
+++ b/embassy-nrf/src/chips/nrf9160.rs
@@ -301,6 +301,8 @@ impl_pwm!(PWM1, PWM1, PWM1);
301impl_pwm!(PWM2, PWM2, PWM2); 301impl_pwm!(PWM2, PWM2, PWM2);
302impl_pwm!(PWM3, PWM3, PWM3); 302impl_pwm!(PWM3, PWM3, PWM3);
303 303
304impl_pdm!(PDM, PDM, PDM);
305
304impl_timer!(TIMER0, TIMER0, TIMER0); 306impl_timer!(TIMER0, TIMER0, TIMER0);
305impl_timer!(TIMER1, TIMER1, TIMER1); 307impl_timer!(TIMER1, TIMER1, TIMER1);
306impl_timer!(TIMER2, TIMER2, TIMER2); 308impl_timer!(TIMER2, TIMER2, TIMER2);
diff --git a/embassy-nrf/src/i2s.rs b/embassy-nrf/src/i2s.rs
index 770df7c89..8a1188ce4 100644
--- a/embassy-nrf/src/i2s.rs
+++ b/embassy-nrf/src/i2s.rs
@@ -14,7 +14,7 @@ use embassy_hal_common::drop::OnDrop;
14use embassy_hal_common::{into_ref, PeripheralRef}; 14use embassy_hal_common::{into_ref, PeripheralRef};
15 15
16use crate::gpio::{AnyPin, Pin as GpioPin}; 16use crate::gpio::{AnyPin, Pin as GpioPin};
17use crate::interrupt::Interrupt; 17use crate::interrupt::{self, Interrupt};
18use crate::pac::i2s::RegisterBlock; 18use crate::pac::i2s::RegisterBlock;
19use crate::util::{slice_in_ram_or, slice_ptr_parts}; 19use crate::util::{slice_in_ram_or, slice_ptr_parts};
20use crate::{Peripheral, EASY_DMA_SIZE}; 20use crate::{Peripheral, EASY_DMA_SIZE};
@@ -363,10 +363,39 @@ impl From<Channels> for u8 {
363 } 363 }
364} 364}
365 365
366/// Interrupt handler.
367pub struct InterruptHandler<T: Instance> {
368 _phantom: PhantomData<T>,
369}
370
371impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
372 unsafe fn on_interrupt() {
373 let device = Device::<T>::new();
374 let s = T::state();
375
376 if device.is_tx_ptr_updated() {
377 trace!("TX INT");
378 s.tx_waker.wake();
379 device.disable_tx_ptr_interrupt();
380 }
381
382 if device.is_rx_ptr_updated() {
383 trace!("RX INT");
384 s.rx_waker.wake();
385 device.disable_rx_ptr_interrupt();
386 }
387
388 if device.is_stopped() {
389 trace!("STOPPED INT");
390 s.stop_waker.wake();
391 device.disable_stopped_interrupt();
392 }
393 }
394}
395
366/// I2S driver. 396/// I2S driver.
367pub struct I2S<'d, T: Instance> { 397pub struct I2S<'d, T: Instance> {
368 i2s: PeripheralRef<'d, T>, 398 i2s: PeripheralRef<'d, T>,
369 irq: PeripheralRef<'d, T::Interrupt>,
370 mck: Option<PeripheralRef<'d, AnyPin>>, 399 mck: Option<PeripheralRef<'d, AnyPin>>,
371 sck: PeripheralRef<'d, AnyPin>, 400 sck: PeripheralRef<'d, AnyPin>,
372 lrck: PeripheralRef<'d, AnyPin>, 401 lrck: PeripheralRef<'d, AnyPin>,
@@ -378,19 +407,18 @@ pub struct I2S<'d, T: Instance> {
378 407
379impl<'d, T: Instance> I2S<'d, T> { 408impl<'d, T: Instance> I2S<'d, T> {
380 /// Create a new I2S in master mode 409 /// Create a new I2S in master mode
381 pub fn master( 410 pub fn new_master(
382 i2s: impl Peripheral<P = T> + 'd, 411 i2s: impl Peripheral<P = T> + 'd,
383 irq: impl Peripheral<P = T::Interrupt> + 'd, 412 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
384 mck: impl Peripheral<P = impl GpioPin> + 'd, 413 mck: impl Peripheral<P = impl GpioPin> + 'd,
385 sck: impl Peripheral<P = impl GpioPin> + 'd, 414 sck: impl Peripheral<P = impl GpioPin> + 'd,
386 lrck: impl Peripheral<P = impl GpioPin> + 'd, 415 lrck: impl Peripheral<P = impl GpioPin> + 'd,
387 master_clock: MasterClock, 416 master_clock: MasterClock,
388 config: Config, 417 config: Config,
389 ) -> Self { 418 ) -> Self {
390 into_ref!(i2s, irq, mck, sck, lrck); 419 into_ref!(i2s, mck, sck, lrck);
391 Self { 420 Self {
392 i2s, 421 i2s,
393 irq,
394 mck: Some(mck.map_into()), 422 mck: Some(mck.map_into()),
395 sck: sck.map_into(), 423 sck: sck.map_into(),
396 lrck: lrck.map_into(), 424 lrck: lrck.map_into(),
@@ -402,17 +430,16 @@ impl<'d, T: Instance> I2S<'d, T> {
402 } 430 }
403 431
404 /// Create a new I2S in slave mode 432 /// Create a new I2S in slave mode
405 pub fn slave( 433 pub fn new_slave(
406 i2s: impl Peripheral<P = T> + 'd, 434 i2s: impl Peripheral<P = T> + 'd,
407 irq: impl Peripheral<P = T::Interrupt> + 'd, 435 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
408 sck: impl Peripheral<P = impl GpioPin> + 'd, 436 sck: impl Peripheral<P = impl GpioPin> + 'd,
409 lrck: impl Peripheral<P = impl GpioPin> + 'd, 437 lrck: impl Peripheral<P = impl GpioPin> + 'd,
410 config: Config, 438 config: Config,
411 ) -> Self { 439 ) -> Self {
412 into_ref!(i2s, irq, sck, lrck); 440 into_ref!(i2s, sck, lrck);
413 Self { 441 Self {
414 i2s, 442 i2s,
415 irq,
416 mck: None, 443 mck: None,
417 sck: sck.map_into(), 444 sck: sck.map_into(),
418 lrck: lrck.map_into(), 445 lrck: lrck.map_into(),
@@ -537,9 +564,8 @@ impl<'d, T: Instance> I2S<'d, T> {
537 } 564 }
538 565
539 fn setup_interrupt(&self) { 566 fn setup_interrupt(&self) {
540 self.irq.set_handler(Self::on_interrupt); 567 unsafe { T::Interrupt::steal() }.unpend();
541 self.irq.unpend(); 568 unsafe { T::Interrupt::steal() }.enable();
542 self.irq.enable();
543 569
544 let device = Device::<T>::new(); 570 let device = Device::<T>::new();
545 device.disable_tx_ptr_interrupt(); 571 device.disable_tx_ptr_interrupt();
@@ -555,29 +581,6 @@ impl<'d, T: Instance> I2S<'d, T> {
555 device.enable_stopped_interrupt(); 581 device.enable_stopped_interrupt();
556 } 582 }
557 583
558 fn on_interrupt(_: *mut ()) {
559 let device = Device::<T>::new();
560 let s = T::state();
561
562 if device.is_tx_ptr_updated() {
563 trace!("TX INT");
564 s.tx_waker.wake();
565 device.disable_tx_ptr_interrupt();
566 }
567
568 if device.is_rx_ptr_updated() {
569 trace!("RX INT");
570 s.rx_waker.wake();
571 device.disable_rx_ptr_interrupt();
572 }
573
574 if device.is_stopped() {
575 trace!("STOPPED INT");
576 s.stop_waker.wake();
577 device.disable_stopped_interrupt();
578 }
579 }
580
581 async fn stop() { 584 async fn stop() {
582 compiler_fence(Ordering::SeqCst); 585 compiler_fence(Ordering::SeqCst);
583 586
@@ -1168,7 +1171,7 @@ pub(crate) mod sealed {
1168 } 1171 }
1169} 1172}
1170 1173
1171/// I2S peripehral instance. 1174/// I2S peripheral instance.
1172pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send { 1175pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {
1173 /// Interrupt for this peripheral. 1176 /// Interrupt for this peripheral.
1174 type Interrupt: Interrupt; 1177 type Interrupt: Interrupt;
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index 3c5db5c7c..cb629902a 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -47,19 +47,21 @@ pub mod nvmc;
47#[cfg(any( 47#[cfg(any(
48 feature = "nrf52810", 48 feature = "nrf52810",
49 feature = "nrf52811", 49 feature = "nrf52811",
50 feature = "nrf52832",
50 feature = "nrf52833", 51 feature = "nrf52833",
51 feature = "nrf52840", 52 feature = "nrf52840",
53 feature = "_nrf5340-app",
52 feature = "_nrf9160" 54 feature = "_nrf9160"
53))] 55))]
54pub mod pdm; 56pub mod pdm;
55pub mod ppi; 57pub mod ppi;
56#[cfg(not(any(feature = "nrf52805", feature = "nrf52820", feature = "_nrf5340-net")))] 58#[cfg(not(any(feature = "nrf52805", feature = "nrf52820", feature = "_nrf5340-net")))]
57pub mod pwm; 59pub mod pwm;
58#[cfg(not(any(feature = "nrf51", feature = "_nrf9160", feature = "_nrf5340")))] 60#[cfg(not(any(feature = "nrf51", feature = "_nrf9160", feature = "_nrf5340-net")))]
59pub mod qdec; 61pub mod qdec;
60#[cfg(any(feature = "nrf52840", feature = "_nrf5340-app"))] 62#[cfg(any(feature = "nrf52840", feature = "_nrf5340-app"))]
61pub mod qspi; 63pub mod qspi;
62#[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] 64#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf9160")))]
63pub mod rng; 65pub mod rng;
64#[cfg(not(any(feature = "nrf52820", feature = "_nrf5340-net")))] 66#[cfg(not(any(feature = "nrf52820", feature = "_nrf5340-net")))]
65pub mod saadc; 67pub mod saadc;
@@ -95,14 +97,39 @@ pub mod wdt;
95#[cfg_attr(feature = "_nrf9160", path = "chips/nrf9160.rs")] 97#[cfg_attr(feature = "_nrf9160", path = "chips/nrf9160.rs")]
96mod chip; 98mod chip;
97 99
98pub use chip::EASY_DMA_SIZE;
99
100pub mod interrupt { 100pub mod interrupt {
101 //! nRF interrupts for cortex-m devices. 101 //! Interrupt definitions and macros to bind them.
102 pub use cortex_m::interrupt::{CriticalSection, Mutex}; 102 pub use cortex_m::interrupt::{CriticalSection, Mutex};
103 pub use embassy_cortex_m::interrupt::*; 103 pub use embassy_cortex_m::interrupt::{Binding, Handler, Interrupt, InterruptExt, Priority};
104 104
105 pub use crate::chip::irqs::*; 105 pub use crate::chip::irqs::*;
106
107 /// Macro to bind interrupts to handlers.
108 ///
109 /// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`)
110 /// and implements the right [`Binding`]s for it. You can pass this struct to drivers to
111 /// prove at compile-time that the right interrupts have been bound.
112 // developer note: this macro can't be in `embassy-cortex-m` due to the use of `$crate`.
113 #[macro_export]
114 macro_rules! bind_interrupts {
115 ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => {
116 $vis struct $name;
117
118 $(
119 #[allow(non_snake_case)]
120 #[no_mangle]
121 unsafe extern "C" fn $irq() {
122 $(
123 <$handler as $crate::interrupt::Handler<$crate::interrupt::$irq>>::on_interrupt();
124 )*
125 }
126
127 $(
128 unsafe impl $crate::interrupt::Binding<$crate::interrupt::$irq, $handler> for $name {}
129 )*
130 )*
131 };
132 }
106} 133}
107 134
108// Reexports 135// Reexports
@@ -111,7 +138,7 @@ pub mod interrupt {
111pub use chip::pac; 138pub use chip::pac;
112#[cfg(not(feature = "unstable-pac"))] 139#[cfg(not(feature = "unstable-pac"))]
113pub(crate) use chip::pac; 140pub(crate) use chip::pac;
114pub use chip::{peripherals, Peripherals}; 141pub use chip::{peripherals, Peripherals, EASY_DMA_SIZE};
115pub use embassy_cortex_m::executor; 142pub use embassy_cortex_m::executor;
116pub use embassy_cortex_m::interrupt::_export::interrupt; 143pub use embassy_cortex_m::interrupt::_export::interrupt;
117pub use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; 144pub use embassy_hal_common::{into_ref, Peripheral, PeripheralRef};
diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs
index 54feca4c1..8815bb316 100644
--- a/embassy-nrf/src/pdm.rs
+++ b/embassy-nrf/src/pdm.rs
@@ -1,25 +1,37 @@
1//! Pulse Density Modulation (PDM) mirophone driver. 1//! Pulse Density Modulation (PDM) mirophone driver.
2 2
3#![macro_use]
4
3use core::marker::PhantomData; 5use core::marker::PhantomData;
4use core::sync::atomic::{compiler_fence, Ordering}; 6use core::sync::atomic::{compiler_fence, Ordering};
5use core::task::Poll; 7use core::task::Poll;
6 8
9use embassy_cortex_m::interrupt::Interrupt;
7use embassy_hal_common::drop::OnDrop; 10use embassy_hal_common::drop::OnDrop;
8use embassy_hal_common::{into_ref, PeripheralRef}; 11use embassy_hal_common::{into_ref, PeripheralRef};
9use embassy_sync::waitqueue::AtomicWaker;
10use futures::future::poll_fn; 12use futures::future::poll_fn;
11 13
12use crate::chip::EASY_DMA_SIZE; 14use crate::chip::EASY_DMA_SIZE;
13use crate::gpio::sealed::Pin; 15use crate::gpio::sealed::Pin;
14use crate::gpio::{AnyPin, Pin as GpioPin}; 16use crate::gpio::{AnyPin, Pin as GpioPin};
15use crate::interrupt::{self, InterruptExt}; 17use crate::interrupt::{self, InterruptExt};
16use crate::peripherals::PDM; 18use crate::Peripheral;
17use crate::{pac, Peripheral}; 19
20/// Interrupt handler.
21pub struct InterruptHandler<T: Instance> {
22 _phantom: PhantomData<T>,
23}
24
25impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
26 unsafe fn on_interrupt() {
27 T::regs().intenclr.write(|w| w.end().clear());
28 T::state().waker.wake();
29 }
30}
18 31
19/// PDM microphone interface 32/// PDM microphone interface
20pub struct Pdm<'d> { 33pub struct Pdm<'d, T: Instance> {
21 irq: PeripheralRef<'d, interrupt::PDM>, 34 _peri: PeripheralRef<'d, T>,
22 phantom: PhantomData<&'d PDM>,
23} 35}
24 36
25/// PDM error. 37/// PDM error.
@@ -35,32 +47,30 @@ pub enum Error {
35 NotRunning, 47 NotRunning,
36} 48}
37 49
38static WAKER: AtomicWaker = AtomicWaker::new();
39static DUMMY_BUFFER: [i16; 1] = [0; 1]; 50static DUMMY_BUFFER: [i16; 1] = [0; 1];
40 51
41impl<'d> Pdm<'d> { 52impl<'d, T: Instance> Pdm<'d, T> {
42 /// Create PDM driver 53 /// Create PDM driver
43 pub fn new( 54 pub fn new(
44 pdm: impl Peripheral<P = PDM> + 'd, 55 pdm: impl Peripheral<P = T> + 'd,
45 irq: impl Peripheral<P = interrupt::PDM> + 'd, 56 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
46 clk: impl Peripheral<P = impl GpioPin> + 'd, 57 clk: impl Peripheral<P = impl GpioPin> + 'd,
47 din: impl Peripheral<P = impl GpioPin> + 'd, 58 din: impl Peripheral<P = impl GpioPin> + 'd,
48 config: Config, 59 config: Config,
49 ) -> Self { 60 ) -> Self {
50 into_ref!(clk, din); 61 into_ref!(pdm, clk, din);
51 Self::new_inner(pdm, irq, clk.map_into(), din.map_into(), config) 62 Self::new_inner(pdm, clk.map_into(), din.map_into(), config)
52 } 63 }
53 64
54 fn new_inner( 65 fn new_inner(
55 _pdm: impl Peripheral<P = PDM> + 'd, 66 pdm: PeripheralRef<'d, T>,
56 irq: impl Peripheral<P = interrupt::PDM> + 'd,
57 clk: PeripheralRef<'d, AnyPin>, 67 clk: PeripheralRef<'d, AnyPin>,
58 din: PeripheralRef<'d, AnyPin>, 68 din: PeripheralRef<'d, AnyPin>,
59 config: Config, 69 config: Config,
60 ) -> Self { 70 ) -> Self {
61 into_ref!(irq); 71 into_ref!(pdm);
62 72
63 let r = Self::regs(); 73 let r = T::regs();
64 74
65 // setup gpio pins 75 // setup gpio pins
66 din.conf().write(|w| w.input().set_bit()); 76 din.conf().write(|w| w.input().set_bit());
@@ -84,26 +94,18 @@ impl<'d> Pdm<'d> {
84 r.gainr.write(|w| w.gainr().default_gain()); 94 r.gainr.write(|w| w.gainr().default_gain());
85 95
86 // IRQ 96 // IRQ
87 irq.disable(); 97 unsafe { T::Interrupt::steal() }.unpend();
88 irq.set_handler(|_| { 98 unsafe { T::Interrupt::steal() }.enable();
89 let r = Self::regs();
90 r.intenclr.write(|w| w.end().clear());
91 WAKER.wake();
92 });
93 irq.enable();
94 99
95 r.enable.write(|w| w.enable().set_bit()); 100 r.enable.write(|w| w.enable().set_bit());
96 101
97 Self { 102 Self { _peri: pdm }
98 phantom: PhantomData,
99 irq,
100 }
101 } 103 }
102 104
103 /// Start sampling microphon data into a dummy buffer 105 /// Start sampling microphon data into a dummy buffer
104 /// Usefull to start the microphon and keep it active between recording samples 106 /// Usefull to start the microphon and keep it active between recording samples
105 pub async fn start(&mut self) { 107 pub async fn start(&mut self) {
106 let r = Self::regs(); 108 let r = T::regs();
107 109
108 // start dummy sampling because microphon needs some setup time 110 // start dummy sampling because microphon needs some setup time
109 r.sample 111 r.sample
@@ -113,13 +115,13 @@ impl<'d> Pdm<'d> {
113 .maxcnt 115 .maxcnt
114 .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) }); 116 .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) });
115 117
116 r.tasks_start.write(|w| w.tasks_start().set_bit()); 118 r.tasks_start.write(|w| unsafe { w.bits(1) });
117 } 119 }
118 120
119 /// Stop sampling microphon data inta a dummy buffer 121 /// Stop sampling microphon data inta a dummy buffer
120 pub async fn stop(&mut self) { 122 pub async fn stop(&mut self) {
121 let r = Self::regs(); 123 let r = T::regs();
122 r.tasks_stop.write(|w| w.tasks_stop().set_bit()); 124 r.tasks_stop.write(|w| unsafe { w.bits(1) });
123 r.events_started.reset(); 125 r.events_started.reset();
124 } 126 }
125 127
@@ -132,9 +134,9 @@ impl<'d> Pdm<'d> {
132 return Err(Error::BufferTooLong); 134 return Err(Error::BufferTooLong);
133 } 135 }
134 136
135 let r = Self::regs(); 137 let r = T::regs();
136 138
137 if r.events_started.read().events_started().bit_is_clear() { 139 if r.events_started.read().bits() == 0 {
138 return Err(Error::NotRunning); 140 return Err(Error::NotRunning);
139 } 141 }
140 142
@@ -179,7 +181,7 @@ impl<'d> Pdm<'d> {
179 } 181 }
180 182
181 async fn wait_for_sample() { 183 async fn wait_for_sample() {
182 let r = Self::regs(); 184 let r = T::regs();
183 185
184 r.events_end.reset(); 186 r.events_end.reset();
185 r.intenset.write(|w| w.end().set()); 187 r.intenset.write(|w| w.end().set());
@@ -187,8 +189,8 @@ impl<'d> Pdm<'d> {
187 compiler_fence(Ordering::SeqCst); 189 compiler_fence(Ordering::SeqCst);
188 190
189 poll_fn(|cx| { 191 poll_fn(|cx| {
190 WAKER.register(cx.waker()); 192 T::state().waker.register(cx.waker());
191 if r.events_end.read().events_end().bit_is_set() { 193 if r.events_end.read().bits() != 0 {
192 return Poll::Ready(()); 194 return Poll::Ready(());
193 } 195 }
194 Poll::Pending 196 Poll::Pending
@@ -197,10 +199,6 @@ impl<'d> Pdm<'d> {
197 199
198 compiler_fence(Ordering::SeqCst); 200 compiler_fence(Ordering::SeqCst);
199 } 201 }
200
201 fn regs() -> &'static pac::pdm::RegisterBlock {
202 unsafe { &*pac::PDM::ptr() }
203 }
204} 202}
205 203
206/// PDM microphone driver Config 204/// PDM microphone driver Config
@@ -238,13 +236,11 @@ pub enum Edge {
238 LeftFalling, 236 LeftFalling,
239} 237}
240 238
241impl<'d> Drop for Pdm<'d> { 239impl<'d, T: Instance> Drop for Pdm<'d, T> {
242 fn drop(&mut self) { 240 fn drop(&mut self) {
243 let r = Self::regs(); 241 let r = T::regs();
244 242
245 r.tasks_stop.write(|w| w.tasks_stop().set_bit()); 243 r.tasks_stop.write(|w| unsafe { w.bits(1) });
246
247 self.irq.disable();
248 244
249 r.enable.write(|w| w.enable().disabled()); 245 r.enable.write(|w| w.enable().disabled());
250 246
@@ -252,3 +248,48 @@ impl<'d> Drop for Pdm<'d> {
252 r.psel.clk.reset(); 248 r.psel.clk.reset();
253 } 249 }
254} 250}
251
252pub(crate) mod sealed {
253 use embassy_sync::waitqueue::AtomicWaker;
254
255 /// Peripheral static state
256 pub struct State {
257 pub waker: AtomicWaker,
258 }
259
260 impl State {
261 pub const fn new() -> Self {
262 Self {
263 waker: AtomicWaker::new(),
264 }
265 }
266 }
267
268 pub trait Instance {
269 fn regs() -> &'static crate::pac::pdm::RegisterBlock;
270 fn state() -> &'static State;
271 }
272}
273
274/// PDM peripheral instance.
275pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {
276 /// Interrupt for this peripheral.
277 type Interrupt: Interrupt;
278}
279
280macro_rules! impl_pdm {
281 ($type:ident, $pac_type:ident, $irq:ident) => {
282 impl crate::pdm::sealed::Instance for peripherals::$type {
283 fn regs() -> &'static crate::pac::pdm::RegisterBlock {
284 unsafe { &*pac::$pac_type::ptr() }
285 }
286 fn state() -> &'static crate::pdm::sealed::State {
287 static STATE: crate::pdm::sealed::State = crate::pdm::sealed::State::new();
288 &STATE
289 }
290 }
291 impl crate::pdm::Instance for peripherals::$type {
292 type Interrupt = crate::interrupt::$irq;
293 }
294 };
295}
diff --git a/embassy-nrf/src/qdec.rs b/embassy-nrf/src/qdec.rs
index c01babca3..4d2a09198 100644
--- a/embassy-nrf/src/qdec.rs
+++ b/embassy-nrf/src/qdec.rs
@@ -1,20 +1,22 @@
1//! Quadrature decoder (QDEC) driver. 1//! Quadrature decoder (QDEC) driver.
2 2
3#![macro_use]
4
3use core::future::poll_fn; 5use core::future::poll_fn;
6use core::marker::PhantomData;
4use core::task::Poll; 7use core::task::Poll;
5 8
9use embassy_cortex_m::interrupt::Interrupt;
6use embassy_hal_common::{into_ref, PeripheralRef}; 10use embassy_hal_common::{into_ref, PeripheralRef};
7use embassy_sync::waitqueue::AtomicWaker;
8 11
9use crate::gpio::sealed::Pin as _; 12use crate::gpio::sealed::Pin as _;
10use crate::gpio::{AnyPin, Pin as GpioPin}; 13use crate::gpio::{AnyPin, Pin as GpioPin};
11use crate::interrupt::InterruptExt; 14use crate::interrupt::InterruptExt;
12use crate::peripherals::QDEC; 15use crate::{interrupt, Peripheral};
13use crate::{interrupt, pac, Peripheral};
14 16
15/// Quadrature decoder driver. 17/// Quadrature decoder driver.
16pub struct Qdec<'d> { 18pub struct Qdec<'d, T: Instance> {
17 _p: PeripheralRef<'d, QDEC>, 19 _p: PeripheralRef<'d, T>,
18} 20}
19 21
20/// QDEC config 22/// QDEC config
@@ -44,44 +46,52 @@ impl Default for Config {
44 } 46 }
45} 47}
46 48
47static WAKER: AtomicWaker = AtomicWaker::new(); 49/// Interrupt handler.
50pub struct InterruptHandler<T: Instance> {
51 _phantom: PhantomData<T>,
52}
48 53
49impl<'d> Qdec<'d> { 54impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
55 unsafe fn on_interrupt() {
56 T::regs().intenclr.write(|w| w.reportrdy().clear());
57 T::state().waker.wake();
58 }
59}
60
61impl<'d, T: Instance> Qdec<'d, T> {
50 /// Create a new QDEC. 62 /// Create a new QDEC.
51 pub fn new( 63 pub fn new(
52 qdec: impl Peripheral<P = QDEC> + 'd, 64 qdec: impl Peripheral<P = T> + 'd,
53 irq: impl Peripheral<P = interrupt::QDEC> + 'd, 65 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
54 a: impl Peripheral<P = impl GpioPin> + 'd, 66 a: impl Peripheral<P = impl GpioPin> + 'd,
55 b: impl Peripheral<P = impl GpioPin> + 'd, 67 b: impl Peripheral<P = impl GpioPin> + 'd,
56 config: Config, 68 config: Config,
57 ) -> Self { 69 ) -> Self {
58 into_ref!(a, b); 70 into_ref!(qdec, a, b);
59 Self::new_inner(qdec, irq, a.map_into(), b.map_into(), None, config) 71 Self::new_inner(qdec, a.map_into(), b.map_into(), None, config)
60 } 72 }
61 73
62 /// Create a new QDEC, with a pin for LED output. 74 /// Create a new QDEC, with a pin for LED output.
63 pub fn new_with_led( 75 pub fn new_with_led(
64 qdec: impl Peripheral<P = QDEC> + 'd, 76 qdec: impl Peripheral<P = T> + 'd,
65 irq: impl Peripheral<P = interrupt::QDEC> + 'd, 77 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
66 a: impl Peripheral<P = impl GpioPin> + 'd, 78 a: impl Peripheral<P = impl GpioPin> + 'd,
67 b: impl Peripheral<P = impl GpioPin> + 'd, 79 b: impl Peripheral<P = impl GpioPin> + 'd,
68 led: impl Peripheral<P = impl GpioPin> + 'd, 80 led: impl Peripheral<P = impl GpioPin> + 'd,
69 config: Config, 81 config: Config,
70 ) -> Self { 82 ) -> Self {
71 into_ref!(a, b, led); 83 into_ref!(qdec, a, b, led);
72 Self::new_inner(qdec, irq, a.map_into(), b.map_into(), Some(led.map_into()), config) 84 Self::new_inner(qdec, a.map_into(), b.map_into(), Some(led.map_into()), config)
73 } 85 }
74 86
75 fn new_inner( 87 fn new_inner(
76 p: impl Peripheral<P = QDEC> + 'd, 88 p: PeripheralRef<'d, T>,
77 irq: impl Peripheral<P = interrupt::QDEC> + 'd,
78 a: PeripheralRef<'d, AnyPin>, 89 a: PeripheralRef<'d, AnyPin>,
79 b: PeripheralRef<'d, AnyPin>, 90 b: PeripheralRef<'d, AnyPin>,
80 led: Option<PeripheralRef<'d, AnyPin>>, 91 led: Option<PeripheralRef<'d, AnyPin>>,
81 config: Config, 92 config: Config,
82 ) -> Self { 93 ) -> Self {
83 into_ref!(p, irq); 94 let r = T::regs();
84 let r = Self::regs();
85 95
86 // Select pins. 96 // Select pins.
87 a.conf().write(|w| w.input().connect().pull().pullup()); 97 a.conf().write(|w| w.input().connect().pull().pullup());
@@ -124,20 +134,15 @@ impl<'d> Qdec<'d> {
124 SamplePeriod::_131ms => w.sampleper()._131ms(), 134 SamplePeriod::_131ms => w.sampleper()._131ms(),
125 }); 135 });
126 136
137 unsafe { T::Interrupt::steal() }.unpend();
138 unsafe { T::Interrupt::steal() }.enable();
139
127 // Enable peripheral 140 // Enable peripheral
128 r.enable.write(|w| w.enable().set_bit()); 141 r.enable.write(|w| w.enable().set_bit());
129 142
130 // Start sampling 143 // Start sampling
131 unsafe { r.tasks_start.write(|w| w.bits(1)) }; 144 unsafe { r.tasks_start.write(|w| w.bits(1)) };
132 145
133 irq.disable();
134 irq.set_handler(|_| {
135 let r = Self::regs();
136 r.intenclr.write(|w| w.reportrdy().clear());
137 WAKER.wake();
138 });
139 irq.enable();
140
141 Self { _p: p } 146 Self { _p: p }
142 } 147 }
143 148
@@ -155,12 +160,12 @@ impl<'d> Qdec<'d> {
155 /// let delta = q.read().await; 160 /// let delta = q.read().await;
156 /// ``` 161 /// ```
157 pub async fn read(&mut self) -> i16 { 162 pub async fn read(&mut self) -> i16 {
158 let t = Self::regs(); 163 let t = T::regs();
159 t.intenset.write(|w| w.reportrdy().set()); 164 t.intenset.write(|w| w.reportrdy().set());
160 unsafe { t.tasks_readclracc.write(|w| w.bits(1)) }; 165 unsafe { t.tasks_readclracc.write(|w| w.bits(1)) };
161 166
162 let value = poll_fn(|cx| { 167 let value = poll_fn(|cx| {
163 WAKER.register(cx.waker()); 168 T::state().waker.register(cx.waker());
164 if t.events_reportrdy.read().bits() == 0 { 169 if t.events_reportrdy.read().bits() == 0 {
165 return Poll::Pending; 170 return Poll::Pending;
166 } else { 171 } else {
@@ -172,10 +177,6 @@ impl<'d> Qdec<'d> {
172 .await; 177 .await;
173 value 178 value
174 } 179 }
175
176 fn regs() -> &'static pac::qdec::RegisterBlock {
177 unsafe { &*pac::QDEC::ptr() }
178 }
179} 180}
180 181
181/// Sample period 182/// Sample period
@@ -236,3 +237,48 @@ pub enum LedPolarity {
236 /// Active low (a low output turns on the LED). 237 /// Active low (a low output turns on the LED).
237 ActiveLow, 238 ActiveLow,
238} 239}
240
241pub(crate) mod sealed {
242 use embassy_sync::waitqueue::AtomicWaker;
243
244 /// Peripheral static state
245 pub struct State {
246 pub waker: AtomicWaker,
247 }
248
249 impl State {
250 pub const fn new() -> Self {
251 Self {
252 waker: AtomicWaker::new(),
253 }
254 }
255 }
256
257 pub trait Instance {
258 fn regs() -> &'static crate::pac::qdec::RegisterBlock;
259 fn state() -> &'static State;
260 }
261}
262
263/// qdec peripheral instance.
264pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {
265 /// Interrupt for this peripheral.
266 type Interrupt: Interrupt;
267}
268
269macro_rules! impl_qdec {
270 ($type:ident, $pac_type:ident, $irq:ident) => {
271 impl crate::qdec::sealed::Instance for peripherals::$type {
272 fn regs() -> &'static crate::pac::qdec::RegisterBlock {
273 unsafe { &*pac::$pac_type::ptr() }
274 }
275 fn state() -> &'static crate::qdec::sealed::State {
276 static STATE: crate::qdec::sealed::State = crate::qdec::sealed::State::new();
277 &STATE
278 }
279 }
280 impl crate::qdec::Instance for peripherals::$type {
281 type Interrupt = crate::interrupt::$irq;
282 }
283 };
284}
diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs
index d514e0274..7f004b9fc 100644
--- a/embassy-nrf/src/qspi.rs
+++ b/embassy-nrf/src/qspi.rs
@@ -3,6 +3,7 @@
3#![macro_use] 3#![macro_use]
4 4
5use core::future::poll_fn; 5use core::future::poll_fn;
6use core::marker::PhantomData;
6use core::ptr; 7use core::ptr;
7use core::task::Poll; 8use core::task::Poll;
8 9
@@ -11,12 +12,12 @@ use embassy_hal_common::{into_ref, PeripheralRef};
11use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash}; 12use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash};
12 13
13use crate::gpio::{self, Pin as GpioPin}; 14use crate::gpio::{self, Pin as GpioPin};
14use crate::interrupt::{Interrupt, InterruptExt}; 15use crate::interrupt::{self, Interrupt, InterruptExt};
15pub use crate::pac::qspi::ifconfig0::{ 16pub use crate::pac::qspi::ifconfig0::{
16 ADDRMODE_A as AddressMode, PPSIZE_A as WritePageSize, READOC_A as ReadOpcode, WRITEOC_A as WriteOpcode, 17 ADDRMODE_A as AddressMode, PPSIZE_A as WritePageSize, READOC_A as ReadOpcode, WRITEOC_A as WriteOpcode,
17}; 18};
18pub use crate::pac::qspi::ifconfig1::SPIMODE_A as SpiMode; 19pub use crate::pac::qspi::ifconfig1::SPIMODE_A as SpiMode;
19use crate::{pac, Peripheral}; 20use crate::Peripheral;
20 21
21/// Deep power-down config. 22/// Deep power-down config.
22pub struct DeepPowerDownConfig { 23pub struct DeepPowerDownConfig {
@@ -114,9 +115,26 @@ pub enum Error {
114 // TODO add "not in data memory" error and check for it 115 // TODO add "not in data memory" error and check for it
115} 116}
116 117
118/// Interrupt handler.
119pub struct InterruptHandler<T: Instance> {
120 _phantom: PhantomData<T>,
121}
122
123impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
124 unsafe fn on_interrupt() {
125 let r = T::regs();
126 let s = T::state();
127
128 if r.events_ready.read().bits() != 0 {
129 s.waker.wake();
130 r.intenclr.write(|w| w.ready().clear());
131 }
132 }
133}
134
117/// QSPI flash driver. 135/// QSPI flash driver.
118pub struct Qspi<'d, T: Instance> { 136pub struct Qspi<'d, T: Instance> {
119 irq: PeripheralRef<'d, T::Interrupt>, 137 _peri: PeripheralRef<'d, T>,
120 dpm_enabled: bool, 138 dpm_enabled: bool,
121 capacity: u32, 139 capacity: u32,
122} 140}
@@ -124,8 +142,8 @@ pub struct Qspi<'d, T: Instance> {
124impl<'d, T: Instance> Qspi<'d, T> { 142impl<'d, T: Instance> Qspi<'d, T> {
125 /// Create a new QSPI driver. 143 /// Create a new QSPI driver.
126 pub fn new( 144 pub fn new(
127 _qspi: impl Peripheral<P = T> + 'd, 145 qspi: impl Peripheral<P = T> + 'd,
128 irq: impl Peripheral<P = T::Interrupt> + 'd, 146 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
129 sck: impl Peripheral<P = impl GpioPin> + 'd, 147 sck: impl Peripheral<P = impl GpioPin> + 'd,
130 csn: impl Peripheral<P = impl GpioPin> + 'd, 148 csn: impl Peripheral<P = impl GpioPin> + 'd,
131 io0: impl Peripheral<P = impl GpioPin> + 'd, 149 io0: impl Peripheral<P = impl GpioPin> + 'd,
@@ -134,7 +152,7 @@ impl<'d, T: Instance> Qspi<'d, T> {
134 io3: impl Peripheral<P = impl GpioPin> + 'd, 152 io3: impl Peripheral<P = impl GpioPin> + 'd,
135 config: Config, 153 config: Config,
136 ) -> Self { 154 ) -> Self {
137 into_ref!(irq, sck, csn, io0, io1, io2, io3); 155 into_ref!(qspi, sck, csn, io0, io1, io2, io3);
138 156
139 let r = T::regs(); 157 let r = T::regs();
140 158
@@ -189,16 +207,15 @@ impl<'d, T: Instance> Qspi<'d, T> {
189 w 207 w
190 }); 208 });
191 209
192 irq.set_handler(Self::on_interrupt); 210 unsafe { T::Interrupt::steal() }.unpend();
193 irq.unpend(); 211 unsafe { T::Interrupt::steal() }.enable();
194 irq.enable();
195 212
196 // Enable it 213 // Enable it
197 r.enable.write(|w| w.enable().enabled()); 214 r.enable.write(|w| w.enable().enabled());
198 215
199 let res = Self { 216 let res = Self {
217 _peri: qspi,
200 dpm_enabled: config.deep_power_down.is_some(), 218 dpm_enabled: config.deep_power_down.is_some(),
201 irq,
202 capacity: config.capacity, 219 capacity: config.capacity,
203 }; 220 };
204 221
@@ -212,16 +229,6 @@ impl<'d, T: Instance> Qspi<'d, T> {
212 res 229 res
213 } 230 }
214 231
215 fn on_interrupt(_: *mut ()) {
216 let r = T::regs();
217 let s = T::state();
218
219 if r.events_ready.read().bits() != 0 {
220 s.ready_waker.wake();
221 r.intenclr.write(|w| w.ready().clear());
222 }
223 }
224
225 /// Do a custom QSPI instruction. 232 /// Do a custom QSPI instruction.
226 pub async fn custom_instruction(&mut self, opcode: u8, req: &[u8], resp: &mut [u8]) -> Result<(), Error> { 233 pub async fn custom_instruction(&mut self, opcode: u8, req: &[u8], resp: &mut [u8]) -> Result<(), Error> {
227 let ondrop = OnDrop::new(Self::blocking_wait_ready); 234 let ondrop = OnDrop::new(Self::blocking_wait_ready);
@@ -310,7 +317,7 @@ impl<'d, T: Instance> Qspi<'d, T> {
310 poll_fn(move |cx| { 317 poll_fn(move |cx| {
311 let r = T::regs(); 318 let r = T::regs();
312 let s = T::state(); 319 let s = T::state();
313 s.ready_waker.register(cx.waker()); 320 s.waker.register(cx.waker());
314 if r.events_ready.read().bits() != 0 { 321 if r.events_ready.read().bits() != 0 {
315 return Poll::Ready(()); 322 return Poll::Ready(());
316 } 323 }
@@ -525,8 +532,6 @@ impl<'d, T: Instance> Drop for Qspi<'d, T> {
525 532
526 r.enable.write(|w| w.enable().disabled()); 533 r.enable.write(|w| w.enable().disabled());
527 534
528 self.irq.disable();
529
530 // Note: we do NOT deconfigure CSN here. If DPM is in use and we disconnect CSN, 535 // Note: we do NOT deconfigure CSN here. If DPM is in use and we disconnect CSN,
531 // leaving it floating, the flash chip might read it as zero which would cause it to 536 // leaving it floating, the flash chip might read it as zero which would cause it to
532 // spuriously exit DPM. 537 // spuriously exit DPM.
@@ -624,27 +629,27 @@ mod _eh1 {
624pub(crate) mod sealed { 629pub(crate) mod sealed {
625 use embassy_sync::waitqueue::AtomicWaker; 630 use embassy_sync::waitqueue::AtomicWaker;
626 631
627 use super::*; 632 /// Peripheral static state
628
629 pub struct State { 633 pub struct State {
630 pub ready_waker: AtomicWaker, 634 pub waker: AtomicWaker,
631 } 635 }
636
632 impl State { 637 impl State {
633 pub const fn new() -> Self { 638 pub const fn new() -> Self {
634 Self { 639 Self {
635 ready_waker: AtomicWaker::new(), 640 waker: AtomicWaker::new(),
636 } 641 }
637 } 642 }
638 } 643 }
639 644
640 pub trait Instance { 645 pub trait Instance {
641 fn regs() -> &'static pac::qspi::RegisterBlock; 646 fn regs() -> &'static crate::pac::qspi::RegisterBlock;
642 fn state() -> &'static State; 647 fn state() -> &'static State;
643 } 648 }
644} 649}
645 650
646/// QSPI peripheral instance. 651/// QSPI peripheral instance.
647pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static { 652pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {
648 /// Interrupt for this peripheral. 653 /// Interrupt for this peripheral.
649 type Interrupt: Interrupt; 654 type Interrupt: Interrupt;
650} 655}
@@ -652,7 +657,7 @@ pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static {
652macro_rules! impl_qspi { 657macro_rules! impl_qspi {
653 ($type:ident, $pac_type:ident, $irq:ident) => { 658 ($type:ident, $pac_type:ident, $irq:ident) => {
654 impl crate::qspi::sealed::Instance for peripherals::$type { 659 impl crate::qspi::sealed::Instance for peripherals::$type {
655 fn regs() -> &'static pac::qspi::RegisterBlock { 660 fn regs() -> &'static crate::pac::qspi::RegisterBlock {
656 unsafe { &*pac::$pac_type::ptr() } 661 unsafe { &*pac::$pac_type::ptr() }
657 } 662 }
658 fn state() -> &'static crate::qspi::sealed::State { 663 fn state() -> &'static crate::qspi::sealed::State {
diff --git a/embassy-nrf/src/rng.rs b/embassy-nrf/src/rng.rs
index b0b3a8eb8..a5602248d 100644
--- a/embassy-nrf/src/rng.rs
+++ b/embassy-nrf/src/rng.rs
@@ -1,83 +1,48 @@
1//! Random Number Generator (RNG) driver. 1//! Random Number Generator (RNG) driver.
2 2
3#![macro_use]
4
3use core::future::poll_fn; 5use core::future::poll_fn;
6use core::marker::PhantomData;
4use core::ptr; 7use core::ptr;
5use core::sync::atomic::{AtomicPtr, Ordering}; 8use core::sync::atomic::{AtomicPtr, Ordering};
6use core::task::Poll; 9use core::task::Poll;
7 10
11use embassy_cortex_m::interrupt::Interrupt;
8use embassy_hal_common::drop::OnDrop; 12use embassy_hal_common::drop::OnDrop;
9use embassy_hal_common::{into_ref, PeripheralRef}; 13use embassy_hal_common::{into_ref, PeripheralRef};
10use embassy_sync::waitqueue::AtomicWaker; 14use embassy_sync::waitqueue::AtomicWaker;
11 15
12use crate::interrupt::InterruptExt; 16use crate::interrupt::InterruptExt;
13use crate::peripherals::RNG; 17use crate::{interrupt, Peripheral};
14use crate::{interrupt, pac, Peripheral};
15
16impl RNG {
17 fn regs() -> &'static pac::rng::RegisterBlock {
18 unsafe { &*pac::RNG::ptr() }
19 }
20}
21
22static STATE: State = State {
23 ptr: AtomicPtr::new(ptr::null_mut()),
24 end: AtomicPtr::new(ptr::null_mut()),
25 waker: AtomicWaker::new(),
26};
27 18
28struct State { 19/// Interrupt handler.
29 ptr: AtomicPtr<u8>, 20pub struct InterruptHandler<T: Instance> {
30 end: AtomicPtr<u8>, 21 _phantom: PhantomData<T>,
31 waker: AtomicWaker,
32} 22}
33 23
34/// A wrapper around an nRF RNG peripheral. 24impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
35/// 25 unsafe fn on_interrupt() {
36/// It has a non-blocking API, and a blocking api through `rand`. 26 let s = T::state();
37pub struct Rng<'d> { 27 let r = T::regs();
38 irq: PeripheralRef<'d, interrupt::RNG>,
39}
40
41impl<'d> Rng<'d> {
42 /// Creates a new RNG driver from the `RNG` peripheral and interrupt.
43 ///
44 /// SAFETY: The future returned from `fill_bytes` must not have its lifetime end without running its destructor,
45 /// e.g. using `mem::forget`.
46 ///
47 /// The synchronous API is safe.
48 pub fn new(_rng: impl Peripheral<P = RNG> + 'd, irq: impl Peripheral<P = interrupt::RNG> + 'd) -> Self {
49 into_ref!(irq);
50
51 let this = Self { irq };
52 28
53 this.stop();
54 this.disable_irq();
55
56 this.irq.set_handler(Self::on_interrupt);
57 this.irq.unpend();
58 this.irq.enable();
59
60 this
61 }
62
63 fn on_interrupt(_: *mut ()) {
64 // Clear the event. 29 // Clear the event.
65 RNG::regs().events_valrdy.reset(); 30 r.events_valrdy.reset();
66 31
67 // Mutate the slice within a critical section, 32 // Mutate the slice within a critical section,
68 // so that the future isn't dropped in between us loading the pointer and actually dereferencing it. 33 // so that the future isn't dropped in between us loading the pointer and actually dereferencing it.
69 let (ptr, end) = critical_section::with(|_| { 34 let (ptr, end) = critical_section::with(|_| {
70 let ptr = STATE.ptr.load(Ordering::Relaxed); 35 let ptr = s.ptr.load(Ordering::Relaxed);
71 // We need to make sure we haven't already filled the whole slice, 36 // We need to make sure we haven't already filled the whole slice,
72 // in case the interrupt fired again before the executor got back to the future. 37 // in case the interrupt fired again before the executor got back to the future.
73 let end = STATE.end.load(Ordering::Relaxed); 38 let end = s.end.load(Ordering::Relaxed);
74 if !ptr.is_null() && ptr != end { 39 if !ptr.is_null() && ptr != end {
75 // If the future was dropped, the pointer would have been set to null, 40 // If the future was dropped, the pointer would have been set to null,
76 // so we're still good to mutate the slice. 41 // so we're still good to mutate the slice.
77 // The safety contract of `Rng::new` means that the future can't have been dropped 42 // The safety contract of `Rng::new` means that the future can't have been dropped
78 // without calling its destructor. 43 // without calling its destructor.
79 unsafe { 44 unsafe {
80 *ptr = RNG::regs().value.read().value().bits(); 45 *ptr = r.value.read().value().bits();
81 } 46 }
82 } 47 }
83 (ptr, end) 48 (ptr, end)
@@ -90,15 +55,15 @@ impl<'d> Rng<'d> {
90 } 55 }
91 56
92 let new_ptr = unsafe { ptr.add(1) }; 57 let new_ptr = unsafe { ptr.add(1) };
93 match STATE 58 match s
94 .ptr 59 .ptr
95 .compare_exchange(ptr, new_ptr, Ordering::Relaxed, Ordering::Relaxed) 60 .compare_exchange(ptr, new_ptr, Ordering::Relaxed, Ordering::Relaxed)
96 { 61 {
97 Ok(_) => { 62 Ok(_) => {
98 let end = STATE.end.load(Ordering::Relaxed); 63 let end = s.end.load(Ordering::Relaxed);
99 // It doesn't matter if `end` was changed under our feet, because then this will just be false. 64 // It doesn't matter if `end` was changed under our feet, because then this will just be false.
100 if new_ptr == end { 65 if new_ptr == end {
101 STATE.waker.wake(); 66 s.waker.wake();
102 } 67 }
103 } 68 }
104 Err(_) => { 69 Err(_) => {
@@ -107,21 +72,53 @@ impl<'d> Rng<'d> {
107 } 72 }
108 } 73 }
109 } 74 }
75}
76
77/// A wrapper around an nRF RNG peripheral.
78///
79/// It has a non-blocking API, and a blocking api through `rand`.
80pub struct Rng<'d, T: Instance> {
81 _peri: PeripheralRef<'d, T>,
82}
83
84impl<'d, T: Instance> Rng<'d, T> {
85 /// Creates a new RNG driver from the `RNG` peripheral and interrupt.
86 ///
87 /// SAFETY: The future returned from `fill_bytes` must not have its lifetime end without running its destructor,
88 /// e.g. using `mem::forget`.
89 ///
90 /// The synchronous API is safe.
91 pub fn new(
92 rng: impl Peripheral<P = T> + 'd,
93 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
94 ) -> Self {
95 into_ref!(rng);
96
97 let this = Self { _peri: rng };
98
99 this.stop();
100 this.disable_irq();
101
102 unsafe { T::Interrupt::steal() }.unpend();
103 unsafe { T::Interrupt::steal() }.enable();
104
105 this
106 }
110 107
111 fn stop(&self) { 108 fn stop(&self) {
112 RNG::regs().tasks_stop.write(|w| unsafe { w.bits(1) }) 109 T::regs().tasks_stop.write(|w| unsafe { w.bits(1) })
113 } 110 }
114 111
115 fn start(&self) { 112 fn start(&self) {
116 RNG::regs().tasks_start.write(|w| unsafe { w.bits(1) }) 113 T::regs().tasks_start.write(|w| unsafe { w.bits(1) })
117 } 114 }
118 115
119 fn enable_irq(&self) { 116 fn enable_irq(&self) {
120 RNG::regs().intenset.write(|w| w.valrdy().set()); 117 T::regs().intenset.write(|w| w.valrdy().set());
121 } 118 }
122 119
123 fn disable_irq(&self) { 120 fn disable_irq(&self) {
124 RNG::regs().intenclr.write(|w| w.valrdy().clear()); 121 T::regs().intenclr.write(|w| w.valrdy().clear());
125 } 122 }
126 123
127 /// Enable or disable the RNG's bias correction. 124 /// Enable or disable the RNG's bias correction.
@@ -131,7 +128,7 @@ impl<'d> Rng<'d> {
131 /// 128 ///
132 /// Defaults to disabled. 129 /// Defaults to disabled.
133 pub fn set_bias_correction(&self, enable: bool) { 130 pub fn set_bias_correction(&self, enable: bool) {
134 RNG::regs().config.write(|w| w.dercen().bit(enable)) 131 T::regs().config.write(|w| w.dercen().bit(enable))
135 } 132 }
136 133
137 /// Fill the buffer with random bytes. 134 /// Fill the buffer with random bytes.
@@ -140,11 +137,13 @@ impl<'d> Rng<'d> {
140 return; // Nothing to fill 137 return; // Nothing to fill
141 } 138 }
142 139
140 let s = T::state();
141
143 let range = dest.as_mut_ptr_range(); 142 let range = dest.as_mut_ptr_range();
144 // Even if we've preempted the interrupt, it can't preempt us again, 143 // Even if we've preempted the interrupt, it can't preempt us again,
145 // so we don't need to worry about the order we write these in. 144 // so we don't need to worry about the order we write these in.
146 STATE.ptr.store(range.start, Ordering::Relaxed); 145 s.ptr.store(range.start, Ordering::Relaxed);
147 STATE.end.store(range.end, Ordering::Relaxed); 146 s.end.store(range.end, Ordering::Relaxed);
148 147
149 self.enable_irq(); 148 self.enable_irq();
150 self.start(); 149 self.start();
@@ -154,16 +153,16 @@ impl<'d> Rng<'d> {
154 self.disable_irq(); 153 self.disable_irq();
155 154
156 // The interrupt is now disabled and can't preempt us anymore, so the order doesn't matter here. 155 // The interrupt is now disabled and can't preempt us anymore, so the order doesn't matter here.
157 STATE.ptr.store(ptr::null_mut(), Ordering::Relaxed); 156 s.ptr.store(ptr::null_mut(), Ordering::Relaxed);
158 STATE.end.store(ptr::null_mut(), Ordering::Relaxed); 157 s.end.store(ptr::null_mut(), Ordering::Relaxed);
159 }); 158 });
160 159
161 poll_fn(|cx| { 160 poll_fn(|cx| {
162 STATE.waker.register(cx.waker()); 161 s.waker.register(cx.waker());
163 162
164 // The interrupt will never modify `end`, so load it first and then get the most up-to-date `ptr`. 163 // The interrupt will never modify `end`, so load it first and then get the most up-to-date `ptr`.
165 let end = STATE.end.load(Ordering::Relaxed); 164 let end = s.end.load(Ordering::Relaxed);
166 let ptr = STATE.ptr.load(Ordering::Relaxed); 165 let ptr = s.ptr.load(Ordering::Relaxed);
167 166
168 if ptr == end { 167 if ptr == end {
169 // We're done. 168 // We're done.
@@ -183,7 +182,7 @@ impl<'d> Rng<'d> {
183 self.start(); 182 self.start();
184 183
185 for byte in dest.iter_mut() { 184 for byte in dest.iter_mut() {
186 let regs = RNG::regs(); 185 let regs = T::regs();
187 while regs.events_valrdy.read().bits() == 0 {} 186 while regs.events_valrdy.read().bits() == 0 {}
188 regs.events_valrdy.reset(); 187 regs.events_valrdy.reset();
189 *byte = regs.value.read().value().bits(); 188 *byte = regs.value.read().value().bits();
@@ -193,13 +192,16 @@ impl<'d> Rng<'d> {
193 } 192 }
194} 193}
195 194
196impl<'d> Drop for Rng<'d> { 195impl<'d, T: Instance> Drop for Rng<'d, T> {
197 fn drop(&mut self) { 196 fn drop(&mut self) {
198 self.irq.disable() 197 self.stop();
198 let s = T::state();
199 s.ptr.store(ptr::null_mut(), Ordering::Relaxed);
200 s.end.store(ptr::null_mut(), Ordering::Relaxed);
199 } 201 }
200} 202}
201 203
202impl<'d> rand_core::RngCore for Rng<'d> { 204impl<'d, T: Instance> rand_core::RngCore for Rng<'d, T> {
203 fn fill_bytes(&mut self, dest: &mut [u8]) { 205 fn fill_bytes(&mut self, dest: &mut [u8]) {
204 self.blocking_fill_bytes(dest); 206 self.blocking_fill_bytes(dest);
205 } 207 }
@@ -223,4 +225,53 @@ impl<'d> rand_core::RngCore for Rng<'d> {
223 } 225 }
224} 226}
225 227
226impl<'d> rand_core::CryptoRng for Rng<'d> {} 228impl<'d, T: Instance> rand_core::CryptoRng for Rng<'d, T> {}
229
230pub(crate) mod sealed {
231 use super::*;
232
233 /// Peripheral static state
234 pub struct State {
235 pub ptr: AtomicPtr<u8>,
236 pub end: AtomicPtr<u8>,
237 pub waker: AtomicWaker,
238 }
239
240 impl State {
241 pub const fn new() -> Self {
242 Self {
243 ptr: AtomicPtr::new(ptr::null_mut()),
244 end: AtomicPtr::new(ptr::null_mut()),
245 waker: AtomicWaker::new(),
246 }
247 }
248 }
249
250 pub trait Instance {
251 fn regs() -> &'static crate::pac::rng::RegisterBlock;
252 fn state() -> &'static State;
253 }
254}
255
256/// RNG peripheral instance.
257pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {
258 /// Interrupt for this peripheral.
259 type Interrupt: Interrupt;
260}
261
262macro_rules! impl_rng {
263 ($type:ident, $pac_type:ident, $irq:ident) => {
264 impl crate::rng::sealed::Instance for peripherals::$type {
265 fn regs() -> &'static crate::pac::rng::RegisterBlock {
266 unsafe { &*pac::$pac_type::ptr() }
267 }
268 fn state() -> &'static crate::rng::sealed::State {
269 static STATE: crate::rng::sealed::State = crate::rng::sealed::State::new();
270 &STATE
271 }
272 }
273 impl crate::rng::Instance for peripherals::$type {
274 type Interrupt = crate::interrupt::$irq;
275 }
276 };
277}
diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs
index 2d01a3dda..af952f03d 100644
--- a/embassy-nrf/src/saadc.rs
+++ b/embassy-nrf/src/saadc.rs
@@ -6,6 +6,7 @@ use core::future::poll_fn;
6use core::sync::atomic::{compiler_fence, Ordering}; 6use core::sync::atomic::{compiler_fence, Ordering};
7use core::task::Poll; 7use core::task::Poll;
8 8
9use embassy_cortex_m::interrupt::{Interrupt, InterruptExt};
9use embassy_hal_common::drop::OnDrop; 10use embassy_hal_common::drop::OnDrop;
10use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; 11use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef};
11use embassy_sync::waitqueue::AtomicWaker; 12use embassy_sync::waitqueue::AtomicWaker;
@@ -17,7 +18,6 @@ use saadc::oversample::OVERSAMPLE_A;
17use saadc::resolution::VAL_A; 18use saadc::resolution::VAL_A;
18 19
19use self::sealed::Input as _; 20use self::sealed::Input as _;
20use crate::interrupt::InterruptExt;
21use crate::ppi::{ConfigurableChannel, Event, Ppi, Task}; 21use crate::ppi::{ConfigurableChannel, Event, Ppi, Task};
22use crate::timer::{Frequency, Instance as TimerInstance, Timer}; 22use crate::timer::{Frequency, Instance as TimerInstance, Timer};
23use crate::{interrupt, pac, peripherals, Peripheral}; 23use crate::{interrupt, pac, peripherals, Peripheral};
@@ -28,9 +28,30 @@ use crate::{interrupt, pac, peripherals, Peripheral};
28#[non_exhaustive] 28#[non_exhaustive]
29pub enum Error {} 29pub enum Error {}
30 30
31/// One-shot and continuous SAADC. 31/// Interrupt handler.
32pub struct Saadc<'d, const N: usize> { 32pub struct InterruptHandler {
33 _p: PeripheralRef<'d, peripherals::SAADC>, 33 _private: (),
34}
35
36impl interrupt::Handler<interrupt::SAADC> for InterruptHandler {
37 unsafe fn on_interrupt() {
38 let r = unsafe { &*SAADC::ptr() };
39
40 if r.events_calibratedone.read().bits() != 0 {
41 r.intenclr.write(|w| w.calibratedone().clear());
42 WAKER.wake();
43 }
44
45 if r.events_end.read().bits() != 0 {
46 r.intenclr.write(|w| w.end().clear());
47 WAKER.wake();
48 }
49
50 if r.events_started.read().bits() != 0 {
51 r.intenclr.write(|w| w.started().clear());
52 WAKER.wake();
53 }
54 }
34} 55}
35 56
36static WAKER: AtomicWaker = AtomicWaker::new(); 57static WAKER: AtomicWaker = AtomicWaker::new();
@@ -114,15 +135,20 @@ pub enum CallbackResult {
114 Stop, 135 Stop,
115} 136}
116 137
138/// One-shot and continuous SAADC.
139pub struct Saadc<'d, const N: usize> {
140 _p: PeripheralRef<'d, peripherals::SAADC>,
141}
142
117impl<'d, const N: usize> Saadc<'d, N> { 143impl<'d, const N: usize> Saadc<'d, N> {
118 /// Create a new SAADC driver. 144 /// Create a new SAADC driver.
119 pub fn new( 145 pub fn new(
120 saadc: impl Peripheral<P = peripherals::SAADC> + 'd, 146 saadc: impl Peripheral<P = peripherals::SAADC> + 'd,
121 irq: impl Peripheral<P = interrupt::SAADC> + 'd, 147 _irq: impl interrupt::Binding<interrupt::SAADC, InterruptHandler> + 'd,
122 config: Config, 148 config: Config,
123 channel_configs: [ChannelConfig; N], 149 channel_configs: [ChannelConfig; N],
124 ) -> Self { 150 ) -> Self {
125 into_ref!(saadc, irq); 151 into_ref!(saadc);
126 152
127 let r = unsafe { &*SAADC::ptr() }; 153 let r = unsafe { &*SAADC::ptr() };
128 154
@@ -163,32 +189,12 @@ impl<'d, const N: usize> Saadc<'d, N> {
163 // Disable all events interrupts 189 // Disable all events interrupts
164 r.intenclr.write(|w| unsafe { w.bits(0x003F_FFFF) }); 190 r.intenclr.write(|w| unsafe { w.bits(0x003F_FFFF) });
165 191
166 irq.set_handler(Self::on_interrupt); 192 unsafe { interrupt::SAADC::steal() }.unpend();
167 irq.unpend(); 193 unsafe { interrupt::SAADC::steal() }.enable();
168 irq.enable();
169 194
170 Self { _p: saadc } 195 Self { _p: saadc }
171 } 196 }
172 197
173 fn on_interrupt(_ctx: *mut ()) {
174 let r = Self::regs();
175
176 if r.events_calibratedone.read().bits() != 0 {
177 r.intenclr.write(|w| w.calibratedone().clear());
178 WAKER.wake();
179 }
180
181 if r.events_end.read().bits() != 0 {
182 r.intenclr.write(|w| w.end().clear());
183 WAKER.wake();
184 }
185
186 if r.events_started.read().bits() != 0 {
187 r.intenclr.write(|w| w.started().clear());
188 WAKER.wake();
189 }
190 }
191
192 fn regs() -> &'static saadc::RegisterBlock { 198 fn regs() -> &'static saadc::RegisterBlock {
193 unsafe { &*SAADC::ptr() } 199 unsafe { &*SAADC::ptr() }
194 } 200 }
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs
index 17e435787..89cbdfee9 100644
--- a/embassy-nrf/src/spim.rs
+++ b/embassy-nrf/src/spim.rs
@@ -3,6 +3,7 @@
3#![macro_use] 3#![macro_use]
4 4
5use core::future::poll_fn; 5use core::future::poll_fn;
6use core::marker::PhantomData;
6use core::sync::atomic::{compiler_fence, Ordering}; 7use core::sync::atomic::{compiler_fence, Ordering};
7use core::task::Poll; 8use core::task::Poll;
8 9
@@ -14,7 +15,7 @@ pub use pac::spim0::frequency::FREQUENCY_A as Frequency;
14use crate::chip::FORCE_COPY_BUFFER_SIZE; 15use crate::chip::FORCE_COPY_BUFFER_SIZE;
15use crate::gpio::sealed::Pin as _; 16use crate::gpio::sealed::Pin as _;
16use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; 17use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits};
17use crate::interrupt::{Interrupt, InterruptExt}; 18use crate::interrupt::{self, Interrupt, InterruptExt};
18use crate::util::{slice_in_ram_or, slice_ptr_parts, slice_ptr_parts_mut}; 19use crate::util::{slice_in_ram_or, slice_ptr_parts, slice_ptr_parts_mut};
19use crate::{pac, Peripheral}; 20use crate::{pac, Peripheral};
20 21
@@ -31,11 +32,6 @@ pub enum Error {
31 BufferNotInRAM, 32 BufferNotInRAM,
32} 33}
33 34
34/// SPIM driver.
35pub struct Spim<'d, T: Instance> {
36 _p: PeripheralRef<'d, T>,
37}
38
39/// SPIM configuration. 35/// SPIM configuration.
40#[non_exhaustive] 36#[non_exhaustive]
41pub struct Config { 37pub struct Config {
@@ -62,11 +58,33 @@ impl Default for Config {
62 } 58 }
63} 59}
64 60
61/// Interrupt handler.
62pub struct InterruptHandler<T: Instance> {
63 _phantom: PhantomData<T>,
64}
65
66impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
67 unsafe fn on_interrupt() {
68 let r = T::regs();
69 let s = T::state();
70
71 if r.events_end.read().bits() != 0 {
72 s.end_waker.wake();
73 r.intenclr.write(|w| w.end().clear());
74 }
75 }
76}
77
78/// SPIM driver.
79pub struct Spim<'d, T: Instance> {
80 _p: PeripheralRef<'d, T>,
81}
82
65impl<'d, T: Instance> Spim<'d, T> { 83impl<'d, T: Instance> Spim<'d, T> {
66 /// Create a new SPIM driver. 84 /// Create a new SPIM driver.
67 pub fn new( 85 pub fn new(
68 spim: impl Peripheral<P = T> + 'd, 86 spim: impl Peripheral<P = T> + 'd,
69 irq: impl Peripheral<P = T::Interrupt> + 'd, 87 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
70 sck: impl Peripheral<P = impl GpioPin> + 'd, 88 sck: impl Peripheral<P = impl GpioPin> + 'd,
71 miso: impl Peripheral<P = impl GpioPin> + 'd, 89 miso: impl Peripheral<P = impl GpioPin> + 'd,
72 mosi: impl Peripheral<P = impl GpioPin> + 'd, 90 mosi: impl Peripheral<P = impl GpioPin> + 'd,
@@ -75,7 +93,6 @@ impl<'d, T: Instance> Spim<'d, T> {
75 into_ref!(sck, miso, mosi); 93 into_ref!(sck, miso, mosi);
76 Self::new_inner( 94 Self::new_inner(
77 spim, 95 spim,
78 irq,
79 sck.map_into(), 96 sck.map_into(),
80 Some(miso.map_into()), 97 Some(miso.map_into()),
81 Some(mosi.map_into()), 98 Some(mosi.map_into()),
@@ -86,36 +103,35 @@ impl<'d, T: Instance> Spim<'d, T> {
86 /// Create a new SPIM driver, capable of TX only (MOSI only). 103 /// Create a new SPIM driver, capable of TX only (MOSI only).
87 pub fn new_txonly( 104 pub fn new_txonly(
88 spim: impl Peripheral<P = T> + 'd, 105 spim: impl Peripheral<P = T> + 'd,
89 irq: impl Peripheral<P = T::Interrupt> + 'd, 106 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
90 sck: impl Peripheral<P = impl GpioPin> + 'd, 107 sck: impl Peripheral<P = impl GpioPin> + 'd,
91 mosi: impl Peripheral<P = impl GpioPin> + 'd, 108 mosi: impl Peripheral<P = impl GpioPin> + 'd,
92 config: Config, 109 config: Config,
93 ) -> Self { 110 ) -> Self {
94 into_ref!(sck, mosi); 111 into_ref!(sck, mosi);
95 Self::new_inner(spim, irq, sck.map_into(), None, Some(mosi.map_into()), config) 112 Self::new_inner(spim, sck.map_into(), None, Some(mosi.map_into()), config)
96 } 113 }
97 114
98 /// Create a new SPIM driver, capable of RX only (MISO only). 115 /// Create a new SPIM driver, capable of RX only (MISO only).
99 pub fn new_rxonly( 116 pub fn new_rxonly(
100 spim: impl Peripheral<P = T> + 'd, 117 spim: impl Peripheral<P = T> + 'd,
101 irq: impl Peripheral<P = T::Interrupt> + 'd, 118 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
102 sck: impl Peripheral<P = impl GpioPin> + 'd, 119 sck: impl Peripheral<P = impl GpioPin> + 'd,
103 miso: impl Peripheral<P = impl GpioPin> + 'd, 120 miso: impl Peripheral<P = impl GpioPin> + 'd,
104 config: Config, 121 config: Config,
105 ) -> Self { 122 ) -> Self {
106 into_ref!(sck, miso); 123 into_ref!(sck, miso);
107 Self::new_inner(spim, irq, sck.map_into(), Some(miso.map_into()), None, config) 124 Self::new_inner(spim, sck.map_into(), Some(miso.map_into()), None, config)
108 } 125 }
109 126
110 fn new_inner( 127 fn new_inner(
111 spim: impl Peripheral<P = T> + 'd, 128 spim: impl Peripheral<P = T> + 'd,
112 irq: impl Peripheral<P = T::Interrupt> + 'd,
113 sck: PeripheralRef<'d, AnyPin>, 129 sck: PeripheralRef<'d, AnyPin>,
114 miso: Option<PeripheralRef<'d, AnyPin>>, 130 miso: Option<PeripheralRef<'d, AnyPin>>,
115 mosi: Option<PeripheralRef<'d, AnyPin>>, 131 mosi: Option<PeripheralRef<'d, AnyPin>>,
116 config: Config, 132 config: Config,
117 ) -> Self { 133 ) -> Self {
118 into_ref!(spim, irq); 134 into_ref!(spim);
119 135
120 let r = T::regs(); 136 let r = T::regs();
121 137
@@ -191,23 +207,12 @@ impl<'d, T: Instance> Spim<'d, T> {
191 // Disable all events interrupts 207 // Disable all events interrupts
192 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); 208 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
193 209
194 irq.set_handler(Self::on_interrupt); 210 unsafe { T::Interrupt::steal() }.unpend();
195 irq.unpend(); 211 unsafe { T::Interrupt::steal() }.enable();
196 irq.enable();
197 212
198 Self { _p: spim } 213 Self { _p: spim }
199 } 214 }
200 215
201 fn on_interrupt(_: *mut ()) {
202 let r = T::regs();
203 let s = T::state();
204
205 if r.events_end.read().bits() != 0 {
206 s.end_waker.wake();
207 r.intenclr.write(|w| w.end().clear());
208 }
209 }
210
211 fn prepare(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> { 216 fn prepare(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> {
212 slice_in_ram_or(tx, Error::BufferNotInRAM)?; 217 slice_in_ram_or(tx, Error::BufferNotInRAM)?;
213 // NOTE: RAM slice check for rx is not necessary, as a mutable 218 // NOTE: RAM slice check for rx is not necessary, as a mutable
diff --git a/embassy-nrf/src/spis.rs b/embassy-nrf/src/spis.rs
index 1b7436477..55b5e060e 100644
--- a/embassy-nrf/src/spis.rs
+++ b/embassy-nrf/src/spis.rs
@@ -2,6 +2,7 @@
2 2
3#![macro_use] 3#![macro_use]
4use core::future::poll_fn; 4use core::future::poll_fn;
5use core::marker::PhantomData;
5use core::sync::atomic::{compiler_fence, Ordering}; 6use core::sync::atomic::{compiler_fence, Ordering};
6use core::task::Poll; 7use core::task::Poll;
7 8
@@ -12,7 +13,7 @@ pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MO
12use crate::chip::FORCE_COPY_BUFFER_SIZE; 13use crate::chip::FORCE_COPY_BUFFER_SIZE;
13use crate::gpio::sealed::Pin as _; 14use crate::gpio::sealed::Pin as _;
14use crate::gpio::{self, AnyPin, Pin as GpioPin}; 15use crate::gpio::{self, AnyPin, Pin as GpioPin};
15use crate::interrupt::{Interrupt, InterruptExt}; 16use crate::interrupt::{self, Interrupt, InterruptExt};
16use crate::util::{slice_in_ram_or, slice_ptr_parts, slice_ptr_parts_mut}; 17use crate::util::{slice_in_ram_or, slice_ptr_parts, slice_ptr_parts_mut};
17use crate::{pac, Peripheral}; 18use crate::{pac, Peripheral};
18 19
@@ -29,11 +30,6 @@ pub enum Error {
29 BufferNotInRAM, 30 BufferNotInRAM,
30} 31}
31 32
32/// SPIS driver.
33pub struct Spis<'d, T: Instance> {
34 _p: PeripheralRef<'d, T>,
35}
36
37/// SPIS configuration. 33/// SPIS configuration.
38#[non_exhaustive] 34#[non_exhaustive]
39pub struct Config { 35pub struct Config {
@@ -67,11 +63,38 @@ impl Default for Config {
67 } 63 }
68} 64}
69 65
66/// Interrupt handler.
67pub struct InterruptHandler<T: Instance> {
68 _phantom: PhantomData<T>,
69}
70
71impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
72 unsafe fn on_interrupt() {
73 let r = T::regs();
74 let s = T::state();
75
76 if r.events_end.read().bits() != 0 {
77 s.waker.wake();
78 r.intenclr.write(|w| w.end().clear());
79 }
80
81 if r.events_acquired.read().bits() != 0 {
82 s.waker.wake();
83 r.intenclr.write(|w| w.acquired().clear());
84 }
85 }
86}
87
88/// SPIS driver.
89pub struct Spis<'d, T: Instance> {
90 _p: PeripheralRef<'d, T>,
91}
92
70impl<'d, T: Instance> Spis<'d, T> { 93impl<'d, T: Instance> Spis<'d, T> {
71 /// Create a new SPIS driver. 94 /// Create a new SPIS driver.
72 pub fn new( 95 pub fn new(
73 spis: impl Peripheral<P = T> + 'd, 96 spis: impl Peripheral<P = T> + 'd,
74 irq: impl Peripheral<P = T::Interrupt> + 'd, 97 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
75 cs: impl Peripheral<P = impl GpioPin> + 'd, 98 cs: impl Peripheral<P = impl GpioPin> + 'd,
76 sck: impl Peripheral<P = impl GpioPin> + 'd, 99 sck: impl Peripheral<P = impl GpioPin> + 'd,
77 miso: impl Peripheral<P = impl GpioPin> + 'd, 100 miso: impl Peripheral<P = impl GpioPin> + 'd,
@@ -81,7 +104,6 @@ impl<'d, T: Instance> Spis<'d, T> {
81 into_ref!(cs, sck, miso, mosi); 104 into_ref!(cs, sck, miso, mosi);
82 Self::new_inner( 105 Self::new_inner(
83 spis, 106 spis,
84 irq,
85 cs.map_into(), 107 cs.map_into(),
86 sck.map_into(), 108 sck.map_into(),
87 Some(miso.map_into()), 109 Some(miso.map_into()),
@@ -93,48 +115,31 @@ impl<'d, T: Instance> Spis<'d, T> {
93 /// Create a new SPIS driver, capable of TX only (MISO only). 115 /// Create a new SPIS driver, capable of TX only (MISO only).
94 pub fn new_txonly( 116 pub fn new_txonly(
95 spis: impl Peripheral<P = T> + 'd, 117 spis: impl Peripheral<P = T> + 'd,
96 irq: impl Peripheral<P = T::Interrupt> + 'd, 118 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
97 cs: impl Peripheral<P = impl GpioPin> + 'd, 119 cs: impl Peripheral<P = impl GpioPin> + 'd,
98 sck: impl Peripheral<P = impl GpioPin> + 'd, 120 sck: impl Peripheral<P = impl GpioPin> + 'd,
99 miso: impl Peripheral<P = impl GpioPin> + 'd, 121 miso: impl Peripheral<P = impl GpioPin> + 'd,
100 config: Config, 122 config: Config,
101 ) -> Self { 123 ) -> Self {
102 into_ref!(cs, sck, miso); 124 into_ref!(cs, sck, miso);
103 Self::new_inner( 125 Self::new_inner(spis, cs.map_into(), sck.map_into(), Some(miso.map_into()), None, config)
104 spis,
105 irq,
106 cs.map_into(),
107 sck.map_into(),
108 Some(miso.map_into()),
109 None,
110 config,
111 )
112 } 126 }
113 127
114 /// Create a new SPIS driver, capable of RX only (MOSI only). 128 /// Create a new SPIS driver, capable of RX only (MOSI only).
115 pub fn new_rxonly( 129 pub fn new_rxonly(
116 spis: impl Peripheral<P = T> + 'd, 130 spis: impl Peripheral<P = T> + 'd,
117 irq: impl Peripheral<P = T::Interrupt> + 'd, 131 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
118 cs: impl Peripheral<P = impl GpioPin> + 'd, 132 cs: impl Peripheral<P = impl GpioPin> + 'd,
119 sck: impl Peripheral<P = impl GpioPin> + 'd, 133 sck: impl Peripheral<P = impl GpioPin> + 'd,
120 mosi: impl Peripheral<P = impl GpioPin> + 'd, 134 mosi: impl Peripheral<P = impl GpioPin> + 'd,
121 config: Config, 135 config: Config,
122 ) -> Self { 136 ) -> Self {
123 into_ref!(cs, sck, mosi); 137 into_ref!(cs, sck, mosi);
124 Self::new_inner( 138 Self::new_inner(spis, cs.map_into(), sck.map_into(), None, Some(mosi.map_into()), config)
125 spis,
126 irq,
127 cs.map_into(),
128 sck.map_into(),
129 None,
130 Some(mosi.map_into()),
131 config,
132 )
133 } 139 }
134 140
135 fn new_inner( 141 fn new_inner(
136 spis: impl Peripheral<P = T> + 'd, 142 spis: impl Peripheral<P = T> + 'd,
137 irq: impl Peripheral<P = T::Interrupt> + 'd,
138 cs: PeripheralRef<'d, AnyPin>, 143 cs: PeripheralRef<'d, AnyPin>,
139 sck: PeripheralRef<'d, AnyPin>, 144 sck: PeripheralRef<'d, AnyPin>,
140 miso: Option<PeripheralRef<'d, AnyPin>>, 145 miso: Option<PeripheralRef<'d, AnyPin>>,
@@ -143,7 +148,7 @@ impl<'d, T: Instance> Spis<'d, T> {
143 ) -> Self { 148 ) -> Self {
144 compiler_fence(Ordering::SeqCst); 149 compiler_fence(Ordering::SeqCst);
145 150
146 into_ref!(spis, irq, cs, sck); 151 into_ref!(spis, cs, sck);
147 152
148 let r = T::regs(); 153 let r = T::regs();
149 154
@@ -209,28 +214,12 @@ impl<'d, T: Instance> Spis<'d, T> {
209 // Disable all events interrupts. 214 // Disable all events interrupts.
210 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); 215 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
211 216
212 irq.set_handler(Self::on_interrupt); 217 unsafe { T::Interrupt::steal() }.unpend();
213 irq.unpend(); 218 unsafe { T::Interrupt::steal() }.enable();
214 irq.enable();
215 219
216 Self { _p: spis } 220 Self { _p: spis }
217 } 221 }
218 222
219 fn on_interrupt(_: *mut ()) {
220 let r = T::regs();
221 let s = T::state();
222
223 if r.events_end.read().bits() != 0 {
224 s.waker.wake();
225 r.intenclr.write(|w| w.end().clear());
226 }
227
228 if r.events_acquired.read().bits() != 0 {
229 s.waker.wake();
230 r.intenclr.write(|w| w.acquired().clear());
231 }
232 }
233
234 fn prepare(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> { 223 fn prepare(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> {
235 slice_in_ram_or(tx, Error::BufferNotInRAM)?; 224 slice_in_ram_or(tx, Error::BufferNotInRAM)?;
236 // NOTE: RAM slice check for rx is not necessary, as a mutable 225 // NOTE: RAM slice check for rx is not necessary, as a mutable
diff --git a/embassy-nrf/src/temp.rs b/embassy-nrf/src/temp.rs
index 5298faabc..3a75ec629 100644
--- a/embassy-nrf/src/temp.rs
+++ b/embassy-nrf/src/temp.rs
@@ -3,6 +3,7 @@
3use core::future::poll_fn; 3use core::future::poll_fn;
4use core::task::Poll; 4use core::task::Poll;
5 5
6use embassy_cortex_m::interrupt::Interrupt;
6use embassy_hal_common::drop::OnDrop; 7use embassy_hal_common::drop::OnDrop;
7use embassy_hal_common::{into_ref, PeripheralRef}; 8use embassy_hal_common::{into_ref, PeripheralRef};
8use embassy_sync::waitqueue::AtomicWaker; 9use embassy_sync::waitqueue::AtomicWaker;
@@ -12,27 +13,39 @@ use crate::interrupt::InterruptExt;
12use crate::peripherals::TEMP; 13use crate::peripherals::TEMP;
13use crate::{interrupt, pac, Peripheral}; 14use crate::{interrupt, pac, Peripheral};
14 15
16/// Interrupt handler.
17pub struct InterruptHandler {
18 _private: (),
19}
20
21impl interrupt::Handler<interrupt::TEMP> for InterruptHandler {
22 unsafe fn on_interrupt() {
23 let r = unsafe { &*pac::TEMP::PTR };
24 r.intenclr.write(|w| w.datardy().clear());
25 WAKER.wake();
26 }
27}
28
15/// Builtin temperature sensor driver. 29/// Builtin temperature sensor driver.
16pub struct Temp<'d> { 30pub struct Temp<'d> {
17 _irq: PeripheralRef<'d, interrupt::TEMP>, 31 _peri: PeripheralRef<'d, TEMP>,
18} 32}
19 33
20static WAKER: AtomicWaker = AtomicWaker::new(); 34static WAKER: AtomicWaker = AtomicWaker::new();
21 35
22impl<'d> Temp<'d> { 36impl<'d> Temp<'d> {
23 /// Create a new temperature sensor driver. 37 /// Create a new temperature sensor driver.
24 pub fn new(_t: impl Peripheral<P = TEMP> + 'd, irq: impl Peripheral<P = interrupt::TEMP> + 'd) -> Self { 38 pub fn new(
25 into_ref!(_t, irq); 39 _peri: impl Peripheral<P = TEMP> + 'd,
40 _irq: impl interrupt::Binding<interrupt::TEMP, InterruptHandler> + 'd,
41 ) -> Self {
42 into_ref!(_peri);
26 43
27 // Enable interrupt that signals temperature values 44 // Enable interrupt that signals temperature values
28 irq.disable(); 45 unsafe { interrupt::TEMP::steal() }.unpend();
29 irq.set_handler(|_| { 46 unsafe { interrupt::TEMP::steal() }.enable();
30 let t = Self::regs(); 47
31 t.intenclr.write(|w| w.datardy().clear()); 48 Self { _peri }
32 WAKER.wake();
33 });
34 irq.enable();
35 Self { _irq: irq }
36 } 49 }
37 50
38 /// Perform an asynchronous temperature measurement. The returned future 51 /// Perform an asynchronous temperature measurement. The returned future
diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs
index 3b0d2f1ca..a9487a9fd 100644
--- a/embassy-nrf/src/timer.rs
+++ b/embassy-nrf/src/timer.rs
@@ -6,15 +6,9 @@
6 6
7#![macro_use] 7#![macro_use]
8 8
9use core::future::poll_fn;
10use core::marker::PhantomData;
11use core::task::Poll;
12
13use embassy_hal_common::drop::OnDrop;
14use embassy_hal_common::{into_ref, PeripheralRef}; 9use embassy_hal_common::{into_ref, PeripheralRef};
15use embassy_sync::waitqueue::AtomicWaker;
16 10
17use crate::interrupt::{Interrupt, InterruptExt}; 11use crate::interrupt::Interrupt;
18use crate::ppi::{Event, Task}; 12use crate::ppi::{Event, Task};
19use crate::{pac, Peripheral}; 13use crate::{pac, Peripheral};
20 14
@@ -26,8 +20,6 @@ pub(crate) mod sealed {
26 /// The number of CC registers this instance has. 20 /// The number of CC registers this instance has.
27 const CCS: usize; 21 const CCS: usize;
28 fn regs() -> &'static pac::timer0::RegisterBlock; 22 fn regs() -> &'static pac::timer0::RegisterBlock;
29 /// Storage for the waker for CC register `n`.
30 fn waker(n: usize) -> &'static AtomicWaker;
31 } 23 }
32 pub trait ExtendedInstance {} 24 pub trait ExtendedInstance {}
33 25
@@ -50,12 +42,6 @@ macro_rules! impl_timer {
50 fn regs() -> &'static pac::timer0::RegisterBlock { 42 fn regs() -> &'static pac::timer0::RegisterBlock {
51 unsafe { &*(pac::$pac_type::ptr() as *const pac::timer0::RegisterBlock) } 43 unsafe { &*(pac::$pac_type::ptr() as *const pac::timer0::RegisterBlock) }
52 } 44 }
53 fn waker(n: usize) -> &'static ::embassy_sync::waitqueue::AtomicWaker {
54 use ::embassy_sync::waitqueue::AtomicWaker;
55 const NEW_AW: AtomicWaker = AtomicWaker::new();
56 static WAKERS: [AtomicWaker; $ccs] = [NEW_AW; $ccs];
57 &WAKERS[n]
58 }
59 } 45 }
60 impl crate::timer::Instance for peripherals::$type { 46 impl crate::timer::Instance for peripherals::$type {
61 type Interrupt = crate::interrupt::$irq; 47 type Interrupt = crate::interrupt::$irq;
@@ -99,59 +85,18 @@ pub enum Frequency {
99/// nRF Timer driver. 85/// nRF Timer driver.
100/// 86///
101/// The timer has an internal counter, which is incremented for every tick of the timer. 87/// The timer has an internal counter, which is incremented for every tick of the timer.
102/// The counter is 32-bit, so it wraps back to 0 at 4294967296. 88/// The counter is 32-bit, so it wraps back to 0 when it reaches 2^32.
103/// 89///
104/// It has either 4 or 6 Capture/Compare registers, which can be used to capture the current state of the counter 90/// It has either 4 or 6 Capture/Compare registers, which can be used to capture the current state of the counter
105/// or trigger an event when the counter reaches a certain value. 91/// or trigger an event when the counter reaches a certain value.
106 92
107pub trait TimerType: sealed::TimerType {}
108
109/// Marker type indicating the timer driver can await expiration (it owns the timer interrupt).
110pub enum Awaitable {}
111
112/// Marker type indicating the timer driver cannot await expiration (it does not own the timer interrupt).
113pub enum NotAwaitable {}
114
115impl sealed::TimerType for Awaitable {}
116impl sealed::TimerType for NotAwaitable {}
117impl TimerType for Awaitable {}
118impl TimerType for NotAwaitable {}
119
120/// Timer driver. 93/// Timer driver.
121pub struct Timer<'d, T: Instance, I: TimerType = NotAwaitable> { 94pub struct Timer<'d, T: Instance> {
122 _p: PeripheralRef<'d, T>, 95 _p: PeripheralRef<'d, T>,
123 _i: PhantomData<I>,
124}
125
126impl<'d, T: Instance> Timer<'d, T, Awaitable> {
127 /// Create a new async-capable timer driver.
128 pub fn new_awaitable(timer: impl Peripheral<P = T> + 'd, irq: impl Peripheral<P = T::Interrupt> + 'd) -> Self {
129 into_ref!(irq);
130
131 irq.set_handler(Self::on_interrupt);
132 irq.unpend();
133 irq.enable();
134
135 Self::new_inner(timer, false)
136 }
137
138 /// Create a new async-capable timer driver in counter mode.
139 pub fn new_awaitable_counter(
140 timer: impl Peripheral<P = T> + 'd,
141 irq: impl Peripheral<P = T::Interrupt> + 'd,
142 ) -> Self {
143 into_ref!(irq);
144
145 irq.set_handler(Self::on_interrupt);
146 irq.unpend();
147 irq.enable();
148
149 Self::new_inner(timer, true)
150 }
151} 96}
152 97
153impl<'d, T: Instance> Timer<'d, T, NotAwaitable> { 98impl<'d, T: Instance> Timer<'d, T> {
154 /// Create a `Timer` driver without an interrupt, meaning `Cc::wait` won't work. 99 /// Create a new `Timer` driver.
155 /// 100 ///
156 /// This can be useful for triggering tasks via PPI 101 /// This can be useful for triggering tasks via PPI
157 /// `Uarte` uses this internally. 102 /// `Uarte` uses this internally.
@@ -159,28 +104,20 @@ impl<'d, T: Instance> Timer<'d, T, NotAwaitable> {
159 Self::new_inner(timer, false) 104 Self::new_inner(timer, false)
160 } 105 }
161 106
162 /// Create a `Timer` driver in counter mode without an interrupt, meaning `Cc::wait` won't work. 107 /// Create a new `Timer` driver in counter mode.
163 /// 108 ///
164 /// This can be useful for triggering tasks via PPI 109 /// This can be useful for triggering tasks via PPI
165 /// `Uarte` uses this internally. 110 /// `Uarte` uses this internally.
166 pub fn new_counter(timer: impl Peripheral<P = T> + 'd) -> Self { 111 pub fn new_counter(timer: impl Peripheral<P = T> + 'd) -> Self {
167 Self::new_inner(timer, true) 112 Self::new_inner(timer, true)
168 } 113 }
169}
170 114
171impl<'d, T: Instance, I: TimerType> Timer<'d, T, I> {
172 /// Create a `Timer` without an interrupt, meaning `Cc::wait` won't work.
173 ///
174 /// This is used by the public constructors.
175 fn new_inner(timer: impl Peripheral<P = T> + 'd, is_counter: bool) -> Self { 115 fn new_inner(timer: impl Peripheral<P = T> + 'd, is_counter: bool) -> Self {
176 into_ref!(timer); 116 into_ref!(timer);
177 117
178 let regs = T::regs(); 118 let regs = T::regs();
179 119
180 let mut this = Self { 120 let mut this = Self { _p: timer };
181 _p: timer,
182 _i: PhantomData,
183 };
184 121
185 // Stop the timer before doing anything else, 122 // Stop the timer before doing anything else,
186 // since changing BITMODE while running can cause 'unpredictable behaviour' according to the specification. 123 // since changing BITMODE while running can cause 'unpredictable behaviour' according to the specification.
@@ -272,31 +209,17 @@ impl<'d, T: Instance, I: TimerType> Timer<'d, T, I> {
272 .write(|w| unsafe { w.prescaler().bits(frequency as u8) }) 209 .write(|w| unsafe { w.prescaler().bits(frequency as u8) })
273 } 210 }
274 211
275 fn on_interrupt(_: *mut ()) {
276 let regs = T::regs();
277 for n in 0..T::CCS {
278 if regs.events_compare[n].read().bits() != 0 {
279 // Clear the interrupt, otherwise the interrupt will be repeatedly raised as soon as the interrupt handler exits.
280 // We can't clear the event, because it's used to poll whether the future is done or still pending.
281 regs.intenclr
282 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << (16 + n))) });
283 T::waker(n).wake();
284 }
285 }
286 }
287
288 /// Returns this timer's `n`th CC register. 212 /// Returns this timer's `n`th CC register.
289 /// 213 ///
290 /// # Panics 214 /// # Panics
291 /// Panics if `n` >= the number of CC registers this timer has (4 for a normal timer, 6 for an extended timer). 215 /// Panics if `n` >= the number of CC registers this timer has (4 for a normal timer, 6 for an extended timer).
292 pub fn cc(&mut self, n: usize) -> Cc<T, I> { 216 pub fn cc(&mut self, n: usize) -> Cc<T> {
293 if n >= T::CCS { 217 if n >= T::CCS {
294 panic!("Cannot get CC register {} of timer with {} CC registers.", n, T::CCS); 218 panic!("Cannot get CC register {} of timer with {} CC registers.", n, T::CCS);
295 } 219 }
296 Cc { 220 Cc {
297 n, 221 n,
298 _p: self._p.reborrow(), 222 _p: self._p.reborrow(),
299 _i: PhantomData,
300 } 223 }
301 } 224 }
302} 225}
@@ -308,49 +231,12 @@ impl<'d, T: Instance, I: TimerType> Timer<'d, T, I> {
308/// 231///
309/// The timer will fire the register's COMPARE event when its counter reaches the value stored in the register. 232/// The timer will fire the register's COMPARE event when its counter reaches the value stored in the register.
310/// When the register's CAPTURE task is triggered, the timer will store the current value of its counter in the register 233/// When the register's CAPTURE task is triggered, the timer will store the current value of its counter in the register
311pub struct Cc<'d, T: Instance, I: TimerType = NotAwaitable> { 234pub struct Cc<'d, T: Instance> {
312 n: usize, 235 n: usize,
313 _p: PeripheralRef<'d, T>, 236 _p: PeripheralRef<'d, T>,
314 _i: PhantomData<I>,
315}
316
317impl<'d, T: Instance> Cc<'d, T, Awaitable> {
318 /// Wait until the timer's counter reaches the value stored in this register.
319 ///
320 /// This requires a mutable reference so that this task's waker cannot be overwritten by a second call to `wait`.
321 pub async fn wait(&mut self) {
322 let regs = T::regs();
323
324 // Enable the interrupt for this CC's COMPARE event.
325 regs.intenset
326 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << (16 + self.n))) });
327
328 // Disable the interrupt if the future is dropped.
329 let on_drop = OnDrop::new(|| {
330 regs.intenclr
331 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << (16 + self.n))) });
332 });
333
334 poll_fn(|cx| {
335 T::waker(self.n).register(cx.waker());
336
337 if regs.events_compare[self.n].read().bits() != 0 {
338 // Reset the register for next time
339 regs.events_compare[self.n].reset();
340 Poll::Ready(())
341 } else {
342 Poll::Pending
343 }
344 })
345 .await;
346
347 // The interrupt was already disabled in the interrupt handler, so there's no need to disable it again.
348 on_drop.defuse();
349 }
350} 237}
351impl<'d, T: Instance> Cc<'d, T, NotAwaitable> {}
352 238
353impl<'d, T: Instance, I: TimerType> Cc<'d, T, I> { 239impl<'d, T: Instance> Cc<'d, T> {
354 /// Get the current value stored in the register. 240 /// Get the current value stored in the register.
355 pub fn read(&self) -> u32 { 241 pub fn read(&self) -> u32 {
356 T::regs().cc[self.n].read().cc().bits() 242 T::regs().cc[self.n].read().cc().bits()
diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs
index 0dcb2b0da..ef4c929a3 100644
--- a/embassy-nrf/src/twim.rs
+++ b/embassy-nrf/src/twim.rs
@@ -3,6 +3,7 @@
3#![macro_use] 3#![macro_use]
4 4
5use core::future::{poll_fn, Future}; 5use core::future::{poll_fn, Future};
6use core::marker::PhantomData;
6use core::sync::atomic::compiler_fence; 7use core::sync::atomic::compiler_fence;
7use core::sync::atomic::Ordering::SeqCst; 8use core::sync::atomic::Ordering::SeqCst;
8use core::task::Poll; 9use core::task::Poll;
@@ -15,7 +16,7 @@ use embassy_time::{Duration, Instant};
15 16
16use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; 17use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
17use crate::gpio::Pin as GpioPin; 18use crate::gpio::Pin as GpioPin;
18use crate::interrupt::{Interrupt, InterruptExt}; 19use crate::interrupt::{self, Interrupt, InterruptExt};
19use crate::util::{slice_in_ram, slice_in_ram_or}; 20use crate::util::{slice_in_ram, slice_in_ram_or};
20use crate::{gpio, pac, Peripheral}; 21use crate::{gpio, pac, Peripheral};
21 22
@@ -92,6 +93,27 @@ pub enum Error {
92 Timeout, 93 Timeout,
93} 94}
94 95
96/// Interrupt handler.
97pub struct InterruptHandler<T: Instance> {
98 _phantom: PhantomData<T>,
99}
100
101impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
102 unsafe fn on_interrupt() {
103 let r = T::regs();
104 let s = T::state();
105
106 if r.events_stopped.read().bits() != 0 {
107 s.end_waker.wake();
108 r.intenclr.write(|w| w.stopped().clear());
109 }
110 if r.events_error.read().bits() != 0 {
111 s.end_waker.wake();
112 r.intenclr.write(|w| w.error().clear());
113 }
114 }
115}
116
95/// TWI driver. 117/// TWI driver.
96pub struct Twim<'d, T: Instance> { 118pub struct Twim<'d, T: Instance> {
97 _p: PeripheralRef<'d, T>, 119 _p: PeripheralRef<'d, T>,
@@ -101,12 +123,12 @@ impl<'d, T: Instance> Twim<'d, T> {
101 /// Create a new TWI driver. 123 /// Create a new TWI driver.
102 pub fn new( 124 pub fn new(
103 twim: impl Peripheral<P = T> + 'd, 125 twim: impl Peripheral<P = T> + 'd,
104 irq: impl Peripheral<P = T::Interrupt> + 'd, 126 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
105 sda: impl Peripheral<P = impl GpioPin> + 'd, 127 sda: impl Peripheral<P = impl GpioPin> + 'd,
106 scl: impl Peripheral<P = impl GpioPin> + 'd, 128 scl: impl Peripheral<P = impl GpioPin> + 'd,
107 config: Config, 129 config: Config,
108 ) -> Self { 130 ) -> Self {
109 into_ref!(twim, irq, sda, scl); 131 into_ref!(twim, sda, scl);
110 132
111 let r = T::regs(); 133 let r = T::regs();
112 134
@@ -152,27 +174,12 @@ impl<'d, T: Instance> Twim<'d, T> {
152 // Disable all events interrupts 174 // Disable all events interrupts
153 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); 175 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
154 176
155 irq.set_handler(Self::on_interrupt); 177 unsafe { T::Interrupt::steal() }.unpend();
156 irq.unpend(); 178 unsafe { T::Interrupt::steal() }.enable();
157 irq.enable();
158 179
159 Self { _p: twim } 180 Self { _p: twim }
160 } 181 }
161 182
162 fn on_interrupt(_: *mut ()) {
163 let r = T::regs();
164 let s = T::state();
165
166 if r.events_stopped.read().bits() != 0 {
167 s.end_waker.wake();
168 r.intenclr.write(|w| w.stopped().clear());
169 }
170 if r.events_error.read().bits() != 0 {
171 s.end_waker.wake();
172 r.intenclr.write(|w| w.error().clear());
173 }
174 }
175
176 /// Set TX buffer, checking that it is in RAM and has suitable length. 183 /// Set TX buffer, checking that it is in RAM and has suitable length.
177 unsafe fn set_tx_buffer(&mut self, buffer: &[u8]) -> Result<(), Error> { 184 unsafe fn set_tx_buffer(&mut self, buffer: &[u8]) -> Result<(), Error> {
178 slice_in_ram_or(buffer, Error::BufferNotInRAM)?; 185 slice_in_ram_or(buffer, Error::BufferNotInRAM)?;
diff --git a/embassy-nrf/src/twis.rs b/embassy-nrf/src/twis.rs
index c514d9f2f..bfa30b044 100644
--- a/embassy-nrf/src/twis.rs
+++ b/embassy-nrf/src/twis.rs
@@ -3,6 +3,7 @@
3#![macro_use] 3#![macro_use]
4 4
5use core::future::{poll_fn, Future}; 5use core::future::{poll_fn, Future};
6use core::marker::PhantomData;
6use core::sync::atomic::compiler_fence; 7use core::sync::atomic::compiler_fence;
7use core::sync::atomic::Ordering::SeqCst; 8use core::sync::atomic::Ordering::SeqCst;
8use core::task::Poll; 9use core::task::Poll;
@@ -14,7 +15,7 @@ use embassy_time::{Duration, Instant};
14 15
15use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; 16use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
16use crate::gpio::Pin as GpioPin; 17use crate::gpio::Pin as GpioPin;
17use crate::interrupt::{Interrupt, InterruptExt}; 18use crate::interrupt::{self, Interrupt, InterruptExt};
18use crate::util::slice_in_ram_or; 19use crate::util::slice_in_ram_or;
19use crate::{gpio, pac, Peripheral}; 20use crate::{gpio, pac, Peripheral};
20 21
@@ -108,6 +109,31 @@ pub enum Command {
108 Write(usize), 109 Write(usize),
109} 110}
110 111
112/// Interrupt handler.
113pub struct InterruptHandler<T: Instance> {
114 _phantom: PhantomData<T>,
115}
116
117impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
118 unsafe fn on_interrupt() {
119 let r = T::regs();
120 let s = T::state();
121
122 if r.events_read.read().bits() != 0 || r.events_write.read().bits() != 0 {
123 s.waker.wake();
124 r.intenclr.modify(|_r, w| w.read().clear().write().clear());
125 }
126 if r.events_stopped.read().bits() != 0 {
127 s.waker.wake();
128 r.intenclr.modify(|_r, w| w.stopped().clear());
129 }
130 if r.events_error.read().bits() != 0 {
131 s.waker.wake();
132 r.intenclr.modify(|_r, w| w.error().clear());
133 }
134 }
135}
136
111/// TWIS driver. 137/// TWIS driver.
112pub struct Twis<'d, T: Instance> { 138pub struct Twis<'d, T: Instance> {
113 _p: PeripheralRef<'d, T>, 139 _p: PeripheralRef<'d, T>,
@@ -117,12 +143,12 @@ impl<'d, T: Instance> Twis<'d, T> {
117 /// Create a new TWIS driver. 143 /// Create a new TWIS driver.
118 pub fn new( 144 pub fn new(
119 twis: impl Peripheral<P = T> + 'd, 145 twis: impl Peripheral<P = T> + 'd,
120 irq: impl Peripheral<P = T::Interrupt> + 'd, 146 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
121 sda: impl Peripheral<P = impl GpioPin> + 'd, 147 sda: impl Peripheral<P = impl GpioPin> + 'd,
122 scl: impl Peripheral<P = impl GpioPin> + 'd, 148 scl: impl Peripheral<P = impl GpioPin> + 'd,
123 config: Config, 149 config: Config,
124 ) -> Self { 150 ) -> Self {
125 into_ref!(twis, irq, sda, scl); 151 into_ref!(twis, sda, scl);
126 152
127 let r = T::regs(); 153 let r = T::regs();
128 154
@@ -178,31 +204,12 @@ impl<'d, T: Instance> Twis<'d, T> {
178 // Generate suspend on read event 204 // Generate suspend on read event
179 r.shorts.write(|w| w.read_suspend().enabled()); 205 r.shorts.write(|w| w.read_suspend().enabled());
180 206
181 irq.set_handler(Self::on_interrupt); 207 unsafe { T::Interrupt::steal() }.unpend();
182 irq.unpend(); 208 unsafe { T::Interrupt::steal() }.enable();
183 irq.enable();
184 209
185 Self { _p: twis } 210 Self { _p: twis }
186 } 211 }
187 212
188 fn on_interrupt(_: *mut ()) {
189 let r = T::regs();
190 let s = T::state();
191
192 if r.events_read.read().bits() != 0 || r.events_write.read().bits() != 0 {
193 s.waker.wake();
194 r.intenclr.modify(|_r, w| w.read().clear().write().clear());
195 }
196 if r.events_stopped.read().bits() != 0 {
197 s.waker.wake();
198 r.intenclr.modify(|_r, w| w.stopped().clear());
199 }
200 if r.events_error.read().bits() != 0 {
201 s.waker.wake();
202 r.intenclr.modify(|_r, w| w.error().clear());
203 }
204 }
205
206 /// Set TX buffer, checking that it is in RAM and has suitable length. 213 /// Set TX buffer, checking that it is in RAM and has suitable length.
207 unsafe fn set_tx_buffer(&mut self, buffer: &[u8]) -> Result<(), Error> { 214 unsafe fn set_tx_buffer(&mut self, buffer: &[u8]) -> Result<(), Error> {
208 slice_in_ram_or(buffer, Error::BufferNotInRAM)?; 215 slice_in_ram_or(buffer, Error::BufferNotInRAM)?;
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs
index 00afbd059..3934d1b55 100644
--- a/embassy-nrf/src/uarte.rs
+++ b/embassy-nrf/src/uarte.rs
@@ -14,6 +14,7 @@
14#![macro_use] 14#![macro_use]
15 15
16use core::future::poll_fn; 16use core::future::poll_fn;
17use core::marker::PhantomData;
17use core::sync::atomic::{compiler_fence, Ordering}; 18use core::sync::atomic::{compiler_fence, Ordering};
18use core::task::Poll; 19use core::task::Poll;
19 20
@@ -26,7 +27,7 @@ pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Pari
26use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; 27use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
27use crate::gpio::sealed::Pin as _; 28use crate::gpio::sealed::Pin as _;
28use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; 29use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits};
29use crate::interrupt::{Interrupt, InterruptExt}; 30use crate::interrupt::{self, Interrupt, InterruptExt};
30use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; 31use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task};
31use crate::timer::{Frequency, Instance as TimerInstance, Timer}; 32use crate::timer::{Frequency, Instance as TimerInstance, Timer};
32use crate::util::slice_in_ram_or; 33use crate::util::slice_in_ram_or;
@@ -62,6 +63,27 @@ pub enum Error {
62 BufferNotInRAM, 63 BufferNotInRAM,
63} 64}
64 65
66/// Interrupt handler.
67pub struct InterruptHandler<T: Instance> {
68 _phantom: PhantomData<T>,
69}
70
71impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
72 unsafe fn on_interrupt() {
73 let r = T::regs();
74 let s = T::state();
75
76 if r.events_endrx.read().bits() != 0 {
77 s.endrx_waker.wake();
78 r.intenclr.write(|w| w.endrx().clear());
79 }
80 if r.events_endtx.read().bits() != 0 {
81 s.endtx_waker.wake();
82 r.intenclr.write(|w| w.endtx().clear());
83 }
84 }
85}
86
65/// UARTE driver. 87/// UARTE driver.
66pub struct Uarte<'d, T: Instance> { 88pub struct Uarte<'d, T: Instance> {
67 tx: UarteTx<'d, T>, 89 tx: UarteTx<'d, T>,
@@ -86,19 +108,19 @@ impl<'d, T: Instance> Uarte<'d, T> {
86 /// Create a new UARTE without hardware flow control 108 /// Create a new UARTE without hardware flow control
87 pub fn new( 109 pub fn new(
88 uarte: impl Peripheral<P = T> + 'd, 110 uarte: impl Peripheral<P = T> + 'd,
89 irq: impl Peripheral<P = T::Interrupt> + 'd, 111 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
90 rxd: impl Peripheral<P = impl GpioPin> + 'd, 112 rxd: impl Peripheral<P = impl GpioPin> + 'd,
91 txd: impl Peripheral<P = impl GpioPin> + 'd, 113 txd: impl Peripheral<P = impl GpioPin> + 'd,
92 config: Config, 114 config: Config,
93 ) -> Self { 115 ) -> Self {
94 into_ref!(rxd, txd); 116 into_ref!(rxd, txd);
95 Self::new_inner(uarte, irq, rxd.map_into(), txd.map_into(), None, None, config) 117 Self::new_inner(uarte, rxd.map_into(), txd.map_into(), None, None, config)
96 } 118 }
97 119
98 /// Create a new UARTE with hardware flow control (RTS/CTS) 120 /// Create a new UARTE with hardware flow control (RTS/CTS)
99 pub fn new_with_rtscts( 121 pub fn new_with_rtscts(
100 uarte: impl Peripheral<P = T> + 'd, 122 uarte: impl Peripheral<P = T> + 'd,
101 irq: impl Peripheral<P = T::Interrupt> + 'd, 123 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
102 rxd: impl Peripheral<P = impl GpioPin> + 'd, 124 rxd: impl Peripheral<P = impl GpioPin> + 'd,
103 txd: impl Peripheral<P = impl GpioPin> + 'd, 125 txd: impl Peripheral<P = impl GpioPin> + 'd,
104 cts: impl Peripheral<P = impl GpioPin> + 'd, 126 cts: impl Peripheral<P = impl GpioPin> + 'd,
@@ -108,7 +130,6 @@ impl<'d, T: Instance> Uarte<'d, T> {
108 into_ref!(rxd, txd, cts, rts); 130 into_ref!(rxd, txd, cts, rts);
109 Self::new_inner( 131 Self::new_inner(
110 uarte, 132 uarte,
111 irq,
112 rxd.map_into(), 133 rxd.map_into(),
113 txd.map_into(), 134 txd.map_into(),
114 Some(cts.map_into()), 135 Some(cts.map_into()),
@@ -119,14 +140,13 @@ impl<'d, T: Instance> Uarte<'d, T> {
119 140
120 fn new_inner( 141 fn new_inner(
121 uarte: impl Peripheral<P = T> + 'd, 142 uarte: impl Peripheral<P = T> + 'd,
122 irq: impl Peripheral<P = T::Interrupt> + 'd,
123 rxd: PeripheralRef<'d, AnyPin>, 143 rxd: PeripheralRef<'d, AnyPin>,
124 txd: PeripheralRef<'d, AnyPin>, 144 txd: PeripheralRef<'d, AnyPin>,
125 cts: Option<PeripheralRef<'d, AnyPin>>, 145 cts: Option<PeripheralRef<'d, AnyPin>>,
126 rts: Option<PeripheralRef<'d, AnyPin>>, 146 rts: Option<PeripheralRef<'d, AnyPin>>,
127 config: Config, 147 config: Config,
128 ) -> Self { 148 ) -> Self {
129 into_ref!(uarte, irq); 149 into_ref!(uarte);
130 150
131 let r = T::regs(); 151 let r = T::regs();
132 152
@@ -148,9 +168,8 @@ impl<'d, T: Instance> Uarte<'d, T> {
148 } 168 }
149 r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) }); 169 r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) });
150 170
151 irq.set_handler(Self::on_interrupt); 171 unsafe { T::Interrupt::steal() }.unpend();
152 irq.unpend(); 172 unsafe { T::Interrupt::steal() }.enable();
153 irq.enable();
154 173
155 let hardware_flow_control = match (rts.is_some(), cts.is_some()) { 174 let hardware_flow_control = match (rts.is_some(), cts.is_some()) {
156 (false, false) => false, 175 (false, false) => false,
@@ -238,20 +257,6 @@ impl<'d, T: Instance> Uarte<'d, T> {
238 Event::from_reg(&r.events_endtx) 257 Event::from_reg(&r.events_endtx)
239 } 258 }
240 259
241 fn on_interrupt(_: *mut ()) {
242 let r = T::regs();
243 let s = T::state();
244
245 if r.events_endrx.read().bits() != 0 {
246 s.endrx_waker.wake();
247 r.intenclr.write(|w| w.endrx().clear());
248 }
249 if r.events_endtx.read().bits() != 0 {
250 s.endtx_waker.wake();
251 r.intenclr.write(|w| w.endtx().clear());
252 }
253 }
254
255 /// Read bytes until the buffer is filled. 260 /// Read bytes until the buffer is filled.
256 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 261 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
257 self.rx.read(buffer).await 262 self.rx.read(buffer).await
@@ -308,34 +313,33 @@ impl<'d, T: Instance> UarteTx<'d, T> {
308 /// Create a new tx-only UARTE without hardware flow control 313 /// Create a new tx-only UARTE without hardware flow control
309 pub fn new( 314 pub fn new(
310 uarte: impl Peripheral<P = T> + 'd, 315 uarte: impl Peripheral<P = T> + 'd,
311 irq: impl Peripheral<P = T::Interrupt> + 'd, 316 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
312 txd: impl Peripheral<P = impl GpioPin> + 'd, 317 txd: impl Peripheral<P = impl GpioPin> + 'd,
313 config: Config, 318 config: Config,
314 ) -> Self { 319 ) -> Self {
315 into_ref!(txd); 320 into_ref!(txd);
316 Self::new_inner(uarte, irq, txd.map_into(), None, config) 321 Self::new_inner(uarte, txd.map_into(), None, config)
317 } 322 }
318 323
319 /// Create a new tx-only UARTE with hardware flow control (RTS/CTS) 324 /// Create a new tx-only UARTE with hardware flow control (RTS/CTS)
320 pub fn new_with_rtscts( 325 pub fn new_with_rtscts(
321 uarte: impl Peripheral<P = T> + 'd, 326 uarte: impl Peripheral<P = T> + 'd,
322 irq: impl Peripheral<P = T::Interrupt> + 'd, 327 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
323 txd: impl Peripheral<P = impl GpioPin> + 'd, 328 txd: impl Peripheral<P = impl GpioPin> + 'd,
324 cts: impl Peripheral<P = impl GpioPin> + 'd, 329 cts: impl Peripheral<P = impl GpioPin> + 'd,
325 config: Config, 330 config: Config,
326 ) -> Self { 331 ) -> Self {
327 into_ref!(txd, cts); 332 into_ref!(txd, cts);
328 Self::new_inner(uarte, irq, txd.map_into(), Some(cts.map_into()), config) 333 Self::new_inner(uarte, txd.map_into(), Some(cts.map_into()), config)
329 } 334 }
330 335
331 fn new_inner( 336 fn new_inner(
332 uarte: impl Peripheral<P = T> + 'd, 337 uarte: impl Peripheral<P = T> + 'd,
333 irq: impl Peripheral<P = T::Interrupt> + 'd,
334 txd: PeripheralRef<'d, AnyPin>, 338 txd: PeripheralRef<'d, AnyPin>,
335 cts: Option<PeripheralRef<'d, AnyPin>>, 339 cts: Option<PeripheralRef<'d, AnyPin>>,
336 config: Config, 340 config: Config,
337 ) -> Self { 341 ) -> Self {
338 into_ref!(uarte, irq); 342 into_ref!(uarte);
339 343
340 let r = T::regs(); 344 let r = T::regs();
341 345
@@ -354,9 +358,8 @@ impl<'d, T: Instance> UarteTx<'d, T> {
354 let hardware_flow_control = cts.is_some(); 358 let hardware_flow_control = cts.is_some();
355 configure(r, config, hardware_flow_control); 359 configure(r, config, hardware_flow_control);
356 360
357 irq.set_handler(Uarte::<T>::on_interrupt); 361 unsafe { T::Interrupt::steal() }.unpend();
358 irq.unpend(); 362 unsafe { T::Interrupt::steal() }.enable();
359 irq.enable();
360 363
361 let s = T::state(); 364 let s = T::state();
362 s.tx_rx_refcount.store(1, Ordering::Relaxed); 365 s.tx_rx_refcount.store(1, Ordering::Relaxed);
@@ -506,34 +509,33 @@ impl<'d, T: Instance> UarteRx<'d, T> {
506 /// Create a new rx-only UARTE without hardware flow control 509 /// Create a new rx-only UARTE without hardware flow control
507 pub fn new( 510 pub fn new(
508 uarte: impl Peripheral<P = T> + 'd, 511 uarte: impl Peripheral<P = T> + 'd,
509 irq: impl Peripheral<P = T::Interrupt> + 'd, 512 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
510 rxd: impl Peripheral<P = impl GpioPin> + 'd, 513 rxd: impl Peripheral<P = impl GpioPin> + 'd,
511 config: Config, 514 config: Config,
512 ) -> Self { 515 ) -> Self {
513 into_ref!(rxd); 516 into_ref!(rxd);
514 Self::new_inner(uarte, irq, rxd.map_into(), None, config) 517 Self::new_inner(uarte, rxd.map_into(), None, config)
515 } 518 }
516 519
517 /// Create a new rx-only UARTE with hardware flow control (RTS/CTS) 520 /// Create a new rx-only UARTE with hardware flow control (RTS/CTS)
518 pub fn new_with_rtscts( 521 pub fn new_with_rtscts(
519 uarte: impl Peripheral<P = T> + 'd, 522 uarte: impl Peripheral<P = T> + 'd,
520 irq: impl Peripheral<P = T::Interrupt> + 'd, 523 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
521 rxd: impl Peripheral<P = impl GpioPin> + 'd, 524 rxd: impl Peripheral<P = impl GpioPin> + 'd,
522 rts: impl Peripheral<P = impl GpioPin> + 'd, 525 rts: impl Peripheral<P = impl GpioPin> + 'd,
523 config: Config, 526 config: Config,
524 ) -> Self { 527 ) -> Self {
525 into_ref!(rxd, rts); 528 into_ref!(rxd, rts);
526 Self::new_inner(uarte, irq, rxd.map_into(), Some(rts.map_into()), config) 529 Self::new_inner(uarte, rxd.map_into(), Some(rts.map_into()), config)
527 } 530 }
528 531
529 fn new_inner( 532 fn new_inner(
530 uarte: impl Peripheral<P = T> + 'd, 533 uarte: impl Peripheral<P = T> + 'd,
531 irq: impl Peripheral<P = T::Interrupt> + 'd,
532 rxd: PeripheralRef<'d, AnyPin>, 534 rxd: PeripheralRef<'d, AnyPin>,
533 rts: Option<PeripheralRef<'d, AnyPin>>, 535 rts: Option<PeripheralRef<'d, AnyPin>>,
534 config: Config, 536 config: Config,
535 ) -> Self { 537 ) -> Self {
536 into_ref!(uarte, irq); 538 into_ref!(uarte);
537 539
538 let r = T::regs(); 540 let r = T::regs();
539 541
@@ -549,9 +551,8 @@ impl<'d, T: Instance> UarteRx<'d, T> {
549 r.psel.txd.write(|w| w.connect().disconnected()); 551 r.psel.txd.write(|w| w.connect().disconnected());
550 r.psel.cts.write(|w| w.connect().disconnected()); 552 r.psel.cts.write(|w| w.connect().disconnected());
551 553
552 irq.set_handler(Uarte::<T>::on_interrupt); 554 unsafe { T::Interrupt::steal() }.unpend();
553 irq.unpend(); 555 unsafe { T::Interrupt::steal() }.enable();
554 irq.enable();
555 556
556 let hardware_flow_control = rts.is_some(); 557 let hardware_flow_control = rts.is_some();
557 configure(r, config, hardware_flow_control); 558 configure(r, config, hardware_flow_control);
diff --git a/embassy-nrf/src/usb.rs b/embassy-nrf/src/usb/mod.rs
index cd142f00f..56de511df 100644
--- a/embassy-nrf/src/usb.rs
+++ b/embassy-nrf/src/usb/mod.rs
@@ -2,10 +2,12 @@
2 2
3#![macro_use] 3#![macro_use]
4 4
5pub mod vbus_detect;
6
5use core::future::poll_fn; 7use core::future::poll_fn;
6use core::marker::PhantomData; 8use core::marker::PhantomData;
7use core::mem::MaybeUninit; 9use core::mem::MaybeUninit;
8use core::sync::atomic::{compiler_fence, AtomicBool, AtomicU32, Ordering}; 10use core::sync::atomic::{compiler_fence, AtomicU32, Ordering};
9use core::task::Poll; 11use core::task::Poll;
10 12
11use cortex_m::peripheral::NVIC; 13use cortex_m::peripheral::NVIC;
@@ -15,7 +17,8 @@ use embassy_usb_driver as driver;
15use embassy_usb_driver::{Direction, EndpointAddress, EndpointError, EndpointInfo, EndpointType, Event, Unsupported}; 17use embassy_usb_driver::{Direction, EndpointAddress, EndpointError, EndpointInfo, EndpointType, Event, Unsupported};
16use pac::usbd::RegisterBlock; 18use pac::usbd::RegisterBlock;
17 19
18use crate::interrupt::{Interrupt, InterruptExt}; 20use self::vbus_detect::VbusDetect;
21use crate::interrupt::{self, Interrupt, InterruptExt};
19use crate::util::slice_in_ram; 22use crate::util::slice_in_ram;
20use crate::{pac, Peripheral}; 23use crate::{pac, Peripheral};
21 24
@@ -26,185 +29,13 @@ static EP_IN_WAKERS: [AtomicWaker; 8] = [NEW_AW; 8];
26static EP_OUT_WAKERS: [AtomicWaker; 8] = [NEW_AW; 8]; 29static EP_OUT_WAKERS: [AtomicWaker; 8] = [NEW_AW; 8];
27static READY_ENDPOINTS: AtomicU32 = AtomicU32::new(0); 30static READY_ENDPOINTS: AtomicU32 = AtomicU32::new(0);
28 31
29/// Trait for detecting USB VBUS power. 32/// Interrupt handler.
30/// 33pub struct InterruptHandler<T: Instance> {
31/// There are multiple ways to detect USB power. The behavior 34 _phantom: PhantomData<T>,
32/// here provides a hook into determining whether it is.
33pub trait VbusDetect {
34 /// Report whether power is detected.
35 ///
36 /// This is indicated by the `USBREGSTATUS.VBUSDETECT` register, or the
37 /// `USBDETECTED`, `USBREMOVED` events from the `POWER` peripheral.
38 fn is_usb_detected(&self) -> bool;
39
40 /// Wait until USB power is ready.
41 ///
42 /// USB power ready is indicated by the `USBREGSTATUS.OUTPUTRDY` register, or the
43 /// `USBPWRRDY` event from the `POWER` peripheral.
44 async fn wait_power_ready(&mut self) -> Result<(), ()>;
45}
46
47/// [`VbusDetect`] implementation using the native hardware POWER peripheral.
48///
49/// Unsuitable for usage with the nRF softdevice, since it reserves exclusive acces
50/// to POWER. In that case, use [`VbusDetectSignal`].
51#[cfg(not(feature = "_nrf5340-app"))]
52pub struct HardwareVbusDetect {
53 _private: (),
54}
55
56static POWER_WAKER: AtomicWaker = NEW_AW;
57
58#[cfg(not(feature = "_nrf5340-app"))]
59impl HardwareVbusDetect {
60 /// Create a new `VbusDetectNative`.
61 pub fn new(power_irq: impl Interrupt) -> Self {
62 let regs = unsafe { &*pac::POWER::ptr() };
63
64 power_irq.set_handler(Self::on_interrupt);
65 power_irq.unpend();
66 power_irq.enable();
67
68 regs.intenset
69 .write(|w| w.usbdetected().set().usbremoved().set().usbpwrrdy().set());
70
71 Self { _private: () }
72 }
73
74 #[cfg(not(feature = "_nrf5340-app"))]
75 fn on_interrupt(_: *mut ()) {
76 let regs = unsafe { &*pac::POWER::ptr() };
77
78 if regs.events_usbdetected.read().bits() != 0 {
79 regs.events_usbdetected.reset();
80 BUS_WAKER.wake();
81 }
82
83 if regs.events_usbremoved.read().bits() != 0 {
84 regs.events_usbremoved.reset();
85 BUS_WAKER.wake();
86 POWER_WAKER.wake();
87 }
88
89 if regs.events_usbpwrrdy.read().bits() != 0 {
90 regs.events_usbpwrrdy.reset();
91 POWER_WAKER.wake();
92 }
93 }
94}
95
96#[cfg(not(feature = "_nrf5340-app"))]
97impl VbusDetect for HardwareVbusDetect {
98 fn is_usb_detected(&self) -> bool {
99 let regs = unsafe { &*pac::POWER::ptr() };
100 regs.usbregstatus.read().vbusdetect().is_vbus_present()
101 }
102
103 async fn wait_power_ready(&mut self) -> Result<(), ()> {
104 poll_fn(move |cx| {
105 POWER_WAKER.register(cx.waker());
106 let regs = unsafe { &*pac::POWER::ptr() };
107
108 if regs.usbregstatus.read().outputrdy().is_ready() {
109 Poll::Ready(Ok(()))
110 } else if !self.is_usb_detected() {
111 Poll::Ready(Err(()))
112 } else {
113 Poll::Pending
114 }
115 })
116 .await
117 }
118}
119
120/// Software-backed [`VbusDetect`] implementation.
121///
122/// This implementation does not interact with the hardware, it allows user code
123/// to notify the power events by calling functions instead.
124///
125/// This is suitable for use with the nRF softdevice, by calling the functions
126/// when the softdevice reports power-related events.
127pub struct SoftwareVbusDetect {
128 usb_detected: AtomicBool,
129 power_ready: AtomicBool,
130}
131
132impl SoftwareVbusDetect {
133 /// Create a new `SoftwareVbusDetect`.
134 pub fn new(usb_detected: bool, power_ready: bool) -> Self {
135 BUS_WAKER.wake();
136
137 Self {
138 usb_detected: AtomicBool::new(usb_detected),
139 power_ready: AtomicBool::new(power_ready),
140 }
141 }
142
143 /// Report whether power was detected.
144 ///
145 /// Equivalent to the `USBDETECTED`, `USBREMOVED` events from the `POWER` peripheral.
146 pub fn detected(&self, detected: bool) {
147 self.usb_detected.store(detected, Ordering::Relaxed);
148 self.power_ready.store(false, Ordering::Relaxed);
149 BUS_WAKER.wake();
150 POWER_WAKER.wake();
151 }
152
153 /// Report when USB power is ready.
154 ///
155 /// Equivalent to the `USBPWRRDY` event from the `POWER` peripheral.
156 pub fn ready(&self) {
157 self.power_ready.store(true, Ordering::Relaxed);
158 POWER_WAKER.wake();
159 }
160}
161
162impl VbusDetect for &SoftwareVbusDetect {
163 fn is_usb_detected(&self) -> bool {
164 self.usb_detected.load(Ordering::Relaxed)
165 }
166
167 async fn wait_power_ready(&mut self) -> Result<(), ()> {
168 poll_fn(move |cx| {
169 POWER_WAKER.register(cx.waker());
170
171 if self.power_ready.load(Ordering::Relaxed) {
172 Poll::Ready(Ok(()))
173 } else if !self.usb_detected.load(Ordering::Relaxed) {
174 Poll::Ready(Err(()))
175 } else {
176 Poll::Pending
177 }
178 })
179 .await
180 }
181} 35}
182 36
183/// USB driver. 37impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
184pub struct Driver<'d, T: Instance, P: VbusDetect> { 38 unsafe fn on_interrupt() {
185 _p: PeripheralRef<'d, T>,
186 alloc_in: Allocator,
187 alloc_out: Allocator,
188 usb_supply: P,
189}
190
191impl<'d, T: Instance, P: VbusDetect> Driver<'d, T, P> {
192 /// Create a new USB driver.
193 pub fn new(usb: impl Peripheral<P = T> + 'd, irq: impl Peripheral<P = T::Interrupt> + 'd, usb_supply: P) -> Self {
194 into_ref!(usb, irq);
195 irq.set_handler(Self::on_interrupt);
196 irq.unpend();
197 irq.enable();
198
199 Self {
200 _p: usb,
201 alloc_in: Allocator::new(),
202 alloc_out: Allocator::new(),
203 usb_supply,
204 }
205 }
206
207 fn on_interrupt(_: *mut ()) {
208 let regs = T::regs(); 39 let regs = T::regs();
209 40
210 if regs.events_usbreset.read().bits() != 0 { 41 if regs.events_usbreset.read().bits() != 0 {
@@ -255,11 +86,40 @@ impl<'d, T: Instance, P: VbusDetect> Driver<'d, T, P> {
255 } 86 }
256} 87}
257 88
258impl<'d, T: Instance, P: VbusDetect + 'd> driver::Driver<'d> for Driver<'d, T, P> { 89/// USB driver.
90pub struct Driver<'d, T: Instance, V: VbusDetect> {
91 _p: PeripheralRef<'d, T>,
92 alloc_in: Allocator,
93 alloc_out: Allocator,
94 vbus_detect: V,
95}
96
97impl<'d, T: Instance, V: VbusDetect> Driver<'d, T, V> {
98 /// Create a new USB driver.
99 pub fn new(
100 usb: impl Peripheral<P = T> + 'd,
101 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
102 vbus_detect: V,
103 ) -> Self {
104 into_ref!(usb);
105
106 unsafe { T::Interrupt::steal() }.unpend();
107 unsafe { T::Interrupt::steal() }.enable();
108
109 Self {
110 _p: usb,
111 alloc_in: Allocator::new(),
112 alloc_out: Allocator::new(),
113 vbus_detect,
114 }
115 }
116}
117
118impl<'d, T: Instance, V: VbusDetect + 'd> driver::Driver<'d> for Driver<'d, T, V> {
259 type EndpointOut = Endpoint<'d, T, Out>; 119 type EndpointOut = Endpoint<'d, T, Out>;
260 type EndpointIn = Endpoint<'d, T, In>; 120 type EndpointIn = Endpoint<'d, T, In>;
261 type ControlPipe = ControlPipe<'d, T>; 121 type ControlPipe = ControlPipe<'d, T>;
262 type Bus = Bus<'d, T, P>; 122 type Bus = Bus<'d, T, V>;
263 123
264 fn alloc_endpoint_in( 124 fn alloc_endpoint_in(
265 &mut self, 125 &mut self,
@@ -298,7 +158,7 @@ impl<'d, T: Instance, P: VbusDetect + 'd> driver::Driver<'d> for Driver<'d, T, P
298 Bus { 158 Bus {
299 _p: unsafe { self._p.clone_unchecked() }, 159 _p: unsafe { self._p.clone_unchecked() },
300 power_available: false, 160 power_available: false,
301 usb_supply: self.usb_supply, 161 vbus_detect: self.vbus_detect,
302 }, 162 },
303 ControlPipe { 163 ControlPipe {
304 _p: self._p, 164 _p: self._p,
@@ -309,13 +169,13 @@ impl<'d, T: Instance, P: VbusDetect + 'd> driver::Driver<'d> for Driver<'d, T, P
309} 169}
310 170
311/// USB bus. 171/// USB bus.
312pub struct Bus<'d, T: Instance, P: VbusDetect> { 172pub struct Bus<'d, T: Instance, V: VbusDetect> {
313 _p: PeripheralRef<'d, T>, 173 _p: PeripheralRef<'d, T>,
314 power_available: bool, 174 power_available: bool,
315 usb_supply: P, 175 vbus_detect: V,
316} 176}
317 177
318impl<'d, T: Instance, P: VbusDetect> driver::Bus for Bus<'d, T, P> { 178impl<'d, T: Instance, V: VbusDetect> driver::Bus for Bus<'d, T, V> {
319 async fn enable(&mut self) { 179 async fn enable(&mut self) {
320 let regs = T::regs(); 180 let regs = T::regs();
321 181
@@ -347,7 +207,7 @@ impl<'d, T: Instance, P: VbusDetect> driver::Bus for Bus<'d, T, P> {
347 w 207 w
348 }); 208 });
349 209
350 if self.usb_supply.wait_power_ready().await.is_ok() { 210 if self.vbus_detect.wait_power_ready().await.is_ok() {
351 // Enable the USB pullup, allowing enumeration. 211 // Enable the USB pullup, allowing enumeration.
352 regs.usbpullup.write(|w| w.connect().enabled()); 212 regs.usbpullup.write(|w| w.connect().enabled());
353 trace!("enabled"); 213 trace!("enabled");
@@ -406,7 +266,7 @@ impl<'d, T: Instance, P: VbusDetect> driver::Bus for Bus<'d, T, P> {
406 trace!("USB event: ready"); 266 trace!("USB event: ready");
407 } 267 }
408 268
409 if self.usb_supply.is_usb_detected() != self.power_available { 269 if self.vbus_detect.is_usb_detected() != self.power_available {
410 self.power_available = !self.power_available; 270 self.power_available = !self.power_available;
411 if self.power_available { 271 if self.power_available {
412 trace!("Power event: available"); 272 trace!("Power event: available");
diff --git a/embassy-nrf/src/usb/vbus_detect.rs b/embassy-nrf/src/usb/vbus_detect.rs
new file mode 100644
index 000000000..cecd4c595
--- /dev/null
+++ b/embassy-nrf/src/usb/vbus_detect.rs
@@ -0,0 +1,177 @@
1//! Trait and implementations for performing VBUS detection.
2
3use core::future::poll_fn;
4use core::sync::atomic::{AtomicBool, Ordering};
5use core::task::Poll;
6
7use embassy_sync::waitqueue::AtomicWaker;
8
9use super::BUS_WAKER;
10use crate::interrupt::{self, Interrupt, InterruptExt};
11use crate::pac;
12
13/// Trait for detecting USB VBUS power.
14///
15/// There are multiple ways to detect USB power. The behavior
16/// here provides a hook into determining whether it is.
17pub trait VbusDetect {
18 /// Report whether power is detected.
19 ///
20 /// This is indicated by the `USBREGSTATUS.VBUSDETECT` register, or the
21 /// `USBDETECTED`, `USBREMOVED` events from the `POWER` peripheral.
22 fn is_usb_detected(&self) -> bool;
23
24 /// Wait until USB power is ready.
25 ///
26 /// USB power ready is indicated by the `USBREGSTATUS.OUTPUTRDY` register, or the
27 /// `USBPWRRDY` event from the `POWER` peripheral.
28 async fn wait_power_ready(&mut self) -> Result<(), ()>;
29}
30
31#[cfg(not(feature = "_nrf5340"))]
32type UsbRegIrq = interrupt::POWER_CLOCK;
33#[cfg(feature = "_nrf5340")]
34type UsbRegIrq = interrupt::USBREGULATOR;
35
36#[cfg(not(feature = "_nrf5340"))]
37type UsbRegPeri = pac::POWER;
38#[cfg(feature = "_nrf5340")]
39type UsbRegPeri = pac::USBREGULATOR;
40
41/// Interrupt handler.
42pub struct InterruptHandler {
43 _private: (),
44}
45
46impl interrupt::Handler<UsbRegIrq> for InterruptHandler {
47 unsafe fn on_interrupt() {
48 let regs = unsafe { &*UsbRegPeri::ptr() };
49
50 if regs.events_usbdetected.read().bits() != 0 {
51 regs.events_usbdetected.reset();
52 BUS_WAKER.wake();
53 }
54
55 if regs.events_usbremoved.read().bits() != 0 {
56 regs.events_usbremoved.reset();
57 BUS_WAKER.wake();
58 POWER_WAKER.wake();
59 }
60
61 if regs.events_usbpwrrdy.read().bits() != 0 {
62 regs.events_usbpwrrdy.reset();
63 POWER_WAKER.wake();
64 }
65 }
66}
67
68/// [`VbusDetect`] implementation using the native hardware POWER peripheral.
69///
70/// Unsuitable for usage with the nRF softdevice, since it reserves exclusive acces
71/// to POWER. In that case, use [`VbusDetectSignal`].
72pub struct HardwareVbusDetect {
73 _private: (),
74}
75
76static POWER_WAKER: AtomicWaker = AtomicWaker::new();
77
78impl HardwareVbusDetect {
79 /// Create a new `VbusDetectNative`.
80 pub fn new(_irq: impl interrupt::Binding<UsbRegIrq, InterruptHandler> + 'static) -> Self {
81 let regs = unsafe { &*UsbRegPeri::ptr() };
82
83 unsafe { UsbRegIrq::steal() }.unpend();
84 unsafe { UsbRegIrq::steal() }.enable();
85
86 regs.intenset
87 .write(|w| w.usbdetected().set().usbremoved().set().usbpwrrdy().set());
88
89 Self { _private: () }
90 }
91}
92
93impl VbusDetect for HardwareVbusDetect {
94 fn is_usb_detected(&self) -> bool {
95 let regs = unsafe { &*UsbRegPeri::ptr() };
96 regs.usbregstatus.read().vbusdetect().is_vbus_present()
97 }
98
99 async fn wait_power_ready(&mut self) -> Result<(), ()> {
100 poll_fn(move |cx| {
101 POWER_WAKER.register(cx.waker());
102 let regs = unsafe { &*UsbRegPeri::ptr() };
103
104 if regs.usbregstatus.read().outputrdy().is_ready() {
105 Poll::Ready(Ok(()))
106 } else if !self.is_usb_detected() {
107 Poll::Ready(Err(()))
108 } else {
109 Poll::Pending
110 }
111 })
112 .await
113 }
114}
115
116/// Software-backed [`VbusDetect`] implementation.
117///
118/// This implementation does not interact with the hardware, it allows user code
119/// to notify the power events by calling functions instead.
120///
121/// This is suitable for use with the nRF softdevice, by calling the functions
122/// when the softdevice reports power-related events.
123pub struct SoftwareVbusDetect {
124 usb_detected: AtomicBool,
125 power_ready: AtomicBool,
126}
127
128impl SoftwareVbusDetect {
129 /// Create a new `SoftwareVbusDetect`.
130 pub fn new(usb_detected: bool, power_ready: bool) -> Self {
131 BUS_WAKER.wake();
132
133 Self {
134 usb_detected: AtomicBool::new(usb_detected),
135 power_ready: AtomicBool::new(power_ready),
136 }
137 }
138
139 /// Report whether power was detected.
140 ///
141 /// Equivalent to the `USBDETECTED`, `USBREMOVED` events from the `POWER` peripheral.
142 pub fn detected(&self, detected: bool) {
143 self.usb_detected.store(detected, Ordering::Relaxed);
144 self.power_ready.store(false, Ordering::Relaxed);
145 BUS_WAKER.wake();
146 POWER_WAKER.wake();
147 }
148
149 /// Report when USB power is ready.
150 ///
151 /// Equivalent to the `USBPWRRDY` event from the `POWER` peripheral.
152 pub fn ready(&self) {
153 self.power_ready.store(true, Ordering::Relaxed);
154 POWER_WAKER.wake();
155 }
156}
157
158impl VbusDetect for &SoftwareVbusDetect {
159 fn is_usb_detected(&self) -> bool {
160 self.usb_detected.load(Ordering::Relaxed)
161 }
162
163 async fn wait_power_ready(&mut self) -> Result<(), ()> {
164 poll_fn(move |cx| {
165 POWER_WAKER.register(cx.waker());
166
167 if self.power_ready.load(Ordering::Relaxed) {
168 Poll::Ready(Ok(()))
169 } else if !self.usb_detected.load(Ordering::Relaxed) {
170 Poll::Ready(Err(()))
171 } else {
172 Poll::Pending
173 }
174 })
175 .await
176 }
177}
diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml
index cfdda076e..cc88d92c7 100644
--- a/examples/nrf52840/Cargo.toml
+++ b/examples/nrf52840/Cargo.toml
@@ -6,7 +6,6 @@ license = "MIT OR Apache-2.0"
6 6
7[features] 7[features]
8default = ["nightly"] 8default = ["nightly"]
9msos-descriptor = ["embassy-usb/msos-descriptor"]
10nightly = ["embassy-executor/nightly", "embassy-nrf/nightly", "embassy-net/nightly", "embassy-nrf/unstable-traits", "embassy-usb", "embedded-io/async", "embassy-net", 9nightly = ["embassy-executor/nightly", "embassy-nrf/nightly", "embassy-net/nightly", "embassy-nrf/unstable-traits", "embassy-usb", "embedded-io/async", "embassy-net",
11 "embassy-lora", "lorawan-device", "lorawan"] 10 "embassy-lora", "lorawan-device", "lorawan"]
12 11
@@ -17,7 +16,7 @@ embassy-executor = { version = "0.1.0", path = "../../embassy-executor", feature
17embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 16embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
18embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } 17embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
19embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"], optional = true } 18embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"], optional = true }
20embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"], optional = true } 19embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt", "msos-descriptor",], optional = true }
21embedded-io = "0.4.0" 20embedded-io = "0.4.0"
22embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx126x", "time", "defmt"], optional = true } 21embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx126x", "time", "defmt"], optional = true }
23 22
@@ -36,7 +35,3 @@ rand = { version = "0.8.4", default-features = false }
36embedded-storage = "0.3.0" 35embedded-storage = "0.3.0"
37usbd-hid = "0.6.0" 36usbd-hid = "0.6.0"
38serde = { version = "1.0.136", default-features = false } 37serde = { version = "1.0.136", default-features = false }
39
40[[bin]]
41name = "usb_serial_winusb"
42required-features = ["msos-descriptor"]
diff --git a/examples/nrf52840/src/bin/awaitable_timer.rs b/examples/nrf52840/src/bin/awaitable_timer.rs
deleted file mode 100644
index b32af236c..000000000
--- a/examples/nrf52840/src/bin/awaitable_timer.rs
+++ /dev/null
@@ -1,26 +0,0 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::info;
6use embassy_executor::Spawner;
7use embassy_nrf::interrupt;
8use embassy_nrf::timer::Timer;
9use {defmt_rtt as _, panic_probe as _};
10
11#[embassy_executor::main]
12async fn main(_spawner: Spawner) {
13 let p = embassy_nrf::init(Default::default());
14 let mut t = Timer::new_awaitable(p.TIMER0, interrupt::take!(TIMER0));
15 // default frequency is 1MHz, so this triggers every second
16 t.cc(0).write(1_000_000);
17 // clear the timer value on cc[0] compare match
18 t.cc(0).short_compare_clear();
19 t.start();
20
21 loop {
22 // wait for compare match
23 t.cc(0).wait().await;
24 info!("hardware timer tick");
25 }
26}
diff --git a/examples/nrf52840/src/bin/buffered_uart.rs b/examples/nrf52840/src/bin/buffered_uart.rs
index 5b934b7d6..238695371 100644
--- a/examples/nrf52840/src/bin/buffered_uart.rs
+++ b/examples/nrf52840/src/bin/buffered_uart.rs
@@ -4,11 +4,15 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::buffered_uarte::BufferedUarte; 7use embassy_nrf::buffered_uarte::{self, BufferedUarte};
8use embassy_nrf::{interrupt, uarte}; 8use embassy_nrf::{bind_interrupts, peripherals, uarte};
9use embedded_io::asynch::Write; 9use embedded_io::asynch::Write;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12bind_interrupts!(struct Irqs {
13 UARTE0_UART0 => buffered_uarte::InterruptHandler<peripherals::UARTE0>;
14});
15
12#[embassy_executor::main] 16#[embassy_executor::main]
13async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
14 let p = embassy_nrf::init(Default::default()); 18 let p = embassy_nrf::init(Default::default());
@@ -19,14 +23,13 @@ async fn main(_spawner: Spawner) {
19 let mut tx_buffer = [0u8; 4096]; 23 let mut tx_buffer = [0u8; 4096];
20 let mut rx_buffer = [0u8; 4096]; 24 let mut rx_buffer = [0u8; 4096];
21 25
22 let irq = interrupt::take!(UARTE0_UART0);
23 let mut u = BufferedUarte::new( 26 let mut u = BufferedUarte::new(
24 p.UARTE0, 27 p.UARTE0,
25 p.TIMER0, 28 p.TIMER0,
26 p.PPI_CH0, 29 p.PPI_CH0,
27 p.PPI_CH1, 30 p.PPI_CH1,
28 p.PPI_GROUP0, 31 p.PPI_GROUP0,
29 irq, 32 Irqs,
30 p.P0_08, 33 p.P0_08,
31 p.P0_06, 34 p.P0_06,
32 config, 35 config,
diff --git a/examples/nrf52840/src/bin/i2s_effect.rs b/examples/nrf52840/src/bin/i2s_effect.rs
index 52d46e4f9..391514d93 100644
--- a/examples/nrf52840/src/bin/i2s_effect.rs
+++ b/examples/nrf52840/src/bin/i2s_effect.rs
@@ -7,7 +7,7 @@ use core::f32::consts::PI;
7use defmt::{error, info}; 7use defmt::{error, info};
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_nrf::i2s::{self, Channels, Config, MasterClock, MultiBuffering, Sample as _, SampleWidth, I2S}; 9use embassy_nrf::i2s::{self, Channels, Config, MasterClock, MultiBuffering, Sample as _, SampleWidth, I2S};
10use embassy_nrf::interrupt; 10use embassy_nrf::{bind_interrupts, peripherals};
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13type Sample = i16; 13type Sample = i16;
@@ -15,6 +15,10 @@ type Sample = i16;
15const NUM_BUFFERS: usize = 2; 15const NUM_BUFFERS: usize = 2;
16const NUM_SAMPLES: usize = 4; 16const NUM_SAMPLES: usize = 4;
17 17
18bind_interrupts!(struct Irqs {
19 I2S => i2s::InterruptHandler<peripherals::I2S>;
20});
21
18#[embassy_executor::main] 22#[embassy_executor::main]
19async fn main(_spawner: Spawner) { 23async fn main(_spawner: Spawner) {
20 let p = embassy_nrf::init(Default::default()); 24 let p = embassy_nrf::init(Default::default());
@@ -28,15 +32,10 @@ async fn main(_spawner: Spawner) {
28 config.sample_width = SampleWidth::_16bit; 32 config.sample_width = SampleWidth::_16bit;
29 config.channels = Channels::MonoLeft; 33 config.channels = Channels::MonoLeft;
30 34
31 let irq = interrupt::take!(I2S);
32 let buffers_out = MultiBuffering::<Sample, NUM_BUFFERS, NUM_SAMPLES>::new(); 35 let buffers_out = MultiBuffering::<Sample, NUM_BUFFERS, NUM_SAMPLES>::new();
33 let buffers_in = MultiBuffering::<Sample, NUM_BUFFERS, NUM_SAMPLES>::new(); 36 let buffers_in = MultiBuffering::<Sample, NUM_BUFFERS, NUM_SAMPLES>::new();
34 let mut full_duplex_stream = I2S::master(p.I2S, irq, p.P0_25, p.P0_26, p.P0_27, master_clock, config).full_duplex( 37 let mut full_duplex_stream = I2S::new_master(p.I2S, Irqs, p.P0_25, p.P0_26, p.P0_27, master_clock, config)
35 p.P0_29, 38 .full_duplex(p.P0_29, p.P0_28, buffers_out, buffers_in);
36 p.P0_28,
37 buffers_out,
38 buffers_in,
39 );
40 39
41 let mut modulator = SineOsc::new(); 40 let mut modulator = SineOsc::new();
42 modulator.set_frequency(8.0, 1.0 / sample_rate as f32); 41 modulator.set_frequency(8.0, 1.0 / sample_rate as f32);
diff --git a/examples/nrf52840/src/bin/i2s_monitor.rs b/examples/nrf52840/src/bin/i2s_monitor.rs
index 5ebfd9542..4ed597c0d 100644
--- a/examples/nrf52840/src/bin/i2s_monitor.rs
+++ b/examples/nrf52840/src/bin/i2s_monitor.rs
@@ -5,14 +5,18 @@
5use defmt::{debug, error, info}; 5use defmt::{debug, error, info};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, MasterClock, Sample as _, SampleWidth, I2S}; 7use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, MasterClock, Sample as _, SampleWidth, I2S};
8use embassy_nrf::interrupt;
9use embassy_nrf::pwm::{Prescaler, SimplePwm}; 8use embassy_nrf::pwm::{Prescaler, SimplePwm};
9use embassy_nrf::{bind_interrupts, peripherals};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12type Sample = i16; 12type Sample = i16;
13 13
14const NUM_SAMPLES: usize = 500; 14const NUM_SAMPLES: usize = 500;
15 15
16bind_interrupts!(struct Irqs {
17 I2S => i2s::InterruptHandler<peripherals::I2S>;
18});
19
16#[embassy_executor::main] 20#[embassy_executor::main]
17async fn main(_spawner: Spawner) { 21async fn main(_spawner: Spawner) {
18 let p = embassy_nrf::init(Default::default()); 22 let p = embassy_nrf::init(Default::default());
@@ -26,10 +30,9 @@ async fn main(_spawner: Spawner) {
26 config.sample_width = SampleWidth::_16bit; 30 config.sample_width = SampleWidth::_16bit;
27 config.channels = Channels::MonoLeft; 31 config.channels = Channels::MonoLeft;
28 32
29 let irq = interrupt::take!(I2S);
30 let buffers = DoubleBuffering::<Sample, NUM_SAMPLES>::new(); 33 let buffers = DoubleBuffering::<Sample, NUM_SAMPLES>::new();
31 let mut input_stream = 34 let mut input_stream =
32 I2S::master(p.I2S, irq, p.P0_25, p.P0_26, p.P0_27, master_clock, config).input(p.P0_29, buffers); 35 I2S::new_master(p.I2S, Irqs, p.P0_25, p.P0_26, p.P0_27, master_clock, config).input(p.P0_29, buffers);
33 36
34 // Configure the PWM to use the pins corresponding to the RGB leds 37 // Configure the PWM to use the pins corresponding to the RGB leds
35 let mut pwm = SimplePwm::new_3ch(p.PWM0, p.P0_23, p.P0_22, p.P0_24); 38 let mut pwm = SimplePwm::new_3ch(p.PWM0, p.P0_23, p.P0_22, p.P0_24);
diff --git a/examples/nrf52840/src/bin/i2s_waveform.rs b/examples/nrf52840/src/bin/i2s_waveform.rs
index eda930677..f2c1166b1 100644
--- a/examples/nrf52840/src/bin/i2s_waveform.rs
+++ b/examples/nrf52840/src/bin/i2s_waveform.rs
@@ -7,13 +7,17 @@ use core::f32::consts::PI;
7use defmt::{error, info}; 7use defmt::{error, info};
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, MasterClock, Sample as _, SampleWidth, I2S}; 9use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, MasterClock, Sample as _, SampleWidth, I2S};
10use embassy_nrf::interrupt; 10use embassy_nrf::{bind_interrupts, peripherals};
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13type Sample = i16; 13type Sample = i16;
14 14
15const NUM_SAMPLES: usize = 50; 15const NUM_SAMPLES: usize = 50;
16 16
17bind_interrupts!(struct Irqs {
18 I2S => i2s::InterruptHandler<peripherals::I2S>;
19});
20
17#[embassy_executor::main] 21#[embassy_executor::main]
18async fn main(_spawner: Spawner) { 22async fn main(_spawner: Spawner) {
19 let p = embassy_nrf::init(Default::default()); 23 let p = embassy_nrf::init(Default::default());
@@ -27,10 +31,9 @@ async fn main(_spawner: Spawner) {
27 config.sample_width = SampleWidth::_16bit; 31 config.sample_width = SampleWidth::_16bit;
28 config.channels = Channels::MonoLeft; 32 config.channels = Channels::MonoLeft;
29 33
30 let irq = interrupt::take!(I2S);
31 let buffers = DoubleBuffering::<Sample, NUM_SAMPLES>::new(); 34 let buffers = DoubleBuffering::<Sample, NUM_SAMPLES>::new();
32 let mut output_stream = 35 let mut output_stream =
33 I2S::master(p.I2S, irq, p.P0_25, p.P0_26, p.P0_27, master_clock, config).output(p.P0_28, buffers); 36 I2S::new_master(p.I2S, Irqs, p.P0_25, p.P0_26, p.P0_27, master_clock, config).output(p.P0_28, buffers);
34 37
35 let mut waveform = Waveform::new(1.0 / sample_rate as f32); 38 let mut waveform = Waveform::new(1.0 / sample_rate as f32);
36 39
diff --git a/examples/nrf52840/src/bin/lora_p2p_report.rs b/examples/nrf52840/src/bin/lora_p2p_report.rs
index d512b83f6..e24f0db03 100644
--- a/examples/nrf52840/src/bin/lora_p2p_report.rs
+++ b/examples/nrf52840/src/bin/lora_p2p_report.rs
@@ -11,11 +11,15 @@ use defmt::*;
11use embassy_executor::Spawner; 11use embassy_executor::Spawner;
12use embassy_lora::sx126x::*; 12use embassy_lora::sx126x::*;
13use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull}; 13use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull};
14use embassy_nrf::{interrupt, spim}; 14use embassy_nrf::{bind_interrupts, peripherals, spim};
15use embassy_time::{Duration, Timer}; 15use embassy_time::{Duration, Timer};
16use lorawan_device::async_device::radio::{Bandwidth, CodingRate, PhyRxTx, RfConfig, SpreadingFactor}; 16use lorawan_device::async_device::radio::{Bandwidth, CodingRate, PhyRxTx, RfConfig, SpreadingFactor};
17use {defmt_rtt as _, panic_probe as _}; 17use {defmt_rtt as _, panic_probe as _};
18 18
19bind_interrupts!(struct Irqs {
20 SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 => spim::InterruptHandler<peripherals::TWISPI1>;
21});
22
19#[embassy_executor::main] 23#[embassy_executor::main]
20async fn main(_spawner: Spawner) { 24async fn main(_spawner: Spawner) {
21 let p = embassy_nrf::init(Default::default()); 25 let p = embassy_nrf::init(Default::default());
@@ -23,8 +27,7 @@ async fn main(_spawner: Spawner) {
23 spi_config.frequency = spim::Frequency::M16; 27 spi_config.frequency = spim::Frequency::M16;
24 28
25 let mut radio = { 29 let mut radio = {
26 let irq = interrupt::take!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); 30 let spim = spim::Spim::new(p.TWISPI1, Irqs, p.P1_11, p.P1_13, p.P1_12, spi_config);
27 let spim = spim::Spim::new(p.TWISPI1, irq, p.P1_11, p.P1_13, p.P1_12, spi_config);
28 31
29 let cs = Output::new(p.P1_10.degrade(), Level::High, OutputDrive::Standard); 32 let cs = Output::new(p.P1_10.degrade(), Level::High, OutputDrive::Standard);
30 let reset = Output::new(p.P1_06.degrade(), Level::High, OutputDrive::Standard); 33 let reset = Output::new(p.P1_06.degrade(), Level::High, OutputDrive::Standard);
diff --git a/examples/nrf52840/src/bin/lora_p2p_sense.rs b/examples/nrf52840/src/bin/lora_p2p_sense.rs
index b9768874b..b6f41ffcc 100644
--- a/examples/nrf52840/src/bin/lora_p2p_sense.rs
+++ b/examples/nrf52840/src/bin/lora_p2p_sense.rs
@@ -12,13 +12,17 @@ use defmt::*;
12use embassy_executor::Spawner; 12use embassy_executor::Spawner;
13use embassy_lora::sx126x::*; 13use embassy_lora::sx126x::*;
14use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull}; 14use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull};
15use embassy_nrf::{interrupt, spim}; 15use embassy_nrf::{bind_interrupts, peripherals, spim};
16use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 16use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
17use embassy_sync::pubsub::{PubSubChannel, Publisher}; 17use embassy_sync::pubsub::{PubSubChannel, Publisher};
18use embassy_time::{Duration, Timer}; 18use embassy_time::{Duration, Timer};
19use lorawan_device::async_device::radio::{Bandwidth, CodingRate, PhyRxTx, RfConfig, SpreadingFactor, TxConfig}; 19use lorawan_device::async_device::radio::{Bandwidth, CodingRate, PhyRxTx, RfConfig, SpreadingFactor, TxConfig};
20use {defmt_rtt as _, panic_probe as _, panic_probe as _}; 20use {defmt_rtt as _, panic_probe as _, panic_probe as _};
21 21
22bind_interrupts!(struct Irqs {
23 SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 => spim::InterruptHandler<peripherals::TWISPI1>;
24});
25
22// Message bus: queue of 2, 1 subscriber (Lora P2P), 2 publishers (temperature, motion detection) 26// Message bus: queue of 2, 1 subscriber (Lora P2P), 2 publishers (temperature, motion detection)
23static MESSAGE_BUS: PubSubChannel<CriticalSectionRawMutex, Message, 2, 1, 2> = PubSubChannel::new(); 27static MESSAGE_BUS: PubSubChannel<CriticalSectionRawMutex, Message, 2, 1, 2> = PubSubChannel::new();
24 28
@@ -58,8 +62,7 @@ async fn main(spawner: Spawner) {
58 spi_config.frequency = spim::Frequency::M16; 62 spi_config.frequency = spim::Frequency::M16;
59 63
60 let mut radio = { 64 let mut radio = {
61 let irq = interrupt::take!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); 65 let spim = spim::Spim::new(p.TWISPI1, Irqs, p.P1_11, p.P1_13, p.P1_12, spi_config);
62 let spim = spim::Spim::new(p.TWISPI1, irq, p.P1_11, p.P1_13, p.P1_12, spi_config);
63 66
64 let cs = Output::new(p.P1_10.degrade(), Level::High, OutputDrive::Standard); 67 let cs = Output::new(p.P1_10.degrade(), Level::High, OutputDrive::Standard);
65 let reset = Output::new(p.P1_06.degrade(), Level::High, OutputDrive::Standard); 68 let reset = Output::new(p.P1_06.degrade(), Level::High, OutputDrive::Standard);
diff --git a/examples/nrf52840/src/bin/pdm.rs b/examples/nrf52840/src/bin/pdm.rs
index 7388580fb..6b41320ca 100644
--- a/examples/nrf52840/src/bin/pdm.rs
+++ b/examples/nrf52840/src/bin/pdm.rs
@@ -4,16 +4,20 @@
4 4
5use defmt::info; 5use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::interrupt; 7use embassy_nrf::pdm::{self, Config, Pdm};
8use embassy_nrf::pdm::{Config, Pdm}; 8use embassy_nrf::{bind_interrupts, peripherals};
9use embassy_time::{Duration, Timer}; 9use embassy_time::{Duration, Timer};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12bind_interrupts!(struct Irqs {
13 PDM => pdm::InterruptHandler<peripherals::PDM>;
14});
15
12#[embassy_executor::main] 16#[embassy_executor::main]
13async fn main(_p: Spawner) { 17async fn main(_p: Spawner) {
14 let p = embassy_nrf::init(Default::default()); 18 let p = embassy_nrf::init(Default::default());
15 let config = Config::default(); 19 let config = Config::default();
16 let mut pdm = Pdm::new(p.PDM, interrupt::take!(PDM), p.P0_01, p.P0_00, config); 20 let mut pdm = Pdm::new(p.PDM, Irqs, p.P0_01, p.P0_00, config);
17 21
18 loop { 22 loop {
19 pdm.start().await; 23 pdm.start().await;
diff --git a/examples/nrf52840/src/bin/qdec.rs b/examples/nrf52840/src/bin/qdec.rs
index 600bba07a..59783d312 100644
--- a/examples/nrf52840/src/bin/qdec.rs
+++ b/examples/nrf52840/src/bin/qdec.rs
@@ -4,16 +4,19 @@
4 4
5use defmt::info; 5use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::interrupt;
8use embassy_nrf::qdec::{self, Qdec}; 7use embassy_nrf::qdec::{self, Qdec};
8use embassy_nrf::{bind_interrupts, peripherals};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11bind_interrupts!(struct Irqs {
12 QDEC => qdec::InterruptHandler<peripherals::QDEC>;
13});
14
11#[embassy_executor::main] 15#[embassy_executor::main]
12async fn main(_spawner: Spawner) { 16async fn main(_spawner: Spawner) {
13 let p = embassy_nrf::init(Default::default()); 17 let p = embassy_nrf::init(Default::default());
14 let irq = interrupt::take!(QDEC);
15 let config = qdec::Config::default(); 18 let config = qdec::Config::default();
16 let mut rotary_enc = Qdec::new(p.QDEC, irq, p.P0_31, p.P0_30, config); 19 let mut rotary_enc = Qdec::new(p.QDEC, Irqs, p.P0_31, p.P0_30, config);
17 20
18 info!("Turn rotary encoder!"); 21 info!("Turn rotary encoder!");
19 let mut value = 0; 22 let mut value = 0;
diff --git a/examples/nrf52840/src/bin/qspi.rs b/examples/nrf52840/src/bin/qspi.rs
index 21a10940d..9e8a01f4e 100644
--- a/examples/nrf52840/src/bin/qspi.rs
+++ b/examples/nrf52840/src/bin/qspi.rs
@@ -5,7 +5,7 @@
5use defmt::{assert_eq, info, unwrap}; 5use defmt::{assert_eq, info, unwrap};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::qspi::Frequency; 7use embassy_nrf::qspi::Frequency;
8use embassy_nrf::{interrupt, qspi}; 8use embassy_nrf::{bind_interrupts, peripherals, qspi};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11const PAGE_SIZE: usize = 4096; 11const PAGE_SIZE: usize = 4096;
@@ -15,6 +15,10 @@ const PAGE_SIZE: usize = 4096;
15#[repr(C, align(4))] 15#[repr(C, align(4))]
16struct AlignedBuf([u8; 4096]); 16struct AlignedBuf([u8; 4096]);
17 17
18bind_interrupts!(struct Irqs {
19 QSPI => qspi::InterruptHandler<peripherals::QSPI>;
20});
21
18#[embassy_executor::main] 22#[embassy_executor::main]
19async fn main(_spawner: Spawner) { 23async fn main(_spawner: Spawner) {
20 let p = embassy_nrf::init(Default::default()); 24 let p = embassy_nrf::init(Default::default());
@@ -26,9 +30,8 @@ async fn main(_spawner: Spawner) {
26 config.write_opcode = qspi::WriteOpcode::PP4IO; 30 config.write_opcode = qspi::WriteOpcode::PP4IO;
27 config.write_page_size = qspi::WritePageSize::_256BYTES; 31 config.write_page_size = qspi::WritePageSize::_256BYTES;
28 32
29 let irq = interrupt::take!(QSPI);
30 let mut q = qspi::Qspi::new( 33 let mut q = qspi::Qspi::new(
31 p.QSPI, irq, p.P0_19, p.P0_17, p.P0_20, p.P0_21, p.P0_22, p.P0_23, config, 34 p.QSPI, Irqs, p.P0_19, p.P0_17, p.P0_20, p.P0_21, p.P0_22, p.P0_23, config,
32 ); 35 );
33 36
34 let mut id = [1; 3]; 37 let mut id = [1; 3];
diff --git a/examples/nrf52840/src/bin/qspi_lowpower.rs b/examples/nrf52840/src/bin/qspi_lowpower.rs
index 20c903914..22a5c0c6d 100644
--- a/examples/nrf52840/src/bin/qspi_lowpower.rs
+++ b/examples/nrf52840/src/bin/qspi_lowpower.rs
@@ -7,7 +7,7 @@ use core::mem;
7use defmt::{info, unwrap}; 7use defmt::{info, unwrap};
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_nrf::qspi::Frequency; 9use embassy_nrf::qspi::Frequency;
10use embassy_nrf::{interrupt, qspi}; 10use embassy_nrf::{bind_interrupts, peripherals, qspi};
11use embassy_time::{Duration, Timer}; 11use embassy_time::{Duration, Timer};
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
@@ -16,10 +16,13 @@ use {defmt_rtt as _, panic_probe as _};
16#[repr(C, align(4))] 16#[repr(C, align(4))]
17struct AlignedBuf([u8; 64]); 17struct AlignedBuf([u8; 64]);
18 18
19bind_interrupts!(struct Irqs {
20 QSPI => qspi::InterruptHandler<peripherals::QSPI>;
21});
22
19#[embassy_executor::main] 23#[embassy_executor::main]
20async fn main(_p: Spawner) { 24async fn main(_p: Spawner) {
21 let mut p = embassy_nrf::init(Default::default()); 25 let mut p = embassy_nrf::init(Default::default());
22 let mut irq = interrupt::take!(QSPI);
23 26
24 loop { 27 loop {
25 // Config for the MX25R64 present in the nRF52840 DK 28 // Config for the MX25R64 present in the nRF52840 DK
@@ -36,7 +39,7 @@ async fn main(_p: Spawner) {
36 39
37 let mut q = qspi::Qspi::new( 40 let mut q = qspi::Qspi::new(
38 &mut p.QSPI, 41 &mut p.QSPI,
39 &mut irq, 42 Irqs,
40 &mut p.P0_19, 43 &mut p.P0_19,
41 &mut p.P0_17, 44 &mut p.P0_17,
42 &mut p.P0_20, 45 &mut p.P0_20,
diff --git a/examples/nrf52840/src/bin/rng.rs b/examples/nrf52840/src/bin/rng.rs
index 647073949..855743f50 100644
--- a/examples/nrf52840/src/bin/rng.rs
+++ b/examples/nrf52840/src/bin/rng.rs
@@ -3,15 +3,19 @@
3#![feature(type_alias_impl_trait)] 3#![feature(type_alias_impl_trait)]
4 4
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_nrf::interrupt;
7use embassy_nrf::rng::Rng; 6use embassy_nrf::rng::Rng;
7use embassy_nrf::{bind_interrupts, peripherals, rng};
8use rand::Rng as _; 8use rand::Rng as _;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11bind_interrupts!(struct Irqs {
12 RNG => rng::InterruptHandler<peripherals::RNG>;
13});
14
11#[embassy_executor::main] 15#[embassy_executor::main]
12async fn main(_spawner: Spawner) { 16async fn main(_spawner: Spawner) {
13 let p = embassy_nrf::init(Default::default()); 17 let p = embassy_nrf::init(Default::default());
14 let mut rng = Rng::new(p.RNG, interrupt::take!(RNG)); 18 let mut rng = Rng::new(p.RNG, Irqs);
15 19
16 // Async API 20 // Async API
17 let mut bytes = [0; 4]; 21 let mut bytes = [0; 4];
diff --git a/examples/nrf52840/src/bin/saadc.rs b/examples/nrf52840/src/bin/saadc.rs
index 7cf588090..ffd9a7f4b 100644
--- a/examples/nrf52840/src/bin/saadc.rs
+++ b/examples/nrf52840/src/bin/saadc.rs
@@ -4,17 +4,21 @@
4 4
5use defmt::info; 5use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::interrupt;
8use embassy_nrf::saadc::{ChannelConfig, Config, Saadc}; 7use embassy_nrf::saadc::{ChannelConfig, Config, Saadc};
8use embassy_nrf::{bind_interrupts, saadc};
9use embassy_time::{Duration, Timer}; 9use embassy_time::{Duration, Timer};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12bind_interrupts!(struct Irqs {
13 SAADC => saadc::InterruptHandler;
14});
15
12#[embassy_executor::main] 16#[embassy_executor::main]
13async fn main(_p: Spawner) { 17async fn main(_p: Spawner) {
14 let mut p = embassy_nrf::init(Default::default()); 18 let mut p = embassy_nrf::init(Default::default());
15 let config = Config::default(); 19 let config = Config::default();
16 let channel_config = ChannelConfig::single_ended(&mut p.P0_02); 20 let channel_config = ChannelConfig::single_ended(&mut p.P0_02);
17 let mut saadc = Saadc::new(p.SAADC, interrupt::take!(SAADC), config, [channel_config]); 21 let mut saadc = Saadc::new(p.SAADC, Irqs, config, [channel_config]);
18 22
19 loop { 23 loop {
20 let mut buf = [0; 1]; 24 let mut buf = [0; 1];
diff --git a/examples/nrf52840/src/bin/saadc_continuous.rs b/examples/nrf52840/src/bin/saadc_continuous.rs
index 2551d15fd..a25e17465 100644
--- a/examples/nrf52840/src/bin/saadc_continuous.rs
+++ b/examples/nrf52840/src/bin/saadc_continuous.rs
@@ -4,14 +4,18 @@
4 4
5use defmt::info; 5use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::interrupt;
8use embassy_nrf::saadc::{CallbackResult, ChannelConfig, Config, Saadc}; 7use embassy_nrf::saadc::{CallbackResult, ChannelConfig, Config, Saadc};
9use embassy_nrf::timer::Frequency; 8use embassy_nrf::timer::Frequency;
9use embassy_nrf::{bind_interrupts, saadc};
10use embassy_time::Duration; 10use embassy_time::Duration;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13// Demonstrates both continuous sampling and scanning multiple channels driven by a PPI linked timer 13// Demonstrates both continuous sampling and scanning multiple channels driven by a PPI linked timer
14 14
15bind_interrupts!(struct Irqs {
16 SAADC => saadc::InterruptHandler;
17});
18
15#[embassy_executor::main] 19#[embassy_executor::main]
16async fn main(_p: Spawner) { 20async fn main(_p: Spawner) {
17 let mut p = embassy_nrf::init(Default::default()); 21 let mut p = embassy_nrf::init(Default::default());
@@ -21,7 +25,7 @@ async fn main(_p: Spawner) {
21 let channel_3_config = ChannelConfig::single_ended(&mut p.P0_04); 25 let channel_3_config = ChannelConfig::single_ended(&mut p.P0_04);
22 let mut saadc = Saadc::new( 26 let mut saadc = Saadc::new(
23 p.SAADC, 27 p.SAADC,
24 interrupt::take!(SAADC), 28 Irqs,
25 config, 29 config,
26 [channel_1_config, channel_2_config, channel_3_config], 30 [channel_1_config, channel_2_config, channel_3_config],
27 ); 31 );
diff --git a/examples/nrf52840/src/bin/spim.rs b/examples/nrf52840/src/bin/spim.rs
index 132e01660..9d1843a8f 100644
--- a/examples/nrf52840/src/bin/spim.rs
+++ b/examples/nrf52840/src/bin/spim.rs
@@ -5,9 +5,13 @@
5use defmt::{info, unwrap}; 5use defmt::{info, unwrap};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::gpio::{Level, Output, OutputDrive}; 7use embassy_nrf::gpio::{Level, Output, OutputDrive};
8use embassy_nrf::{interrupt, spim}; 8use embassy_nrf::{bind_interrupts, peripherals, spim};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11bind_interrupts!(struct Irqs {
12 SPIM3 => spim::InterruptHandler<peripherals::SPI3>;
13});
14
11#[embassy_executor::main] 15#[embassy_executor::main]
12async fn main(_spawner: Spawner) { 16async fn main(_spawner: Spawner) {
13 let p = embassy_nrf::init(Default::default()); 17 let p = embassy_nrf::init(Default::default());
@@ -16,8 +20,7 @@ async fn main(_spawner: Spawner) {
16 let mut config = spim::Config::default(); 20 let mut config = spim::Config::default();
17 config.frequency = spim::Frequency::M16; 21 config.frequency = spim::Frequency::M16;
18 22
19 let irq = interrupt::take!(SPIM3); 23 let mut spim = spim::Spim::new(p.SPI3, Irqs, p.P0_29, p.P0_28, p.P0_30, config);
20 let mut spim = spim::Spim::new(p.SPI3, irq, p.P0_29, p.P0_28, p.P0_30, config);
21 24
22 let mut ncs = Output::new(p.P0_31, Level::High, OutputDrive::Standard); 25 let mut ncs = Output::new(p.P0_31, Level::High, OutputDrive::Standard);
23 26
diff --git a/examples/nrf52840/src/bin/spis.rs b/examples/nrf52840/src/bin/spis.rs
index fe3b0c53d..77b6e8b64 100644
--- a/examples/nrf52840/src/bin/spis.rs
+++ b/examples/nrf52840/src/bin/spis.rs
@@ -4,17 +4,20 @@
4 4
5use defmt::info; 5use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::interrupt;
8use embassy_nrf::spis::{Config, Spis}; 7use embassy_nrf::spis::{Config, Spis};
8use embassy_nrf::{bind_interrupts, peripherals, spis};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11bind_interrupts!(struct Irqs {
12 SPIM2_SPIS2_SPI2 => spis::InterruptHandler<peripherals::SPI2>;
13});
14
11#[embassy_executor::main] 15#[embassy_executor::main]
12async fn main(_spawner: Spawner) { 16async fn main(_spawner: Spawner) {
13 let p = embassy_nrf::init(Default::default()); 17 let p = embassy_nrf::init(Default::default());
14 info!("Running!"); 18 info!("Running!");
15 19
16 let irq = interrupt::take!(SPIM2_SPIS2_SPI2); 20 let mut spis = Spis::new(p.SPI2, Irqs, p.P0_31, p.P0_29, p.P0_28, p.P0_30, Config::default());
17 let mut spis = Spis::new(p.SPI2, irq, p.P0_31, p.P0_29, p.P0_28, p.P0_30, Config::default());
18 21
19 loop { 22 loop {
20 let mut rx_buf = [0_u8; 64]; 23 let mut rx_buf = [0_u8; 64];
diff --git a/examples/nrf52840/src/bin/temp.rs b/examples/nrf52840/src/bin/temp.rs
index b06ac709e..70957548f 100644
--- a/examples/nrf52840/src/bin/temp.rs
+++ b/examples/nrf52840/src/bin/temp.rs
@@ -4,16 +4,19 @@
4 4
5use defmt::info; 5use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::interrupt;
8use embassy_nrf::temp::Temp; 7use embassy_nrf::temp::Temp;
8use embassy_nrf::{bind_interrupts, temp};
9use embassy_time::{Duration, Timer}; 9use embassy_time::{Duration, Timer};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12bind_interrupts!(struct Irqs {
13 TEMP => temp::InterruptHandler;
14});
15
12#[embassy_executor::main] 16#[embassy_executor::main]
13async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
14 let p = embassy_nrf::init(Default::default()); 18 let p = embassy_nrf::init(Default::default());
15 let irq = interrupt::take!(TEMP); 19 let mut temp = Temp::new(p.TEMP, Irqs);
16 let mut temp = Temp::new(p.TEMP, irq);
17 20
18 loop { 21 loop {
19 let value = temp.read().await; 22 let value = temp.read().await;
diff --git a/examples/nrf52840/src/bin/twim.rs b/examples/nrf52840/src/bin/twim.rs
index a027cc1e7..959e3a4be 100644
--- a/examples/nrf52840/src/bin/twim.rs
+++ b/examples/nrf52840/src/bin/twim.rs
@@ -8,19 +8,22 @@
8 8
9use defmt::*; 9use defmt::*;
10use embassy_executor::Spawner; 10use embassy_executor::Spawner;
11use embassy_nrf::interrupt;
12use embassy_nrf::twim::{self, Twim}; 11use embassy_nrf::twim::{self, Twim};
12use embassy_nrf::{bind_interrupts, peripherals};
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15const ADDRESS: u8 = 0x50; 15const ADDRESS: u8 = 0x50;
16 16
17bind_interrupts!(struct Irqs {
18 SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0 => twim::InterruptHandler<peripherals::TWISPI0>;
19});
20
17#[embassy_executor::main] 21#[embassy_executor::main]
18async fn main(_spawner: Spawner) { 22async fn main(_spawner: Spawner) {
19 let p = embassy_nrf::init(Default::default()); 23 let p = embassy_nrf::init(Default::default());
20 info!("Initializing TWI..."); 24 info!("Initializing TWI...");
21 let config = twim::Config::default(); 25 let config = twim::Config::default();
22 let irq = interrupt::take!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); 26 let mut twi = Twim::new(p.TWISPI0, Irqs, p.P0_03, p.P0_04, config);
23 let mut twi = Twim::new(p.TWISPI0, irq, p.P0_03, p.P0_04, config);
24 27
25 info!("Reading..."); 28 info!("Reading...");
26 29
diff --git a/examples/nrf52840/src/bin/twim_lowpower.rs b/examples/nrf52840/src/bin/twim_lowpower.rs
index e30cc9688..0970d3c3c 100644
--- a/examples/nrf52840/src/bin/twim_lowpower.rs
+++ b/examples/nrf52840/src/bin/twim_lowpower.rs
@@ -12,25 +12,28 @@ use core::mem;
12 12
13use defmt::*; 13use defmt::*;
14use embassy_executor::Spawner; 14use embassy_executor::Spawner;
15use embassy_nrf::interrupt;
16use embassy_nrf::twim::{self, Twim}; 15use embassy_nrf::twim::{self, Twim};
16use embassy_nrf::{bind_interrupts, peripherals};
17use embassy_time::{Duration, Timer}; 17use embassy_time::{Duration, Timer};
18use {defmt_rtt as _, panic_probe as _}; 18use {defmt_rtt as _, panic_probe as _};
19 19
20const ADDRESS: u8 = 0x50; 20const ADDRESS: u8 = 0x50;
21 21
22bind_interrupts!(struct Irqs {
23 SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0 => twim::InterruptHandler<peripherals::TWISPI0>;
24});
25
22#[embassy_executor::main] 26#[embassy_executor::main]
23async fn main(_p: Spawner) { 27async fn main(_p: Spawner) {
24 let mut p = embassy_nrf::init(Default::default()); 28 let mut p = embassy_nrf::init(Default::default());
25 info!("Started!"); 29 info!("Started!");
26 let mut irq = interrupt::take!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
27 30
28 loop { 31 loop {
29 info!("Initializing TWI..."); 32 info!("Initializing TWI...");
30 let config = twim::Config::default(); 33 let config = twim::Config::default();
31 34
32 // Create the TWIM instance with borrowed singletons, so they're not consumed. 35 // Create the TWIM instance with borrowed singletons, so they're not consumed.
33 let mut twi = Twim::new(&mut p.TWISPI0, &mut irq, &mut p.P0_03, &mut p.P0_04, config); 36 let mut twi = Twim::new(&mut p.TWISPI0, Irqs, &mut p.P0_03, &mut p.P0_04, config);
34 37
35 info!("Reading..."); 38 info!("Reading...");
36 39
diff --git a/examples/nrf52840/src/bin/twis.rs b/examples/nrf52840/src/bin/twis.rs
index 54cba9494..aa42b679e 100644
--- a/examples/nrf52840/src/bin/twis.rs
+++ b/examples/nrf52840/src/bin/twis.rs
@@ -6,19 +6,21 @@
6 6
7use defmt::*; 7use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_nrf::interrupt;
10use embassy_nrf::twis::{self, Command, Twis}; 9use embassy_nrf::twis::{self, Command, Twis};
10use embassy_nrf::{bind_interrupts, peripherals};
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13bind_interrupts!(struct Irqs {
14 SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0 => twis::InterruptHandler<peripherals::TWISPI0>;
15});
16
13#[embassy_executor::main] 17#[embassy_executor::main]
14async fn main(_spawner: Spawner) { 18async fn main(_spawner: Spawner) {
15 let p = embassy_nrf::init(Default::default()); 19 let p = embassy_nrf::init(Default::default());
16 20
17 let irq = interrupt::take!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
18 let mut config = twis::Config::default(); 21 let mut config = twis::Config::default();
19 // Set i2c address 22 config.address0 = 0x55; // Set i2c address
20 config.address0 = 0x55; 23 let mut i2c = Twis::new(p.TWISPI0, Irqs, p.P0_03, p.P0_04, config);
21 let mut i2c = Twis::new(p.TWISPI0, irq, p.P0_03, p.P0_04, config);
22 24
23 info!("Listening..."); 25 info!("Listening...");
24 loop { 26 loop {
diff --git a/examples/nrf52840/src/bin/uart.rs b/examples/nrf52840/src/bin/uart.rs
index 600f7a6ef..50d5cab8c 100644
--- a/examples/nrf52840/src/bin/uart.rs
+++ b/examples/nrf52840/src/bin/uart.rs
@@ -4,9 +4,13 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::{interrupt, uarte}; 7use embassy_nrf::{bind_interrupts, peripherals, uarte};
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
10bind_interrupts!(struct Irqs {
11 UARTE0_UART0 => uarte::InterruptHandler<peripherals::UARTE0>;
12});
13
10#[embassy_executor::main] 14#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 15async fn main(_spawner: Spawner) {
12 let p = embassy_nrf::init(Default::default()); 16 let p = embassy_nrf::init(Default::default());
@@ -14,8 +18,7 @@ async fn main(_spawner: Spawner) {
14 config.parity = uarte::Parity::EXCLUDED; 18 config.parity = uarte::Parity::EXCLUDED;
15 config.baudrate = uarte::Baudrate::BAUD115200; 19 config.baudrate = uarte::Baudrate::BAUD115200;
16 20
17 let irq = interrupt::take!(UARTE0_UART0); 21 let mut uart = uarte::Uarte::new(p.UARTE0, Irqs, p.P0_08, p.P0_06, config);
18 let mut uart = uarte::Uarte::new(p.UARTE0, irq, p.P0_08, p.P0_06, config);
19 22
20 info!("uarte initialized!"); 23 info!("uarte initialized!");
21 24
diff --git a/examples/nrf52840/src/bin/uart_idle.rs b/examples/nrf52840/src/bin/uart_idle.rs
index 6af4f7097..e1f42fa6c 100644
--- a/examples/nrf52840/src/bin/uart_idle.rs
+++ b/examples/nrf52840/src/bin/uart_idle.rs
@@ -4,9 +4,14 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::{interrupt, uarte}; 7use embassy_nrf::peripherals::UARTE0;
8use embassy_nrf::{bind_interrupts, uarte};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(struct Irqs {
12 UARTE0_UART0 => uarte::InterruptHandler<UARTE0>;
13});
14
10#[embassy_executor::main] 15#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 16async fn main(_spawner: Spawner) {
12 let p = embassy_nrf::init(Default::default()); 17 let p = embassy_nrf::init(Default::default());
@@ -14,8 +19,7 @@ async fn main(_spawner: Spawner) {
14 config.parity = uarte::Parity::EXCLUDED; 19 config.parity = uarte::Parity::EXCLUDED;
15 config.baudrate = uarte::Baudrate::BAUD115200; 20 config.baudrate = uarte::Baudrate::BAUD115200;
16 21
17 let irq = interrupt::take!(UARTE0_UART0); 22 let uart = uarte::Uarte::new(p.UARTE0, Irqs, p.P0_08, p.P0_06, config);
18 let uart = uarte::Uarte::new(p.UARTE0, irq, p.P0_08, p.P0_06, config);
19 let (mut tx, mut rx) = uart.split_with_idle(p.TIMER0, p.PPI_CH0, p.PPI_CH1); 23 let (mut tx, mut rx) = uart.split_with_idle(p.TIMER0, p.PPI_CH0, p.PPI_CH1);
20 24
21 info!("uarte initialized!"); 25 info!("uarte initialized!");
diff --git a/examples/nrf52840/src/bin/uart_split.rs b/examples/nrf52840/src/bin/uart_split.rs
index 1adaf53fd..9979a1d53 100644
--- a/examples/nrf52840/src/bin/uart_split.rs
+++ b/examples/nrf52840/src/bin/uart_split.rs
@@ -6,13 +6,17 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::peripherals::UARTE0; 7use embassy_nrf::peripherals::UARTE0;
8use embassy_nrf::uarte::UarteRx; 8use embassy_nrf::uarte::UarteRx;
9use embassy_nrf::{interrupt, uarte}; 9use embassy_nrf::{bind_interrupts, uarte};
10use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; 10use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
11use embassy_sync::channel::Channel; 11use embassy_sync::channel::Channel;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14static CHANNEL: Channel<ThreadModeRawMutex, [u8; 8], 1> = Channel::new(); 14static CHANNEL: Channel<ThreadModeRawMutex, [u8; 8], 1> = Channel::new();
15 15
16bind_interrupts!(struct Irqs {
17 UARTE0_UART0 => uarte::InterruptHandler<UARTE0>;
18});
19
16#[embassy_executor::main] 20#[embassy_executor::main]
17async fn main(spawner: Spawner) { 21async fn main(spawner: Spawner) {
18 let p = embassy_nrf::init(Default::default()); 22 let p = embassy_nrf::init(Default::default());
@@ -20,8 +24,7 @@ async fn main(spawner: Spawner) {
20 config.parity = uarte::Parity::EXCLUDED; 24 config.parity = uarte::Parity::EXCLUDED;
21 config.baudrate = uarte::Baudrate::BAUD115200; 25 config.baudrate = uarte::Baudrate::BAUD115200;
22 26
23 let irq = interrupt::take!(UARTE0_UART0); 27 let uart = uarte::Uarte::new(p.UARTE0, Irqs, p.P0_08, p.P0_06, config);
24 let uart = uarte::Uarte::new(p.UARTE0, irq, p.P0_08, p.P0_06, config);
25 let (mut tx, rx) = uart.split(); 28 let (mut tx, rx) = uart.split();
26 29
27 info!("uarte initialized!"); 30 info!("uarte initialized!");
diff --git a/examples/nrf52840/src/bin/usb_ethernet.rs b/examples/nrf52840/src/bin/usb_ethernet.rs
index 979780896..b8a72313a 100644
--- a/examples/nrf52840/src/bin/usb_ethernet.rs
+++ b/examples/nrf52840/src/bin/usb_ethernet.rs
@@ -9,8 +9,9 @@ use embassy_executor::Spawner;
9use embassy_net::tcp::TcpSocket; 9use embassy_net::tcp::TcpSocket;
10use embassy_net::{Stack, StackResources}; 10use embassy_net::{Stack, StackResources};
11use embassy_nrf::rng::Rng; 11use embassy_nrf::rng::Rng;
12use embassy_nrf::usb::{Driver, HardwareVbusDetect}; 12use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
13use embassy_nrf::{interrupt, pac, peripherals}; 13use embassy_nrf::usb::Driver;
14use embassy_nrf::{bind_interrupts, pac, peripherals, rng, usb};
14use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; 15use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState};
15use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; 16use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
16use embassy_usb::{Builder, Config, UsbDevice}; 17use embassy_usb::{Builder, Config, UsbDevice};
@@ -18,6 +19,12 @@ use embedded_io::asynch::Write;
18use static_cell::StaticCell; 19use static_cell::StaticCell;
19use {defmt_rtt as _, panic_probe as _}; 20use {defmt_rtt as _, panic_probe as _};
20 21
22bind_interrupts!(struct Irqs {
23 USBD => usb::InterruptHandler<peripherals::USBD>;
24 POWER_CLOCK => usb::vbus_detect::InterruptHandler;
25 RNG => rng::InterruptHandler<peripherals::RNG>;
26});
27
21type MyDriver = Driver<'static, peripherals::USBD, HardwareVbusDetect>; 28type MyDriver = Driver<'static, peripherals::USBD, HardwareVbusDetect>;
22 29
23macro_rules! singleton { 30macro_rules! singleton {
@@ -56,9 +63,7 @@ async fn main(spawner: Spawner) {
56 while clock.events_hfclkstarted.read().bits() != 1 {} 63 while clock.events_hfclkstarted.read().bits() != 1 {}
57 64
58 // Create the driver, from the HAL. 65 // Create the driver, from the HAL.
59 let irq = interrupt::take!(USBD); 66 let driver = Driver::new(p.USBD, Irqs, HardwareVbusDetect::new(Irqs));
60 let power_irq = interrupt::take!(POWER_CLOCK);
61 let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
62 67
63 // Create embassy-usb Config 68 // Create embassy-usb Config
64 let mut config = Config::new(0xc0de, 0xcafe); 69 let mut config = Config::new(0xc0de, 0xcafe);
@@ -82,6 +87,7 @@ async fn main(spawner: Spawner) {
82 &mut singleton!([0; 256])[..], 87 &mut singleton!([0; 256])[..],
83 &mut singleton!([0; 256])[..], 88 &mut singleton!([0; 256])[..],
84 &mut singleton!([0; 128])[..], 89 &mut singleton!([0; 128])[..],
90 &mut singleton!([0; 128])[..],
85 ); 91 );
86 92
87 // Our MAC addr. 93 // Our MAC addr.
@@ -108,7 +114,7 @@ async fn main(spawner: Spawner) {
108 //}); 114 //});
109 115
110 // Generate random seed 116 // Generate random seed
111 let mut rng = Rng::new(p.RNG, interrupt::take!(RNG)); 117 let mut rng = Rng::new(p.RNG, Irqs);
112 let mut seed = [0; 8]; 118 let mut seed = [0; 8];
113 rng.blocking_fill_bytes(&mut seed); 119 rng.blocking_fill_bytes(&mut seed);
114 let seed = u64::from_le_bytes(seed); 120 let seed = u64::from_le_bytes(seed);
diff --git a/examples/nrf52840/src/bin/usb_hid_keyboard.rs b/examples/nrf52840/src/bin/usb_hid_keyboard.rs
index 3d8a114cd..7ccd2946a 100644
--- a/examples/nrf52840/src/bin/usb_hid_keyboard.rs
+++ b/examples/nrf52840/src/bin/usb_hid_keyboard.rs
@@ -10,8 +10,9 @@ use embassy_executor::Spawner;
10use embassy_futures::join::join; 10use embassy_futures::join::join;
11use embassy_futures::select::{select, Either}; 11use embassy_futures::select::{select, Either};
12use embassy_nrf::gpio::{Input, Pin, Pull}; 12use embassy_nrf::gpio::{Input, Pin, Pull};
13use embassy_nrf::usb::{Driver, HardwareVbusDetect}; 13use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
14use embassy_nrf::{interrupt, pac}; 14use embassy_nrf::usb::Driver;
15use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
15use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 16use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
16use embassy_sync::signal::Signal; 17use embassy_sync::signal::Signal;
17use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; 18use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State};
@@ -20,6 +21,11 @@ use embassy_usb::{Builder, Config, Handler};
20use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; 21use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
21use {defmt_rtt as _, panic_probe as _}; 22use {defmt_rtt as _, panic_probe as _};
22 23
24bind_interrupts!(struct Irqs {
25 USBD => usb::InterruptHandler<peripherals::USBD>;
26 POWER_CLOCK => usb::vbus_detect::InterruptHandler;
27});
28
23static SUSPENDED: AtomicBool = AtomicBool::new(false); 29static SUSPENDED: AtomicBool = AtomicBool::new(false);
24 30
25#[embassy_executor::main] 31#[embassy_executor::main]
@@ -32,9 +38,7 @@ async fn main(_spawner: Spawner) {
32 while clock.events_hfclkstarted.read().bits() != 1 {} 38 while clock.events_hfclkstarted.read().bits() != 1 {}
33 39
34 // Create the driver, from the HAL. 40 // Create the driver, from the HAL.
35 let irq = interrupt::take!(USBD); 41 let driver = Driver::new(p.USBD, Irqs, HardwareVbusDetect::new(Irqs));
36 let power_irq = interrupt::take!(POWER_CLOCK);
37 let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
38 42
39 // Create embassy-usb Config 43 // Create embassy-usb Config
40 let mut config = Config::new(0xc0de, 0xcafe); 44 let mut config = Config::new(0xc0de, 0xcafe);
@@ -50,6 +54,7 @@ async fn main(_spawner: Spawner) {
50 let mut device_descriptor = [0; 256]; 54 let mut device_descriptor = [0; 256];
51 let mut config_descriptor = [0; 256]; 55 let mut config_descriptor = [0; 256];
52 let mut bos_descriptor = [0; 256]; 56 let mut bos_descriptor = [0; 256];
57 let mut msos_descriptor = [0; 256];
53 let mut control_buf = [0; 64]; 58 let mut control_buf = [0; 64];
54 let request_handler = MyRequestHandler {}; 59 let request_handler = MyRequestHandler {};
55 let mut device_handler = MyDeviceHandler::new(); 60 let mut device_handler = MyDeviceHandler::new();
@@ -62,6 +67,7 @@ async fn main(_spawner: Spawner) {
62 &mut device_descriptor, 67 &mut device_descriptor,
63 &mut config_descriptor, 68 &mut config_descriptor,
64 &mut bos_descriptor, 69 &mut bos_descriptor,
70 &mut msos_descriptor,
65 &mut control_buf, 71 &mut control_buf,
66 ); 72 );
67 73
diff --git a/examples/nrf52840/src/bin/usb_hid_mouse.rs b/examples/nrf52840/src/bin/usb_hid_mouse.rs
index d7c9d55b7..edf634a5e 100644
--- a/examples/nrf52840/src/bin/usb_hid_mouse.rs
+++ b/examples/nrf52840/src/bin/usb_hid_mouse.rs
@@ -7,8 +7,9 @@ use core::mem;
7use defmt::*; 7use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_futures::join::join; 9use embassy_futures::join::join;
10use embassy_nrf::usb::{Driver, HardwareVbusDetect}; 10use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
11use embassy_nrf::{interrupt, pac}; 11use embassy_nrf::usb::Driver;
12use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
12use embassy_time::{Duration, Timer}; 13use embassy_time::{Duration, Timer};
13use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; 14use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State};
14use embassy_usb::control::OutResponse; 15use embassy_usb::control::OutResponse;
@@ -16,6 +17,11 @@ use embassy_usb::{Builder, Config};
16use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; 17use usbd_hid::descriptor::{MouseReport, SerializedDescriptor};
17use {defmt_rtt as _, panic_probe as _}; 18use {defmt_rtt as _, panic_probe as _};
18 19
20bind_interrupts!(struct Irqs {
21 USBD => usb::InterruptHandler<peripherals::USBD>;
22 POWER_CLOCK => usb::vbus_detect::InterruptHandler;
23});
24
19#[embassy_executor::main] 25#[embassy_executor::main]
20async fn main(_spawner: Spawner) { 26async fn main(_spawner: Spawner) {
21 let p = embassy_nrf::init(Default::default()); 27 let p = embassy_nrf::init(Default::default());
@@ -26,9 +32,7 @@ async fn main(_spawner: Spawner) {
26 while clock.events_hfclkstarted.read().bits() != 1 {} 32 while clock.events_hfclkstarted.read().bits() != 1 {}
27 33
28 // Create the driver, from the HAL. 34 // Create the driver, from the HAL.
29 let irq = interrupt::take!(USBD); 35 let driver = Driver::new(p.USBD, Irqs, HardwareVbusDetect::new(Irqs));
30 let power_irq = interrupt::take!(POWER_CLOCK);
31 let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
32 36
33 // Create embassy-usb Config 37 // Create embassy-usb Config
34 let mut config = Config::new(0xc0de, 0xcafe); 38 let mut config = Config::new(0xc0de, 0xcafe);
@@ -43,6 +47,7 @@ async fn main(_spawner: Spawner) {
43 let mut device_descriptor = [0; 256]; 47 let mut device_descriptor = [0; 256];
44 let mut config_descriptor = [0; 256]; 48 let mut config_descriptor = [0; 256];
45 let mut bos_descriptor = [0; 256]; 49 let mut bos_descriptor = [0; 256];
50 let mut msos_descriptor = [0; 256];
46 let mut control_buf = [0; 64]; 51 let mut control_buf = [0; 64];
47 let request_handler = MyRequestHandler {}; 52 let request_handler = MyRequestHandler {};
48 53
@@ -54,6 +59,7 @@ async fn main(_spawner: Spawner) {
54 &mut device_descriptor, 59 &mut device_descriptor,
55 &mut config_descriptor, 60 &mut config_descriptor,
56 &mut bos_descriptor, 61 &mut bos_descriptor,
62 &mut msos_descriptor,
57 &mut control_buf, 63 &mut control_buf,
58 ); 64 );
59 65
diff --git a/examples/nrf52840/src/bin/usb_serial.rs b/examples/nrf52840/src/bin/usb_serial.rs
index 102d7ea60..9727a4f57 100644
--- a/examples/nrf52840/src/bin/usb_serial.rs
+++ b/examples/nrf52840/src/bin/usb_serial.rs
@@ -7,13 +7,19 @@ use core::mem;
7use defmt::{info, panic}; 7use defmt::{info, panic};
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_futures::join::join; 9use embassy_futures::join::join;
10use embassy_nrf::usb::{Driver, HardwareVbusDetect, Instance, VbusDetect}; 10use embassy_nrf::usb::vbus_detect::{HardwareVbusDetect, VbusDetect};
11use embassy_nrf::{interrupt, pac}; 11use embassy_nrf::usb::{Driver, Instance};
12use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
12use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 13use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
13use embassy_usb::driver::EndpointError; 14use embassy_usb::driver::EndpointError;
14use embassy_usb::{Builder, Config}; 15use embassy_usb::{Builder, Config};
15use {defmt_rtt as _, panic_probe as _}; 16use {defmt_rtt as _, panic_probe as _};
16 17
18bind_interrupts!(struct Irqs {
19 USBD => usb::InterruptHandler<peripherals::USBD>;
20 POWER_CLOCK => usb::vbus_detect::InterruptHandler;
21});
22
17#[embassy_executor::main] 23#[embassy_executor::main]
18async fn main(_spawner: Spawner) { 24async fn main(_spawner: Spawner) {
19 let p = embassy_nrf::init(Default::default()); 25 let p = embassy_nrf::init(Default::default());
@@ -24,9 +30,7 @@ async fn main(_spawner: Spawner) {
24 while clock.events_hfclkstarted.read().bits() != 1 {} 30 while clock.events_hfclkstarted.read().bits() != 1 {}
25 31
26 // Create the driver, from the HAL. 32 // Create the driver, from the HAL.
27 let irq = interrupt::take!(USBD); 33 let driver = Driver::new(p.USBD, Irqs, HardwareVbusDetect::new(Irqs));
28 let power_irq = interrupt::take!(POWER_CLOCK);
29 let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
30 34
31 // Create embassy-usb Config 35 // Create embassy-usb Config
32 let mut config = Config::new(0xc0de, 0xcafe); 36 let mut config = Config::new(0xc0de, 0xcafe);
@@ -48,6 +52,7 @@ async fn main(_spawner: Spawner) {
48 let mut device_descriptor = [0; 256]; 52 let mut device_descriptor = [0; 256];
49 let mut config_descriptor = [0; 256]; 53 let mut config_descriptor = [0; 256];
50 let mut bos_descriptor = [0; 256]; 54 let mut bos_descriptor = [0; 256];
55 let mut msos_descriptor = [0; 256];
51 let mut control_buf = [0; 64]; 56 let mut control_buf = [0; 64];
52 57
53 let mut state = State::new(); 58 let mut state = State::new();
@@ -58,6 +63,7 @@ async fn main(_spawner: Spawner) {
58 &mut device_descriptor, 63 &mut device_descriptor,
59 &mut config_descriptor, 64 &mut config_descriptor,
60 &mut bos_descriptor, 65 &mut bos_descriptor,
66 &mut msos_descriptor,
61 &mut control_buf, 67 &mut control_buf,
62 ); 68 );
63 69
diff --git a/examples/nrf52840/src/bin/usb_serial_multitask.rs b/examples/nrf52840/src/bin/usb_serial_multitask.rs
index 558d4ba60..6da2c2a2f 100644
--- a/examples/nrf52840/src/bin/usb_serial_multitask.rs
+++ b/examples/nrf52840/src/bin/usb_serial_multitask.rs
@@ -6,14 +6,29 @@ use core::mem;
6 6
7use defmt::{info, panic, unwrap}; 7use defmt::{info, panic, unwrap};
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_nrf::usb::{Driver, HardwareVbusDetect}; 9use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
10use embassy_nrf::{interrupt, pac, peripherals}; 10use embassy_nrf::usb::Driver;
11use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
11use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 12use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
12use embassy_usb::driver::EndpointError; 13use embassy_usb::driver::EndpointError;
13use embassy_usb::{Builder, Config, UsbDevice}; 14use embassy_usb::{Builder, Config, UsbDevice};
14use static_cell::StaticCell; 15use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _}; 16use {defmt_rtt as _, panic_probe as _};
16 17
18bind_interrupts!(struct Irqs {
19 USBD => usb::InterruptHandler<peripherals::USBD>;
20 POWER_CLOCK => usb::vbus_detect::InterruptHandler;
21});
22
23macro_rules! singleton {
24 ($val:expr) => {{
25 type T = impl Sized;
26 static STATIC_CELL: StaticCell<T> = StaticCell::new();
27 let (x,) = STATIC_CELL.init(($val,));
28 x
29 }};
30}
31
17type MyDriver = Driver<'static, peripherals::USBD, HardwareVbusDetect>; 32type MyDriver = Driver<'static, peripherals::USBD, HardwareVbusDetect>;
18 33
19#[embassy_executor::task] 34#[embassy_executor::task]
@@ -39,10 +54,9 @@ async fn main(spawner: Spawner) {
39 info!("Enabling ext hfosc..."); 54 info!("Enabling ext hfosc...");
40 clock.tasks_hfclkstart.write(|w| unsafe { w.bits(1) }); 55 clock.tasks_hfclkstart.write(|w| unsafe { w.bits(1) });
41 while clock.events_hfclkstarted.read().bits() != 1 {} 56 while clock.events_hfclkstarted.read().bits() != 1 {}
57
42 // Create the driver, from the HAL. 58 // Create the driver, from the HAL.
43 let irq = interrupt::take!(USBD); 59 let driver = Driver::new(p.USBD, Irqs, HardwareVbusDetect::new(Irqs));
44 let power_irq = interrupt::take!(POWER_CLOCK);
45 let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
46 60
47 // Create embassy-usb Config 61 // Create embassy-usb Config
48 let mut config = Config::new(0xc0de, 0xcafe); 62 let mut config = Config::new(0xc0de, 0xcafe);
@@ -59,34 +73,21 @@ async fn main(spawner: Spawner) {
59 config.device_protocol = 0x01; 73 config.device_protocol = 0x01;
60 config.composite_with_iads = true; 74 config.composite_with_iads = true;
61 75
62 struct Resources { 76 let state = singleton!(State::new());
63 device_descriptor: [u8; 256],
64 config_descriptor: [u8; 256],
65 bos_descriptor: [u8; 256],
66 control_buf: [u8; 64],
67 serial_state: State<'static>,
68 }
69 static RESOURCES: StaticCell<Resources> = StaticCell::new();
70 let res = RESOURCES.init(Resources {
71 device_descriptor: [0; 256],
72 config_descriptor: [0; 256],
73 bos_descriptor: [0; 256],
74 control_buf: [0; 64],
75 serial_state: State::new(),
76 });
77 77
78 // Create embassy-usb DeviceBuilder using the driver and config. 78 // Create embassy-usb DeviceBuilder using the driver and config.
79 let mut builder = Builder::new( 79 let mut builder = Builder::new(
80 driver, 80 driver,
81 config, 81 config,
82 &mut res.device_descriptor, 82 &mut singleton!([0; 256])[..],
83 &mut res.config_descriptor, 83 &mut singleton!([0; 256])[..],
84 &mut res.bos_descriptor, 84 &mut singleton!([0; 256])[..],
85 &mut res.control_buf, 85 &mut singleton!([0; 128])[..],
86 &mut singleton!([0; 128])[..],
86 ); 87 );
87 88
88 // Create classes on the builder. 89 // Create classes on the builder.
89 let class = CdcAcmClass::new(&mut builder, &mut res.serial_state, 64); 90 let class = CdcAcmClass::new(&mut builder, state, 64);
90 91
91 // Build the builder. 92 // Build the builder.
92 let usb = builder.build(); 93 let usb = builder.build();
diff --git a/examples/nrf52840/src/bin/usb_serial_winusb.rs b/examples/nrf52840/src/bin/usb_serial_winusb.rs
index 6561fc3b4..6e4f71a48 100644
--- a/examples/nrf52840/src/bin/usb_serial_winusb.rs
+++ b/examples/nrf52840/src/bin/usb_serial_winusb.rs
@@ -7,8 +7,9 @@ use core::mem;
7use defmt::{info, panic}; 7use defmt::{info, panic};
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_futures::join::join; 9use embassy_futures::join::join;
10use embassy_nrf::usb::{Driver, HardwareVbusDetect, Instance, VbusDetect}; 10use embassy_nrf::usb::vbus_detect::{HardwareVbusDetect, VbusDetect};
11use embassy_nrf::{interrupt, pac}; 11use embassy_nrf::usb::{Driver, Instance};
12use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
12use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 13use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
13use embassy_usb::driver::EndpointError; 14use embassy_usb::driver::EndpointError;
14use embassy_usb::msos::{self, windows_version}; 15use embassy_usb::msos::{self, windows_version};
@@ -16,6 +17,11 @@ use embassy_usb::types::InterfaceNumber;
16use embassy_usb::{Builder, Config}; 17use embassy_usb::{Builder, Config};
17use {defmt_rtt as _, panic_probe as _}; 18use {defmt_rtt as _, panic_probe as _};
18 19
20bind_interrupts!(struct Irqs {
21 USBD => usb::InterruptHandler<peripherals::USBD>;
22 POWER_CLOCK => usb::vbus_detect::InterruptHandler;
23});
24
19// This is a randomly generated GUID to allow clients on Windows to find our device 25// This is a randomly generated GUID to allow clients on Windows to find our device
20const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"]; 26const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"];
21 27
@@ -29,9 +35,7 @@ async fn main(_spawner: Spawner) {
29 while clock.events_hfclkstarted.read().bits() != 1 {} 35 while clock.events_hfclkstarted.read().bits() != 1 {}
30 36
31 // Create the driver, from the HAL. 37 // Create the driver, from the HAL.
32 let irq = interrupt::take!(USBD); 38 let driver = Driver::new(p.USBD, Irqs, HardwareVbusDetect::new(Irqs));
33 let power_irq = interrupt::take!(POWER_CLOCK);
34 let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
35 39
36 // Create embassy-usb Config 40 // Create embassy-usb Config
37 let mut config = Config::new(0xc0de, 0xcafe); 41 let mut config = Config::new(0xc0de, 0xcafe);
diff --git a/examples/nrf5340/src/bin/uart.rs b/examples/nrf5340/src/bin/uart.rs
index 5f448c2ba..d68539702 100644
--- a/examples/nrf5340/src/bin/uart.rs
+++ b/examples/nrf5340/src/bin/uart.rs
@@ -4,9 +4,14 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::{interrupt, uarte}; 7use embassy_nrf::peripherals::SERIAL0;
8use embassy_nrf::{bind_interrupts, uarte};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(struct Irqs {
12 SERIAL0 => uarte::InterruptHandler<SERIAL0>;
13});
14
10#[embassy_executor::main] 15#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 16async fn main(_spawner: Spawner) {
12 let p = embassy_nrf::init(Default::default()); 17 let p = embassy_nrf::init(Default::default());
@@ -14,8 +19,7 @@ async fn main(_spawner: Spawner) {
14 config.parity = uarte::Parity::EXCLUDED; 19 config.parity = uarte::Parity::EXCLUDED;
15 config.baudrate = uarte::Baudrate::BAUD115200; 20 config.baudrate = uarte::Baudrate::BAUD115200;
16 21
17 let irq = interrupt::take!(SERIAL0); 22 let mut uart = uarte::Uarte::new(p.SERIAL0, Irqs, p.P1_00, p.P1_01, config);
18 let mut uart = uarte::Uarte::new(p.SERIAL0, irq, p.P1_00, p.P1_01, config);
19 23
20 info!("uarte initialized!"); 24 info!("uarte initialized!");
21 25
diff --git a/tests/nrf/src/bin/buffered_uart.rs b/tests/nrf/src/bin/buffered_uart.rs
index 0550b0bb7..e73d4f0b0 100644
--- a/tests/nrf/src/bin/buffered_uart.rs
+++ b/tests/nrf/src/bin/buffered_uart.rs
@@ -5,10 +5,14 @@
5use defmt::{assert_eq, *}; 5use defmt::{assert_eq, *};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_futures::join::join; 7use embassy_futures::join::join;
8use embassy_nrf::buffered_uarte::BufferedUarte; 8use embassy_nrf::buffered_uarte::{self, BufferedUarte};
9use embassy_nrf::{interrupt, uarte}; 9use embassy_nrf::{bind_interrupts, peripherals, uarte};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12bind_interrupts!(struct Irqs {
13 UARTE0_UART0 => buffered_uarte::InterruptHandler<peripherals::UARTE0>;
14});
15
12#[embassy_executor::main] 16#[embassy_executor::main]
13async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
14 let p = embassy_nrf::init(Default::default()); 18 let p = embassy_nrf::init(Default::default());
@@ -25,7 +29,7 @@ async fn main(_spawner: Spawner) {
25 p.PPI_CH0, 29 p.PPI_CH0,
26 p.PPI_CH1, 30 p.PPI_CH1,
27 p.PPI_GROUP0, 31 p.PPI_GROUP0,
28 interrupt::take!(UARTE0_UART0), 32 Irqs,
29 p.P1_03, 33 p.P1_03,
30 p.P1_02, 34 p.P1_02,
31 config.clone(), 35 config.clone(),
diff --git a/tests/nrf/src/bin/buffered_uart_spam.rs b/tests/nrf/src/bin/buffered_uart_spam.rs
index 57aaeca45..74eda6d01 100644
--- a/tests/nrf/src/bin/buffered_uart_spam.rs
+++ b/tests/nrf/src/bin/buffered_uart_spam.rs
@@ -7,14 +7,19 @@ use core::ptr::NonNull;
7 7
8use defmt::{assert_eq, *}; 8use defmt::{assert_eq, *};
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_nrf::buffered_uarte::BufferedUarte; 10use embassy_nrf::buffered_uarte::{self, BufferedUarte};
11use embassy_nrf::gpio::{Level, Output, OutputDrive}; 11use embassy_nrf::gpio::{Level, Output, OutputDrive};
12use embassy_nrf::ppi::{Event, Ppi, Task}; 12use embassy_nrf::ppi::{Event, Ppi, Task};
13use embassy_nrf::uarte::Uarte; 13use embassy_nrf::uarte::Uarte;
14use embassy_nrf::{interrupt, pac, uarte}; 14use embassy_nrf::{bind_interrupts, pac, peripherals, uarte};
15use embassy_time::{Duration, Timer}; 15use embassy_time::{Duration, Timer};
16use {defmt_rtt as _, panic_probe as _}; 16use {defmt_rtt as _, panic_probe as _};
17 17
18bind_interrupts!(struct Irqs {
19 UARTE0_UART0 => buffered_uarte::InterruptHandler<peripherals::UARTE0>;
20 UARTE1 => uarte::InterruptHandler<peripherals::UARTE1>;
21});
22
18#[embassy_executor::main] 23#[embassy_executor::main]
19async fn main(_spawner: Spawner) { 24async fn main(_spawner: Spawner) {
20 let mut p = embassy_nrf::init(Default::default()); 25 let mut p = embassy_nrf::init(Default::default());
@@ -33,7 +38,7 @@ async fn main(_spawner: Spawner) {
33 p.PPI_CH0, 38 p.PPI_CH0,
34 p.PPI_CH1, 39 p.PPI_CH1,
35 p.PPI_GROUP0, 40 p.PPI_GROUP0,
36 interrupt::take!(UARTE0_UART0), 41 Irqs,
37 p.P1_03, 42 p.P1_03,
38 p.P1_04, 43 p.P1_04,
39 config.clone(), 44 config.clone(),
@@ -49,7 +54,7 @@ async fn main(_spawner: Spawner) {
49 // Tx spam in a loop. 54 // Tx spam in a loop.
50 const NSPAM: usize = 17; 55 const NSPAM: usize = 17;
51 static mut TX_BUF: [u8; NSPAM] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; 56 static mut TX_BUF: [u8; NSPAM] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
52 let _spam = Uarte::new(p.UARTE1, interrupt::take!(UARTE1), p.P1_01, p.P1_02, config.clone()); 57 let _spam = Uarte::new(p.UARTE1, Irqs, p.P1_01, p.P1_02, config.clone());
53 let spam_peri: pac::UARTE1 = unsafe { mem::transmute(()) }; 58 let spam_peri: pac::UARTE1 = unsafe { mem::transmute(()) };
54 let event = unsafe { Event::new_unchecked(NonNull::new_unchecked(&spam_peri.events_endtx as *const _ as _)) }; 59 let event = unsafe { Event::new_unchecked(NonNull::new_unchecked(&spam_peri.events_endtx as *const _ as _)) };
55 let task = unsafe { Task::new_unchecked(NonNull::new_unchecked(&spam_peri.tasks_starttx as *const _ as _)) }; 60 let task = unsafe { Task::new_unchecked(NonNull::new_unchecked(&spam_peri.tasks_starttx as *const _ as _)) };