diff options
| author | Matous Hybl <[email protected]> | 2022-01-10 19:37:15 +0100 |
|---|---|---|
| committer | Matous Hybl <[email protected]> | 2022-01-14 12:50:58 +0100 |
| commit | 66e46d8012a74c1207ccc37e96bdaf1d3eef0e9e (patch) | |
| tree | 0dd5bb42e0109b0e93c5350479bbf42d160f44ee | |
| parent | 167af012114cca8747e65d0dc5157f066bb2ed5d (diff) | |
Add the possibility to reconfigure Spi mode and bit order configuration on the fly.
| -rw-r--r-- | embassy-stm32/src/spi/mod.rs | 107 | ||||
| -rw-r--r-- | embassy-stm32/src/subghz/mod.rs | 4 |
2 files changed, 88 insertions, 23 deletions
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 4ae45a9be..f83ef7852 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs | |||
| @@ -34,7 +34,8 @@ pub enum Error { | |||
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | // TODO move upwards in the tree | 36 | // TODO move upwards in the tree |
| 37 | pub enum ByteOrder { | 37 | #[derive(Copy, Clone)] |
| 38 | pub enum BitOrder { | ||
| 38 | LsbFirst, | 39 | LsbFirst, |
| 39 | MsbFirst, | 40 | MsbFirst, |
| 40 | } | 41 | } |
| @@ -88,16 +89,40 @@ impl WordSize { | |||
| 88 | } | 89 | } |
| 89 | 90 | ||
| 90 | #[non_exhaustive] | 91 | #[non_exhaustive] |
| 92 | #[derive(Copy, Clone)] | ||
| 91 | pub struct Config { | 93 | pub struct Config { |
| 92 | pub mode: Mode, | 94 | pub mode: Mode, |
| 93 | pub byte_order: ByteOrder, | 95 | pub bit_order: BitOrder, |
| 94 | } | 96 | } |
| 95 | 97 | ||
| 96 | impl Default for Config { | 98 | impl Default for Config { |
| 97 | fn default() -> Self { | 99 | fn default() -> Self { |
| 98 | Self { | 100 | Self { |
| 99 | mode: MODE_0, | 101 | mode: MODE_0, |
| 100 | byte_order: ByteOrder::MsbFirst, | 102 | bit_order: BitOrder::MsbFirst, |
| 103 | } | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | impl Config { | ||
| 108 | fn raw_phase(&self) -> vals::Cpha { | ||
| 109 | match self.mode.phase { | ||
| 110 | Phase::CaptureOnSecondTransition => vals::Cpha::SECONDEDGE, | ||
| 111 | Phase::CaptureOnFirstTransition => vals::Cpha::FIRSTEDGE, | ||
| 112 | } | ||
| 113 | } | ||
| 114 | |||
| 115 | fn raw_polarity(&self) -> vals::Cpol { | ||
| 116 | match self.mode.polarity { | ||
| 117 | Polarity::IdleHigh => vals::Cpol::IDLEHIGH, | ||
| 118 | Polarity::IdleLow => vals::Cpol::IDLELOW, | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | fn raw_byte_order(&self) -> vals::Lsbfirst { | ||
| 123 | match self.bit_order { | ||
| 124 | BitOrder::LsbFirst => vals::Lsbfirst::LSBFIRST, | ||
| 125 | BitOrder::MsbFirst => vals::Lsbfirst::MSBFIRST, | ||
| 101 | } | 126 | } |
| 102 | } | 127 | } |
| 103 | } | 128 | } |
| @@ -156,24 +181,10 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 156 | let pclk = T::frequency(); | 181 | let pclk = T::frequency(); |
| 157 | let br = compute_baud_rate(pclk, freq.into()); | 182 | let br = compute_baud_rate(pclk, freq.into()); |
| 158 | 183 | ||
| 159 | let cpha = match config.mode.phase { | 184 | let cpha = config.raw_phase(); |
| 160 | Phase::CaptureOnSecondTransition => vals::Cpha::SECONDEDGE, | 185 | let cpol = config.raw_polarity(); |
| 161 | Phase::CaptureOnFirstTransition => vals::Cpha::FIRSTEDGE, | ||
| 162 | }; | ||
| 163 | let cpol = match config.mode.polarity { | ||
| 164 | Polarity::IdleHigh => vals::Cpol::IDLEHIGH, | ||
| 165 | Polarity::IdleLow => vals::Cpol::IDLELOW, | ||
| 166 | }; | ||
| 167 | 186 | ||
| 168 | #[cfg(not(spi_v3))] | 187 | let lsbfirst = config.raw_byte_order(); |
| 169 | use vals::Lsbfirst; | ||
| 170 | #[cfg(spi_v3)] | ||
| 171 | use vals::Lsbfrst as Lsbfirst; | ||
| 172 | |||
| 173 | let lsbfirst = match config.byte_order { | ||
| 174 | ByteOrder::LsbFirst => Lsbfirst::LSBFIRST, | ||
| 175 | ByteOrder::MsbFirst => Lsbfirst::MSBFIRST, | ||
| 176 | }; | ||
| 177 | 188 | ||
| 178 | T::enable(); | 189 | T::enable(); |
| 179 | T::reset(); | 190 | T::reset(); |
| @@ -230,7 +241,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 230 | w.set_ssoe(false); | 241 | w.set_ssoe(false); |
| 231 | w.set_cpha(cpha); | 242 | w.set_cpha(cpha); |
| 232 | w.set_cpol(cpol); | 243 | w.set_cpol(cpol); |
| 233 | w.set_lsbfrst(lsbfirst); | 244 | w.set_lsbfirst(lsbfirst); |
| 234 | w.set_ssm(true); | 245 | w.set_ssm(true); |
| 235 | w.set_master(vals::Master::MASTER); | 246 | w.set_master(vals::Master::MASTER); |
| 236 | w.set_comm(vals::Comm::FULLDUPLEX); | 247 | w.set_comm(vals::Comm::FULLDUPLEX); |
| @@ -266,6 +277,60 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 266 | } | 277 | } |
| 267 | } | 278 | } |
| 268 | 279 | ||
| 280 | /// Reconfigures it with the supplied config. | ||
| 281 | pub fn reconfigure(&mut self, config: Config) { | ||
| 282 | let cpha = config.raw_phase(); | ||
| 283 | let cpol = config.raw_polarity(); | ||
| 284 | |||
| 285 | let lsbfirst = config.raw_byte_order(); | ||
| 286 | |||
| 287 | #[cfg(any(spi_v1, spi_f1, spi_v2))] | ||
| 288 | unsafe { | ||
| 289 | T::regs().cr1().modify(|w| { | ||
| 290 | w.set_cpha(cpha); | ||
| 291 | w.set_cpol(cpol); | ||
| 292 | w.set_lsbfirst(lsbfirst); | ||
| 293 | }); | ||
| 294 | } | ||
| 295 | |||
| 296 | #[cfg(spi_v3)] | ||
| 297 | unsafe { | ||
| 298 | T::regs().cfg2().modify(|w| { | ||
| 299 | w.set_cpha(cpha); | ||
| 300 | w.set_cpol(cpol); | ||
| 301 | w.set_lsbfirst(lsbfirst); | ||
| 302 | }); | ||
| 303 | } | ||
| 304 | } | ||
| 305 | |||
| 306 | pub fn get_current_config(&self) -> Config { | ||
| 307 | #[cfg(any(spi_v1, spi_f1, spi_v2))] | ||
| 308 | let cfg = unsafe { T::regs().cr1().read() }; | ||
| 309 | #[cfg(spi_v3)] | ||
| 310 | let cfg = unsafe { T::regs().cfg2().read() }; | ||
| 311 | let polarity = if cfg.cpol() == vals::Cpol::IDLELOW { | ||
| 312 | Polarity::IdleLow | ||
| 313 | } else { | ||
| 314 | Polarity::IdleHigh | ||
| 315 | }; | ||
| 316 | let phase = if cfg.cpha() == vals::Cpha::FIRSTEDGE { | ||
| 317 | Phase::CaptureOnFirstTransition | ||
| 318 | } else { | ||
| 319 | Phase::CaptureOnSecondTransition | ||
| 320 | }; | ||
| 321 | |||
| 322 | let bit_order = if cfg.lsbfirst() == vals::Lsbfirst::LSBFIRST { | ||
| 323 | BitOrder::LsbFirst | ||
| 324 | } else { | ||
| 325 | BitOrder::MsbFirst | ||
| 326 | }; | ||
| 327 | |||
| 328 | Config { | ||
| 329 | mode: Mode { polarity, phase }, | ||
| 330 | bit_order, | ||
| 331 | } | ||
| 332 | } | ||
| 333 | |||
| 269 | fn set_word_size(&mut self, word_size: WordSize) { | 334 | fn set_word_size(&mut self, word_size: WordSize) { |
| 270 | if self.current_word_size == word_size { | 335 | if self.current_word_size == word_size { |
| 271 | return; | 336 | return; |
diff --git a/embassy-stm32/src/subghz/mod.rs b/embassy-stm32/src/subghz/mod.rs index ba333c70d..7d74569f3 100644 --- a/embassy-stm32/src/subghz/mod.rs +++ b/embassy-stm32/src/subghz/mod.rs | |||
| @@ -82,7 +82,7 @@ use crate::{ | |||
| 82 | pac, | 82 | pac, |
| 83 | peripherals::SUBGHZSPI, | 83 | peripherals::SUBGHZSPI, |
| 84 | rcc::sealed::RccPeripheral, | 84 | rcc::sealed::RccPeripheral, |
| 85 | spi::{ByteOrder, Config as SpiConfig, MisoPin, MosiPin, SckPin, Spi}, | 85 | spi::{BitOrder, Config as SpiConfig, MisoPin, MosiPin, SckPin, Spi}, |
| 86 | time::Hertz, | 86 | time::Hertz, |
| 87 | }; | 87 | }; |
| 88 | use embassy::util::Unborrow; | 88 | use embassy::util::Unborrow; |
| @@ -233,7 +233,7 @@ impl<'d, Tx, Rx> SubGhz<'d, Tx, Rx> { | |||
| 233 | let clk = Hertz(core::cmp::min(SUBGHZSPI::frequency().0 / 2, 16_000_000)); | 233 | let clk = Hertz(core::cmp::min(SUBGHZSPI::frequency().0 / 2, 16_000_000)); |
| 234 | let mut config = SpiConfig::default(); | 234 | let mut config = SpiConfig::default(); |
| 235 | config.mode = MODE_0; | 235 | config.mode = MODE_0; |
| 236 | config.byte_order = ByteOrder::MsbFirst; | 236 | config.bit_order = BitOrder::MsbFirst; |
| 237 | let spi = Spi::new(peri, sck, mosi, miso, txdma, rxdma, clk, config); | 237 | let spi = Spi::new(peri, sck, mosi, miso, txdma, rxdma, clk, config); |
| 238 | 238 | ||
| 239 | unsafe { wakeup() }; | 239 | unsafe { wakeup() }; |
