aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-03-20 03:38:21 +0100
committerDario Nieuwenhuis <[email protected]>2021-03-29 00:58:57 +0200
commitf36cbe5e0cfa0a791d53ae6ddde40d69982867f4 (patch)
treeba0cda897e7aa91e2f7fc73772b57d07db136166
parentba6e0a405831793ab1e5acaa4694171199012df0 (diff)
nrf/spim: do not use PeripheralMutex
-rw-r--r--embassy-nrf-examples/src/bin/spim.rs4
-rw-r--r--embassy-nrf/src/spim.rs130
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"]
8mod example_common; 8mod example_common;
9use embassy_nrf::gpio::{Level, Output}; 9use embassy_nrf::gpio::{Level, Output, OutputDrive};
10use embassy_nrf::peripherals::Peripherals; 10use embassy_nrf::peripherals::Peripherals;
11use embassy_traits::spi::FullDuplex; 11use embassy_traits::spi::FullDuplex;
12use example_common::*; 12use 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;
4use core::sync::atomic::{compiler_fence, Ordering}; 4use core::sync::atomic::{compiler_fence, Ordering};
5use core::task::Poll; 5use core::task::Poll;
6use embassy::traits; 6use embassy::traits;
7use embassy::util::{PeripheralBorrow, WakerRegistration}; 7use embassy::util::{wake_on_interrupt, PeripheralBorrow};
8use embassy_extras::peripheral::{PeripheralMutex, PeripheralState};
9use futures::future::poll_fn; 8use futures::future::poll_fn;
10use traits::spi::FullDuplex; 9use traits::spi::FullDuplex;
11 10
@@ -26,13 +25,9 @@ pub enum Error {
26 DMABufferNotInDataMemory, 25 DMABufferNotInDataMemory,
27} 26}
28 27
29struct State<T: Instance> {
30 spim: T,
31 waker: WakerRegistration,
32}
33
34pub struct Spim<'d, T: Instance> { 28pub 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
149impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> { 135impl<'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
231impl<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
241mod sealed { 217mod sealed {
242 use super::*; 218 use super::*;
243 219