aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Dodd <[email protected]>2021-05-05 14:50:28 +0100
committerRichard Dodd <[email protected]>2021-05-05 14:50:28 +0100
commit1ad18aa09a8f6aefafab0b9e29c2c31dc614a320 (patch)
treed047596f2630815f92935e218ccf2368199a3b03
parente40346a54495e2cf2de6cf45c8c6e87bb634165f (diff)
Implement the blocking hal api for SPIM.
-rw-r--r--embassy-nrf/src/spim.rs105
1 files changed, 105 insertions, 0 deletions
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs
index d6b9ee8d8..d233a8af8 100644
--- a/embassy-nrf/src/spim.rs
+++ b/embassy-nrf/src/spim.rs
@@ -218,6 +218,111 @@ 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 let s = T::state();
236
237 // Set up the DMA write.
238 r.txd
239 .ptr
240 .write(|w| unsafe { w.ptr().bits(words.as_ptr() as u32) });
241 r.txd
242 .maxcnt
243 .write(|w| unsafe { w.maxcnt().bits(words.len() as _) });
244
245 // Set up the DMA read.
246 r.rxd
247 .ptr
248 .write(|w| unsafe { w.ptr().bits(words.as_mut_ptr() as u32) });
249 r.rxd
250 .maxcnt
251 .write(|w| unsafe { w.maxcnt().bits(words.len() as _) });
252
253 // Reset and enable the event
254 r.events_end.reset();
255 r.intenset.write(|w| w.end().set());
256
257 // Start SPI transaction.
258 r.tasks_start.write(|w| unsafe { w.bits(1) });
259
260 // Conservative compiler fence to prevent optimizations that do not
261 // take in to account actions by DMA. The fence has been placed here,
262 // after all possible DMA actions have completed.
263 compiler_fence(Ordering::SeqCst);
264
265 // Wait for 'end' event.
266 while r.events_end.read().bits() == 0 {
267 continue;
268 }
269
270 Ok(words)
271 }
272}
273
274impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u8> for Spim<'d, T> {
275 type Error = Error;
276
277 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
278 slice_in_ram_or(words, Error::DMABufferNotInDataMemory)?;
279 let mut recv: &mut [u8] = &mut [];
280
281 // Conservative compiler fence to prevent optimizations that do not
282 // take in to account actions by DMA. The fence has been placed here,
283 // before any DMA action has started.
284 compiler_fence(Ordering::SeqCst);
285
286 let r = T::regs();
287 let s = T::state();
288
289 // Set up the DMA write.
290 r.txd
291 .ptr
292 .write(|w| unsafe { w.ptr().bits(words.as_ptr() as u32) });
293 r.txd
294 .maxcnt
295 .write(|w| unsafe { w.maxcnt().bits(words.len() as _) });
296
297 // Set up the DMA read.
298 r.rxd
299 .ptr
300 .write(|w| unsafe { w.ptr().bits(recv.as_mut_ptr() as u32) });
301 r.rxd
302 .maxcnt
303 .write(|w| unsafe { w.maxcnt().bits(recv.len() as _) });
304
305 // Reset and enable the event
306 r.events_end.reset();
307 r.intenset.write(|w| w.end().set());
308
309 // Start SPI transaction.
310 r.tasks_start.write(|w| unsafe { w.bits(1) });
311
312 // Conservative compiler fence to prevent optimizations that do not
313 // take in to account actions by DMA. The fence has been placed here,
314 // after all possible DMA actions have completed.
315 compiler_fence(Ordering::SeqCst);
316
317 // Wait for 'end' event.
318 while r.events_end.read().bits() == 0 {
319 continue;
320 }
321
322 Ok(())
323 }
324}
325
221mod sealed { 326mod sealed {
222 use super::*; 327 use super::*;
223 328