diff options
| author | Dario Nieuwenhuis <[email protected]> | 2021-03-20 03:38:21 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2021-03-29 00:58:57 +0200 |
| commit | f36cbe5e0cfa0a791d53ae6ddde40d69982867f4 (patch) | |
| tree | ba0cda897e7aa91e2f7fc73772b57d07db136166 | |
| parent | ba6e0a405831793ab1e5acaa4694171199012df0 (diff) | |
nrf/spim: do not use PeripheralMutex
| -rw-r--r-- | embassy-nrf-examples/src/bin/spim.rs | 4 | ||||
| -rw-r--r-- | embassy-nrf/src/spim.rs | 130 |
2 files changed, 55 insertions, 79 deletions
diff --git a/embassy-nrf-examples/src/bin/spim.rs b/embassy-nrf-examples/src/bin/spim.rs index 8eaac5e15..b7436332e 100644 --- a/embassy-nrf-examples/src/bin/spim.rs +++ b/embassy-nrf-examples/src/bin/spim.rs | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #[path = "../example_common.rs"] | 7 | #[path = "../example_common.rs"] |
| 8 | mod example_common; | 8 | mod example_common; |
| 9 | use embassy_nrf::gpio::{Level, Output}; | 9 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; |
| 10 | use embassy_nrf::peripherals::Peripherals; | 10 | use embassy_nrf::peripherals::Peripherals; |
| 11 | use embassy_traits::spi::FullDuplex; | 11 | use embassy_traits::spi::FullDuplex; |
| 12 | use example_common::*; | 12 | use example_common::*; |
| @@ -37,7 +37,7 @@ async fn run() { | |||
| 37 | let spim = spim::Spim::new(p.spim3, irq, p.p0_29, p.p0_28, p.p0_30, config); | 37 | let spim = spim::Spim::new(p.spim3, irq, p.p0_29, p.p0_28, p.p0_30, config); |
| 38 | pin_mut!(spim); | 38 | pin_mut!(spim); |
| 39 | 39 | ||
| 40 | let mut ncs = Output::new(p.p0_31, Level::High); | 40 | let mut ncs = Output::new(p.p0_31, Level::High, OutputDrive::Standard); |
| 41 | 41 | ||
| 42 | // Example on how to talk to an ENC28J60 chip | 42 | // Example on how to talk to an ENC28J60 chip |
| 43 | 43 | ||
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs index 38cfa0052..33005188a 100644 --- a/embassy-nrf/src/spim.rs +++ b/embassy-nrf/src/spim.rs | |||
| @@ -4,8 +4,7 @@ use core::pin::Pin; | |||
| 4 | use core::sync::atomic::{compiler_fence, Ordering}; | 4 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 5 | use core::task::Poll; | 5 | use core::task::Poll; |
| 6 | use embassy::traits; | 6 | use embassy::traits; |
| 7 | use embassy::util::{PeripheralBorrow, WakerRegistration}; | 7 | use embassy::util::{wake_on_interrupt, PeripheralBorrow}; |
| 8 | use embassy_extras::peripheral::{PeripheralMutex, PeripheralState}; | ||
| 9 | use futures::future::poll_fn; | 8 | use futures::future::poll_fn; |
| 10 | use traits::spi::FullDuplex; | 9 | use traits::spi::FullDuplex; |
| 11 | 10 | ||
| @@ -26,13 +25,9 @@ pub enum Error { | |||
| 26 | DMABufferNotInDataMemory, | 25 | DMABufferNotInDataMemory, |
| 27 | } | 26 | } |
| 28 | 27 | ||
| 29 | struct State<T: Instance> { | ||
| 30 | spim: T, | ||
| 31 | waker: WakerRegistration, | ||
| 32 | } | ||
| 33 | |||
| 34 | pub struct Spim<'d, T: Instance> { | 28 | pub struct Spim<'d, T: Instance> { |
| 35 | inner: PeripheralMutex<State<T>>, | 29 | spim: T, |
| 30 | irq: T::Interrupt, | ||
| 36 | phantom: PhantomData<&'d mut T>, | 31 | phantom: PhantomData<&'d mut T>, |
| 37 | } | 32 | } |
| 38 | 33 | ||
| @@ -130,20 +125,11 @@ impl<'d, T: Instance> Spim<'d, T> { | |||
| 130 | r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); | 125 | r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); |
| 131 | 126 | ||
| 132 | Self { | 127 | Self { |
| 133 | inner: PeripheralMutex::new( | 128 | spim, |
| 134 | State { | 129 | irq, |
| 135 | spim, | ||
| 136 | waker: WakerRegistration::new(), | ||
| 137 | }, | ||
| 138 | irq, | ||
| 139 | ), | ||
| 140 | phantom: PhantomData, | 130 | phantom: PhantomData, |
| 141 | } | 131 | } |
| 142 | } | 132 | } |
| 143 | |||
| 144 | fn inner(self: Pin<&mut Self>) -> Pin<&mut PeripheralMutex<State<T>>> { | ||
| 145 | unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) } | ||
| 146 | } | ||
| 147 | } | 133 | } |
| 148 | 134 | ||
| 149 | impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> { | 135 | impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> { |
| @@ -157,69 +143,69 @@ impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> { | |||
| 157 | type WriteReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a; | 143 | type WriteReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a; |
| 158 | 144 | ||
| 159 | fn read<'a>(self: Pin<&'a mut Self>, data: &'a mut [u8]) -> Self::ReadFuture<'a> { | 145 | fn read<'a>(self: Pin<&'a mut Self>, data: &'a mut [u8]) -> Self::ReadFuture<'a> { |
| 160 | async move { todo!() } | 146 | self.read_write(data, &[]) |
| 161 | } | 147 | } |
| 162 | fn write<'a>(self: Pin<&'a mut Self>, data: &'a [u8]) -> Self::WriteFuture<'a> { | 148 | fn write<'a>(self: Pin<&'a mut Self>, data: &'a [u8]) -> Self::WriteFuture<'a> { |
| 163 | async move { todo!() } | 149 | self.read_write(&mut [], data) |
| 164 | } | 150 | } |
| 165 | 151 | ||
| 166 | fn read_write<'a>( | 152 | fn read_write<'a>( |
| 167 | mut self: Pin<&'a mut Self>, | 153 | self: Pin<&'a mut Self>, |
| 168 | rx: &'a mut [u8], | 154 | rx: &'a mut [u8], |
| 169 | tx: &'a [u8], | 155 | tx: &'a [u8], |
| 170 | ) -> Self::WriteReadFuture<'a> { | 156 | ) -> Self::WriteReadFuture<'a> { |
| 171 | async move { | 157 | async move { |
| 158 | let this = unsafe { self.get_unchecked_mut() }; | ||
| 172 | slice_in_ram_or(rx, Error::DMABufferNotInDataMemory)?; | 159 | slice_in_ram_or(rx, Error::DMABufferNotInDataMemory)?; |
| 173 | slice_in_ram_or(tx, Error::DMABufferNotInDataMemory)?; | 160 | slice_in_ram_or(tx, Error::DMABufferNotInDataMemory)?; |
| 174 | 161 | ||
| 175 | self.as_mut().inner().register_interrupt(); | 162 | // Conservative compiler fence to prevent optimizations that do not |
| 176 | self.as_mut().inner().with(|s, _irq| { | 163 | // take in to account actions by DMA. The fence has been placed here, |
| 177 | // Conservative compiler fence to prevent optimizations that do not | 164 | // before any DMA action has started. |
| 178 | // take in to account actions by DMA. The fence has been placed here, | 165 | compiler_fence(Ordering::SeqCst); |
| 179 | // before any DMA action has started. | 166 | |
| 180 | compiler_fence(Ordering::SeqCst); | 167 | let r = this.spim.regs(); |
| 181 | 168 | ||
| 182 | let r = s.spim.regs(); | 169 | // Set up the DMA write. |
| 183 | 170 | r.txd | |
| 184 | // Set up the DMA write. | 171 | .ptr |
| 185 | r.txd | 172 | .write(|w| unsafe { w.ptr().bits(tx.as_ptr() as u32) }); |
| 186 | .ptr | 173 | r.txd |
| 187 | .write(|w| unsafe { w.ptr().bits(tx.as_ptr() as u32) }); | 174 | .maxcnt |
| 188 | r.txd | 175 | .write(|w| unsafe { w.maxcnt().bits(tx.len() as _) }); |
| 189 | .maxcnt | 176 | |
| 190 | .write(|w| unsafe { w.maxcnt().bits(tx.len() as _) }); | 177 | // Set up the DMA read. |
| 191 | 178 | r.rxd | |
| 192 | // Set up the DMA read. | 179 | .ptr |
| 193 | r.rxd | 180 | .write(|w| unsafe { w.ptr().bits(rx.as_mut_ptr() as u32) }); |
| 194 | .ptr | 181 | r.rxd |
| 195 | .write(|w| unsafe { w.ptr().bits(rx.as_mut_ptr() as u32) }); | 182 | .maxcnt |
| 196 | r.rxd | 183 | .write(|w| unsafe { w.maxcnt().bits(rx.len() as _) }); |
| 197 | .maxcnt | 184 | |
| 198 | .write(|w| unsafe { w.maxcnt().bits(rx.len() as _) }); | 185 | // Reset and enable the event |
| 199 | 186 | r.events_end.reset(); | |
| 200 | // Reset and enable the event | 187 | r.intenset.write(|w| w.end().set()); |
| 201 | r.events_end.reset(); | 188 | |
| 202 | r.intenset.write(|w| w.end().set()); | 189 | // Start SPI transaction. |
| 203 | 190 | r.tasks_start.write(|w| unsafe { w.bits(1) }); | |
| 204 | // Start SPI transaction. | 191 | |
| 205 | r.tasks_start.write(|w| unsafe { w.bits(1) }); | 192 | // Conservative compiler fence to prevent optimizations that do not |
| 206 | 193 | // take in to account actions by DMA. The fence has been placed here, | |
| 207 | // Conservative compiler fence to prevent optimizations that do not | 194 | // after all possible DMA actions have completed. |
| 208 | // take in to account actions by DMA. The fence has been placed here, | 195 | compiler_fence(Ordering::SeqCst); |
| 209 | // after all possible DMA actions have completed. | ||
| 210 | compiler_fence(Ordering::SeqCst); | ||
| 211 | }); | ||
| 212 | 196 | ||
| 213 | // Wait for 'end' event. | 197 | // Wait for 'end' event. |
| 214 | poll_fn(|cx| { | 198 | poll_fn(|cx| { |
| 215 | self.as_mut().inner().with(|s, _irq| { | 199 | let r = this.spim.regs(); |
| 216 | let r = s.spim.regs(); | 200 | |
| 217 | if r.events_end.read().bits() != 0 { | 201 | if r.events_end.read().bits() != 0 { |
| 218 | return Poll::Ready(()); | 202 | r.events_end.reset(); |
| 219 | } | 203 | return Poll::Ready(()); |
| 220 | s.waker.register(cx.waker()); | 204 | } |
| 221 | Poll::Pending | 205 | |
| 222 | }) | 206 | wake_on_interrupt(&mut this.irq, cx.waker()); |
| 207 | |||
| 208 | Poll::Pending | ||
| 223 | }) | 209 | }) |
| 224 | .await; | 210 | .await; |
| 225 | 211 | ||
| @@ -228,16 +214,6 @@ impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> { | |||
| 228 | } | 214 | } |
| 229 | } | 215 | } |
| 230 | 216 | ||
| 231 | impl<U: Instance> PeripheralState for State<U> { | ||
| 232 | type Interrupt = U::Interrupt; | ||
| 233 | fn on_interrupt(&mut self) { | ||
| 234 | if self.spim.regs().events_end.read().bits() != 0 { | ||
| 235 | self.spim.regs().intenclr.write(|w| w.end().clear()); | ||
| 236 | self.waker.wake() | ||
| 237 | } | ||
| 238 | } | ||
| 239 | } | ||
| 240 | |||
| 241 | mod sealed { | 217 | mod sealed { |
| 242 | use super::*; | 218 | use super::*; |
| 243 | 219 | ||
