aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob McWhirter <[email protected]>2021-05-12 14:18:42 -0400
committerBob McWhirter <[email protected]>2021-05-12 14:18:42 -0400
commit07db3ed7c10915f16eeda08909f04afd92902b1b (patch)
tree6ef1caa7795e346e314a06d5e30769b6e0952065
parent36c16dbef8786a5323f722034936c5bd2482f681 (diff)
Further improvement to SPIv2.
-rw-r--r--embassy-stm32/src/lib.rs2
-rw-r--r--embassy-stm32/src/spi.rs152
2 files changed, 121 insertions, 33 deletions
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index b54bc4a49..3d8416c78 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -23,7 +23,7 @@ pub mod usart;
23 23
24// This must go LAST so that it sees the `impl_foo!` macros 24// This must go LAST so that it sees the `impl_foo!` macros
25mod pac; 25mod pac;
26mod time; 26pub mod time;
27 27
28pub use embassy_macros::interrupt; 28pub use embassy_macros::interrupt;
29pub use pac::{interrupt, peripherals, Peripherals}; 29pub use pac::{interrupt, peripherals, Peripherals};
diff --git a/embassy-stm32/src/spi.rs b/embassy-stm32/src/spi.rs
index d95224582..40944d74c 100644
--- a/embassy-stm32/src/spi.rs
+++ b/embassy-stm32/src/spi.rs
@@ -11,12 +11,48 @@ use crate::pac::gpio::vals::{Afr, Moder};
11use crate::pac::spi; 11use crate::pac::spi;
12use crate::pac::gpio::Gpio; 12use crate::pac::gpio::Gpio;
13use crate::time::Hertz; 13use crate::time::Hertz;
14//use crate::pac::spi; 14use term::terminfo::parm::Param::Words;
15
16#[non_exhaustive]
17pub struct Config {
18 pub mode: Mode,
19 pub byte_order: ByteOrder,
20}
21
22impl Default for Config {
23 fn default() -> Self {
24 Self {
25 mode: MODE_0,
26 byte_order: ByteOrder::MsbFirst,
27 }
28 }
29}
15 30
16// TODO move upwards in the tree 31// TODO move upwards in the tree
17pub enum ByteOrder { 32pub enum ByteOrder {
18 LsbFirst, 33 LsbFirst,
19 MsbFirst 34 MsbFirst,
35}
36
37enum WordSize {
38 EightBit,
39 SixteenBit,
40}
41
42impl WordSize {
43 fn ds(&self) -> spi::vals::Ds {
44 match self {
45 WordSize::EightBit => spi::vals::Ds::EIGHTBIT,
46 WordSize::SixteenBit => spi::vals::Ds::SIXTEENBIT,
47 }
48 }
49
50 fn frxth(&self) -> spi::vals::Frxth {
51 match self {
52 WordSize::EightBit => spi::vals::Frxth::QUARTER,
53 WordSize::SixteenBit => spi::vals::Frxth::HALF,
54 }
55 }
20} 56}
21 57
22pub struct Spi<'d, T: Instance> { 58pub struct Spi<'d, T: Instance> {
@@ -34,9 +70,8 @@ impl<'d, T: Instance> Spi<'d, T> {
34 sck: impl Unborrow<Target=impl Sck<T>>, 70 sck: impl Unborrow<Target=impl Sck<T>>,
35 mosi: impl Unborrow<Target=impl Mosi<T>>, 71 mosi: impl Unborrow<Target=impl Mosi<T>>,
36 miso: impl Unborrow<Target=impl Miso<T>>, 72 miso: impl Unborrow<Target=impl Miso<T>>,
37 mode: Mode,
38 byte_order: ByteOrder,
39 freq: F, 73 freq: F,
74 config: Config,
40 ) -> Self 75 ) -> Self
41 where 76 where
42 F: Into<Hertz> 77 F: Into<Hertz>
@@ -54,16 +89,9 @@ impl<'d, T: Instance> Spi<'d, T> {
54 let mosi = mosi.degrade(); 89 let mosi = mosi.degrade();
55 let miso = miso.degrade(); 90 let miso = miso.degrade();
56 91
57 // FRXTH: RXNE event is generated if the FIFO level is greater than or equal to
58 // 8-bit
59 // DS: 8-bit data size
60 // SSOE: Slave Select output disabled
61 unsafe { 92 unsafe {
62 T::regs().cr2() 93 T::regs().cr2()
63 .write(|w| { 94 .write(|w| {
64 // 8-bit transfers
65 w.set_ds( spi::vals::Ds(0b0111));
66 w.set_frxth( spi::vals::Frxth::QUARTER);
67 w.set_ssoe(false); 95 w.set_ssoe(false);
68 }); 96 });
69 } 97 }
@@ -73,12 +101,12 @@ impl<'d, T: Instance> Spi<'d, T> {
73 unsafe { 101 unsafe {
74 T::regs().cr1().write(|w| { 102 T::regs().cr1().write(|w| {
75 w.set_cpha( 103 w.set_cpha(
76 match mode.phase == Phase::CaptureOnSecondTransition { 104 match config.mode.phase == Phase::CaptureOnSecondTransition {
77 true => spi::vals::Cpha::SECONDEDGE, 105 true => spi::vals::Cpha::SECONDEDGE,
78 false => spi::vals::Cpha::FIRSTEDGE, 106 false => spi::vals::Cpha::FIRSTEDGE,
79 } 107 }
80 ); 108 );
81 w.set_cpol(match mode.polarity == Polarity::IdleHigh { 109 w.set_cpol(match config.mode.polarity == Polarity::IdleHigh {
82 true => spi::vals::Cpol::IDLEHIGH, 110 true => spi::vals::Cpol::IDLEHIGH,
83 false => spi::vals::Cpol::IDLELOW, 111 false => spi::vals::Cpol::IDLELOW,
84 }); 112 });
@@ -87,7 +115,7 @@ impl<'d, T: Instance> Spi<'d, T> {
87 w.set_br(spi::vals::Br(br)); 115 w.set_br(spi::vals::Br(br));
88 w.set_spe(true); 116 w.set_spe(true);
89 w.set_lsbfirst( 117 w.set_lsbfirst(
90 match byte_order { 118 match config.byte_order {
91 ByteOrder::LsbFirst => spi::vals::Lsbfirst::LSBFIRST, 119 ByteOrder::LsbFirst => spi::vals::Lsbfirst::LSBFIRST,
92 ByteOrder::MsbFirst => spi::vals::Lsbfirst::MSBFIRST, 120 ByteOrder::MsbFirst => spi::vals::Lsbfirst::MSBFIRST,
93 } 121 }
@@ -97,8 +125,7 @@ impl<'d, T: Instance> Spi<'d, T> {
97 w.set_crcen(false); 125 w.set_crcen(false);
98 w.set_bidimode(spi::vals::Bidimode::UNIDIRECTIONAL); 126 w.set_bidimode(spi::vals::Bidimode::UNIDIRECTIONAL);
99 }); 127 });
100 T::regs().cr2().write(|w| { 128 T::regs().cr2().write(|w| {})
101 })
102 } 129 }
103 130
104 Self { 131 Self {
@@ -134,6 +161,16 @@ impl<'d, T: Instance> Spi<'d, T> {
134 _ => 0b111, 161 _ => 0b111,
135 } 162 }
136 } 163 }
164
165 fn set_word_size(word_size: WordSize) {
166 unsafe {
167 T::regs().cr2()
168 .write(|w| {
169 w.set_ds(word_size.ds());
170 w.set_frxth(word_size.frxth());
171 });
172 }
173 }
137} 174}
138 175
139impl<'d, T: Instance> Drop for Spi<'d, T> { 176impl<'d, T: Instance> Drop for Spi<'d, T> {
@@ -156,6 +193,7 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u8> for Spi<'d, T> {
156 type Error = Error; 193 type Error = Error;
157 194
158 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { 195 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
196 Self::set_word_size(WordSize::EightBit);
159 let regs = T::regs(); 197 let regs = T::regs();
160 198
161 for word in words.iter() { 199 for word in words.iter() {
@@ -190,6 +228,7 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spi<'d, T> {
190 type Error = Error; 228 type Error = Error;
191 229
192 fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { 230 fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
231 Self::set_word_size(WordSize::EightBit);
193 let regs = T::regs(); 232 let regs = T::regs();
194 233
195 for word in words.iter_mut() { 234 for word in words.iter_mut() {
@@ -203,6 +242,36 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spi<'d, T> {
203 // spin waiting for inbound to shift in. 242 // spin waiting for inbound to shift in.
204 } 243 }
205 *word = unsafe { regs.dr().read().0 as u8 }; 244 *word = unsafe { regs.dr().read().0 as u8 };
245 let sr = unsafe { regs.sr().read() };
246 if sr.fre() {
247 return Err(Error::Framing);
248 }
249 if sr.ovr() {
250 return Err(Error::Overrun);
251 }
252 if sr.crcerr() {
253 return Err(Error::Crc);
254 }
255 }
256
257 Ok(words)
258 }
259}
260
261impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u16> for Spi<'d, T> {
262 type Error = Error;
263
264 fn write(&mut self, words: &[u16]) -> Result<(), Self::Error> {
265 Self::set_word_size(WordSize::SixteenBit);
266 let regs = T::regs();
267
268 for word in words.iter() {
269 while unsafe { !regs.sr().read().txe() } {
270 // spin
271 }
272 unsafe {
273 regs.dr().write(|reg| reg.0 = *word as u32);
274 }
206 loop { 275 loop {
207 let sr = unsafe { regs.sr().read() }; 276 let sr = unsafe { regs.sr().read() };
208 if sr.fre() { 277 if sr.fre() {
@@ -220,6 +289,40 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spi<'d, T> {
220 } 289 }
221 } 290 }
222 291
292 Ok(())
293 }
294}
295
296impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u16> for Spi<'d, T> {
297 type Error = Error;
298
299 fn transfer<'w>(&mut self, words: &'w mut [u16]) -> Result<&'w [u16], Self::Error> {
300 Self::set_word_size(WordSize::SixteenBit);
301 let regs = T::regs();
302
303 for word in words.iter_mut() {
304 while unsafe { !regs.sr().read().txe() } {
305 // spin
306 }
307 unsafe {
308 regs.dr().write(|reg| reg.0 = *word as u32);
309 }
310 while unsafe { !regs.sr().read().rxne() } {
311 // spin waiting for inbound to shift in.
312 }
313 *word = unsafe { regs.dr().read().0 as u16 };
314 let sr = unsafe { regs.sr().read() };
315 if sr.fre() {
316 return Err(Error::Framing);
317 }
318 if sr.ovr() {
319 return Err(Error::Overrun);
320 }
321 if sr.crcerr() {
322 return Err(Error::Crc);
323 }
324 }
325
223 Ok(words) 326 Ok(words)
224 } 327 }
225} 328}
@@ -229,21 +332,8 @@ pub(crate) mod sealed {
229 use super::*; 332 use super::*;
230 use embassy::util::AtomicWaker; 333 use embassy::util::AtomicWaker;
231 334
232 //pub struct State {
233 //pub end_waker: AtomicWaker,
234 //}
235
236 //impl State {
237 //pub const fn new() -> Self {
238 //Self {
239 //end_waker: AtomicWaker::new(),
240 //}
241 //}
242 //}
243
244 pub trait Instance { 335 pub trait Instance {
245 fn regs() -> &'static spi::Spi; 336 fn regs() -> &'static spi::Spi;
246 //fn state() -> &'static State;
247 } 337 }
248 338
249 pub trait Sck<T: Instance>: Pin { 339 pub trait Sck<T: Instance>: Pin {
@@ -268,9 +358,7 @@ pub(crate) mod sealed {
268 } 358 }
269} 359}
270 360
271pub trait Instance: sealed::Instance + 'static { 361pub trait Instance: sealed::Instance + 'static {}
272 //type Interrupt: Interrupt;
273}
274 362
275pub trait Sck<T: Instance>: sealed::Sck<T> + 'static {} 363pub trait Sck<T: Instance>: sealed::Sck<T> + 'static {}
276 364