diff options
| -rw-r--r-- | embassy-nrf/src/spim.rs | 97 |
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. | ||
| 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 | |||
| 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 | |||
| 270 | impl<'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 | |||
| 221 | mod sealed { | 318 | mod sealed { |
| 222 | use super::*; | 319 | use super::*; |
| 223 | 320 | ||
