diff options
| author | Bob McWhirter <[email protected]> | 2021-05-12 14:18:42 -0400 |
|---|---|---|
| committer | Bob McWhirter <[email protected]> | 2021-05-12 14:18:42 -0400 |
| commit | 07db3ed7c10915f16eeda08909f04afd92902b1b (patch) | |
| tree | 6ef1caa7795e346e314a06d5e30769b6e0952065 | |
| parent | 36c16dbef8786a5323f722034936c5bd2482f681 (diff) | |
Further improvement to SPIv2.
| -rw-r--r-- | embassy-stm32/src/lib.rs | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/spi.rs | 152 |
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 |
| 25 | mod pac; | 25 | mod pac; |
| 26 | mod time; | 26 | pub mod time; |
| 27 | 27 | ||
| 28 | pub use embassy_macros::interrupt; | 28 | pub use embassy_macros::interrupt; |
| 29 | pub use pac::{interrupt, peripherals, Peripherals}; | 29 | pub 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}; | |||
| 11 | use crate::pac::spi; | 11 | use crate::pac::spi; |
| 12 | use crate::pac::gpio::Gpio; | 12 | use crate::pac::gpio::Gpio; |
| 13 | use crate::time::Hertz; | 13 | use crate::time::Hertz; |
| 14 | //use crate::pac::spi; | 14 | use term::terminfo::parm::Param::Words; |
| 15 | |||
| 16 | #[non_exhaustive] | ||
| 17 | pub struct Config { | ||
| 18 | pub mode: Mode, | ||
| 19 | pub byte_order: ByteOrder, | ||
| 20 | } | ||
| 21 | |||
| 22 | impl 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 |
| 17 | pub enum ByteOrder { | 32 | pub enum ByteOrder { |
| 18 | LsbFirst, | 33 | LsbFirst, |
| 19 | MsbFirst | 34 | MsbFirst, |
| 35 | } | ||
| 36 | |||
| 37 | enum WordSize { | ||
| 38 | EightBit, | ||
| 39 | SixteenBit, | ||
| 40 | } | ||
| 41 | |||
| 42 | impl 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 | ||
| 22 | pub struct Spi<'d, T: Instance> { | 58 | pub 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 | ||
| 139 | impl<'d, T: Instance> Drop for Spi<'d, T> { | 176 | impl<'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 | |||
| 261 | impl<'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 | |||
| 296 | impl<'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 | ||
| 271 | pub trait Instance: sealed::Instance + 'static { | 361 | pub trait Instance: sealed::Instance + 'static {} |
| 272 | //type Interrupt: Interrupt; | ||
| 273 | } | ||
| 274 | 362 | ||
| 275 | pub trait Sck<T: Instance>: sealed::Sck<T> + 'static {} | 363 | pub trait Sck<T: Instance>: sealed::Sck<T> + 'static {} |
| 276 | 364 | ||
