aboutsummaryrefslogtreecommitdiff
path: root/embassy-nrf/src
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-nrf/src')
-rw-r--r--embassy-nrf/src/fmt.rs45
-rw-r--r--embassy-nrf/src/gpiote.rs1
-rw-r--r--embassy-nrf/src/lib.rs1
-rw-r--r--embassy-nrf/src/spim.rs130
-rw-r--r--embassy-nrf/src/spis.rs45
-rw-r--r--embassy-nrf/src/temp.rs1
-rw-r--r--embassy-nrf/src/twim.rs9
7 files changed, 135 insertions, 97 deletions
diff --git a/embassy-nrf/src/fmt.rs b/embassy-nrf/src/fmt.rs
index 066970813..78e583c1c 100644
--- a/embassy-nrf/src/fmt.rs
+++ b/embassy-nrf/src/fmt.rs
@@ -1,6 +1,8 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused_macros)]
3 3
4use core::fmt::{Debug, Display, LowerHex};
5
4#[cfg(all(feature = "defmt", feature = "log"))] 6#[cfg(all(feature = "defmt", feature = "log"))]
5compile_error!("You may not enable both `defmt` and `log` features."); 7compile_error!("You may not enable both `defmt` and `log` features.");
6 8
@@ -81,14 +83,17 @@ macro_rules! todo {
81 }; 83 };
82} 84}
83 85
86#[cfg(not(feature = "defmt"))]
84macro_rules! unreachable { 87macro_rules! unreachable {
85 ($($x:tt)*) => { 88 ($($x:tt)*) => {
86 { 89 ::core::unreachable!($($x)*)
87 #[cfg(not(feature = "defmt"))] 90 };
88 ::core::unreachable!($($x)*); 91}
89 #[cfg(feature = "defmt")] 92
90 ::defmt::unreachable!($($x)*); 93#[cfg(feature = "defmt")]
91 } 94macro_rules! unreachable {
95 ($($x:tt)*) => {
96 ::defmt::unreachable!($($x)*)
92 }; 97 };
93} 98}
94 99
@@ -223,3 +228,31 @@ impl<T, E> Try for Result<T, E> {
223 self 228 self
224 } 229 }
225} 230}
231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]);
234
235impl<'a> Debug for Bytes<'a> {
236 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
237 write!(f, "{:#02x?}", self.0)
238 }
239}
240
241impl<'a> Display for Bytes<'a> {
242 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
243 write!(f, "{:#02x?}", self.0)
244 }
245}
246
247impl<'a> LowerHex for Bytes<'a> {
248 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
249 write!(f, "{:#02x?}", self.0)
250 }
251}
252
253#[cfg(feature = "defmt")]
254impl<'a> defmt::Format for Bytes<'a> {
255 fn format(&self, fmt: defmt::Formatter) {
256 defmt::write!(fmt, "{:02x}", self.0)
257 }
258}
diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs
index 7488bc085..d16b4a43b 100644
--- a/embassy-nrf/src/gpiote.rs
+++ b/embassy-nrf/src/gpiote.rs
@@ -86,7 +86,6 @@ pub(crate) fn init(irq_prio: crate::interrupt::Priority) {
86 unsafe { irq.enable() }; 86 unsafe { irq.enable() };
87 87
88 let g = regs(); 88 let g = regs();
89 g.events_port.write(|w| w);
90 g.intenset.write(|w| w.port().set()); 89 g.intenset.write(|w| w.port().set());
91} 90}
92 91
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index 355a00497..9c4b6569d 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -102,6 +102,7 @@ mod chip;
102#[macro_export] 102#[macro_export]
103macro_rules! bind_interrupts { 103macro_rules! bind_interrupts {
104 ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => { 104 ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => {
105 #[derive(Copy, Clone)]
105 $vis struct $name; 106 $vis struct $name;
106 107
107 $( 108 $(
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs
index d131a43dd..4828af43e 100644
--- a/embassy-nrf/src/spim.rs
+++ b/embassy-nrf/src/spim.rs
@@ -68,8 +68,14 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
68 let r = T::regs(); 68 let r = T::regs();
69 let s = T::state(); 69 let s = T::state();
70 70
71 #[cfg(feature = "_nrf52832_anomaly_109")]
72 if r.events_started.read().bits() != 0 {
73 s.waker.wake();
74 r.intenclr.write(|w| w.started().clear());
75 }
76
71 if r.events_end.read().bits() != 0 { 77 if r.events_end.read().bits() != 0 {
72 s.end_waker.wake(); 78 s.waker.wake();
73 r.intenclr.write(|w| w.end().clear()); 79 r.intenclr.write(|w| w.end().clear());
74 } 80 }
75 } 81 }
@@ -167,42 +173,10 @@ impl<'d, T: Instance> Spim<'d, T> {
167 // Enable SPIM instance. 173 // Enable SPIM instance.
168 r.enable.write(|w| w.enable().enabled()); 174 r.enable.write(|w| w.enable().enabled());
169 175
170 // Configure mode. 176 let mut spim = Self { _p: spim };
171 let mode = config.mode;
172 r.config.write(|w| {
173 match mode {
174 MODE_0 => {
175 w.order().msb_first();
176 w.cpol().active_high();
177 w.cpha().leading();
178 }
179 MODE_1 => {
180 w.order().msb_first();
181 w.cpol().active_high();
182 w.cpha().trailing();
183 }
184 MODE_2 => {
185 w.order().msb_first();
186 w.cpol().active_low();
187 w.cpha().leading();
188 }
189 MODE_3 => {
190 w.order().msb_first();
191 w.cpol().active_low();
192 w.cpha().trailing();
193 }
194 }
195 177
196 w 178 // Apply runtime peripheral configuration
197 }); 179 Self::set_config(&mut spim, &config);
198
199 // Configure frequency.
200 let frequency = config.frequency;
201 r.frequency.write(|w| w.frequency().variant(frequency));
202
203 // Set over-read character
204 let orc = config.orc;
205 r.orc.write(|w| unsafe { w.orc().bits(orc) });
206 180
207 // Disable all events interrupts 181 // Disable all events interrupts
208 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); 182 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
@@ -210,7 +184,7 @@ impl<'d, T: Instance> Spim<'d, T> {
210 T::Interrupt::unpend(); 184 T::Interrupt::unpend();
211 unsafe { T::Interrupt::enable() }; 185 unsafe { T::Interrupt::enable() };
212 186
213 Self { _p: spim } 187 spim
214 } 188 }
215 189
216 fn prepare(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> { 190 fn prepare(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> {
@@ -223,14 +197,32 @@ impl<'d, T: Instance> Spim<'d, T> {
223 let r = T::regs(); 197 let r = T::regs();
224 198
225 // Set up the DMA write. 199 // Set up the DMA write.
226 let (ptr, len) = slice_ptr_parts(tx); 200 let (ptr, tx_len) = slice_ptr_parts(tx);
227 r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) }); 201 r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) });
228 r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); 202 r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(tx_len as _) });
229 203
230 // Set up the DMA read. 204 // Set up the DMA read.
231 let (ptr, len) = slice_ptr_parts_mut(rx); 205 let (ptr, rx_len) = slice_ptr_parts_mut(rx);
232 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) }); 206 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) });
233 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); 207 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(rx_len as _) });
208
209 #[cfg(feature = "_nrf52832_anomaly_109")]
210 {
211 let s = T::state();
212
213 r.events_started.reset();
214
215 // Set rx/tx buffer lengths to 0...
216 r.txd.maxcnt.reset();
217 r.rxd.maxcnt.reset();
218
219 // ...and keep track of original buffer lengths...
220 s.tx.store(tx_len as _, Ordering::Relaxed);
221 s.rx.store(rx_len as _, Ordering::Relaxed);
222
223 // ...signalling the start of the fake transfer.
224 r.intenset.write(|w| w.started().bit(true));
225 }
234 226
235 // Reset and enable the event 227 // Reset and enable the event
236 r.events_end.reset(); 228 r.events_end.reset();
@@ -245,6 +237,9 @@ impl<'d, T: Instance> Spim<'d, T> {
245 fn blocking_inner_from_ram(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> { 237 fn blocking_inner_from_ram(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> {
246 self.prepare(rx, tx)?; 238 self.prepare(rx, tx)?;
247 239
240 #[cfg(feature = "_nrf52832_anomaly_109")]
241 while let Poll::Pending = self.nrf52832_dma_workaround_status() {}
242
248 // Wait for 'end' event. 243 // Wait for 'end' event.
249 while T::regs().events_end.read().bits() == 0 {} 244 while T::regs().events_end.read().bits() == 0 {}
250 245
@@ -269,9 +264,19 @@ impl<'d, T: Instance> Spim<'d, T> {
269 async fn async_inner_from_ram(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> { 264 async fn async_inner_from_ram(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> {
270 self.prepare(rx, tx)?; 265 self.prepare(rx, tx)?;
271 266
267 #[cfg(feature = "_nrf52832_anomaly_109")]
268 poll_fn(|cx| {
269 let s = T::state();
270
271 s.waker.register(cx.waker());
272
273 self.nrf52832_dma_workaround_status()
274 })
275 .await;
276
272 // Wait for 'end' event. 277 // Wait for 'end' event.
273 poll_fn(|cx| { 278 poll_fn(|cx| {
274 T::state().end_waker.register(cx.waker()); 279 T::state().waker.register(cx.waker());
275 if T::regs().events_end.read().bits() != 0 { 280 if T::regs().events_end.read().bits() != 0 {
276 return Poll::Ready(()); 281 return Poll::Ready(());
277 } 282 }
@@ -362,6 +367,32 @@ impl<'d, T: Instance> Spim<'d, T> {
362 pub async fn write_from_ram(&mut self, data: &[u8]) -> Result<(), Error> { 367 pub async fn write_from_ram(&mut self, data: &[u8]) -> Result<(), Error> {
363 self.async_inner_from_ram(&mut [], data).await 368 self.async_inner_from_ram(&mut [], data).await
364 } 369 }
370
371 #[cfg(feature = "_nrf52832_anomaly_109")]
372 fn nrf52832_dma_workaround_status(&mut self) -> Poll<()> {
373 let r = T::regs();
374 if r.events_started.read().bits() != 0 {
375 let s = T::state();
376
377 // Handle the first "fake" transmission
378 r.events_started.reset();
379 r.events_end.reset();
380
381 // Update DMA registers with correct rx/tx buffer sizes
382 r.rxd
383 .maxcnt
384 .write(|w| unsafe { w.maxcnt().bits(s.rx.load(Ordering::Relaxed)) });
385 r.txd
386 .maxcnt
387 .write(|w| unsafe { w.maxcnt().bits(s.tx.load(Ordering::Relaxed)) });
388
389 r.intenset.write(|w| w.end().set());
390 // ... and start actual, hopefully glitch-free transmission
391 r.tasks_start.write(|w| unsafe { w.bits(1) });
392 return Poll::Ready(());
393 }
394 Poll::Pending
395 }
365} 396}
366 397
367impl<'d, T: Instance> Drop for Spim<'d, T> { 398impl<'d, T: Instance> Drop for Spim<'d, T> {
@@ -386,18 +417,29 @@ impl<'d, T: Instance> Drop for Spim<'d, T> {
386} 417}
387 418
388pub(crate) mod sealed { 419pub(crate) mod sealed {
420 #[cfg(feature = "_nrf52832_anomaly_109")]
421 use core::sync::atomic::AtomicU8;
422
389 use embassy_sync::waitqueue::AtomicWaker; 423 use embassy_sync::waitqueue::AtomicWaker;
390 424
391 use super::*; 425 use super::*;
392 426
393 pub struct State { 427 pub struct State {
394 pub end_waker: AtomicWaker, 428 pub waker: AtomicWaker,
429 #[cfg(feature = "_nrf52832_anomaly_109")]
430 pub rx: AtomicU8,
431 #[cfg(feature = "_nrf52832_anomaly_109")]
432 pub tx: AtomicU8,
395 } 433 }
396 434
397 impl State { 435 impl State {
398 pub const fn new() -> Self { 436 pub const fn new() -> Self {
399 Self { 437 Self {
400 end_waker: AtomicWaker::new(), 438 waker: AtomicWaker::new(),
439 #[cfg(feature = "_nrf52832_anomaly_109")]
440 rx: AtomicU8::new(0),
441 #[cfg(feature = "_nrf52832_anomaly_109")]
442 tx: AtomicU8::new(0),
401 } 443 }
402 } 444 }
403 } 445 }
diff --git a/embassy-nrf/src/spis.rs b/embassy-nrf/src/spis.rs
index 212825121..e695ba6b7 100644
--- a/embassy-nrf/src/spis.rs
+++ b/embassy-nrf/src/spis.rs
@@ -169,47 +169,10 @@ impl<'d, T: Instance> Spis<'d, T> {
169 // Enable SPIS instance. 169 // Enable SPIS instance.
170 r.enable.write(|w| w.enable().enabled()); 170 r.enable.write(|w| w.enable().enabled());
171 171
172 // Configure mode. 172 let mut spis = Self { _p: spis };
173 let mode = config.mode;
174 r.config.write(|w| {
175 match mode {
176 MODE_0 => {
177 w.order().msb_first();
178 w.cpol().active_high();
179 w.cpha().leading();
180 }
181 MODE_1 => {
182 w.order().msb_first();
183 w.cpol().active_high();
184 w.cpha().trailing();
185 }
186 MODE_2 => {
187 w.order().msb_first();
188 w.cpol().active_low();
189 w.cpha().leading();
190 }
191 MODE_3 => {
192 w.order().msb_first();
193 w.cpol().active_low();
194 w.cpha().trailing();
195 }
196 }
197 173
198 w 174 // Apply runtime peripheral configuration
199 }); 175 Self::set_config(&mut spis, &config);
200
201 // Set over-read character.
202 let orc = config.orc;
203 r.orc.write(|w| unsafe { w.orc().bits(orc) });
204
205 // Set default character.
206 let def = config.def;
207 r.def.write(|w| unsafe { w.def().bits(def) });
208
209 // Configure auto-acquire on 'transfer end' event.
210 if config.auto_acquire {
211 r.shorts.write(|w| w.end_acquire().bit(true));
212 }
213 176
214 // Disable all events interrupts. 177 // Disable all events interrupts.
215 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); 178 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
@@ -217,7 +180,7 @@ impl<'d, T: Instance> Spis<'d, T> {
217 T::Interrupt::unpend(); 180 T::Interrupt::unpend();
218 unsafe { T::Interrupt::enable() }; 181 unsafe { T::Interrupt::enable() };
219 182
220 Self { _p: spis } 183 spis
221 } 184 }
222 185
223 fn prepare(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> { 186 fn prepare(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> {
diff --git a/embassy-nrf/src/temp.rs b/embassy-nrf/src/temp.rs
index cec46d8d0..5e2998b10 100644
--- a/embassy-nrf/src/temp.rs
+++ b/embassy-nrf/src/temp.rs
@@ -57,7 +57,6 @@ impl<'d> Temp<'d> {
57 /// ```no_run 57 /// ```no_run
58 /// use embassy_nrf::{bind_interrupts, temp}; 58 /// use embassy_nrf::{bind_interrupts, temp};
59 /// use embassy_nrf::temp::Temp; 59 /// use embassy_nrf::temp::Temp;
60 /// use embassy_time::{Duration, Timer};
61 /// 60 ///
62 /// bind_interrupts!(struct Irqs { 61 /// bind_interrupts!(struct Irqs {
63 /// TEMP => temp::InterruptHandler; 62 /// TEMP => temp::InterruptHandler;
diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs
index fdea480e3..fe38fb102 100644
--- a/embassy-nrf/src/twim.rs
+++ b/embassy-nrf/src/twim.rs
@@ -167,9 +167,10 @@ impl<'d, T: Instance> Twim<'d, T> {
167 // Enable TWIM instance. 167 // Enable TWIM instance.
168 r.enable.write(|w| w.enable().enabled()); 168 r.enable.write(|w| w.enable().enabled());
169 169
170 // Configure frequency. 170 let mut twim = Self { _p: twim };
171 r.frequency 171
172 .write(|w| unsafe { w.frequency().bits(config.frequency as u32) }); 172 // Apply runtime peripheral configuration
173 Self::set_config(&mut twim, &config);
173 174
174 // Disable all events interrupts 175 // Disable all events interrupts
175 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); 176 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
@@ -177,7 +178,7 @@ impl<'d, T: Instance> Twim<'d, T> {
177 T::Interrupt::unpend(); 178 T::Interrupt::unpend();
178 unsafe { T::Interrupt::enable() }; 179 unsafe { T::Interrupt::enable() };
179 180
180 Self { _p: twim } 181 twim
181 } 182 }
182 183
183 /// Set TX buffer, checking that it is in RAM and has suitable length. 184 /// Set TX buffer, checking that it is in RAM and has suitable length.