diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-03-06 00:41:47 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-03-06 00:41:47 +0100 |
| commit | 18fe398673f55b07159d01a230910bb9689c1525 (patch) | |
| tree | 85c92ef10298ccaedec58c0582af1bf05753192e | |
| parent | 403a83e08da67ebb20d04b1675a34c12752a94fc (diff) | |
| parent | f5e09a8f4a6d7b1bd6723c60915cb9f29cf352f7 (diff) | |
Merge pull request #1224 from embassy-rs/interrupt-binding
nrf: new interrupt binding traits/macro
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. | ||
| 21 | pub 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. | ||
| 44 | pub 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)] |
| 18 | pub struct Handler { | 48 | pub struct DynHandler { |
| 19 | pub func: AtomicPtr<()>, | 49 | pub func: AtomicPtr<()>, |
| 20 | pub ctx: AtomicPtr<()>, | 50 | pub ctx: AtomicPtr<()>, |
| 21 | } | 51 | } |
| 22 | 52 | ||
| 23 | impl Handler { | 53 | impl 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 | ||
| 11 | use core::cmp::min; | 11 | use core::cmp::min; |
| 12 | use core::future::poll_fn; | 12 | use core::future::poll_fn; |
| 13 | use core::marker::PhantomData; | ||
| 13 | use core::slice; | 14 | use core::slice; |
| 14 | use core::sync::atomic::{compiler_fence, AtomicU8, AtomicUsize, Ordering}; | 15 | use core::sync::atomic::{compiler_fence, AtomicU8, AtomicUsize, Ordering}; |
| 15 | use core::task::Poll; | 16 | use core::task::Poll; |
| @@ -23,7 +24,7 @@ pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Pari | |||
| 23 | 24 | ||
| 24 | use crate::gpio::sealed::Pin; | 25 | use crate::gpio::sealed::Pin; |
| 25 | use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; | 26 | use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; |
| 26 | use crate::interrupt::InterruptExt; | 27 | use crate::interrupt::{self, InterruptExt}; |
| 27 | use crate::ppi::{ | 28 | use 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. | ||
| 76 | pub struct InterruptHandler<U: UarteInstance> { | ||
| 77 | _phantom: PhantomData<U>, | ||
| 78 | } | ||
| 79 | |||
| 80 | impl<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. |
| 75 | pub struct BufferedUarte<'d, U: UarteInstance, T: TimerInstance> { | 183 | pub 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 | ||
| 141 | impl_twis!(TWI0, TWIS0, TWIM0_TWIS0_TWI0); | 141 | impl_twis!(TWI0, TWIS0, TWIM0_TWIS0_TWI0); |
| 142 | 142 | ||
| 143 | impl_qdec!(QDEC, QDEC, QDEC); | ||
| 144 | |||
| 145 | impl_rng!(RNG, RNG, RNG); | ||
| 146 | |||
| 143 | impl_timer!(TIMER0, TIMER0, TIMER0); | 147 | impl_timer!(TIMER0, TIMER0, TIMER0); |
| 144 | impl_timer!(TIMER1, TIMER1, TIMER1); | 148 | impl_timer!(TIMER1, TIMER1, TIMER1); |
| 145 | impl_timer!(TIMER2, TIMER2, TIMER2); | 149 | impl_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 | ||
| 149 | impl_pwm!(PWM0, PWM0, PWM0); | 149 | impl_pwm!(PWM0, PWM0, PWM0); |
| 150 | 150 | ||
| 151 | impl_pdm!(PDM, PDM, PDM); | ||
| 152 | |||
| 153 | impl_qdec!(QDEC, QDEC, QDEC); | ||
| 154 | |||
| 155 | impl_rng!(RNG, RNG, RNG); | ||
| 156 | |||
| 151 | impl_timer!(TIMER0, TIMER0, TIMER0); | 157 | impl_timer!(TIMER0, TIMER0, TIMER0); |
| 152 | impl_timer!(TIMER1, TIMER1, TIMER1); | 158 | impl_timer!(TIMER1, TIMER1, TIMER1); |
| 153 | impl_timer!(TIMER2, TIMER2, TIMER2); | 159 | impl_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 | ||
| 151 | impl_pwm!(PWM0, PWM0, PWM0); | 151 | impl_pwm!(PWM0, PWM0, PWM0); |
| 152 | 152 | ||
| 153 | impl_pdm!(PDM, PDM, PDM); | ||
| 154 | |||
| 155 | impl_qdec!(QDEC, QDEC, QDEC); | ||
| 156 | |||
| 157 | impl_rng!(RNG, RNG, RNG); | ||
| 158 | |||
| 153 | impl_timer!(TIMER0, TIMER0, TIMER0); | 159 | impl_timer!(TIMER0, TIMER0, TIMER0); |
| 154 | impl_timer!(TIMER1, TIMER1, TIMER1); | 160 | impl_timer!(TIMER1, TIMER1, TIMER1); |
| 155 | impl_timer!(TIMER2, TIMER2, TIMER2); | 161 | impl_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); | |||
| 153 | impl_timer!(TIMER2, TIMER2, TIMER2); | 153 | impl_timer!(TIMER2, TIMER2, TIMER2); |
| 154 | impl_timer!(TIMER3, TIMER3, TIMER3, extended); | 154 | impl_timer!(TIMER3, TIMER3, TIMER3, extended); |
| 155 | 155 | ||
| 156 | impl_qdec!(QDEC, QDEC, QDEC); | ||
| 157 | |||
| 158 | impl_rng!(RNG, RNG, RNG); | ||
| 159 | |||
| 156 | impl_pin!(P0_00, 0, 0); | 160 | impl_pin!(P0_00, 0, 0); |
| 157 | impl_pin!(P0_01, 0, 1); | 161 | impl_pin!(P0_01, 0, 1); |
| 158 | impl_pin!(P0_02, 0, 2); | 162 | impl_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 | ||
| 151 | impl_uarte!(UARTE0, UARTE0, UARTE0_UART0); | 154 | impl_uarte!(UARTE0, UARTE0, UARTE0_UART0); |
| @@ -168,6 +171,12 @@ impl_pwm!(PWM0, PWM0, PWM0); | |||
| 168 | impl_pwm!(PWM1, PWM1, PWM1); | 171 | impl_pwm!(PWM1, PWM1, PWM1); |
| 169 | impl_pwm!(PWM2, PWM2, PWM2); | 172 | impl_pwm!(PWM2, PWM2, PWM2); |
| 170 | 173 | ||
| 174 | impl_pdm!(PDM, PDM, PDM); | ||
| 175 | |||
| 176 | impl_qdec!(QDEC, QDEC, QDEC); | ||
| 177 | |||
| 178 | impl_rng!(RNG, RNG, RNG); | ||
| 179 | |||
| 171 | impl_timer!(TIMER0, TIMER0, TIMER0); | 180 | impl_timer!(TIMER0, TIMER0, TIMER0); |
| 172 | impl_timer!(TIMER1, TIMER1, TIMER1); | 181 | impl_timer!(TIMER1, TIMER1, TIMER1); |
| 173 | impl_timer!(TIMER2, TIMER2, TIMER2); | 182 | impl_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); | |||
| 197 | impl_pwm!(PWM2, PWM2, PWM2); | 197 | impl_pwm!(PWM2, PWM2, PWM2); |
| 198 | impl_pwm!(PWM3, PWM3, PWM3); | 198 | impl_pwm!(PWM3, PWM3, PWM3); |
| 199 | 199 | ||
| 200 | impl_pdm!(PDM, PDM, PDM); | ||
| 201 | |||
| 202 | impl_qdec!(QDEC, QDEC, QDEC); | ||
| 203 | |||
| 204 | impl_rng!(RNG, RNG, RNG); | ||
| 205 | |||
| 200 | impl_timer!(TIMER0, TIMER0, TIMER0); | 206 | impl_timer!(TIMER0, TIMER0, TIMER0); |
| 201 | impl_timer!(TIMER1, TIMER1, TIMER1); | 207 | impl_timer!(TIMER1, TIMER1, TIMER1); |
| 202 | impl_timer!(TIMER2, TIMER2, TIMER2); | 208 | impl_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 | ||
| 209 | impl_qspi!(QSPI, QSPI, QSPI); | 209 | impl_qspi!(QSPI, QSPI, QSPI); |
| 210 | 210 | ||
| 211 | impl_pdm!(PDM, PDM, PDM); | ||
| 212 | |||
| 213 | impl_qdec!(QDEC, QDEC, QDEC); | ||
| 214 | |||
| 215 | impl_rng!(RNG, RNG, RNG); | ||
| 216 | |||
| 211 | impl_pin!(P0_00, 0, 0); | 217 | impl_pin!(P0_00, 0, 0); |
| 212 | impl_pin!(P0_01, 0, 1); | 218 | impl_pin!(P0_01, 0, 1); |
| 213 | impl_pin!(P0_02, 0, 2); | 219 | impl_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 | ||
| 399 | impl_qspi!(QSPI, QSPI, QSPI); | 406 | impl_qspi!(QSPI, QSPI, QSPI); |
| 400 | 407 | ||
| 408 | impl_pdm!(PDM0, PDM0, PDM0); | ||
| 409 | |||
| 410 | impl_qdec!(QDEC0, QDEC0, QDEC0); | ||
| 411 | impl_qdec!(QDEC1, QDEC1, QDEC1); | ||
| 412 | |||
| 401 | impl_pin!(P0_00, 0, 0); | 413 | impl_pin!(P0_00, 0, 0); |
| 402 | impl_pin!(P0_01, 0, 1); | 414 | impl_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); | |||
| 252 | impl_timer!(TIMER1, TIMER1, TIMER1); | 255 | impl_timer!(TIMER1, TIMER1, TIMER1); |
| 253 | impl_timer!(TIMER2, TIMER2, TIMER2); | 256 | impl_timer!(TIMER2, TIMER2, TIMER2); |
| 254 | 257 | ||
| 258 | impl_rng!(RNG, RNG, RNG); | ||
| 259 | |||
| 255 | impl_pin!(P0_00, 0, 0); | 260 | impl_pin!(P0_00, 0, 0); |
| 256 | impl_pin!(P0_01, 0, 1); | 261 | impl_pin!(P0_01, 0, 1); |
| 257 | impl_pin!(P0_02, 0, 2); | 262 | impl_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); | |||
| 301 | impl_pwm!(PWM2, PWM2, PWM2); | 301 | impl_pwm!(PWM2, PWM2, PWM2); |
| 302 | impl_pwm!(PWM3, PWM3, PWM3); | 302 | impl_pwm!(PWM3, PWM3, PWM3); |
| 303 | 303 | ||
| 304 | impl_pdm!(PDM, PDM, PDM); | ||
| 305 | |||
| 304 | impl_timer!(TIMER0, TIMER0, TIMER0); | 306 | impl_timer!(TIMER0, TIMER0, TIMER0); |
| 305 | impl_timer!(TIMER1, TIMER1, TIMER1); | 307 | impl_timer!(TIMER1, TIMER1, TIMER1); |
| 306 | impl_timer!(TIMER2, TIMER2, TIMER2); | 308 | impl_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; | |||
| 14 | use embassy_hal_common::{into_ref, PeripheralRef}; | 14 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 15 | 15 | ||
| 16 | use crate::gpio::{AnyPin, Pin as GpioPin}; | 16 | use crate::gpio::{AnyPin, Pin as GpioPin}; |
| 17 | use crate::interrupt::Interrupt; | 17 | use crate::interrupt::{self, Interrupt}; |
| 18 | use crate::pac::i2s::RegisterBlock; | 18 | use crate::pac::i2s::RegisterBlock; |
| 19 | use crate::util::{slice_in_ram_or, slice_ptr_parts}; | 19 | use crate::util::{slice_in_ram_or, slice_ptr_parts}; |
| 20 | use crate::{Peripheral, EASY_DMA_SIZE}; | 20 | use crate::{Peripheral, EASY_DMA_SIZE}; |
| @@ -363,10 +363,39 @@ impl From<Channels> for u8 { | |||
| 363 | } | 363 | } |
| 364 | } | 364 | } |
| 365 | 365 | ||
| 366 | /// Interrupt handler. | ||
| 367 | pub struct InterruptHandler<T: Instance> { | ||
| 368 | _phantom: PhantomData<T>, | ||
| 369 | } | ||
| 370 | |||
| 371 | impl<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. |
| 367 | pub struct I2S<'d, T: Instance> { | 397 | pub 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 | ||
| 379 | impl<'d, T: Instance> I2S<'d, T> { | 408 | impl<'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. |
| 1172 | pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send { | 1175 | pub 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 | ))] |
| 54 | pub mod pdm; | 56 | pub mod pdm; |
| 55 | pub mod ppi; | 57 | pub mod ppi; |
| 56 | #[cfg(not(any(feature = "nrf52805", feature = "nrf52820", feature = "_nrf5340-net")))] | 58 | #[cfg(not(any(feature = "nrf52805", feature = "nrf52820", feature = "_nrf5340-net")))] |
| 57 | pub mod pwm; | 59 | pub mod pwm; |
| 58 | #[cfg(not(any(feature = "nrf51", feature = "_nrf9160", feature = "_nrf5340")))] | 60 | #[cfg(not(any(feature = "nrf51", feature = "_nrf9160", feature = "_nrf5340-net")))] |
| 59 | pub mod qdec; | 61 | pub mod qdec; |
| 60 | #[cfg(any(feature = "nrf52840", feature = "_nrf5340-app"))] | 62 | #[cfg(any(feature = "nrf52840", feature = "_nrf5340-app"))] |
| 61 | pub mod qspi; | 63 | pub mod qspi; |
| 62 | #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] | 64 | #[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf9160")))] |
| 63 | pub mod rng; | 65 | pub mod rng; |
| 64 | #[cfg(not(any(feature = "nrf52820", feature = "_nrf5340-net")))] | 66 | #[cfg(not(any(feature = "nrf52820", feature = "_nrf5340-net")))] |
| 65 | pub mod saadc; | 67 | pub 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")] |
| 96 | mod chip; | 98 | mod chip; |
| 97 | 99 | ||
| 98 | pub use chip::EASY_DMA_SIZE; | ||
| 99 | |||
| 100 | pub mod interrupt { | 100 | pub 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 { | |||
| 111 | pub use chip::pac; | 138 | pub use chip::pac; |
| 112 | #[cfg(not(feature = "unstable-pac"))] | 139 | #[cfg(not(feature = "unstable-pac"))] |
| 113 | pub(crate) use chip::pac; | 140 | pub(crate) use chip::pac; |
| 114 | pub use chip::{peripherals, Peripherals}; | 141 | pub use chip::{peripherals, Peripherals, EASY_DMA_SIZE}; |
| 115 | pub use embassy_cortex_m::executor; | 142 | pub use embassy_cortex_m::executor; |
| 116 | pub use embassy_cortex_m::interrupt::_export::interrupt; | 143 | pub use embassy_cortex_m::interrupt::_export::interrupt; |
| 117 | pub use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; | 144 | pub 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 | |||
| 3 | use core::marker::PhantomData; | 5 | use core::marker::PhantomData; |
| 4 | use core::sync::atomic::{compiler_fence, Ordering}; | 6 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 5 | use core::task::Poll; | 7 | use core::task::Poll; |
| 6 | 8 | ||
| 9 | use embassy_cortex_m::interrupt::Interrupt; | ||
| 7 | use embassy_hal_common::drop::OnDrop; | 10 | use embassy_hal_common::drop::OnDrop; |
| 8 | use embassy_hal_common::{into_ref, PeripheralRef}; | 11 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 9 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 10 | use futures::future::poll_fn; | 12 | use futures::future::poll_fn; |
| 11 | 13 | ||
| 12 | use crate::chip::EASY_DMA_SIZE; | 14 | use crate::chip::EASY_DMA_SIZE; |
| 13 | use crate::gpio::sealed::Pin; | 15 | use crate::gpio::sealed::Pin; |
| 14 | use crate::gpio::{AnyPin, Pin as GpioPin}; | 16 | use crate::gpio::{AnyPin, Pin as GpioPin}; |
| 15 | use crate::interrupt::{self, InterruptExt}; | 17 | use crate::interrupt::{self, InterruptExt}; |
| 16 | use crate::peripherals::PDM; | 18 | use crate::Peripheral; |
| 17 | use crate::{pac, Peripheral}; | 19 | |
| 20 | /// Interrupt handler. | ||
| 21 | pub struct InterruptHandler<T: Instance> { | ||
| 22 | _phantom: PhantomData<T>, | ||
| 23 | } | ||
| 24 | |||
| 25 | impl<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 |
| 20 | pub struct Pdm<'d> { | 33 | pub 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 | ||
| 38 | static WAKER: AtomicWaker = AtomicWaker::new(); | ||
| 39 | static DUMMY_BUFFER: [i16; 1] = [0; 1]; | 50 | static DUMMY_BUFFER: [i16; 1] = [0; 1]; |
| 40 | 51 | ||
| 41 | impl<'d> Pdm<'d> { | 52 | impl<'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 | ||
| 241 | impl<'d> Drop for Pdm<'d> { | 239 | impl<'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 | |||
| 252 | pub(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. | ||
| 275 | pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send { | ||
| 276 | /// Interrupt for this peripheral. | ||
| 277 | type Interrupt: Interrupt; | ||
| 278 | } | ||
| 279 | |||
| 280 | macro_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 | |||
| 3 | use core::future::poll_fn; | 5 | use core::future::poll_fn; |
| 6 | use core::marker::PhantomData; | ||
| 4 | use core::task::Poll; | 7 | use core::task::Poll; |
| 5 | 8 | ||
| 9 | use embassy_cortex_m::interrupt::Interrupt; | ||
| 6 | use embassy_hal_common::{into_ref, PeripheralRef}; | 10 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 7 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 8 | 11 | ||
| 9 | use crate::gpio::sealed::Pin as _; | 12 | use crate::gpio::sealed::Pin as _; |
| 10 | use crate::gpio::{AnyPin, Pin as GpioPin}; | 13 | use crate::gpio::{AnyPin, Pin as GpioPin}; |
| 11 | use crate::interrupt::InterruptExt; | 14 | use crate::interrupt::InterruptExt; |
| 12 | use crate::peripherals::QDEC; | 15 | use crate::{interrupt, Peripheral}; |
| 13 | use crate::{interrupt, pac, Peripheral}; | ||
| 14 | 16 | ||
| 15 | /// Quadrature decoder driver. | 17 | /// Quadrature decoder driver. |
| 16 | pub struct Qdec<'d> { | 18 | pub 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 | ||
| 47 | static WAKER: AtomicWaker = AtomicWaker::new(); | 49 | /// Interrupt handler. |
| 50 | pub struct InterruptHandler<T: Instance> { | ||
| 51 | _phantom: PhantomData<T>, | ||
| 52 | } | ||
| 48 | 53 | ||
| 49 | impl<'d> Qdec<'d> { | 54 | impl<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 | |||
| 61 | impl<'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 | |||
| 241 | pub(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. | ||
| 264 | pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send { | ||
| 265 | /// Interrupt for this peripheral. | ||
| 266 | type Interrupt: Interrupt; | ||
| 267 | } | ||
| 268 | |||
| 269 | macro_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 | ||
| 5 | use core::future::poll_fn; | 5 | use core::future::poll_fn; |
| 6 | use core::marker::PhantomData; | ||
| 6 | use core::ptr; | 7 | use core::ptr; |
| 7 | use core::task::Poll; | 8 | use core::task::Poll; |
| 8 | 9 | ||
| @@ -11,12 +12,12 @@ use embassy_hal_common::{into_ref, PeripheralRef}; | |||
| 11 | use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash}; | 12 | use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash}; |
| 12 | 13 | ||
| 13 | use crate::gpio::{self, Pin as GpioPin}; | 14 | use crate::gpio::{self, Pin as GpioPin}; |
| 14 | use crate::interrupt::{Interrupt, InterruptExt}; | 15 | use crate::interrupt::{self, Interrupt, InterruptExt}; |
| 15 | pub use crate::pac::qspi::ifconfig0::{ | 16 | pub 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 | }; |
| 18 | pub use crate::pac::qspi::ifconfig1::SPIMODE_A as SpiMode; | 19 | pub use crate::pac::qspi::ifconfig1::SPIMODE_A as SpiMode; |
| 19 | use crate::{pac, Peripheral}; | 20 | use crate::Peripheral; |
| 20 | 21 | ||
| 21 | /// Deep power-down config. | 22 | /// Deep power-down config. |
| 22 | pub struct DeepPowerDownConfig { | 23 | pub 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. | ||
| 119 | pub struct InterruptHandler<T: Instance> { | ||
| 120 | _phantom: PhantomData<T>, | ||
| 121 | } | ||
| 122 | |||
| 123 | impl<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. |
| 118 | pub struct Qspi<'d, T: Instance> { | 136 | pub 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> { | |||
| 124 | impl<'d, T: Instance> Qspi<'d, T> { | 142 | impl<'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 { | |||
| 624 | pub(crate) mod sealed { | 629 | pub(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. |
| 647 | pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static { | 652 | pub 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 { | |||
| 652 | macro_rules! impl_qspi { | 657 | macro_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 | |||
| 3 | use core::future::poll_fn; | 5 | use core::future::poll_fn; |
| 6 | use core::marker::PhantomData; | ||
| 4 | use core::ptr; | 7 | use core::ptr; |
| 5 | use core::sync::atomic::{AtomicPtr, Ordering}; | 8 | use core::sync::atomic::{AtomicPtr, Ordering}; |
| 6 | use core::task::Poll; | 9 | use core::task::Poll; |
| 7 | 10 | ||
| 11 | use embassy_cortex_m::interrupt::Interrupt; | ||
| 8 | use embassy_hal_common::drop::OnDrop; | 12 | use embassy_hal_common::drop::OnDrop; |
| 9 | use embassy_hal_common::{into_ref, PeripheralRef}; | 13 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 10 | use embassy_sync::waitqueue::AtomicWaker; | 14 | use embassy_sync::waitqueue::AtomicWaker; |
| 11 | 15 | ||
| 12 | use crate::interrupt::InterruptExt; | 16 | use crate::interrupt::InterruptExt; |
| 13 | use crate::peripherals::RNG; | 17 | use crate::{interrupt, Peripheral}; |
| 14 | use crate::{interrupt, pac, Peripheral}; | ||
| 15 | |||
| 16 | impl RNG { | ||
| 17 | fn regs() -> &'static pac::rng::RegisterBlock { | ||
| 18 | unsafe { &*pac::RNG::ptr() } | ||
| 19 | } | ||
| 20 | } | ||
| 21 | |||
| 22 | static STATE: State = State { | ||
| 23 | ptr: AtomicPtr::new(ptr::null_mut()), | ||
| 24 | end: AtomicPtr::new(ptr::null_mut()), | ||
| 25 | waker: AtomicWaker::new(), | ||
| 26 | }; | ||
| 27 | 18 | ||
| 28 | struct State { | 19 | /// Interrupt handler. |
| 29 | ptr: AtomicPtr<u8>, | 20 | pub 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. | 24 | impl<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(); |
| 37 | pub struct Rng<'d> { | 27 | let r = T::regs(); |
| 38 | irq: PeripheralRef<'d, interrupt::RNG>, | ||
| 39 | } | ||
| 40 | |||
| 41 | impl<'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`. | ||
| 80 | pub struct Rng<'d, T: Instance> { | ||
| 81 | _peri: PeripheralRef<'d, T>, | ||
| 82 | } | ||
| 83 | |||
| 84 | impl<'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 | ||
| 196 | impl<'d> Drop for Rng<'d> { | 195 | impl<'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 | ||
| 202 | impl<'d> rand_core::RngCore for Rng<'d> { | 204 | impl<'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 | ||
| 226 | impl<'d> rand_core::CryptoRng for Rng<'d> {} | 228 | impl<'d, T: Instance> rand_core::CryptoRng for Rng<'d, T> {} |
| 229 | |||
| 230 | pub(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. | ||
| 257 | pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send { | ||
| 258 | /// Interrupt for this peripheral. | ||
| 259 | type Interrupt: Interrupt; | ||
| 260 | } | ||
| 261 | |||
| 262 | macro_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; | |||
| 6 | use core::sync::atomic::{compiler_fence, Ordering}; | 6 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 7 | use core::task::Poll; | 7 | use core::task::Poll; |
| 8 | 8 | ||
| 9 | use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; | ||
| 9 | use embassy_hal_common::drop::OnDrop; | 10 | use embassy_hal_common::drop::OnDrop; |
| 10 | use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; | 11 | use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; |
| 11 | use embassy_sync::waitqueue::AtomicWaker; | 12 | use embassy_sync::waitqueue::AtomicWaker; |
| @@ -17,7 +18,6 @@ use saadc::oversample::OVERSAMPLE_A; | |||
| 17 | use saadc::resolution::VAL_A; | 18 | use saadc::resolution::VAL_A; |
| 18 | 19 | ||
| 19 | use self::sealed::Input as _; | 20 | use self::sealed::Input as _; |
| 20 | use crate::interrupt::InterruptExt; | ||
| 21 | use crate::ppi::{ConfigurableChannel, Event, Ppi, Task}; | 21 | use crate::ppi::{ConfigurableChannel, Event, Ppi, Task}; |
| 22 | use crate::timer::{Frequency, Instance as TimerInstance, Timer}; | 22 | use crate::timer::{Frequency, Instance as TimerInstance, Timer}; |
| 23 | use crate::{interrupt, pac, peripherals, Peripheral}; | 23 | use crate::{interrupt, pac, peripherals, Peripheral}; |
| @@ -28,9 +28,30 @@ use crate::{interrupt, pac, peripherals, Peripheral}; | |||
| 28 | #[non_exhaustive] | 28 | #[non_exhaustive] |
| 29 | pub enum Error {} | 29 | pub enum Error {} |
| 30 | 30 | ||
| 31 | /// One-shot and continuous SAADC. | 31 | /// Interrupt handler. |
| 32 | pub struct Saadc<'d, const N: usize> { | 32 | pub struct InterruptHandler { |
| 33 | _p: PeripheralRef<'d, peripherals::SAADC>, | 33 | _private: (), |
| 34 | } | ||
| 35 | |||
| 36 | impl 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 | ||
| 36 | static WAKER: AtomicWaker = AtomicWaker::new(); | 57 | static 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. | ||
| 139 | pub struct Saadc<'d, const N: usize> { | ||
| 140 | _p: PeripheralRef<'d, peripherals::SAADC>, | ||
| 141 | } | ||
| 142 | |||
| 117 | impl<'d, const N: usize> Saadc<'d, N> { | 143 | impl<'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 | ||
| 5 | use core::future::poll_fn; | 5 | use core::future::poll_fn; |
| 6 | use core::marker::PhantomData; | ||
| 6 | use core::sync::atomic::{compiler_fence, Ordering}; | 7 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 7 | use core::task::Poll; | 8 | use core::task::Poll; |
| 8 | 9 | ||
| @@ -14,7 +15,7 @@ pub use pac::spim0::frequency::FREQUENCY_A as Frequency; | |||
| 14 | use crate::chip::FORCE_COPY_BUFFER_SIZE; | 15 | use crate::chip::FORCE_COPY_BUFFER_SIZE; |
| 15 | use crate::gpio::sealed::Pin as _; | 16 | use crate::gpio::sealed::Pin as _; |
| 16 | use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; | 17 | use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; |
| 17 | use crate::interrupt::{Interrupt, InterruptExt}; | 18 | use crate::interrupt::{self, Interrupt, InterruptExt}; |
| 18 | use crate::util::{slice_in_ram_or, slice_ptr_parts, slice_ptr_parts_mut}; | 19 | use crate::util::{slice_in_ram_or, slice_ptr_parts, slice_ptr_parts_mut}; |
| 19 | use crate::{pac, Peripheral}; | 20 | use crate::{pac, Peripheral}; |
| 20 | 21 | ||
| @@ -31,11 +32,6 @@ pub enum Error { | |||
| 31 | BufferNotInRAM, | 32 | BufferNotInRAM, |
| 32 | } | 33 | } |
| 33 | 34 | ||
| 34 | /// SPIM driver. | ||
| 35 | pub struct Spim<'d, T: Instance> { | ||
| 36 | _p: PeripheralRef<'d, T>, | ||
| 37 | } | ||
| 38 | |||
| 39 | /// SPIM configuration. | 35 | /// SPIM configuration. |
| 40 | #[non_exhaustive] | 36 | #[non_exhaustive] |
| 41 | pub struct Config { | 37 | pub struct Config { |
| @@ -62,11 +58,33 @@ impl Default for Config { | |||
| 62 | } | 58 | } |
| 63 | } | 59 | } |
| 64 | 60 | ||
| 61 | /// Interrupt handler. | ||
| 62 | pub struct InterruptHandler<T: Instance> { | ||
| 63 | _phantom: PhantomData<T>, | ||
| 64 | } | ||
| 65 | |||
| 66 | impl<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. | ||
| 79 | pub struct Spim<'d, T: Instance> { | ||
| 80 | _p: PeripheralRef<'d, T>, | ||
| 81 | } | ||
| 82 | |||
| 65 | impl<'d, T: Instance> Spim<'d, T> { | 83 | impl<'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] |
| 4 | use core::future::poll_fn; | 4 | use core::future::poll_fn; |
| 5 | use core::marker::PhantomData; | ||
| 5 | use core::sync::atomic::{compiler_fence, Ordering}; | 6 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 6 | use core::task::Poll; | 7 | use 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 | |||
| 12 | use crate::chip::FORCE_COPY_BUFFER_SIZE; | 13 | use crate::chip::FORCE_COPY_BUFFER_SIZE; |
| 13 | use crate::gpio::sealed::Pin as _; | 14 | use crate::gpio::sealed::Pin as _; |
| 14 | use crate::gpio::{self, AnyPin, Pin as GpioPin}; | 15 | use crate::gpio::{self, AnyPin, Pin as GpioPin}; |
| 15 | use crate::interrupt::{Interrupt, InterruptExt}; | 16 | use crate::interrupt::{self, Interrupt, InterruptExt}; |
| 16 | use crate::util::{slice_in_ram_or, slice_ptr_parts, slice_ptr_parts_mut}; | 17 | use crate::util::{slice_in_ram_or, slice_ptr_parts, slice_ptr_parts_mut}; |
| 17 | use crate::{pac, Peripheral}; | 18 | use crate::{pac, Peripheral}; |
| 18 | 19 | ||
| @@ -29,11 +30,6 @@ pub enum Error { | |||
| 29 | BufferNotInRAM, | 30 | BufferNotInRAM, |
| 30 | } | 31 | } |
| 31 | 32 | ||
| 32 | /// SPIS driver. | ||
| 33 | pub struct Spis<'d, T: Instance> { | ||
| 34 | _p: PeripheralRef<'d, T>, | ||
| 35 | } | ||
| 36 | |||
| 37 | /// SPIS configuration. | 33 | /// SPIS configuration. |
| 38 | #[non_exhaustive] | 34 | #[non_exhaustive] |
| 39 | pub struct Config { | 35 | pub struct Config { |
| @@ -67,11 +63,38 @@ impl Default for Config { | |||
| 67 | } | 63 | } |
| 68 | } | 64 | } |
| 69 | 65 | ||
| 66 | /// Interrupt handler. | ||
| 67 | pub struct InterruptHandler<T: Instance> { | ||
| 68 | _phantom: PhantomData<T>, | ||
| 69 | } | ||
| 70 | |||
| 71 | impl<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. | ||
| 89 | pub struct Spis<'d, T: Instance> { | ||
| 90 | _p: PeripheralRef<'d, T>, | ||
| 91 | } | ||
| 92 | |||
| 70 | impl<'d, T: Instance> Spis<'d, T> { | 93 | impl<'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 @@ | |||
| 3 | use core::future::poll_fn; | 3 | use core::future::poll_fn; |
| 4 | use core::task::Poll; | 4 | use core::task::Poll; |
| 5 | 5 | ||
| 6 | use embassy_cortex_m::interrupt::Interrupt; | ||
| 6 | use embassy_hal_common::drop::OnDrop; | 7 | use embassy_hal_common::drop::OnDrop; |
| 7 | use embassy_hal_common::{into_ref, PeripheralRef}; | 8 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 8 | use embassy_sync::waitqueue::AtomicWaker; | 9 | use embassy_sync::waitqueue::AtomicWaker; |
| @@ -12,27 +13,39 @@ use crate::interrupt::InterruptExt; | |||
| 12 | use crate::peripherals::TEMP; | 13 | use crate::peripherals::TEMP; |
| 13 | use crate::{interrupt, pac, Peripheral}; | 14 | use crate::{interrupt, pac, Peripheral}; |
| 14 | 15 | ||
| 16 | /// Interrupt handler. | ||
| 17 | pub struct InterruptHandler { | ||
| 18 | _private: (), | ||
| 19 | } | ||
| 20 | |||
| 21 | impl 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. |
| 16 | pub struct Temp<'d> { | 30 | pub struct Temp<'d> { |
| 17 | _irq: PeripheralRef<'d, interrupt::TEMP>, | 31 | _peri: PeripheralRef<'d, TEMP>, |
| 18 | } | 32 | } |
| 19 | 33 | ||
| 20 | static WAKER: AtomicWaker = AtomicWaker::new(); | 34 | static WAKER: AtomicWaker = AtomicWaker::new(); |
| 21 | 35 | ||
| 22 | impl<'d> Temp<'d> { | 36 | impl<'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 | ||
| 9 | use core::future::poll_fn; | ||
| 10 | use core::marker::PhantomData; | ||
| 11 | use core::task::Poll; | ||
| 12 | |||
| 13 | use embassy_hal_common::drop::OnDrop; | ||
| 14 | use embassy_hal_common::{into_ref, PeripheralRef}; | 9 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 15 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 16 | 10 | ||
| 17 | use crate::interrupt::{Interrupt, InterruptExt}; | 11 | use crate::interrupt::Interrupt; |
| 18 | use crate::ppi::{Event, Task}; | 12 | use crate::ppi::{Event, Task}; |
| 19 | use crate::{pac, Peripheral}; | 13 | use 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 | ||
| 107 | pub trait TimerType: sealed::TimerType {} | ||
| 108 | |||
| 109 | /// Marker type indicating the timer driver can await expiration (it owns the timer interrupt). | ||
| 110 | pub enum Awaitable {} | ||
| 111 | |||
| 112 | /// Marker type indicating the timer driver cannot await expiration (it does not own the timer interrupt). | ||
| 113 | pub enum NotAwaitable {} | ||
| 114 | |||
| 115 | impl sealed::TimerType for Awaitable {} | ||
| 116 | impl sealed::TimerType for NotAwaitable {} | ||
| 117 | impl TimerType for Awaitable {} | ||
| 118 | impl TimerType for NotAwaitable {} | ||
| 119 | |||
| 120 | /// Timer driver. | 93 | /// Timer driver. |
| 121 | pub struct Timer<'d, T: Instance, I: TimerType = NotAwaitable> { | 94 | pub struct Timer<'d, T: Instance> { |
| 122 | _p: PeripheralRef<'d, T>, | 95 | _p: PeripheralRef<'d, T>, |
| 123 | _i: PhantomData<I>, | ||
| 124 | } | ||
| 125 | |||
| 126 | impl<'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 | ||
| 153 | impl<'d, T: Instance> Timer<'d, T, NotAwaitable> { | 98 | impl<'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 | ||
| 171 | impl<'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 |
| 311 | pub struct Cc<'d, T: Instance, I: TimerType = NotAwaitable> { | 234 | pub 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 | |||
| 317 | impl<'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 | } |
| 351 | impl<'d, T: Instance> Cc<'d, T, NotAwaitable> {} | ||
| 352 | 238 | ||
| 353 | impl<'d, T: Instance, I: TimerType> Cc<'d, T, I> { | 239 | impl<'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 | ||
| 5 | use core::future::{poll_fn, Future}; | 5 | use core::future::{poll_fn, Future}; |
| 6 | use core::marker::PhantomData; | ||
| 6 | use core::sync::atomic::compiler_fence; | 7 | use core::sync::atomic::compiler_fence; |
| 7 | use core::sync::atomic::Ordering::SeqCst; | 8 | use core::sync::atomic::Ordering::SeqCst; |
| 8 | use core::task::Poll; | 9 | use core::task::Poll; |
| @@ -15,7 +16,7 @@ use embassy_time::{Duration, Instant}; | |||
| 15 | 16 | ||
| 16 | use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; | 17 | use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; |
| 17 | use crate::gpio::Pin as GpioPin; | 18 | use crate::gpio::Pin as GpioPin; |
| 18 | use crate::interrupt::{Interrupt, InterruptExt}; | 19 | use crate::interrupt::{self, Interrupt, InterruptExt}; |
| 19 | use crate::util::{slice_in_ram, slice_in_ram_or}; | 20 | use crate::util::{slice_in_ram, slice_in_ram_or}; |
| 20 | use crate::{gpio, pac, Peripheral}; | 21 | use crate::{gpio, pac, Peripheral}; |
| 21 | 22 | ||
| @@ -92,6 +93,27 @@ pub enum Error { | |||
| 92 | Timeout, | 93 | Timeout, |
| 93 | } | 94 | } |
| 94 | 95 | ||
| 96 | /// Interrupt handler. | ||
| 97 | pub struct InterruptHandler<T: Instance> { | ||
| 98 | _phantom: PhantomData<T>, | ||
| 99 | } | ||
| 100 | |||
| 101 | impl<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. |
| 96 | pub struct Twim<'d, T: Instance> { | 118 | pub 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 | ||
| 5 | use core::future::{poll_fn, Future}; | 5 | use core::future::{poll_fn, Future}; |
| 6 | use core::marker::PhantomData; | ||
| 6 | use core::sync::atomic::compiler_fence; | 7 | use core::sync::atomic::compiler_fence; |
| 7 | use core::sync::atomic::Ordering::SeqCst; | 8 | use core::sync::atomic::Ordering::SeqCst; |
| 8 | use core::task::Poll; | 9 | use core::task::Poll; |
| @@ -14,7 +15,7 @@ use embassy_time::{Duration, Instant}; | |||
| 14 | 15 | ||
| 15 | use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; | 16 | use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; |
| 16 | use crate::gpio::Pin as GpioPin; | 17 | use crate::gpio::Pin as GpioPin; |
| 17 | use crate::interrupt::{Interrupt, InterruptExt}; | 18 | use crate::interrupt::{self, Interrupt, InterruptExt}; |
| 18 | use crate::util::slice_in_ram_or; | 19 | use crate::util::slice_in_ram_or; |
| 19 | use crate::{gpio, pac, Peripheral}; | 20 | use 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. | ||
| 113 | pub struct InterruptHandler<T: Instance> { | ||
| 114 | _phantom: PhantomData<T>, | ||
| 115 | } | ||
| 116 | |||
| 117 | impl<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. |
| 112 | pub struct Twis<'d, T: Instance> { | 138 | pub 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 | ||
| 16 | use core::future::poll_fn; | 16 | use core::future::poll_fn; |
| 17 | use core::marker::PhantomData; | ||
| 17 | use core::sync::atomic::{compiler_fence, Ordering}; | 18 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 18 | use core::task::Poll; | 19 | use core::task::Poll; |
| 19 | 20 | ||
| @@ -26,7 +27,7 @@ pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Pari | |||
| 26 | use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; | 27 | use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; |
| 27 | use crate::gpio::sealed::Pin as _; | 28 | use crate::gpio::sealed::Pin as _; |
| 28 | use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; | 29 | use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; |
| 29 | use crate::interrupt::{Interrupt, InterruptExt}; | 30 | use crate::interrupt::{self, Interrupt, InterruptExt}; |
| 30 | use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; | 31 | use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; |
| 31 | use crate::timer::{Frequency, Instance as TimerInstance, Timer}; | 32 | use crate::timer::{Frequency, Instance as TimerInstance, Timer}; |
| 32 | use crate::util::slice_in_ram_or; | 33 | use crate::util::slice_in_ram_or; |
| @@ -62,6 +63,27 @@ pub enum Error { | |||
| 62 | BufferNotInRAM, | 63 | BufferNotInRAM, |
| 63 | } | 64 | } |
| 64 | 65 | ||
| 66 | /// Interrupt handler. | ||
| 67 | pub struct InterruptHandler<T: Instance> { | ||
| 68 | _phantom: PhantomData<T>, | ||
| 69 | } | ||
| 70 | |||
| 71 | impl<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. |
| 66 | pub struct Uarte<'d, T: Instance> { | 88 | pub 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 | ||
| 5 | pub mod vbus_detect; | ||
| 6 | |||
| 5 | use core::future::poll_fn; | 7 | use core::future::poll_fn; |
| 6 | use core::marker::PhantomData; | 8 | use core::marker::PhantomData; |
| 7 | use core::mem::MaybeUninit; | 9 | use core::mem::MaybeUninit; |
| 8 | use core::sync::atomic::{compiler_fence, AtomicBool, AtomicU32, Ordering}; | 10 | use core::sync::atomic::{compiler_fence, AtomicU32, Ordering}; |
| 9 | use core::task::Poll; | 11 | use core::task::Poll; |
| 10 | 12 | ||
| 11 | use cortex_m::peripheral::NVIC; | 13 | use cortex_m::peripheral::NVIC; |
| @@ -15,7 +17,8 @@ use embassy_usb_driver as driver; | |||
| 15 | use embassy_usb_driver::{Direction, EndpointAddress, EndpointError, EndpointInfo, EndpointType, Event, Unsupported}; | 17 | use embassy_usb_driver::{Direction, EndpointAddress, EndpointError, EndpointInfo, EndpointType, Event, Unsupported}; |
| 16 | use pac::usbd::RegisterBlock; | 18 | use pac::usbd::RegisterBlock; |
| 17 | 19 | ||
| 18 | use crate::interrupt::{Interrupt, InterruptExt}; | 20 | use self::vbus_detect::VbusDetect; |
| 21 | use crate::interrupt::{self, Interrupt, InterruptExt}; | ||
| 19 | use crate::util::slice_in_ram; | 22 | use crate::util::slice_in_ram; |
| 20 | use crate::{pac, Peripheral}; | 23 | use crate::{pac, Peripheral}; |
| 21 | 24 | ||
| @@ -26,185 +29,13 @@ static EP_IN_WAKERS: [AtomicWaker; 8] = [NEW_AW; 8]; | |||
| 26 | static EP_OUT_WAKERS: [AtomicWaker; 8] = [NEW_AW; 8]; | 29 | static EP_OUT_WAKERS: [AtomicWaker; 8] = [NEW_AW; 8]; |
| 27 | static READY_ENDPOINTS: AtomicU32 = AtomicU32::new(0); | 30 | static READY_ENDPOINTS: AtomicU32 = AtomicU32::new(0); |
| 28 | 31 | ||
| 29 | /// Trait for detecting USB VBUS power. | 32 | /// Interrupt handler. |
| 30 | /// | 33 | pub 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. | ||
| 33 | pub 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"))] | ||
| 52 | pub struct HardwareVbusDetect { | ||
| 53 | _private: (), | ||
| 54 | } | ||
| 55 | |||
| 56 | static POWER_WAKER: AtomicWaker = NEW_AW; | ||
| 57 | |||
| 58 | #[cfg(not(feature = "_nrf5340-app"))] | ||
| 59 | impl 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"))] | ||
| 97 | impl 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. | ||
| 127 | pub struct SoftwareVbusDetect { | ||
| 128 | usb_detected: AtomicBool, | ||
| 129 | power_ready: AtomicBool, | ||
| 130 | } | ||
| 131 | |||
| 132 | impl 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 | |||
| 162 | impl 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. | 37 | impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> { |
| 184 | pub 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 | |||
| 191 | impl<'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 | ||
| 258 | impl<'d, T: Instance, P: VbusDetect + 'd> driver::Driver<'d> for Driver<'d, T, P> { | 89 | /// USB driver. |
| 90 | pub 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 | |||
| 97 | impl<'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 | |||
| 118 | impl<'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. |
| 312 | pub struct Bus<'d, T: Instance, P: VbusDetect> { | 172 | pub 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 | ||
| 318 | impl<'d, T: Instance, P: VbusDetect> driver::Bus for Bus<'d, T, P> { | 178 | impl<'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 | |||
| 3 | use core::future::poll_fn; | ||
| 4 | use core::sync::atomic::{AtomicBool, Ordering}; | ||
| 5 | use core::task::Poll; | ||
| 6 | |||
| 7 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 8 | |||
| 9 | use super::BUS_WAKER; | ||
| 10 | use crate::interrupt::{self, Interrupt, InterruptExt}; | ||
| 11 | use 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. | ||
| 17 | pub 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"))] | ||
| 32 | type UsbRegIrq = interrupt::POWER_CLOCK; | ||
| 33 | #[cfg(feature = "_nrf5340")] | ||
| 34 | type UsbRegIrq = interrupt::USBREGULATOR; | ||
| 35 | |||
| 36 | #[cfg(not(feature = "_nrf5340"))] | ||
| 37 | type UsbRegPeri = pac::POWER; | ||
| 38 | #[cfg(feature = "_nrf5340")] | ||
| 39 | type UsbRegPeri = pac::USBREGULATOR; | ||
| 40 | |||
| 41 | /// Interrupt handler. | ||
| 42 | pub struct InterruptHandler { | ||
| 43 | _private: (), | ||
| 44 | } | ||
| 45 | |||
| 46 | impl 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`]. | ||
| 72 | pub struct HardwareVbusDetect { | ||
| 73 | _private: (), | ||
| 74 | } | ||
| 75 | |||
| 76 | static POWER_WAKER: AtomicWaker = AtomicWaker::new(); | ||
| 77 | |||
| 78 | impl 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 | |||
| 93 | impl 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. | ||
| 123 | pub struct SoftwareVbusDetect { | ||
| 124 | usb_detected: AtomicBool, | ||
| 125 | power_ready: AtomicBool, | ||
| 126 | } | ||
| 127 | |||
| 128 | impl 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 | |||
| 158 | impl 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] |
| 8 | default = ["nightly"] | 8 | default = ["nightly"] |
| 9 | msos-descriptor = ["embassy-usb/msos-descriptor"] | ||
| 10 | nightly = ["embassy-executor/nightly", "embassy-nrf/nightly", "embassy-net/nightly", "embassy-nrf/unstable-traits", "embassy-usb", "embedded-io/async", "embassy-net", | 9 | nightly = ["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 | |||
| 17 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 16 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 18 | embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | 17 | embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } |
| 19 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"], optional = true } | 18 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"], optional = true } |
| 20 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"], optional = true } | 19 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt", "msos-descriptor",], optional = true } |
| 21 | embedded-io = "0.4.0" | 20 | embedded-io = "0.4.0" |
| 22 | embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx126x", "time", "defmt"], optional = true } | 21 | embassy-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 } | |||
| 36 | embedded-storage = "0.3.0" | 35 | embedded-storage = "0.3.0" |
| 37 | usbd-hid = "0.6.0" | 36 | usbd-hid = "0.6.0" |
| 38 | serde = { version = "1.0.136", default-features = false } | 37 | serde = { version = "1.0.136", default-features = false } |
| 39 | |||
| 40 | [[bin]] | ||
| 41 | name = "usb_serial_winusb" | ||
| 42 | required-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 | |||
| 5 | use defmt::info; | ||
| 6 | use embassy_executor::Spawner; | ||
| 7 | use embassy_nrf::interrupt; | ||
| 8 | use embassy_nrf::timer::Timer; | ||
| 9 | use {defmt_rtt as _, panic_probe as _}; | ||
| 10 | |||
| 11 | #[embassy_executor::main] | ||
| 12 | async 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 | ||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_nrf::buffered_uarte::BufferedUarte; | 7 | use embassy_nrf::buffered_uarte::{self, BufferedUarte}; |
| 8 | use embassy_nrf::{interrupt, uarte}; | 8 | use embassy_nrf::{bind_interrupts, peripherals, uarte}; |
| 9 | use embedded_io::asynch::Write; | 9 | use embedded_io::asynch::Write; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| 12 | bind_interrupts!(struct Irqs { | ||
| 13 | UARTE0_UART0 => buffered_uarte::InterruptHandler<peripherals::UARTE0>; | ||
| 14 | }); | ||
| 15 | |||
| 12 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 13 | async fn main(_spawner: Spawner) { | 17 | async 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; | |||
| 7 | use defmt::{error, info}; | 7 | use defmt::{error, info}; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_nrf::i2s::{self, Channels, Config, MasterClock, MultiBuffering, Sample as _, SampleWidth, I2S}; | 9 | use embassy_nrf::i2s::{self, Channels, Config, MasterClock, MultiBuffering, Sample as _, SampleWidth, I2S}; |
| 10 | use embassy_nrf::interrupt; | 10 | use embassy_nrf::{bind_interrupts, peripherals}; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
| 13 | type Sample = i16; | 13 | type Sample = i16; |
| @@ -15,6 +15,10 @@ type Sample = i16; | |||
| 15 | const NUM_BUFFERS: usize = 2; | 15 | const NUM_BUFFERS: usize = 2; |
| 16 | const NUM_SAMPLES: usize = 4; | 16 | const NUM_SAMPLES: usize = 4; |
| 17 | 17 | ||
| 18 | bind_interrupts!(struct Irqs { | ||
| 19 | I2S => i2s::InterruptHandler<peripherals::I2S>; | ||
| 20 | }); | ||
| 21 | |||
| 18 | #[embassy_executor::main] | 22 | #[embassy_executor::main] |
| 19 | async fn main(_spawner: Spawner) { | 23 | async 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 @@ | |||
| 5 | use defmt::{debug, error, info}; | 5 | use defmt::{debug, error, info}; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, MasterClock, Sample as _, SampleWidth, I2S}; | 7 | use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, MasterClock, Sample as _, SampleWidth, I2S}; |
| 8 | use embassy_nrf::interrupt; | ||
| 9 | use embassy_nrf::pwm::{Prescaler, SimplePwm}; | 8 | use embassy_nrf::pwm::{Prescaler, SimplePwm}; |
| 9 | use embassy_nrf::{bind_interrupts, peripherals}; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| 12 | type Sample = i16; | 12 | type Sample = i16; |
| 13 | 13 | ||
| 14 | const NUM_SAMPLES: usize = 500; | 14 | const NUM_SAMPLES: usize = 500; |
| 15 | 15 | ||
| 16 | bind_interrupts!(struct Irqs { | ||
| 17 | I2S => i2s::InterruptHandler<peripherals::I2S>; | ||
| 18 | }); | ||
| 19 | |||
| 16 | #[embassy_executor::main] | 20 | #[embassy_executor::main] |
| 17 | async fn main(_spawner: Spawner) { | 21 | async 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; | |||
| 7 | use defmt::{error, info}; | 7 | use defmt::{error, info}; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, MasterClock, Sample as _, SampleWidth, I2S}; | 9 | use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, MasterClock, Sample as _, SampleWidth, I2S}; |
| 10 | use embassy_nrf::interrupt; | 10 | use embassy_nrf::{bind_interrupts, peripherals}; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
| 13 | type Sample = i16; | 13 | type Sample = i16; |
| 14 | 14 | ||
| 15 | const NUM_SAMPLES: usize = 50; | 15 | const NUM_SAMPLES: usize = 50; |
| 16 | 16 | ||
| 17 | bind_interrupts!(struct Irqs { | ||
| 18 | I2S => i2s::InterruptHandler<peripherals::I2S>; | ||
| 19 | }); | ||
| 20 | |||
| 17 | #[embassy_executor::main] | 21 | #[embassy_executor::main] |
| 18 | async fn main(_spawner: Spawner) { | 22 | async 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::*; | |||
| 11 | use embassy_executor::Spawner; | 11 | use embassy_executor::Spawner; |
| 12 | use embassy_lora::sx126x::*; | 12 | use embassy_lora::sx126x::*; |
| 13 | use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull}; | 13 | use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull}; |
| 14 | use embassy_nrf::{interrupt, spim}; | 14 | use embassy_nrf::{bind_interrupts, peripherals, spim}; |
| 15 | use embassy_time::{Duration, Timer}; | 15 | use embassy_time::{Duration, Timer}; |
| 16 | use lorawan_device::async_device::radio::{Bandwidth, CodingRate, PhyRxTx, RfConfig, SpreadingFactor}; | 16 | use lorawan_device::async_device::radio::{Bandwidth, CodingRate, PhyRxTx, RfConfig, SpreadingFactor}; |
| 17 | use {defmt_rtt as _, panic_probe as _}; | 17 | use {defmt_rtt as _, panic_probe as _}; |
| 18 | 18 | ||
| 19 | bind_interrupts!(struct Irqs { | ||
| 20 | SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 => spim::InterruptHandler<peripherals::TWISPI1>; | ||
| 21 | }); | ||
| 22 | |||
| 19 | #[embassy_executor::main] | 23 | #[embassy_executor::main] |
| 20 | async fn main(_spawner: Spawner) { | 24 | async 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::*; | |||
| 12 | use embassy_executor::Spawner; | 12 | use embassy_executor::Spawner; |
| 13 | use embassy_lora::sx126x::*; | 13 | use embassy_lora::sx126x::*; |
| 14 | use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull}; | 14 | use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull}; |
| 15 | use embassy_nrf::{interrupt, spim}; | 15 | use embassy_nrf::{bind_interrupts, peripherals, spim}; |
| 16 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 16 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
| 17 | use embassy_sync::pubsub::{PubSubChannel, Publisher}; | 17 | use embassy_sync::pubsub::{PubSubChannel, Publisher}; |
| 18 | use embassy_time::{Duration, Timer}; | 18 | use embassy_time::{Duration, Timer}; |
| 19 | use lorawan_device::async_device::radio::{Bandwidth, CodingRate, PhyRxTx, RfConfig, SpreadingFactor, TxConfig}; | 19 | use lorawan_device::async_device::radio::{Bandwidth, CodingRate, PhyRxTx, RfConfig, SpreadingFactor, TxConfig}; |
| 20 | use {defmt_rtt as _, panic_probe as _, panic_probe as _}; | 20 | use {defmt_rtt as _, panic_probe as _, panic_probe as _}; |
| 21 | 21 | ||
| 22 | bind_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) |
| 23 | static MESSAGE_BUS: PubSubChannel<CriticalSectionRawMutex, Message, 2, 1, 2> = PubSubChannel::new(); | 27 | static 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 | ||
| 5 | use defmt::info; | 5 | use defmt::info; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_nrf::interrupt; | 7 | use embassy_nrf::pdm::{self, Config, Pdm}; |
| 8 | use embassy_nrf::pdm::{Config, Pdm}; | 8 | use embassy_nrf::{bind_interrupts, peripherals}; |
| 9 | use embassy_time::{Duration, Timer}; | 9 | use embassy_time::{Duration, Timer}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| 12 | bind_interrupts!(struct Irqs { | ||
| 13 | PDM => pdm::InterruptHandler<peripherals::PDM>; | ||
| 14 | }); | ||
| 15 | |||
| 12 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 13 | async fn main(_p: Spawner) { | 17 | async 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 | ||
| 5 | use defmt::info; | 5 | use defmt::info; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_nrf::interrupt; | ||
| 8 | use embassy_nrf::qdec::{self, Qdec}; | 7 | use embassy_nrf::qdec::{self, Qdec}; |
| 8 | use embassy_nrf::{bind_interrupts, peripherals}; | ||
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| 11 | bind_interrupts!(struct Irqs { | ||
| 12 | QDEC => qdec::InterruptHandler<peripherals::QDEC>; | ||
| 13 | }); | ||
| 14 | |||
| 11 | #[embassy_executor::main] | 15 | #[embassy_executor::main] |
| 12 | async fn main(_spawner: Spawner) { | 16 | async 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 @@ | |||
| 5 | use defmt::{assert_eq, info, unwrap}; | 5 | use defmt::{assert_eq, info, unwrap}; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_nrf::qspi::Frequency; | 7 | use embassy_nrf::qspi::Frequency; |
| 8 | use embassy_nrf::{interrupt, qspi}; | 8 | use embassy_nrf::{bind_interrupts, peripherals, qspi}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| 11 | const PAGE_SIZE: usize = 4096; | 11 | const PAGE_SIZE: usize = 4096; |
| @@ -15,6 +15,10 @@ const PAGE_SIZE: usize = 4096; | |||
| 15 | #[repr(C, align(4))] | 15 | #[repr(C, align(4))] |
| 16 | struct AlignedBuf([u8; 4096]); | 16 | struct AlignedBuf([u8; 4096]); |
| 17 | 17 | ||
| 18 | bind_interrupts!(struct Irqs { | ||
| 19 | QSPI => qspi::InterruptHandler<peripherals::QSPI>; | ||
| 20 | }); | ||
| 21 | |||
| 18 | #[embassy_executor::main] | 22 | #[embassy_executor::main] |
| 19 | async fn main(_spawner: Spawner) { | 23 | async 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; | |||
| 7 | use defmt::{info, unwrap}; | 7 | use defmt::{info, unwrap}; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_nrf::qspi::Frequency; | 9 | use embassy_nrf::qspi::Frequency; |
| 10 | use embassy_nrf::{interrupt, qspi}; | 10 | use embassy_nrf::{bind_interrupts, peripherals, qspi}; |
| 11 | use embassy_time::{Duration, Timer}; | 11 | use embassy_time::{Duration, Timer}; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {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))] |
| 17 | struct AlignedBuf([u8; 64]); | 17 | struct AlignedBuf([u8; 64]); |
| 18 | 18 | ||
| 19 | bind_interrupts!(struct Irqs { | ||
| 20 | QSPI => qspi::InterruptHandler<peripherals::QSPI>; | ||
| 21 | }); | ||
| 22 | |||
| 19 | #[embassy_executor::main] | 23 | #[embassy_executor::main] |
| 20 | async fn main(_p: Spawner) { | 24 | async 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 | ||
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_nrf::interrupt; | ||
| 7 | use embassy_nrf::rng::Rng; | 6 | use embassy_nrf::rng::Rng; |
| 7 | use embassy_nrf::{bind_interrupts, peripherals, rng}; | ||
| 8 | use rand::Rng as _; | 8 | use rand::Rng as _; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| 11 | bind_interrupts!(struct Irqs { | ||
| 12 | RNG => rng::InterruptHandler<peripherals::RNG>; | ||
| 13 | }); | ||
| 14 | |||
| 11 | #[embassy_executor::main] | 15 | #[embassy_executor::main] |
| 12 | async fn main(_spawner: Spawner) { | 16 | async 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 | ||
| 5 | use defmt::info; | 5 | use defmt::info; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_nrf::interrupt; | ||
| 8 | use embassy_nrf::saadc::{ChannelConfig, Config, Saadc}; | 7 | use embassy_nrf::saadc::{ChannelConfig, Config, Saadc}; |
| 8 | use embassy_nrf::{bind_interrupts, saadc}; | ||
| 9 | use embassy_time::{Duration, Timer}; | 9 | use embassy_time::{Duration, Timer}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| 12 | bind_interrupts!(struct Irqs { | ||
| 13 | SAADC => saadc::InterruptHandler; | ||
| 14 | }); | ||
| 15 | |||
| 12 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 13 | async fn main(_p: Spawner) { | 17 | async 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 | ||
| 5 | use defmt::info; | 5 | use defmt::info; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_nrf::interrupt; | ||
| 8 | use embassy_nrf::saadc::{CallbackResult, ChannelConfig, Config, Saadc}; | 7 | use embassy_nrf::saadc::{CallbackResult, ChannelConfig, Config, Saadc}; |
| 9 | use embassy_nrf::timer::Frequency; | 8 | use embassy_nrf::timer::Frequency; |
| 9 | use embassy_nrf::{bind_interrupts, saadc}; | ||
| 10 | use embassy_time::Duration; | 10 | use embassy_time::Duration; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {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 | ||
| 15 | bind_interrupts!(struct Irqs { | ||
| 16 | SAADC => saadc::InterruptHandler; | ||
| 17 | }); | ||
| 18 | |||
| 15 | #[embassy_executor::main] | 19 | #[embassy_executor::main] |
| 16 | async fn main(_p: Spawner) { | 20 | async 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 @@ | |||
| 5 | use defmt::{info, unwrap}; | 5 | use defmt::{info, unwrap}; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; | 7 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; |
| 8 | use embassy_nrf::{interrupt, spim}; | 8 | use embassy_nrf::{bind_interrupts, peripherals, spim}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| 11 | bind_interrupts!(struct Irqs { | ||
| 12 | SPIM3 => spim::InterruptHandler<peripherals::SPI3>; | ||
| 13 | }); | ||
| 14 | |||
| 11 | #[embassy_executor::main] | 15 | #[embassy_executor::main] |
| 12 | async fn main(_spawner: Spawner) { | 16 | async 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 | ||
| 5 | use defmt::info; | 5 | use defmt::info; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_nrf::interrupt; | ||
| 8 | use embassy_nrf::spis::{Config, Spis}; | 7 | use embassy_nrf::spis::{Config, Spis}; |
| 8 | use embassy_nrf::{bind_interrupts, peripherals, spis}; | ||
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| 11 | bind_interrupts!(struct Irqs { | ||
| 12 | SPIM2_SPIS2_SPI2 => spis::InterruptHandler<peripherals::SPI2>; | ||
| 13 | }); | ||
| 14 | |||
| 11 | #[embassy_executor::main] | 15 | #[embassy_executor::main] |
| 12 | async fn main(_spawner: Spawner) { | 16 | async 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 | ||
| 5 | use defmt::info; | 5 | use defmt::info; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_nrf::interrupt; | ||
| 8 | use embassy_nrf::temp::Temp; | 7 | use embassy_nrf::temp::Temp; |
| 8 | use embassy_nrf::{bind_interrupts, temp}; | ||
| 9 | use embassy_time::{Duration, Timer}; | 9 | use embassy_time::{Duration, Timer}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| 12 | bind_interrupts!(struct Irqs { | ||
| 13 | TEMP => temp::InterruptHandler; | ||
| 14 | }); | ||
| 15 | |||
| 12 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 13 | async fn main(_spawner: Spawner) { | 17 | async 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 | ||
| 9 | use defmt::*; | 9 | use defmt::*; |
| 10 | use embassy_executor::Spawner; | 10 | use embassy_executor::Spawner; |
| 11 | use embassy_nrf::interrupt; | ||
| 12 | use embassy_nrf::twim::{self, Twim}; | 11 | use embassy_nrf::twim::{self, Twim}; |
| 12 | use embassy_nrf::{bind_interrupts, peripherals}; | ||
| 13 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 14 | ||
| 15 | const ADDRESS: u8 = 0x50; | 15 | const ADDRESS: u8 = 0x50; |
| 16 | 16 | ||
| 17 | bind_interrupts!(struct Irqs { | ||
| 18 | SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0 => twim::InterruptHandler<peripherals::TWISPI0>; | ||
| 19 | }); | ||
| 20 | |||
| 17 | #[embassy_executor::main] | 21 | #[embassy_executor::main] |
| 18 | async fn main(_spawner: Spawner) { | 22 | async 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 | ||
| 13 | use defmt::*; | 13 | use defmt::*; |
| 14 | use embassy_executor::Spawner; | 14 | use embassy_executor::Spawner; |
| 15 | use embassy_nrf::interrupt; | ||
| 16 | use embassy_nrf::twim::{self, Twim}; | 15 | use embassy_nrf::twim::{self, Twim}; |
| 16 | use embassy_nrf::{bind_interrupts, peripherals}; | ||
| 17 | use embassy_time::{Duration, Timer}; | 17 | use embassy_time::{Duration, Timer}; |
| 18 | use {defmt_rtt as _, panic_probe as _}; | 18 | use {defmt_rtt as _, panic_probe as _}; |
| 19 | 19 | ||
| 20 | const ADDRESS: u8 = 0x50; | 20 | const ADDRESS: u8 = 0x50; |
| 21 | 21 | ||
| 22 | bind_interrupts!(struct Irqs { | ||
| 23 | SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0 => twim::InterruptHandler<peripherals::TWISPI0>; | ||
| 24 | }); | ||
| 25 | |||
| 22 | #[embassy_executor::main] | 26 | #[embassy_executor::main] |
| 23 | async fn main(_p: Spawner) { | 27 | async 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 | ||
| 7 | use defmt::*; | 7 | use defmt::*; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_nrf::interrupt; | ||
| 10 | use embassy_nrf::twis::{self, Command, Twis}; | 9 | use embassy_nrf::twis::{self, Command, Twis}; |
| 10 | use embassy_nrf::{bind_interrupts, peripherals}; | ||
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
| 13 | bind_interrupts!(struct Irqs { | ||
| 14 | SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0 => twis::InterruptHandler<peripherals::TWISPI0>; | ||
| 15 | }); | ||
| 16 | |||
| 13 | #[embassy_executor::main] | 17 | #[embassy_executor::main] |
| 14 | async fn main(_spawner: Spawner) { | 18 | async 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 | ||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_nrf::{interrupt, uarte}; | 7 | use embassy_nrf::{bind_interrupts, peripherals, uarte}; |
| 8 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 9 | ||
| 10 | bind_interrupts!(struct Irqs { | ||
| 11 | UARTE0_UART0 => uarte::InterruptHandler<peripherals::UARTE0>; | ||
| 12 | }); | ||
| 13 | |||
| 10 | #[embassy_executor::main] | 14 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 15 | async 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 | ||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_nrf::{interrupt, uarte}; | 7 | use embassy_nrf::peripherals::UARTE0; |
| 8 | use embassy_nrf::{bind_interrupts, uarte}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 10 | ||
| 11 | bind_interrupts!(struct Irqs { | ||
| 12 | UARTE0_UART0 => uarte::InterruptHandler<UARTE0>; | ||
| 13 | }); | ||
| 14 | |||
| 10 | #[embassy_executor::main] | 15 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 16 | async 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::*; | |||
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_nrf::peripherals::UARTE0; | 7 | use embassy_nrf::peripherals::UARTE0; |
| 8 | use embassy_nrf::uarte::UarteRx; | 8 | use embassy_nrf::uarte::UarteRx; |
| 9 | use embassy_nrf::{interrupt, uarte}; | 9 | use embassy_nrf::{bind_interrupts, uarte}; |
| 10 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; | 10 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; |
| 11 | use embassy_sync::channel::Channel; | 11 | use embassy_sync::channel::Channel; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
| 14 | static CHANNEL: Channel<ThreadModeRawMutex, [u8; 8], 1> = Channel::new(); | 14 | static CHANNEL: Channel<ThreadModeRawMutex, [u8; 8], 1> = Channel::new(); |
| 15 | 15 | ||
| 16 | bind_interrupts!(struct Irqs { | ||
| 17 | UARTE0_UART0 => uarte::InterruptHandler<UARTE0>; | ||
| 18 | }); | ||
| 19 | |||
| 16 | #[embassy_executor::main] | 20 | #[embassy_executor::main] |
| 17 | async fn main(spawner: Spawner) { | 21 | async 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; | |||
| 9 | use embassy_net::tcp::TcpSocket; | 9 | use embassy_net::tcp::TcpSocket; |
| 10 | use embassy_net::{Stack, StackResources}; | 10 | use embassy_net::{Stack, StackResources}; |
| 11 | use embassy_nrf::rng::Rng; | 11 | use embassy_nrf::rng::Rng; |
| 12 | use embassy_nrf::usb::{Driver, HardwareVbusDetect}; | 12 | use embassy_nrf::usb::vbus_detect::HardwareVbusDetect; |
| 13 | use embassy_nrf::{interrupt, pac, peripherals}; | 13 | use embassy_nrf::usb::Driver; |
| 14 | use embassy_nrf::{bind_interrupts, pac, peripherals, rng, usb}; | ||
| 14 | use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; | 15 | use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; |
| 15 | use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; | 16 | use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; |
| 16 | use embassy_usb::{Builder, Config, UsbDevice}; | 17 | use embassy_usb::{Builder, Config, UsbDevice}; |
| @@ -18,6 +19,12 @@ use embedded_io::asynch::Write; | |||
| 18 | use static_cell::StaticCell; | 19 | use static_cell::StaticCell; |
| 19 | use {defmt_rtt as _, panic_probe as _}; | 20 | use {defmt_rtt as _, panic_probe as _}; |
| 20 | 21 | ||
| 22 | bind_interrupts!(struct Irqs { | ||
| 23 | USBD => usb::InterruptHandler<peripherals::USBD>; | ||
| 24 | POWER_CLOCK => usb::vbus_detect::InterruptHandler; | ||
| 25 | RNG => rng::InterruptHandler<peripherals::RNG>; | ||
| 26 | }); | ||
| 27 | |||
| 21 | type MyDriver = Driver<'static, peripherals::USBD, HardwareVbusDetect>; | 28 | type MyDriver = Driver<'static, peripherals::USBD, HardwareVbusDetect>; |
| 22 | 29 | ||
| 23 | macro_rules! singleton { | 30 | macro_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; | |||
| 10 | use embassy_futures::join::join; | 10 | use embassy_futures::join::join; |
| 11 | use embassy_futures::select::{select, Either}; | 11 | use embassy_futures::select::{select, Either}; |
| 12 | use embassy_nrf::gpio::{Input, Pin, Pull}; | 12 | use embassy_nrf::gpio::{Input, Pin, Pull}; |
| 13 | use embassy_nrf::usb::{Driver, HardwareVbusDetect}; | 13 | use embassy_nrf::usb::vbus_detect::HardwareVbusDetect; |
| 14 | use embassy_nrf::{interrupt, pac}; | 14 | use embassy_nrf::usb::Driver; |
| 15 | use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; | ||
| 15 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 16 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
| 16 | use embassy_sync::signal::Signal; | 17 | use embassy_sync::signal::Signal; |
| 17 | use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; | 18 | use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; |
| @@ -20,6 +21,11 @@ use embassy_usb::{Builder, Config, Handler}; | |||
| 20 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; | 21 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; |
| 21 | use {defmt_rtt as _, panic_probe as _}; | 22 | use {defmt_rtt as _, panic_probe as _}; |
| 22 | 23 | ||
| 24 | bind_interrupts!(struct Irqs { | ||
| 25 | USBD => usb::InterruptHandler<peripherals::USBD>; | ||
| 26 | POWER_CLOCK => usb::vbus_detect::InterruptHandler; | ||
| 27 | }); | ||
| 28 | |||
| 23 | static SUSPENDED: AtomicBool = AtomicBool::new(false); | 29 | static 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; | |||
| 7 | use defmt::*; | 7 | use defmt::*; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_futures::join::join; | 9 | use embassy_futures::join::join; |
| 10 | use embassy_nrf::usb::{Driver, HardwareVbusDetect}; | 10 | use embassy_nrf::usb::vbus_detect::HardwareVbusDetect; |
| 11 | use embassy_nrf::{interrupt, pac}; | 11 | use embassy_nrf::usb::Driver; |
| 12 | use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; | ||
| 12 | use embassy_time::{Duration, Timer}; | 13 | use embassy_time::{Duration, Timer}; |
| 13 | use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; | 14 | use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; |
| 14 | use embassy_usb::control::OutResponse; | 15 | use embassy_usb::control::OutResponse; |
| @@ -16,6 +17,11 @@ use embassy_usb::{Builder, Config}; | |||
| 16 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; | 17 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; |
| 17 | use {defmt_rtt as _, panic_probe as _}; | 18 | use {defmt_rtt as _, panic_probe as _}; |
| 18 | 19 | ||
| 20 | bind_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] |
| 20 | async fn main(_spawner: Spawner) { | 26 | async 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; | |||
| 7 | use defmt::{info, panic}; | 7 | use defmt::{info, panic}; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_futures::join::join; | 9 | use embassy_futures::join::join; |
| 10 | use embassy_nrf::usb::{Driver, HardwareVbusDetect, Instance, VbusDetect}; | 10 | use embassy_nrf::usb::vbus_detect::{HardwareVbusDetect, VbusDetect}; |
| 11 | use embassy_nrf::{interrupt, pac}; | 11 | use embassy_nrf::usb::{Driver, Instance}; |
| 12 | use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; | ||
| 12 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 13 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 13 | use embassy_usb::driver::EndpointError; | 14 | use embassy_usb::driver::EndpointError; |
| 14 | use embassy_usb::{Builder, Config}; | 15 | use embassy_usb::{Builder, Config}; |
| 15 | use {defmt_rtt as _, panic_probe as _}; | 16 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 17 | ||
| 18 | bind_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] |
| 18 | async fn main(_spawner: Spawner) { | 24 | async 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 | ||
| 7 | use defmt::{info, panic, unwrap}; | 7 | use defmt::{info, panic, unwrap}; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_nrf::usb::{Driver, HardwareVbusDetect}; | 9 | use embassy_nrf::usb::vbus_detect::HardwareVbusDetect; |
| 10 | use embassy_nrf::{interrupt, pac, peripherals}; | 10 | use embassy_nrf::usb::Driver; |
| 11 | use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; | ||
| 11 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 12 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 12 | use embassy_usb::driver::EndpointError; | 13 | use embassy_usb::driver::EndpointError; |
| 13 | use embassy_usb::{Builder, Config, UsbDevice}; | 14 | use embassy_usb::{Builder, Config, UsbDevice}; |
| 14 | use static_cell::StaticCell; | 15 | use static_cell::StaticCell; |
| 15 | use {defmt_rtt as _, panic_probe as _}; | 16 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 17 | ||
| 18 | bind_interrupts!(struct Irqs { | ||
| 19 | USBD => usb::InterruptHandler<peripherals::USBD>; | ||
| 20 | POWER_CLOCK => usb::vbus_detect::InterruptHandler; | ||
| 21 | }); | ||
| 22 | |||
| 23 | macro_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 | |||
| 17 | type MyDriver = Driver<'static, peripherals::USBD, HardwareVbusDetect>; | 32 | type 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; | |||
| 7 | use defmt::{info, panic}; | 7 | use defmt::{info, panic}; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_futures::join::join; | 9 | use embassy_futures::join::join; |
| 10 | use embassy_nrf::usb::{Driver, HardwareVbusDetect, Instance, VbusDetect}; | 10 | use embassy_nrf::usb::vbus_detect::{HardwareVbusDetect, VbusDetect}; |
| 11 | use embassy_nrf::{interrupt, pac}; | 11 | use embassy_nrf::usb::{Driver, Instance}; |
| 12 | use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; | ||
| 12 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 13 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 13 | use embassy_usb::driver::EndpointError; | 14 | use embassy_usb::driver::EndpointError; |
| 14 | use embassy_usb::msos::{self, windows_version}; | 15 | use embassy_usb::msos::{self, windows_version}; |
| @@ -16,6 +17,11 @@ use embassy_usb::types::InterfaceNumber; | |||
| 16 | use embassy_usb::{Builder, Config}; | 17 | use embassy_usb::{Builder, Config}; |
| 17 | use {defmt_rtt as _, panic_probe as _}; | 18 | use {defmt_rtt as _, panic_probe as _}; |
| 18 | 19 | ||
| 20 | bind_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 |
| 20 | const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"]; | 26 | const 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 | ||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_nrf::{interrupt, uarte}; | 7 | use embassy_nrf::peripherals::SERIAL0; |
| 8 | use embassy_nrf::{bind_interrupts, uarte}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 10 | ||
| 11 | bind_interrupts!(struct Irqs { | ||
| 12 | SERIAL0 => uarte::InterruptHandler<SERIAL0>; | ||
| 13 | }); | ||
| 14 | |||
| 10 | #[embassy_executor::main] | 15 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 16 | async 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 @@ | |||
| 5 | use defmt::{assert_eq, *}; | 5 | use defmt::{assert_eq, *}; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_futures::join::join; | 7 | use embassy_futures::join::join; |
| 8 | use embassy_nrf::buffered_uarte::BufferedUarte; | 8 | use embassy_nrf::buffered_uarte::{self, BufferedUarte}; |
| 9 | use embassy_nrf::{interrupt, uarte}; | 9 | use embassy_nrf::{bind_interrupts, peripherals, uarte}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| 12 | bind_interrupts!(struct Irqs { | ||
| 13 | UARTE0_UART0 => buffered_uarte::InterruptHandler<peripherals::UARTE0>; | ||
| 14 | }); | ||
| 15 | |||
| 12 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 13 | async fn main(_spawner: Spawner) { | 17 | async 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 | ||
| 8 | use defmt::{assert_eq, *}; | 8 | use defmt::{assert_eq, *}; |
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_nrf::buffered_uarte::BufferedUarte; | 10 | use embassy_nrf::buffered_uarte::{self, BufferedUarte}; |
| 11 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; | 11 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; |
| 12 | use embassy_nrf::ppi::{Event, Ppi, Task}; | 12 | use embassy_nrf::ppi::{Event, Ppi, Task}; |
| 13 | use embassy_nrf::uarte::Uarte; | 13 | use embassy_nrf::uarte::Uarte; |
| 14 | use embassy_nrf::{interrupt, pac, uarte}; | 14 | use embassy_nrf::{bind_interrupts, pac, peripherals, uarte}; |
| 15 | use embassy_time::{Duration, Timer}; | 15 | use embassy_time::{Duration, Timer}; |
| 16 | use {defmt_rtt as _, panic_probe as _}; | 16 | use {defmt_rtt as _, panic_probe as _}; |
| 17 | 17 | ||
| 18 | bind_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] |
| 19 | async fn main(_spawner: Spawner) { | 24 | async 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 _)) }; |
