aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-04-14 16:37:10 +0200
committerDario Nieuwenhuis <[email protected]>2021-04-14 17:04:40 +0200
commitc15411d1bdbc54caa0e9879ea1de8c43025f2090 (patch)
tree14409a127ac5cfe41acdeb506fd3107a05ad7e5e
parent8b1ffb2cb7bd2e0c0f50eefb2391c15ae3050e73 (diff)
Remove Pin from SPI
-rw-r--r--embassy-nrf-examples/src/bin/spim.rs12
-rw-r--r--embassy-nrf/src/spim.rs61
-rw-r--r--embassy-stm32/src/f4/spi.rs56
-rw-r--r--embassy-traits/src/spi.rs6
4 files changed, 76 insertions, 59 deletions
diff --git a/embassy-nrf-examples/src/bin/spim.rs b/embassy-nrf-examples/src/bin/spim.rs
index 6d0fa93d0..27486374f 100644
--- a/embassy-nrf-examples/src/bin/spim.rs
+++ b/embassy-nrf-examples/src/bin/spim.rs
@@ -17,7 +17,6 @@ use embassy_nrf::{interrupt, spim};
17use embassy_traits::spi::FullDuplex; 17use embassy_traits::spi::FullDuplex;
18use embedded_hal::digital::v2::*; 18use embedded_hal::digital::v2::*;
19use example_common::*; 19use example_common::*;
20use futures::pin_mut;
21 20
22#[embassy::main] 21#[embassy::main]
23async fn main(spawner: Spawner) { 22async fn main(spawner: Spawner) {
@@ -32,8 +31,7 @@ async fn main(spawner: Spawner) {
32 }; 31 };
33 32
34 let irq = interrupt::take!(SPIM3); 33 let irq = interrupt::take!(SPIM3);
35 let spim = spim::Spim::new(p.SPIM3, irq, p.P0_29, p.P0_28, p.P0_30, config); 34 let mut spim = spim::Spim::new(p.SPIM3, irq, p.P0_29, p.P0_28, p.P0_30, config);
36 pin_mut!(spim);
37 35
38 let mut ncs = Output::new(p.P0_31, Level::High, OutputDrive::Standard); 36 let mut ncs = Output::new(p.P0_31, Level::High, OutputDrive::Standard);
39 37
@@ -44,7 +42,7 @@ async fn main(spawner: Spawner) {
44 ncs.set_low().unwrap(); 42 ncs.set_low().unwrap();
45 cortex_m::asm::delay(5); 43 cortex_m::asm::delay(5);
46 let tx = [0xFF]; 44 let tx = [0xFF];
47 unwrap!(spim.as_mut().read_write(&mut [], &tx).await); 45 unwrap!(spim.read_write(&mut [], &tx).await);
48 cortex_m::asm::delay(10); 46 cortex_m::asm::delay(10);
49 ncs.set_high().unwrap(); 47 ncs.set_high().unwrap();
50 48
@@ -57,7 +55,7 @@ async fn main(spawner: Spawner) {
57 ncs.set_low().unwrap(); 55 ncs.set_low().unwrap();
58 cortex_m::asm::delay(5000); 56 cortex_m::asm::delay(5000);
59 let tx = [0b000_11101, 0]; 57 let tx = [0b000_11101, 0];
60 unwrap!(spim.as_mut().read_write(&mut rx, &tx).await); 58 unwrap!(spim.read_write(&mut rx, &tx).await);
61 cortex_m::asm::delay(5000); 59 cortex_m::asm::delay(5000);
62 ncs.set_high().unwrap(); 60 ncs.set_high().unwrap();
63 info!("estat: {=[?]}", rx); 61 info!("estat: {=[?]}", rx);
@@ -67,7 +65,7 @@ async fn main(spawner: Spawner) {
67 ncs.set_low().unwrap(); 65 ncs.set_low().unwrap();
68 cortex_m::asm::delay(5); 66 cortex_m::asm::delay(5);
69 let tx = [0b100_11111, 0b11]; 67 let tx = [0b100_11111, 0b11];
70 unwrap!(spim.as_mut().read_write(&mut rx, &tx).await); 68 unwrap!(spim.read_write(&mut rx, &tx).await);
71 cortex_m::asm::delay(10); 69 cortex_m::asm::delay(10);
72 ncs.set_high().unwrap(); 70 ncs.set_high().unwrap();
73 71
@@ -76,7 +74,7 @@ async fn main(spawner: Spawner) {
76 ncs.set_low().unwrap(); 74 ncs.set_low().unwrap();
77 cortex_m::asm::delay(5); 75 cortex_m::asm::delay(5);
78 let tx = [0b000_10010, 0]; 76 let tx = [0b000_10010, 0];
79 unwrap!(spim.as_mut().read_write(&mut rx, &tx).await); 77 unwrap!(spim.read_write(&mut rx, &tx).await);
80 cortex_m::asm::delay(10); 78 cortex_m::asm::delay(10);
81 ncs.set_high().unwrap(); 79 ncs.set_high().unwrap();
82 80
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs
index 93ca52c63..bbe1eedf9 100644
--- a/embassy-nrf/src/spim.rs
+++ b/embassy-nrf/src/spim.rs
@@ -1,10 +1,10 @@
1use core::future::Future; 1use core::future::Future;
2use core::marker::PhantomData; 2use core::marker::PhantomData;
3use core::pin::Pin;
4use core::sync::atomic::{compiler_fence, Ordering}; 3use core::sync::atomic::{compiler_fence, Ordering};
5use core::task::Poll; 4use core::task::Poll;
5use embassy::interrupt::InterruptExt;
6use embassy::traits; 6use embassy::traits;
7use embassy::util::{wake_on_interrupt, PeripheralBorrow}; 7use embassy::util::{AtomicWaker, PeripheralBorrow};
8use embassy_extras::unborrow; 8use embassy_extras::unborrow;
9use futures::future::poll_fn; 9use futures::future::poll_fn;
10use traits::spi::FullDuplex; 10use traits::spi::FullDuplex;
@@ -50,7 +50,7 @@ impl<'d, T: Instance> Spim<'d, T> {
50 ) -> Self { 50 ) -> Self {
51 unborrow!(spim, irq, sck, miso, mosi); 51 unborrow!(spim, irq, sck, miso, mosi);
52 52
53 let r = spim.regs(); 53 let r = T::regs();
54 54
55 // Configure pins 55 // Configure pins
56 sck.conf().write(|w| w.dir().output().drive().h0h1()); 56 sck.conf().write(|w| w.dir().output().drive().h0h1());
@@ -122,12 +122,26 @@ impl<'d, T: Instance> Spim<'d, T> {
122 // Disable all events interrupts 122 // Disable all events interrupts
123 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); 123 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
124 124
125 irq.set_handler(Self::on_interrupt);
126 irq.unpend();
127 irq.enable();
128
125 Self { 129 Self {
126 peri: spim, 130 peri: spim,
127 irq, 131 irq,
128 phantom: PhantomData, 132 phantom: PhantomData,
129 } 133 }
130 } 134 }
135
136 fn on_interrupt(_: *mut ()) {
137 let r = T::regs();
138 let s = T::state();
139
140 if r.events_end.read().bits() != 0 {
141 s.end_waker.wake();
142 r.intenclr.write(|w| w.end().clear());
143 }
144 }
131} 145}
132 146
133impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> { 147impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> {
@@ -140,20 +154,15 @@ impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> {
140 #[rustfmt::skip] 154 #[rustfmt::skip]
141 type WriteReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a; 155 type WriteReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
142 156
143 fn read<'a>(self: Pin<&'a mut Self>, data: &'a mut [u8]) -> Self::ReadFuture<'a> { 157 fn read<'a>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'a> {
144 self.read_write(data, &[]) 158 self.read_write(data, &[])
145 } 159 }
146 fn write<'a>(self: Pin<&'a mut Self>, data: &'a [u8]) -> Self::WriteFuture<'a> { 160 fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> {
147 self.read_write(&mut [], data) 161 self.read_write(&mut [], data)
148 } 162 }
149 163
150 fn read_write<'a>( 164 fn read_write<'a>(&'a mut self, rx: &'a mut [u8], tx: &'a [u8]) -> Self::WriteReadFuture<'a> {
151 self: Pin<&'a mut Self>,
152 rx: &'a mut [u8],
153 tx: &'a [u8],
154 ) -> Self::WriteReadFuture<'a> {
155 async move { 165 async move {
156 let this = unsafe { self.get_unchecked_mut() };
157 slice_in_ram_or(rx, Error::DMABufferNotInDataMemory)?; 166 slice_in_ram_or(rx, Error::DMABufferNotInDataMemory)?;
158 slice_in_ram_or(tx, Error::DMABufferNotInDataMemory)?; 167 slice_in_ram_or(tx, Error::DMABufferNotInDataMemory)?;
159 168
@@ -162,7 +171,8 @@ impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> {
162 // before any DMA action has started. 171 // before any DMA action has started.
163 compiler_fence(Ordering::SeqCst); 172 compiler_fence(Ordering::SeqCst);
164 173
165 let r = this.peri.regs(); 174 let r = T::regs();
175 let s = T::state();
166 176
167 // Set up the DMA write. 177 // Set up the DMA write.
168 r.txd 178 r.txd
@@ -194,15 +204,11 @@ impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> {
194 204
195 // Wait for 'end' event. 205 // Wait for 'end' event.
196 poll_fn(|cx| { 206 poll_fn(|cx| {
197 let r = this.peri.regs(); 207 s.end_waker.register(cx.waker());
198
199 if r.events_end.read().bits() != 0 { 208 if r.events_end.read().bits() != 0 {
200 r.events_end.reset();
201 return Poll::Ready(()); 209 return Poll::Ready(());
202 } 210 }
203 211
204 wake_on_interrupt(&mut this.irq, cx.waker());
205
206 Poll::Pending 212 Poll::Pending
207 }) 213 })
208 .await; 214 .await;
@@ -215,8 +221,21 @@ impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> {
215mod sealed { 221mod sealed {
216 use super::*; 222 use super::*;
217 223
224 pub struct State {
225 pub end_waker: AtomicWaker,
226 }
227
228 impl State {
229 pub const fn new() -> Self {
230 Self {
231 end_waker: AtomicWaker::new(),
232 }
233 }
234 }
235
218 pub trait Instance { 236 pub trait Instance {
219 fn regs(&self) -> &pac::spim0::RegisterBlock; 237 fn regs() -> &'static pac::spim0::RegisterBlock;
238 fn state() -> &'static State;
220 } 239 }
221} 240}
222 241
@@ -227,9 +246,13 @@ pub trait Instance: sealed::Instance + 'static {
227macro_rules! impl_instance { 246macro_rules! impl_instance {
228 ($type:ident, $irq:ident) => { 247 ($type:ident, $irq:ident) => {
229 impl sealed::Instance for peripherals::$type { 248 impl sealed::Instance for peripherals::$type {
230 fn regs(&self) -> &pac::spim0::RegisterBlock { 249 fn regs() -> &'static pac::spim0::RegisterBlock {
231 unsafe { &*pac::$type::ptr() } 250 unsafe { &*pac::$type::ptr() }
232 } 251 }
252 fn state() -> &'static sealed::State {
253 static STATE: sealed::State = sealed::State::new();
254 &STATE
255 }
233 } 256 }
234 impl Instance for peripherals::$type { 257 impl Instance for peripherals::$type {
235 type Interrupt = interrupt::$irq; 258 type Interrupt = interrupt::$irq;
diff --git a/embassy-stm32/src/f4/spi.rs b/embassy-stm32/src/f4/spi.rs
index bc73611fd..65bf7287a 100644
--- a/embassy-stm32/src/f4/spi.rs
+++ b/embassy-stm32/src/f4/spi.rs
@@ -214,14 +214,13 @@ where
214 type ReadFuture<'a> = impl Future<Output = Result<(), Error>> + 'a; 214 type ReadFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
215 type WriteReadFuture<'a> = impl Future<Output = Result<(), Error>> + 'a; 215 type WriteReadFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
216 216
217 fn read<'a>(self: Pin<&'a mut Self>, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { 217 fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
218 let this = unsafe { self.get_unchecked_mut() };
219 #[allow(mutable_transmutes)] 218 #[allow(mutable_transmutes)]
220 let static_buf: &'static mut [u8] = unsafe { mem::transmute(buf) }; 219 let static_buf: &'static mut [u8] = unsafe { mem::transmute(buf) };
221 220
222 async move { 221 async move {
223 let rx_stream = this.rx_stream.take().unwrap(); 222 let rx_stream = self.rx_stream.take().unwrap();
224 let spi = this.spi.take().unwrap(); 223 let spi = self.spi.take().unwrap();
225 224
226 spi.cr2.modify(|_, w| w.errie().set_bit()); 225 spi.cr2.modify(|_, w| w.errie().set_bit());
227 226
@@ -236,8 +235,8 @@ where
236 .double_buffer(false), 235 .double_buffer(false),
237 ); 236 );
238 237
239 let fut = InterruptFuture::new(&mut this.rx_int); 238 let fut = InterruptFuture::new(&mut self.rx_int);
240 let fut_err = InterruptFuture::new(&mut this.spi_int); 239 let fut_err = InterruptFuture::new(&mut self.spi_int);
241 240
242 rx_transfer.start(|_spi| {}); 241 rx_transfer.start(|_spi| {});
243 future::select(fut, fut_err).await; 242 future::select(fut, fut_err).await;
@@ -245,21 +244,20 @@ where
245 let (rx_stream, spi, _buf, _) = rx_transfer.free(); 244 let (rx_stream, spi, _buf, _) = rx_transfer.free();
246 245
247 spi.cr2.modify(|_, w| w.errie().clear_bit()); 246 spi.cr2.modify(|_, w| w.errie().clear_bit());
248 this.rx_stream.replace(rx_stream); 247 self.rx_stream.replace(rx_stream);
249 this.spi.replace(spi); 248 self.spi.replace(spi);
250 249
251 Ok(()) 250 Ok(())
252 } 251 }
253 } 252 }
254 253
255 fn write<'a>(self: Pin<&'a mut Self>, buf: &'a [u8]) -> Self::WriteFuture<'a> { 254 fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> {
256 let this = unsafe { self.get_unchecked_mut() };
257 #[allow(mutable_transmutes)] 255 #[allow(mutable_transmutes)]
258 let static_buf: &'static mut [u8] = unsafe { mem::transmute(buf) }; 256 let static_buf: &'static mut [u8] = unsafe { mem::transmute(buf) };
259 257
260 async move { 258 async move {
261 let tx_stream = this.tx_stream.take().unwrap(); 259 let tx_stream = self.tx_stream.take().unwrap();
262 let spi = this.spi.take().unwrap(); 260 let spi = self.spi.take().unwrap();
263 261
264 // let mut tx_transfer = Transfer::init( 262 // let mut tx_transfer = Transfer::init(
265 // tx_stream, 263 // tx_stream,
@@ -272,7 +270,7 @@ where
272 // .double_buffer(false), 270 // .double_buffer(false),
273 // ); 271 // );
274 // 272 //
275 // let fut = InterruptFuture::new(&mut this.tx_int); 273 // let fut = InterruptFuture::new(&mut self.tx_int);
276 // 274 //
277 // tx_transfer.start(|_spi| {}); 275 // tx_transfer.start(|_spi| {});
278 // fut.await; 276 // fut.await;
@@ -284,28 +282,26 @@ where
284 nb::block!(write_sr(&spi, byte)); 282 nb::block!(write_sr(&spi, byte));
285 } 283 }
286 284
287 this.tx_stream.replace(tx_stream); 285 self.tx_stream.replace(tx_stream);
288 this.spi.replace(spi); 286 self.spi.replace(spi);
289 287
290 Ok(()) 288 Ok(())
291 } 289 }
292 } 290 }
293 291
294 fn read_write<'a>( 292 fn read_write<'a>(
295 self: Pin<&'a mut Self>, 293 &'a mut self,
296 read_buf: &'a mut [u8], 294 read_buf: &'a mut [u8],
297 write_buf: &'a [u8], 295 write_buf: &'a [u8],
298 ) -> Self::WriteReadFuture<'a> { 296 ) -> Self::WriteReadFuture<'a> {
299 let this = unsafe { self.get_unchecked_mut() };
300
301 #[allow(mutable_transmutes)] 297 #[allow(mutable_transmutes)]
302 let write_static_buf: &'static mut [u8] = unsafe { mem::transmute(write_buf) }; 298 let write_static_buf: &'static mut [u8] = unsafe { mem::transmute(write_buf) };
303 let read_static_buf: &'static mut [u8] = unsafe { mem::transmute(read_buf) }; 299 let read_static_buf: &'static mut [u8] = unsafe { mem::transmute(read_buf) };
304 300
305 async move { 301 async move {
306 let tx_stream = this.tx_stream.take().unwrap(); 302 let tx_stream = self.tx_stream.take().unwrap();
307 let rx_stream = this.rx_stream.take().unwrap(); 303 let rx_stream = self.rx_stream.take().unwrap();
308 let spi_tx = this.spi.take().unwrap(); 304 let spi_tx = self.spi.take().unwrap();
309 let spi_rx: SPI = unsafe { mem::transmute_copy(&spi_tx) }; 305 let spi_rx: SPI = unsafe { mem::transmute_copy(&spi_tx) };
310 306
311 spi_rx 307 spi_rx
@@ -334,9 +330,9 @@ where
334 // .double_buffer(false), 330 // .double_buffer(false),
335 // ); 331 // );
336 // 332 //
337 // let tx_fut = InterruptFuture::new(&mut this.tx_int); 333 // let tx_fut = InterruptFuture::new(&mut self.tx_int);
338 // let rx_fut = InterruptFuture::new(&mut this.rx_int); 334 // let rx_fut = InterruptFuture::new(&mut self.rx_int);
339 // let rx_fut_err = InterruptFuture::new(&mut this.spi_int); 335 // let rx_fut_err = InterruptFuture::new(&mut self.spi_int);
340 // 336 //
341 // rx_transfer.start(|_spi| {}); 337 // rx_transfer.start(|_spi| {});
342 // tx_transfer.start(|_spi| {}); 338 // tx_transfer.start(|_spi| {});
@@ -352,7 +348,7 @@ where
352 for i in 0..(read_static_buf.len() - 1) { 348 for i in 0..(read_static_buf.len() - 1) {
353 let byte = write_static_buf[i]; 349 let byte = write_static_buf[i];
354 loop { 350 loop {
355 let fut = InterruptFuture::new(&mut this.spi_int); 351 let fut = InterruptFuture::new(&mut self.spi_int);
356 match write_sr(&spi_tx, byte) { 352 match write_sr(&spi_tx, byte) {
357 Ok(()) => break, 353 Ok(()) => break,
358 _ => {} 354 _ => {}
@@ -361,7 +357,7 @@ where
361 } 357 }
362 358
363 loop { 359 loop {
364 let fut = InterruptFuture::new(&mut this.spi_int); 360 let fut = InterruptFuture::new(&mut self.spi_int);
365 match read_sr(&spi_tx) { 361 match read_sr(&spi_tx) {
366 Ok(byte) => { 362 Ok(byte) => {
367 read_static_buf[i] = byte; 363 read_static_buf[i] = byte;
@@ -381,9 +377,9 @@ where
381 .rxneie() 377 .rxneie()
382 .clear_bit() 378 .clear_bit()
383 }); 379 });
384 this.rx_stream.replace(rx_stream); 380 self.rx_stream.replace(rx_stream);
385 this.tx_stream.replace(tx_stream); 381 self.tx_stream.replace(tx_stream);
386 this.spi.replace(spi_rx); 382 self.spi.replace(spi_rx);
387 383
388 Ok(()) 384 Ok(())
389 } 385 }
@@ -421,7 +417,7 @@ macro_rules! spi {
421 impl Instance for pac::$SPI { 417 impl Instance for pac::$SPI {
422 unsafe fn enable_clock() { 418 unsafe fn enable_clock() {
423 const EN_BIT: u8 = $en; 419 const EN_BIT: u8 = $en;
424 // NOTE(unsafe) this reference will only be used for atomic writes with no side effects. 420 // NOTE(unsafe) self reference will only be used for atomic writes with no side effects.
425 let rcc = &(*pac::RCC::ptr()); 421 let rcc = &(*pac::RCC::ptr());
426 // Enable clock. 422 // Enable clock.
427 bb::set(&rcc.$apbXenr, EN_BIT); 423 bb::set(&rcc.$apbXenr, EN_BIT);
diff --git a/embassy-traits/src/spi.rs b/embassy-traits/src/spi.rs
index 9f08e7402..771ebf2f0 100644
--- a/embassy-traits/src/spi.rs
+++ b/embassy-traits/src/spi.rs
@@ -33,10 +33,10 @@ pub trait FullDuplex<Word> {
33 where 33 where
34 Self: 'a; 34 Self: 'a;
35 35
36 fn read<'a>(self: Pin<&'a mut Self>, data: &'a mut [Word]) -> Self::ReadFuture<'a>; 36 fn read<'a>(&'a mut self, data: &'a mut [Word]) -> Self::ReadFuture<'a>;
37 fn write<'a>(self: Pin<&'a mut Self>, data: &'a [Word]) -> Self::WriteFuture<'a>; 37 fn write<'a>(&'a mut self, data: &'a [Word]) -> Self::WriteFuture<'a>;
38 fn read_write<'a>( 38 fn read_write<'a>(
39 self: Pin<&'a mut Self>, 39 &'a mut self,
40 read: &'a mut [Word], 40 read: &'a mut [Word],
41 write: &'a [Word], 41 write: &'a [Word],
42 ) -> Self::WriteReadFuture<'a>; 42 ) -> Self::WriteReadFuture<'a>;