diff options
| author | Dario Nieuwenhuis <[email protected]> | 2022-01-13 20:00:33 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2022-01-13 23:56:39 +0100 |
| commit | a287fef687b47edc57e17131e3d663cd860ad471 (patch) | |
| tree | f2d3b0b55d568eaee70f1714c485b3b0e77ecb18 | |
| parent | 7086642ce43de7c2fe476da94ec53ed6282087ec (diff) | |
nrf/spim: expose all functionality as inherent methods.
| -rw-r--r-- | embassy-nrf/src/spim.rs | 65 | ||||
| -rw-r--r-- | examples/nrf/src/bin/spim.rs | 9 |
2 files changed, 47 insertions, 27 deletions
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs index 8159cefe8..e767bc703 100644 --- a/embassy-nrf/src/spim.rs +++ b/embassy-nrf/src/spim.rs | |||
| @@ -133,9 +133,7 @@ impl<'d, T: Instance> Spim<'d, T> { | |||
| 133 | 133 | ||
| 134 | // Set over-read character | 134 | // Set over-read character |
| 135 | let orc = config.orc; | 135 | let orc = config.orc; |
| 136 | r.orc.write(|w| | 136 | r.orc.write(|w| unsafe { w.orc().bits(orc) }); |
| 137 | // The ORC field is 8 bits long, so any u8 is a valid value to write. | ||
| 138 | unsafe { w.orc().bits(orc) }); | ||
| 139 | 137 | ||
| 140 | // Disable all events interrupts | 138 | // Disable all events interrupts |
| 141 | r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); | 139 | r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); |
| @@ -159,14 +157,11 @@ impl<'d, T: Instance> Spim<'d, T> { | |||
| 159 | } | 157 | } |
| 160 | } | 158 | } |
| 161 | 159 | ||
| 162 | fn start_transfer(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> { | 160 | fn prepare(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> { |
| 163 | slice_in_ram_or(tx, Error::DMABufferNotInDataMemory)?; | 161 | slice_in_ram_or(tx, Error::DMABufferNotInDataMemory)?; |
| 164 | // NOTE: RAM slice check for rx is not necessary, as a mutable | 162 | // NOTE: RAM slice check for rx is not necessary, as a mutable |
| 165 | // slice can only be built from data located in RAM. | 163 | // slice can only be built from data located in RAM. |
| 166 | 164 | ||
| 167 | // Conservative compiler fence to prevent optimizations that do not | ||
| 168 | // take in to account actions by DMA. The fence has been placed here, | ||
| 169 | // before any DMA action has started. | ||
| 170 | compiler_fence(Ordering::SeqCst); | 165 | compiler_fence(Ordering::SeqCst); |
| 171 | 166 | ||
| 172 | let r = T::regs(); | 167 | let r = T::regs(); |
| @@ -191,22 +186,19 @@ impl<'d, T: Instance> Spim<'d, T> { | |||
| 191 | Ok(()) | 186 | Ok(()) |
| 192 | } | 187 | } |
| 193 | 188 | ||
| 194 | fn blocking_transfer(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> { | 189 | fn blocking_inner(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> { |
| 195 | self.start_transfer(rx, tx)?; | 190 | self.prepare(rx, tx)?; |
| 196 | 191 | ||
| 197 | // Wait for 'end' event. | 192 | // Wait for 'end' event. |
| 198 | while T::regs().events_end.read().bits() == 0 {} | 193 | while T::regs().events_end.read().bits() == 0 {} |
| 199 | 194 | ||
| 200 | // Conservative compiler fence to prevent optimizations that do not | ||
| 201 | // take in to account actions by DMA. The fence has been placed here, | ||
| 202 | // after all possible DMA actions have completed. | ||
| 203 | compiler_fence(Ordering::SeqCst); | 195 | compiler_fence(Ordering::SeqCst); |
| 204 | 196 | ||
| 205 | Ok(()) | 197 | Ok(()) |
| 206 | } | 198 | } |
| 207 | 199 | ||
| 208 | async fn async_transfer(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> { | 200 | async fn async_inner(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> { |
| 209 | self.start_transfer(rx, tx)?; | 201 | self.prepare(rx, tx)?; |
| 210 | 202 | ||
| 211 | // Wait for 'end' event. | 203 | // Wait for 'end' event. |
| 212 | poll_fn(|cx| { | 204 | poll_fn(|cx| { |
| @@ -219,13 +211,42 @@ impl<'d, T: Instance> Spim<'d, T> { | |||
| 219 | }) | 211 | }) |
| 220 | .await; | 212 | .await; |
| 221 | 213 | ||
| 222 | // Conservative compiler fence to prevent optimizations that do not | ||
| 223 | // take in to account actions by DMA. The fence has been placed here, | ||
| 224 | // after all possible DMA actions have completed. | ||
| 225 | compiler_fence(Ordering::SeqCst); | 214 | compiler_fence(Ordering::SeqCst); |
| 226 | 215 | ||
| 227 | Ok(()) | 216 | Ok(()) |
| 228 | } | 217 | } |
| 218 | |||
| 219 | pub fn blocking_read(&mut self, data: &mut [u8]) -> Result<(), Error> { | ||
| 220 | self.blocking_inner(data, &[]) | ||
| 221 | } | ||
| 222 | |||
| 223 | pub fn blocking_transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> { | ||
| 224 | self.blocking_inner(read, write) | ||
| 225 | } | ||
| 226 | |||
| 227 | pub fn blocking_transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Error> { | ||
| 228 | self.blocking_inner(data, data) | ||
| 229 | } | ||
| 230 | |||
| 231 | pub fn blocking_write(&mut self, data: &[u8]) -> Result<(), Error> { | ||
| 232 | self.blocking_inner(&mut [], data) | ||
| 233 | } | ||
| 234 | |||
| 235 | pub async fn read(&mut self, data: &mut [u8]) -> Result<(), Error> { | ||
| 236 | self.async_inner(data, &[]).await | ||
| 237 | } | ||
| 238 | |||
| 239 | pub async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> { | ||
| 240 | self.async_inner(read, write).await | ||
| 241 | } | ||
| 242 | |||
| 243 | pub async fn transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Error> { | ||
| 244 | self.async_inner(data, data).await | ||
| 245 | } | ||
| 246 | |||
| 247 | pub async fn write(&mut self, data: &[u8]) -> Result<(), Error> { | ||
| 248 | self.async_inner(&mut [], data).await | ||
| 249 | } | ||
| 229 | } | 250 | } |
| 230 | 251 | ||
| 231 | impl<'d, T: Instance> Drop for Spim<'d, T> { | 252 | impl<'d, T: Instance> Drop for Spim<'d, T> { |
| @@ -257,7 +278,7 @@ impl<'d, T: Instance> Read<u8> for Spim<'d, T> { | |||
| 257 | = impl Future<Output = Result<(), Self::Error>> + 'a; | 278 | = impl Future<Output = Result<(), Self::Error>> + 'a; |
| 258 | 279 | ||
| 259 | fn read<'a>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'a> { | 280 | fn read<'a>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'a> { |
| 260 | self.read_write(data, &[]) | 281 | self.read(data) |
| 261 | } | 282 | } |
| 262 | } | 283 | } |
| 263 | 284 | ||
| @@ -268,7 +289,7 @@ impl<'d, T: Instance> Write<u8> for Spim<'d, T> { | |||
| 268 | = impl Future<Output = Result<(), Self::Error>> + 'a; | 289 | = impl Future<Output = Result<(), Self::Error>> + 'a; |
| 269 | 290 | ||
| 270 | fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> { | 291 | fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> { |
| 271 | self.read_write(&mut [], data) | 292 | self.write(data) |
| 272 | } | 293 | } |
| 273 | } | 294 | } |
| 274 | 295 | ||
| @@ -279,14 +300,14 @@ impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> { | |||
| 279 | = impl Future<Output = Result<(), Self::Error>> + 'a; | 300 | = impl Future<Output = Result<(), Self::Error>> + 'a; |
| 280 | 301 | ||
| 281 | fn read_write<'a>(&'a mut self, rx: &'a mut [u8], tx: &'a [u8]) -> Self::WriteReadFuture<'a> { | 302 | fn read_write<'a>(&'a mut self, rx: &'a mut [u8], tx: &'a [u8]) -> Self::WriteReadFuture<'a> { |
| 282 | self.async_transfer(rx, tx) | 303 | self.transfer(rx, tx) |
| 283 | } | 304 | } |
| 284 | } | 305 | } |
| 285 | 306 | ||
| 286 | impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spim<'d, T> { | 307 | impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spim<'d, T> { |
| 287 | type Error = Error; | 308 | type Error = Error; |
| 288 | fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { | 309 | fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { |
| 289 | self.blocking_transfer(words, words)?; | 310 | self.blocking_transfer_in_place(words)?; |
| 290 | Ok(words) | 311 | Ok(words) |
| 291 | } | 312 | } |
| 292 | } | 313 | } |
| @@ -295,7 +316,7 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u8> for Spim<'d, T> { | |||
| 295 | type Error = Error; | 316 | type Error = Error; |
| 296 | 317 | ||
| 297 | fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { | 318 | fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { |
| 298 | self.blocking_transfer(&mut [], words) | 319 | self.blocking_write(words) |
| 299 | } | 320 | } |
| 300 | } | 321 | } |
| 301 | 322 | ||
diff --git a/examples/nrf/src/bin/spim.rs b/examples/nrf/src/bin/spim.rs index fc31d140a..cda3baa26 100644 --- a/examples/nrf/src/bin/spim.rs +++ b/examples/nrf/src/bin/spim.rs | |||
| @@ -9,7 +9,6 @@ use embassy::executor::Spawner; | |||
| 9 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; | 9 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; |
| 10 | use embassy_nrf::Peripherals; | 10 | use embassy_nrf::Peripherals; |
| 11 | use embassy_nrf::{interrupt, spim}; | 11 | use embassy_nrf::{interrupt, spim}; |
| 12 | use embassy_traits::spi::FullDuplex; | ||
| 13 | use example_common::*; | 12 | use example_common::*; |
| 14 | 13 | ||
| 15 | #[embassy::main] | 14 | #[embassy::main] |
| @@ -31,7 +30,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 31 | ncs.set_low(); | 30 | ncs.set_low(); |
| 32 | cortex_m::asm::delay(5); | 31 | cortex_m::asm::delay(5); |
| 33 | let tx = [0xFF]; | 32 | let tx = [0xFF]; |
| 34 | unwrap!(spim.read_write(&mut [], &tx).await); | 33 | unwrap!(spim.transfer(&mut [], &tx).await); |
| 35 | cortex_m::asm::delay(10); | 34 | cortex_m::asm::delay(10); |
| 36 | ncs.set_high(); | 35 | ncs.set_high(); |
| 37 | 36 | ||
| @@ -44,7 +43,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 44 | ncs.set_low(); | 43 | ncs.set_low(); |
| 45 | cortex_m::asm::delay(5000); | 44 | cortex_m::asm::delay(5000); |
| 46 | let tx = [0b000_11101, 0]; | 45 | let tx = [0b000_11101, 0]; |
| 47 | unwrap!(spim.read_write(&mut rx, &tx).await); | 46 | unwrap!(spim.transfer(&mut rx, &tx).await); |
| 48 | cortex_m::asm::delay(5000); | 47 | cortex_m::asm::delay(5000); |
| 49 | ncs.set_high(); | 48 | ncs.set_high(); |
| 50 | info!("estat: {=[?]}", rx); | 49 | info!("estat: {=[?]}", rx); |
| @@ -54,7 +53,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 54 | ncs.set_low(); | 53 | ncs.set_low(); |
| 55 | cortex_m::asm::delay(5); | 54 | cortex_m::asm::delay(5); |
| 56 | let tx = [0b100_11111, 0b11]; | 55 | let tx = [0b100_11111, 0b11]; |
| 57 | unwrap!(spim.read_write(&mut rx, &tx).await); | 56 | unwrap!(spim.transfer(&mut rx, &tx).await); |
| 58 | cortex_m::asm::delay(10); | 57 | cortex_m::asm::delay(10); |
| 59 | ncs.set_high(); | 58 | ncs.set_high(); |
| 60 | 59 | ||
| @@ -63,7 +62,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 63 | ncs.set_low(); | 62 | ncs.set_low(); |
| 64 | cortex_m::asm::delay(5); | 63 | cortex_m::asm::delay(5); |
| 65 | let tx = [0b000_10010, 0]; | 64 | let tx = [0b000_10010, 0]; |
| 66 | unwrap!(spim.read_write(&mut rx, &tx).await); | 65 | unwrap!(spim.transfer(&mut rx, &tx).await); |
| 67 | cortex_m::asm::delay(10); | 66 | cortex_m::asm::delay(10); |
| 68 | ncs.set_high(); | 67 | ncs.set_high(); |
| 69 | 68 | ||
