diff options
| -rw-r--r-- | embassy-stm32/src/spi/mod.rs | 122 |
1 files changed, 56 insertions, 66 deletions
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 5d919f923..8befaf529 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs | |||
| @@ -152,34 +152,43 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | let pclk = T::frequency(); | 154 | let pclk = T::frequency(); |
| 155 | let br = Self::compute_baud_rate(pclk, freq.into()); | 155 | let br = compute_baud_rate(pclk, freq.into()); |
| 156 | |||
| 157 | let cpha = match config.mode.phase { | ||
| 158 | Phase::CaptureOnSecondTransition => vals::Cpha::SECONDEDGE, | ||
| 159 | Phase::CaptureOnFirstTransition => vals::Cpha::FIRSTEDGE, | ||
| 160 | }; | ||
| 161 | let cpol = match config.mode.polarity { | ||
| 162 | Polarity::IdleHigh => vals::Cpol::IDLEHIGH, | ||
| 163 | Polarity::IdleLow => vals::Cpol::IDLELOW, | ||
| 164 | }; | ||
| 165 | |||
| 166 | #[cfg(not(spi_v3))] | ||
| 167 | use vals::Lsbfirst; | ||
| 168 | #[cfg(spi_v3)] | ||
| 169 | use vals::Lsbfrst as Lsbfirst; | ||
| 170 | |||
| 171 | let lsbfirst = match config.byte_order { | ||
| 172 | ByteOrder::LsbFirst => Lsbfirst::LSBFIRST, | ||
| 173 | ByteOrder::MsbFirst => Lsbfirst::MSBFIRST, | ||
| 174 | }; | ||
| 175 | |||
| 176 | T::enable(); | ||
| 177 | T::reset(); | ||
| 156 | 178 | ||
| 157 | #[cfg(any(spi_v1, spi_f1))] | 179 | #[cfg(any(spi_v1, spi_f1))] |
| 158 | unsafe { | 180 | unsafe { |
| 159 | T::enable(); | ||
| 160 | T::reset(); | ||
| 161 | T::regs().cr2().modify(|w| { | 181 | T::regs().cr2().modify(|w| { |
| 162 | w.set_ssoe(false); | 182 | w.set_ssoe(false); |
| 163 | }); | 183 | }); |
| 164 | T::regs().cr1().modify(|w| { | 184 | T::regs().cr1().modify(|w| { |
| 165 | w.set_cpha( | 185 | w.set_cpha(cpha); |
| 166 | match config.mode.phase == Phase::CaptureOnSecondTransition { | 186 | w.set_cpol(cpol); |
| 167 | true => vals::Cpha::SECONDEDGE, | ||
| 168 | false => vals::Cpha::FIRSTEDGE, | ||
| 169 | }, | ||
| 170 | ); | ||
| 171 | w.set_cpol(match config.mode.polarity == Polarity::IdleHigh { | ||
| 172 | true => vals::Cpol::IDLEHIGH, | ||
| 173 | false => vals::Cpol::IDLELOW, | ||
| 174 | }); | ||
| 175 | 187 | ||
| 176 | w.set_mstr(vals::Mstr::MASTER); | 188 | w.set_mstr(vals::Mstr::MASTER); |
| 177 | w.set_br(vals::Br(br)); | 189 | w.set_br(br); |
| 178 | w.set_spe(true); | 190 | w.set_spe(true); |
| 179 | w.set_lsbfirst(match config.byte_order { | 191 | w.set_lsbfirst(lsbfirst); |
| 180 | ByteOrder::LsbFirst => vals::Lsbfirst::LSBFIRST, | ||
| 181 | ByteOrder::MsbFirst => vals::Lsbfirst::MSBFIRST, | ||
| 182 | }); | ||
| 183 | w.set_ssi(true); | 192 | w.set_ssi(true); |
| 184 | w.set_ssm(true); | 193 | w.set_ssm(true); |
| 185 | w.set_crcen(false); | 194 | w.set_crcen(false); |
| @@ -192,31 +201,18 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 192 | } | 201 | } |
| 193 | #[cfg(spi_v2)] | 202 | #[cfg(spi_v2)] |
| 194 | unsafe { | 203 | unsafe { |
| 195 | T::enable(); | ||
| 196 | T::reset(); | ||
| 197 | T::regs().cr2().modify(|w| { | 204 | T::regs().cr2().modify(|w| { |
| 198 | w.set_frxth(WordSize::EightBit.frxth()); | 205 | w.set_frxth(WordSize::EightBit.frxth()); |
| 199 | w.set_ds(WordSize::EightBit.ds()); | 206 | w.set_ds(WordSize::EightBit.ds()); |
| 200 | w.set_ssoe(false); | 207 | w.set_ssoe(false); |
| 201 | }); | 208 | }); |
| 202 | T::regs().cr1().modify(|w| { | 209 | T::regs().cr1().modify(|w| { |
| 203 | w.set_cpha( | 210 | w.set_cpha(cpha); |
| 204 | match config.mode.phase == Phase::CaptureOnSecondTransition { | 211 | w.set_cpol(cpol); |
| 205 | true => vals::Cpha::SECONDEDGE, | ||
| 206 | false => vals::Cpha::FIRSTEDGE, | ||
| 207 | }, | ||
| 208 | ); | ||
| 209 | w.set_cpol(match config.mode.polarity == Polarity::IdleHigh { | ||
| 210 | true => vals::Cpol::IDLEHIGH, | ||
| 211 | false => vals::Cpol::IDLELOW, | ||
| 212 | }); | ||
| 213 | 212 | ||
| 214 | w.set_mstr(vals::Mstr::MASTER); | 213 | w.set_mstr(vals::Mstr::MASTER); |
| 215 | w.set_br(vals::Br(br)); | 214 | w.set_br(br); |
| 216 | w.set_lsbfirst(match config.byte_order { | 215 | w.set_lsbfirst(lsbfirst); |
| 217 | ByteOrder::LsbFirst => vals::Lsbfirst::LSBFIRST, | ||
| 218 | ByteOrder::MsbFirst => vals::Lsbfirst::MSBFIRST, | ||
| 219 | }); | ||
| 220 | w.set_ssi(true); | 216 | w.set_ssi(true); |
| 221 | w.set_ssm(true); | 217 | w.set_ssm(true); |
| 222 | w.set_crcen(false); | 218 | w.set_crcen(false); |
| @@ -226,26 +222,13 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 226 | } | 222 | } |
| 227 | #[cfg(spi_v3)] | 223 | #[cfg(spi_v3)] |
| 228 | unsafe { | 224 | unsafe { |
| 229 | T::enable(); | ||
| 230 | T::reset(); | ||
| 231 | T::regs().ifcr().write(|w| w.0 = 0xffff_ffff); | 225 | T::regs().ifcr().write(|w| w.0 = 0xffff_ffff); |
| 232 | T::regs().cfg2().modify(|w| { | 226 | T::regs().cfg2().modify(|w| { |
| 233 | //w.set_ssoe(true); | 227 | //w.set_ssoe(true); |
| 234 | w.set_ssoe(false); | 228 | w.set_ssoe(false); |
| 235 | w.set_cpha( | 229 | w.set_cpha(cpha); |
| 236 | match config.mode.phase == Phase::CaptureOnSecondTransition { | 230 | w.set_cpol(cpol); |
| 237 | true => vals::Cpha::SECONDEDGE, | 231 | w.set_lsbfrst(lsbfirst); |
| 238 | false => vals::Cpha::FIRSTEDGE, | ||
| 239 | }, | ||
| 240 | ); | ||
| 241 | w.set_cpol(match config.mode.polarity == Polarity::IdleHigh { | ||
| 242 | true => vals::Cpol::IDLEHIGH, | ||
| 243 | false => vals::Cpol::IDLELOW, | ||
| 244 | }); | ||
| 245 | w.set_lsbfrst(match config.byte_order { | ||
| 246 | ByteOrder::LsbFirst => vals::Lsbfrst::LSBFIRST, | ||
| 247 | ByteOrder::MsbFirst => vals::Lsbfrst::MSBFIRST, | ||
| 248 | }); | ||
| 249 | w.set_ssm(true); | 232 | w.set_ssm(true); |
| 250 | w.set_master(vals::Master::MASTER); | 233 | w.set_master(vals::Master::MASTER); |
| 251 | w.set_comm(vals::Comm::FULLDUPLEX); | 234 | w.set_comm(vals::Comm::FULLDUPLEX); |
| @@ -257,7 +240,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 257 | }); | 240 | }); |
| 258 | T::regs().cfg1().modify(|w| { | 241 | T::regs().cfg1().modify(|w| { |
| 259 | w.set_crcen(false); | 242 | w.set_crcen(false); |
| 260 | w.set_mbr(vals::Mbr(br)); | 243 | w.set_mbr(br); |
| 261 | w.set_dsize(WordSize::EightBit.dsize()); | 244 | w.set_dsize(WordSize::EightBit.dsize()); |
| 262 | }); | 245 | }); |
| 263 | T::regs().cr2().modify(|w| { | 246 | T::regs().cr2().modify(|w| { |
| @@ -281,20 +264,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 281 | } | 264 | } |
| 282 | } | 265 | } |
| 283 | 266 | ||
| 284 | fn compute_baud_rate(clocks: Hertz, freq: Hertz) -> u8 { | ||
| 285 | match clocks.0 / freq.0 { | ||
| 286 | 0 => unreachable!(), | ||
| 287 | 1..=2 => 0b000, | ||
| 288 | 3..=5 => 0b001, | ||
| 289 | 6..=11 => 0b010, | ||
| 290 | 12..=23 => 0b011, | ||
| 291 | 24..=39 => 0b100, | ||
| 292 | 40..=95 => 0b101, | ||
| 293 | 96..=191 => 0b110, | ||
| 294 | _ => 0b111, | ||
| 295 | } | ||
| 296 | } | ||
| 297 | |||
| 298 | fn set_word_size(&mut self, word_size: WordSize) { | 267 | fn set_word_size(&mut self, word_size: WordSize) { |
| 299 | if self.current_word_size == word_size { | 268 | if self.current_word_size == word_size { |
| 300 | return; | 269 | return; |
| @@ -355,6 +324,27 @@ impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> { | |||
| 355 | } | 324 | } |
| 356 | } | 325 | } |
| 357 | 326 | ||
| 327 | #[cfg(not(spi_v3))] | ||
| 328 | use vals::Br; | ||
| 329 | #[cfg(spi_v3)] | ||
| 330 | use vals::Mbr as Br; | ||
| 331 | |||
| 332 | fn compute_baud_rate(clocks: Hertz, freq: Hertz) -> Br { | ||
| 333 | let val = match clocks.0 / freq.0 { | ||
| 334 | 0 => unreachable!(), | ||
| 335 | 1..=2 => 0b000, | ||
| 336 | 3..=5 => 0b001, | ||
| 337 | 6..=11 => 0b010, | ||
| 338 | 12..=23 => 0b011, | ||
| 339 | 24..=39 => 0b100, | ||
| 340 | 40..=95 => 0b101, | ||
| 341 | 96..=191 => 0b110, | ||
| 342 | _ => 0b111, | ||
| 343 | }; | ||
| 344 | |||
| 345 | Br(val) | ||
| 346 | } | ||
| 347 | |||
| 358 | trait RegsExt { | 348 | trait RegsExt { |
| 359 | fn tx_ptr<W>(&self) -> *mut W; | 349 | fn tx_ptr<W>(&self) -> *mut W; |
| 360 | fn rx_ptr<W>(&self) -> *mut W; | 350 | fn rx_ptr<W>(&self) -> *mut W; |
