diff options
| author | Richard Dodd <[email protected]> | 2021-05-05 14:50:28 +0100 |
|---|---|---|
| committer | Richard Dodd <[email protected]> | 2021-05-05 14:50:28 +0100 |
| commit | 1ad18aa09a8f6aefafab0b9e29c2c31dc614a320 (patch) | |
| tree | d047596f2630815f92935e218ccf2368199a3b03 | |
| parent | e40346a54495e2cf2de6cf45c8c6e87bb634165f (diff) | |
Implement the blocking hal api for SPIM.
| -rw-r--r-- | embassy-nrf/src/spim.rs | 105 |
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. | ||
| 224 | impl<'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 | |||
| 274 | impl<'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 | |||
| 221 | mod sealed { | 326 | mod sealed { |
| 222 | use super::*; | 327 | use super::*; |
| 223 | 328 | ||
