aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-nrf/src/spim.rs97
1 files changed, 97 insertions, 0 deletions
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs
index d6b9ee8d8..3370e1243 100644
--- a/embassy-nrf/src/spim.rs
+++ b/embassy-nrf/src/spim.rs
@@ -218,6 +218,103 @@ impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> {
218 } 218 }
219} 219}
220 220
221// Blocking functions are provided by implementing `embedded_hal` traits.
222//
223// Code could be shared between traits to reduce code size.
224impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spim<'d, T> {
225 type Error = Error;
226 fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
227 slice_in_ram_or(words, Error::DMABufferNotInDataMemory)?;
228
229 // Conservative compiler fence to prevent optimizations that do not
230 // take in to account actions by DMA. The fence has been placed here,
231 // before any DMA action has started.
232 compiler_fence(Ordering::SeqCst);
233
234 let r = T::regs();
235
236 // Set up the DMA write.
237 r.txd
238 .ptr
239 .write(|w| unsafe { w.ptr().bits(words.as_ptr() as u32) });
240 r.txd
241 .maxcnt
242 .write(|w| unsafe { w.maxcnt().bits(words.len() as _) });
243
244 // Set up the DMA read.
245 r.rxd
246 .ptr
247 .write(|w| unsafe { w.ptr().bits(words.as_mut_ptr() as u32) });
248 r.rxd
249 .maxcnt
250 .write(|w| unsafe { w.maxcnt().bits(words.len() as _) });
251
252 // Disable the end event since we are busy-polling.
253 r.events_end.reset();
254
255 // Start SPI transaction.
256 r.tasks_start.write(|w| unsafe { w.bits(1) });
257
258 // Wait for 'end' event.
259 while r.events_end.read().bits() == 0 {}
260
261 // Conservative compiler fence to prevent optimizations that do not
262 // take in to account actions by DMA. The fence has been placed here,
263 // after all possible DMA actions have completed.
264 compiler_fence(Ordering::SeqCst);
265
266 Ok(words)
267 }
268}
269
270impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u8> for Spim<'d, T> {
271 type Error = Error;
272
273 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
274 slice_in_ram_or(words, Error::DMABufferNotInDataMemory)?;
275 let mut recv: &mut [u8] = &mut [];
276
277 // Conservative compiler fence to prevent optimizations that do not
278 // take in to account actions by DMA. The fence has been placed here,
279 // before any DMA action has started.
280 compiler_fence(Ordering::SeqCst);
281
282 let r = T::regs();
283
284 // Set up the DMA write.
285 r.txd
286 .ptr
287 .write(|w| unsafe { w.ptr().bits(words.as_ptr() as u32) });
288 r.txd
289 .maxcnt
290 .write(|w| unsafe { w.maxcnt().bits(words.len() as _) });
291
292 // Set up the DMA read.
293 r.rxd
294 .ptr
295 .write(|w| unsafe { w.ptr().bits(recv.as_mut_ptr() as u32) });
296 r.rxd
297 .maxcnt
298 .write(|w| unsafe { w.maxcnt().bits(recv.len() as _) });
299
300 // Disable the end event since we are busy-polling.
301 r.events_end.reset();
302
303 // Start SPI transaction.
304 r.tasks_start.write(|w| unsafe { w.bits(1) });
305
306 // Wait for 'end' event.
307 while r.events_end.read().bits() == 0 {}
308
309 // Conservative compiler fence to prevent optimizations that do not
310 // take in to account actions by DMA. The fence has been placed here,
311 // after all possible DMA actions have completed.
312 compiler_fence(Ordering::SeqCst);
313
314 Ok(())
315 }
316}
317
221mod sealed { 318mod sealed {
222 use super::*; 319 use super::*;
223 320