diff options
| author | Grant Miller <[email protected]> | 2021-12-06 15:19:24 -0600 |
|---|---|---|
| committer | Grant Miller <[email protected]> | 2021-12-06 15:19:24 -0600 |
| commit | a35f337bd68645dbc0462d09220457c22bbd5c17 (patch) | |
| tree | 6fd006100f80de82286c92c2e04e2b1d7d99d3ac | |
| parent | 75374ce7e853143fdc16bd194342e6ef8bcac513 (diff) | |
Move Spi::new and Spi::compute_baud_rate to mod
| -rw-r--r-- | embassy-stm32/src/spi/mod.rs | 188 | ||||
| -rw-r--r-- | embassy-stm32/src/spi/v1.rs | 105 | ||||
| -rw-r--r-- | embassy-stm32/src/spi/v2.rs | 108 | ||||
| -rw-r--r-- | embassy-stm32/src/spi/v3.rs | 119 |
4 files changed, 191 insertions, 329 deletions
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 4899676eb..70f40f0ea 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs | |||
| @@ -1,11 +1,15 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | use crate::dma; | 3 | use crate::dma; |
| 4 | use crate::gpio::sealed::{AFType, Pin}; | ||
| 4 | use crate::gpio::{AnyPin, NoPin, OptionalPin}; | 5 | use crate::gpio::{AnyPin, NoPin, OptionalPin}; |
| 5 | use crate::pac::spi::vals; | 6 | use crate::pac::spi::vals; |
| 6 | use crate::peripherals; | 7 | use crate::peripherals; |
| 7 | use crate::rcc::RccPeripheral; | 8 | use crate::rcc::RccPeripheral; |
| 9 | use crate::time::Hertz; | ||
| 8 | use core::marker::PhantomData; | 10 | use core::marker::PhantomData; |
| 11 | use embassy::util::Unborrow; | ||
| 12 | use embassy_hal_common::unborrow; | ||
| 9 | 13 | ||
| 10 | #[cfg_attr(spi_v1, path = "v1.rs")] | 14 | #[cfg_attr(spi_v1, path = "v1.rs")] |
| 11 | #[cfg_attr(spi_f1, path = "v1.rs")] | 15 | #[cfg_attr(spi_f1, path = "v1.rs")] |
| @@ -102,6 +106,190 @@ pub struct Spi<'d, T: Instance, Tx, Rx> { | |||
| 102 | phantom: PhantomData<&'d mut T>, | 106 | phantom: PhantomData<&'d mut T>, |
| 103 | } | 107 | } |
| 104 | 108 | ||
| 109 | impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | ||
| 110 | pub fn new<F>( | ||
| 111 | _peri: impl Unborrow<Target = T> + 'd, | ||
| 112 | sck: impl Unborrow<Target = impl SckPin<T>>, | ||
| 113 | mosi: impl Unborrow<Target = impl MosiPin<T>>, | ||
| 114 | miso: impl Unborrow<Target = impl MisoPin<T>>, | ||
| 115 | txdma: impl Unborrow<Target = Tx>, | ||
| 116 | rxdma: impl Unborrow<Target = Rx>, | ||
| 117 | freq: F, | ||
| 118 | config: Config, | ||
| 119 | ) -> Self | ||
| 120 | where | ||
| 121 | F: Into<Hertz>, | ||
| 122 | { | ||
| 123 | unborrow!(sck, mosi, miso, txdma, rxdma); | ||
| 124 | |||
| 125 | let sck_af = sck.af_num(); | ||
| 126 | let mosi_af = mosi.af_num(); | ||
| 127 | let miso_af = miso.af_num(); | ||
| 128 | let sck = sck.degrade_optional(); | ||
| 129 | let mosi = mosi.degrade_optional(); | ||
| 130 | let miso = miso.degrade_optional(); | ||
| 131 | |||
| 132 | unsafe { | ||
| 133 | sck.as_ref().map(|x| { | ||
| 134 | x.set_as_af(sck_af, AFType::OutputPushPull); | ||
| 135 | #[cfg(any(spi_v2, spi_v3))] | ||
| 136 | x.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 137 | }); | ||
| 138 | mosi.as_ref().map(|x| { | ||
| 139 | x.set_as_af(mosi_af, AFType::OutputPushPull); | ||
| 140 | #[cfg(any(spi_v2, spi_v3))] | ||
| 141 | x.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 142 | }); | ||
| 143 | miso.as_ref().map(|x| { | ||
| 144 | x.set_as_af(miso_af, AFType::Input); | ||
| 145 | #[cfg(any(spi_v2, spi_v3))] | ||
| 146 | x.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 147 | }); | ||
| 148 | } | ||
| 149 | |||
| 150 | let pclk = T::frequency(); | ||
| 151 | let br = Self::compute_baud_rate(pclk, freq.into()); | ||
| 152 | |||
| 153 | #[cfg(any(spi_v1, spi_f1))] | ||
| 154 | unsafe { | ||
| 155 | T::enable(); | ||
| 156 | T::reset(); | ||
| 157 | T::regs().cr2().modify(|w| { | ||
| 158 | w.set_ssoe(false); | ||
| 159 | }); | ||
| 160 | T::regs().cr1().modify(|w| { | ||
| 161 | w.set_cpha( | ||
| 162 | match config.mode.phase == Phase::CaptureOnSecondTransition { | ||
| 163 | true => vals::Cpha::SECONDEDGE, | ||
| 164 | false => vals::Cpha::FIRSTEDGE, | ||
| 165 | }, | ||
| 166 | ); | ||
| 167 | w.set_cpol(match config.mode.polarity == Polarity::IdleHigh { | ||
| 168 | true => vals::Cpol::IDLEHIGH, | ||
| 169 | false => vals::Cpol::IDLELOW, | ||
| 170 | }); | ||
| 171 | |||
| 172 | w.set_mstr(vals::Mstr::MASTER); | ||
| 173 | w.set_br(vals::Br(br)); | ||
| 174 | w.set_spe(true); | ||
| 175 | w.set_lsbfirst(match config.byte_order { | ||
| 176 | ByteOrder::LsbFirst => vals::Lsbfirst::LSBFIRST, | ||
| 177 | ByteOrder::MsbFirst => vals::Lsbfirst::MSBFIRST, | ||
| 178 | }); | ||
| 179 | w.set_ssi(true); | ||
| 180 | w.set_ssm(true); | ||
| 181 | w.set_crcen(false); | ||
| 182 | w.set_bidimode(vals::Bidimode::UNIDIRECTIONAL); | ||
| 183 | if mosi.is_none() { | ||
| 184 | w.set_rxonly(vals::Rxonly::OUTPUTDISABLED); | ||
| 185 | } | ||
| 186 | w.set_dff(WordSize::EightBit.dff()) | ||
| 187 | }); | ||
| 188 | } | ||
| 189 | #[cfg(spi_v2)] | ||
| 190 | unsafe { | ||
| 191 | T::enable(); | ||
| 192 | T::reset(); | ||
| 193 | T::regs().cr2().modify(|w| { | ||
| 194 | w.set_ssoe(false); | ||
| 195 | }); | ||
| 196 | T::regs().cr1().modify(|w| { | ||
| 197 | w.set_cpha( | ||
| 198 | match config.mode.phase == Phase::CaptureOnSecondTransition { | ||
| 199 | true => vals::Cpha::SECONDEDGE, | ||
| 200 | false => vals::Cpha::FIRSTEDGE, | ||
| 201 | }, | ||
| 202 | ); | ||
| 203 | w.set_cpol(match config.mode.polarity == Polarity::IdleHigh { | ||
| 204 | true => vals::Cpol::IDLEHIGH, | ||
| 205 | false => vals::Cpol::IDLELOW, | ||
| 206 | }); | ||
| 207 | |||
| 208 | w.set_mstr(vals::Mstr::MASTER); | ||
| 209 | w.set_br(vals::Br(br)); | ||
| 210 | w.set_lsbfirst(match config.byte_order { | ||
| 211 | ByteOrder::LsbFirst => vals::Lsbfirst::LSBFIRST, | ||
| 212 | ByteOrder::MsbFirst => vals::Lsbfirst::MSBFIRST, | ||
| 213 | }); | ||
| 214 | w.set_ssi(true); | ||
| 215 | w.set_ssm(true); | ||
| 216 | w.set_crcen(false); | ||
| 217 | w.set_bidimode(vals::Bidimode::UNIDIRECTIONAL); | ||
| 218 | w.set_spe(true); | ||
| 219 | }); | ||
| 220 | } | ||
| 221 | #[cfg(spi_v3)] | ||
| 222 | unsafe { | ||
| 223 | T::enable(); | ||
| 224 | T::reset(); | ||
| 225 | T::regs().ifcr().write(|w| w.0 = 0xffff_ffff); | ||
| 226 | T::regs().cfg2().modify(|w| { | ||
| 227 | //w.set_ssoe(true); | ||
| 228 | w.set_ssoe(false); | ||
| 229 | w.set_cpha( | ||
| 230 | match config.mode.phase == Phase::CaptureOnSecondTransition { | ||
| 231 | true => vals::Cpha::SECONDEDGE, | ||
| 232 | false => vals::Cpha::FIRSTEDGE, | ||
| 233 | }, | ||
| 234 | ); | ||
| 235 | w.set_cpol(match config.mode.polarity == Polarity::IdleHigh { | ||
| 236 | true => vals::Cpol::IDLEHIGH, | ||
| 237 | false => vals::Cpol::IDLELOW, | ||
| 238 | }); | ||
| 239 | w.set_lsbfrst(match config.byte_order { | ||
| 240 | ByteOrder::LsbFirst => vals::Lsbfrst::LSBFIRST, | ||
| 241 | ByteOrder::MsbFirst => vals::Lsbfrst::MSBFIRST, | ||
| 242 | }); | ||
| 243 | w.set_ssm(true); | ||
| 244 | w.set_master(vals::Master::MASTER); | ||
| 245 | w.set_comm(vals::Comm::FULLDUPLEX); | ||
| 246 | w.set_ssom(vals::Ssom::ASSERTED); | ||
| 247 | w.set_midi(0); | ||
| 248 | w.set_mssi(0); | ||
| 249 | w.set_afcntr(vals::Afcntr::CONTROLLED); | ||
| 250 | w.set_ssiop(vals::Ssiop::ACTIVEHIGH); | ||
| 251 | }); | ||
| 252 | T::regs().cfg1().modify(|w| { | ||
| 253 | w.set_crcen(false); | ||
| 254 | w.set_mbr(vals::Mbr(br)); | ||
| 255 | w.set_dsize(WordSize::EightBit.dsize()); | ||
| 256 | }); | ||
| 257 | T::regs().cr2().modify(|w| { | ||
| 258 | w.set_tsize(0); | ||
| 259 | w.set_tser(0); | ||
| 260 | }); | ||
| 261 | T::regs().cr1().modify(|w| { | ||
| 262 | w.set_ssi(false); | ||
| 263 | w.set_spe(true); | ||
| 264 | }); | ||
| 265 | } | ||
| 266 | |||
| 267 | Self { | ||
| 268 | sck, | ||
| 269 | mosi, | ||
| 270 | miso, | ||
| 271 | txdma, | ||
| 272 | rxdma, | ||
| 273 | current_word_size: WordSize::EightBit, | ||
| 274 | phantom: PhantomData, | ||
| 275 | } | ||
| 276 | } | ||
| 277 | |||
| 278 | fn compute_baud_rate(clocks: Hertz, freq: Hertz) -> u8 { | ||
| 279 | match clocks.0 / freq.0 { | ||
| 280 | 0 => unreachable!(), | ||
| 281 | 1..=2 => 0b000, | ||
| 282 | 3..=5 => 0b001, | ||
| 283 | 6..=11 => 0b010, | ||
| 284 | 12..=23 => 0b011, | ||
| 285 | 24..=39 => 0b100, | ||
| 286 | 40..=95 => 0b101, | ||
| 287 | 96..=191 => 0b110, | ||
| 288 | _ => 0b111, | ||
| 289 | } | ||
| 290 | } | ||
| 291 | } | ||
| 292 | |||
| 105 | pub(crate) mod sealed { | 293 | pub(crate) mod sealed { |
| 106 | use super::*; | 294 | use super::*; |
| 107 | 295 | ||
diff --git a/embassy-stm32/src/spi/v1.rs b/embassy-stm32/src/spi/v1.rs index 1b870c2dc..8cdc3cd59 100644 --- a/embassy-stm32/src/spi/v1.rs +++ b/embassy-stm32/src/spi/v1.rs | |||
| @@ -1,19 +1,10 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | use crate::dma::NoDma; | 3 | use crate::dma::NoDma; |
| 4 | use crate::gpio::sealed::AFType; | ||
| 5 | use crate::gpio::sealed::Pin; | 4 | use crate::gpio::sealed::Pin; |
| 6 | use crate::pac::spi; | 5 | use crate::spi::{Error, Instance, RxDmaChannel, TxDmaChannel, WordSize}; |
| 7 | use crate::spi::{ | ||
| 8 | ByteOrder, Config, Error, Instance, MisoPin, MosiPin, RxDmaChannel, SckPin, TxDmaChannel, | ||
| 9 | WordSize, | ||
| 10 | }; | ||
| 11 | use crate::time::Hertz; | ||
| 12 | use core::future::Future; | 6 | use core::future::Future; |
| 13 | use core::marker::PhantomData; | ||
| 14 | use core::ptr; | 7 | use core::ptr; |
| 15 | use embassy::util::Unborrow; | ||
| 16 | use embassy_hal_common::unborrow; | ||
| 17 | use embassy_traits::spi as traits; | 8 | use embassy_traits::spi as traits; |
| 18 | pub use embedded_hal::blocking; | 9 | pub use embedded_hal::blocking; |
| 19 | pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; | 10 | pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; |
| @@ -22,100 +13,6 @@ use futures::future::join3; | |||
| 22 | use super::Spi; | 13 | use super::Spi; |
| 23 | 14 | ||
| 24 | impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | 15 | impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { |
| 25 | pub fn new<F>( | ||
| 26 | _peri: impl Unborrow<Target = T> + 'd, | ||
| 27 | sck: impl Unborrow<Target = impl SckPin<T>>, | ||
| 28 | mosi: impl Unborrow<Target = impl MosiPin<T>>, | ||
| 29 | miso: impl Unborrow<Target = impl MisoPin<T>>, | ||
| 30 | txdma: impl Unborrow<Target = Tx>, | ||
| 31 | rxdma: impl Unborrow<Target = Rx>, | ||
| 32 | freq: F, | ||
| 33 | config: Config, | ||
| 34 | ) -> Self | ||
| 35 | where | ||
| 36 | F: Into<Hertz>, | ||
| 37 | { | ||
| 38 | unborrow!(sck, mosi, miso, txdma, rxdma); | ||
| 39 | |||
| 40 | let sck_af = sck.af_num(); | ||
| 41 | let mosi_af = mosi.af_num(); | ||
| 42 | let miso_af = miso.af_num(); | ||
| 43 | let sck = sck.degrade_optional(); | ||
| 44 | let mosi = mosi.degrade_optional(); | ||
| 45 | let miso = miso.degrade_optional(); | ||
| 46 | |||
| 47 | unsafe { | ||
| 48 | sck.as_ref() | ||
| 49 | .map(|x| x.set_as_af(sck_af, AFType::OutputPushPull)); | ||
| 50 | mosi.as_ref() | ||
| 51 | .map(|x| x.set_as_af(mosi_af, AFType::OutputPushPull)); | ||
| 52 | miso.as_ref().map(|x| x.set_as_af(miso_af, AFType::Input)); | ||
| 53 | } | ||
| 54 | |||
| 55 | let pclk = T::frequency(); | ||
| 56 | let br = Self::compute_baud_rate(pclk, freq.into()); | ||
| 57 | |||
| 58 | unsafe { | ||
| 59 | T::enable(); | ||
| 60 | T::reset(); | ||
| 61 | T::regs().cr2().modify(|w| { | ||
| 62 | w.set_ssoe(false); | ||
| 63 | }); | ||
| 64 | T::regs().cr1().modify(|w| { | ||
| 65 | w.set_cpha( | ||
| 66 | match config.mode.phase == Phase::CaptureOnSecondTransition { | ||
| 67 | true => spi::vals::Cpha::SECONDEDGE, | ||
| 68 | false => spi::vals::Cpha::FIRSTEDGE, | ||
| 69 | }, | ||
| 70 | ); | ||
| 71 | w.set_cpol(match config.mode.polarity == Polarity::IdleHigh { | ||
| 72 | true => spi::vals::Cpol::IDLEHIGH, | ||
| 73 | false => spi::vals::Cpol::IDLELOW, | ||
| 74 | }); | ||
| 75 | |||
| 76 | w.set_mstr(spi::vals::Mstr::MASTER); | ||
| 77 | w.set_br(spi::vals::Br(br)); | ||
| 78 | w.set_spe(true); | ||
| 79 | w.set_lsbfirst(match config.byte_order { | ||
| 80 | ByteOrder::LsbFirst => spi::vals::Lsbfirst::LSBFIRST, | ||
| 81 | ByteOrder::MsbFirst => spi::vals::Lsbfirst::MSBFIRST, | ||
| 82 | }); | ||
| 83 | w.set_ssi(true); | ||
| 84 | w.set_ssm(true); | ||
| 85 | w.set_crcen(false); | ||
| 86 | w.set_bidimode(spi::vals::Bidimode::UNIDIRECTIONAL); | ||
| 87 | if mosi.is_none() { | ||
| 88 | w.set_rxonly(spi::vals::Rxonly::OUTPUTDISABLED); | ||
| 89 | } | ||
| 90 | w.set_dff(WordSize::EightBit.dff()) | ||
| 91 | }); | ||
| 92 | } | ||
| 93 | |||
| 94 | Self { | ||
| 95 | sck, | ||
| 96 | mosi, | ||
| 97 | miso, | ||
| 98 | txdma, | ||
| 99 | rxdma, | ||
| 100 | current_word_size: WordSize::EightBit, | ||
| 101 | phantom: PhantomData, | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | fn compute_baud_rate(clocks: Hertz, freq: Hertz) -> u8 { | ||
| 106 | match clocks.0 / freq.0 { | ||
| 107 | 0 => unreachable!(), | ||
| 108 | 1..=2 => 0b000, | ||
| 109 | 3..=5 => 0b001, | ||
| 110 | 6..=11 => 0b010, | ||
| 111 | 12..=23 => 0b011, | ||
| 112 | 24..=39 => 0b100, | ||
| 113 | 40..=95 => 0b101, | ||
| 114 | 96..=191 => 0b110, | ||
| 115 | _ => 0b111, | ||
| 116 | } | ||
| 117 | } | ||
| 118 | |||
| 119 | fn set_word_size(&mut self, word_size: WordSize) { | 16 | fn set_word_size(&mut self, word_size: WordSize) { |
| 120 | if self.current_word_size == word_size { | 17 | if self.current_word_size == word_size { |
| 121 | return; | 18 | return; |
diff --git a/embassy-stm32/src/spi/v2.rs b/embassy-stm32/src/spi/v2.rs index 94e5ca087..a34266992 100644 --- a/embassy-stm32/src/spi/v2.rs +++ b/embassy-stm32/src/spi/v2.rs | |||
| @@ -2,17 +2,9 @@ | |||
| 2 | 2 | ||
| 3 | use crate::dma::NoDma; | 3 | use crate::dma::NoDma; |
| 4 | use crate::gpio::sealed::Pin; | 4 | use crate::gpio::sealed::Pin; |
| 5 | use crate::pac::spi; | 5 | use crate::spi::{Error, Instance, RxDmaChannel, TxDmaChannel, WordSize}; |
| 6 | use crate::spi::{ | ||
| 7 | ByteOrder, Config, Error, Instance, MisoPin, MosiPin, RxDmaChannel, SckPin, TxDmaChannel, | ||
| 8 | WordSize, | ||
| 9 | }; | ||
| 10 | use crate::time::Hertz; | ||
| 11 | use core::future::Future; | 6 | use core::future::Future; |
| 12 | use core::marker::PhantomData; | ||
| 13 | use core::ptr; | 7 | use core::ptr; |
| 14 | use embassy::util::Unborrow; | ||
| 15 | use embassy_hal_common::unborrow; | ||
| 16 | use embassy_traits::spi as traits; | 8 | use embassy_traits::spi as traits; |
| 17 | pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; | 9 | pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; |
| 18 | use futures::future::{join, join3}; | 10 | use futures::future::{join, join3}; |
| @@ -20,104 +12,6 @@ use futures::future::{join, join3}; | |||
| 20 | use super::Spi; | 12 | use super::Spi; |
| 21 | 13 | ||
| 22 | impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | 14 | impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { |
| 23 | pub fn new<F>( | ||
| 24 | _peri: impl Unborrow<Target = T> + 'd, | ||
| 25 | sck: impl Unborrow<Target = impl SckPin<T>>, | ||
| 26 | mosi: impl Unborrow<Target = impl MosiPin<T>>, | ||
| 27 | miso: impl Unborrow<Target = impl MisoPin<T>>, | ||
| 28 | txdma: impl Unborrow<Target = Tx>, | ||
| 29 | rxdma: impl Unborrow<Target = Rx>, | ||
| 30 | freq: F, | ||
| 31 | config: Config, | ||
| 32 | ) -> Self | ||
| 33 | where | ||
| 34 | F: Into<Hertz>, | ||
| 35 | { | ||
| 36 | unborrow!(sck, mosi, miso, txdma, rxdma); | ||
| 37 | |||
| 38 | let sck_af = sck.af_num(); | ||
| 39 | let mosi_af = mosi.af_num(); | ||
| 40 | let miso_af = miso.af_num(); | ||
| 41 | let sck = sck.degrade_optional(); | ||
| 42 | let mosi = mosi.degrade_optional(); | ||
| 43 | let miso = miso.degrade_optional(); | ||
| 44 | |||
| 45 | unsafe { | ||
| 46 | sck.as_ref().map(|x| { | ||
| 47 | x.set_as_af(sck_af, crate::gpio::sealed::AFType::OutputPushPull); | ||
| 48 | x.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 49 | }); | ||
| 50 | mosi.as_ref().map(|x| { | ||
| 51 | x.set_as_af(mosi_af, crate::gpio::sealed::AFType::OutputPushPull); | ||
| 52 | x.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 53 | }); | ||
| 54 | miso.as_ref().map(|x| { | ||
| 55 | x.set_as_af(miso_af, crate::gpio::sealed::AFType::Input); | ||
| 56 | x.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 57 | }); | ||
| 58 | } | ||
| 59 | |||
| 60 | let pclk = T::frequency(); | ||
| 61 | let freq = freq.into(); | ||
| 62 | let br = Self::compute_baud_rate(pclk, freq); | ||
| 63 | |||
| 64 | unsafe { | ||
| 65 | T::enable(); | ||
| 66 | T::reset(); | ||
| 67 | T::regs().cr2().modify(|w| { | ||
| 68 | w.set_ssoe(false); | ||
| 69 | }); | ||
| 70 | T::regs().cr1().modify(|w| { | ||
| 71 | w.set_cpha( | ||
| 72 | match config.mode.phase == Phase::CaptureOnSecondTransition { | ||
| 73 | true => spi::vals::Cpha::SECONDEDGE, | ||
| 74 | false => spi::vals::Cpha::FIRSTEDGE, | ||
| 75 | }, | ||
| 76 | ); | ||
| 77 | w.set_cpol(match config.mode.polarity == Polarity::IdleHigh { | ||
| 78 | true => spi::vals::Cpol::IDLEHIGH, | ||
| 79 | false => spi::vals::Cpol::IDLELOW, | ||
| 80 | }); | ||
| 81 | |||
| 82 | w.set_mstr(spi::vals::Mstr::MASTER); | ||
| 83 | w.set_br(spi::vals::Br(br)); | ||
| 84 | w.set_lsbfirst(match config.byte_order { | ||
| 85 | ByteOrder::LsbFirst => spi::vals::Lsbfirst::LSBFIRST, | ||
| 86 | ByteOrder::MsbFirst => spi::vals::Lsbfirst::MSBFIRST, | ||
| 87 | }); | ||
| 88 | w.set_ssi(true); | ||
| 89 | w.set_ssm(true); | ||
| 90 | w.set_crcen(false); | ||
| 91 | w.set_bidimode(spi::vals::Bidimode::UNIDIRECTIONAL); | ||
| 92 | w.set_spe(true); | ||
| 93 | }); | ||
| 94 | } | ||
| 95 | |||
| 96 | Self { | ||
| 97 | sck, | ||
| 98 | mosi, | ||
| 99 | miso, | ||
| 100 | txdma, | ||
| 101 | rxdma, | ||
| 102 | current_word_size: WordSize::EightBit, | ||
| 103 | phantom: PhantomData, | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | fn compute_baud_rate(clocks: Hertz, freq: Hertz) -> u8 { | ||
| 108 | match clocks.0 / freq.0 { | ||
| 109 | 0 => unreachable!(), | ||
| 110 | 1..=2 => 0b000, | ||
| 111 | 3..=5 => 0b001, | ||
| 112 | 6..=11 => 0b010, | ||
| 113 | 12..=23 => 0b011, | ||
| 114 | 24..=39 => 0b100, | ||
| 115 | 40..=95 => 0b101, | ||
| 116 | 96..=191 => 0b110, | ||
| 117 | _ => 0b111, | ||
| 118 | } | ||
| 119 | } | ||
| 120 | |||
| 121 | fn set_word_size(&mut self, word_size: WordSize) { | 15 | fn set_word_size(&mut self, word_size: WordSize) { |
| 122 | if self.current_word_size == word_size { | 16 | if self.current_word_size == word_size { |
| 123 | return; | 17 | return; |
diff --git a/embassy-stm32/src/spi/v3.rs b/embassy-stm32/src/spi/v3.rs index 99c3eac10..59afa553b 100644 --- a/embassy-stm32/src/spi/v3.rs +++ b/embassy-stm32/src/spi/v3.rs | |||
| @@ -2,17 +2,9 @@ | |||
| 2 | 2 | ||
| 3 | use crate::dma::NoDma; | 3 | use crate::dma::NoDma; |
| 4 | use crate::gpio::sealed::Pin; | 4 | use crate::gpio::sealed::Pin; |
| 5 | use crate::pac::spi; | 5 | use crate::spi::{Error, Instance, RxDmaChannel, TxDmaChannel, WordSize}; |
| 6 | use crate::spi::{ | ||
| 7 | ByteOrder, Config, Error, Instance, MisoPin, MosiPin, RxDmaChannel, SckPin, TxDmaChannel, | ||
| 8 | WordSize, | ||
| 9 | }; | ||
| 10 | use crate::time::Hertz; | ||
| 11 | use core::future::Future; | 6 | use core::future::Future; |
| 12 | use core::marker::PhantomData; | ||
| 13 | use core::ptr; | 7 | use core::ptr; |
| 14 | use embassy::util::Unborrow; | ||
| 15 | use embassy_hal_common::unborrow; | ||
| 16 | use embassy_traits::spi as traits; | 8 | use embassy_traits::spi as traits; |
| 17 | pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; | 9 | pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; |
| 18 | 10 | ||
| @@ -21,115 +13,6 @@ use futures::future::join3; | |||
| 21 | use super::Spi; | 13 | use super::Spi; |
| 22 | 14 | ||
| 23 | impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | 15 | impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { |
| 24 | pub fn new<F>( | ||
| 25 | _peri: impl Unborrow<Target = T> + 'd, | ||
| 26 | sck: impl Unborrow<Target = impl SckPin<T>>, | ||
| 27 | mosi: impl Unborrow<Target = impl MosiPin<T>>, | ||
| 28 | miso: impl Unborrow<Target = impl MisoPin<T>>, | ||
| 29 | txdma: impl Unborrow<Target = Tx>, | ||
| 30 | rxdma: impl Unborrow<Target = Rx>, | ||
| 31 | freq: F, | ||
| 32 | config: Config, | ||
| 33 | ) -> Self | ||
| 34 | where | ||
| 35 | F: Into<Hertz>, | ||
| 36 | { | ||
| 37 | unborrow!(sck, mosi, miso, txdma, rxdma); | ||
| 38 | |||
| 39 | let sck_af = sck.af_num(); | ||
| 40 | let mosi_af = mosi.af_num(); | ||
| 41 | let miso_af = miso.af_num(); | ||
| 42 | let sck = sck.degrade_optional(); | ||
| 43 | let mosi = mosi.degrade_optional(); | ||
| 44 | let miso = miso.degrade_optional(); | ||
| 45 | |||
| 46 | unsafe { | ||
| 47 | sck.as_ref().map(|x| { | ||
| 48 | x.set_as_af(sck_af, crate::gpio::sealed::AFType::OutputPushPull); | ||
| 49 | x.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 50 | }); | ||
| 51 | mosi.as_ref().map(|x| { | ||
| 52 | x.set_as_af(mosi_af, crate::gpio::sealed::AFType::OutputPushPull); | ||
| 53 | x.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 54 | }); | ||
| 55 | miso.as_ref().map(|x| { | ||
| 56 | x.set_as_af(miso_af, crate::gpio::sealed::AFType::Input); | ||
| 57 | x.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 58 | }); | ||
| 59 | } | ||
| 60 | |||
| 61 | let pclk = T::frequency(); | ||
| 62 | let br = Self::compute_baud_rate(pclk, freq.into()); | ||
| 63 | unsafe { | ||
| 64 | T::enable(); | ||
| 65 | T::reset(); | ||
| 66 | T::regs().ifcr().write(|w| w.0 = 0xffff_ffff); | ||
| 67 | T::regs().cfg2().modify(|w| { | ||
| 68 | //w.set_ssoe(true); | ||
| 69 | w.set_ssoe(false); | ||
| 70 | w.set_cpha( | ||
| 71 | match config.mode.phase == Phase::CaptureOnSecondTransition { | ||
| 72 | true => spi::vals::Cpha::SECONDEDGE, | ||
| 73 | false => spi::vals::Cpha::FIRSTEDGE, | ||
| 74 | }, | ||
| 75 | ); | ||
| 76 | w.set_cpol(match config.mode.polarity == Polarity::IdleHigh { | ||
| 77 | true => spi::vals::Cpol::IDLEHIGH, | ||
| 78 | false => spi::vals::Cpol::IDLELOW, | ||
| 79 | }); | ||
| 80 | w.set_lsbfrst(match config.byte_order { | ||
| 81 | ByteOrder::LsbFirst => spi::vals::Lsbfrst::LSBFIRST, | ||
| 82 | ByteOrder::MsbFirst => spi::vals::Lsbfrst::MSBFIRST, | ||
| 83 | }); | ||
| 84 | w.set_ssm(true); | ||
| 85 | w.set_master(spi::vals::Master::MASTER); | ||
| 86 | w.set_comm(spi::vals::Comm::FULLDUPLEX); | ||
| 87 | w.set_ssom(spi::vals::Ssom::ASSERTED); | ||
| 88 | w.set_midi(0); | ||
| 89 | w.set_mssi(0); | ||
| 90 | w.set_afcntr(spi::vals::Afcntr::CONTROLLED); | ||
| 91 | w.set_ssiop(spi::vals::Ssiop::ACTIVEHIGH); | ||
| 92 | }); | ||
| 93 | T::regs().cfg1().modify(|w| { | ||
| 94 | w.set_crcen(false); | ||
| 95 | w.set_mbr(spi::vals::Mbr(br)); | ||
| 96 | w.set_dsize(WordSize::EightBit.dsize()); | ||
| 97 | }); | ||
| 98 | T::regs().cr2().modify(|w| { | ||
| 99 | w.set_tsize(0); | ||
| 100 | w.set_tser(0); | ||
| 101 | }); | ||
| 102 | T::regs().cr1().modify(|w| { | ||
| 103 | w.set_ssi(false); | ||
| 104 | w.set_spe(true); | ||
| 105 | }); | ||
| 106 | } | ||
| 107 | |||
| 108 | Self { | ||
| 109 | sck, | ||
| 110 | mosi, | ||
| 111 | miso, | ||
| 112 | txdma, | ||
| 113 | rxdma, | ||
| 114 | current_word_size: WordSize::EightBit, | ||
| 115 | phantom: PhantomData, | ||
| 116 | } | ||
| 117 | } | ||
| 118 | |||
| 119 | fn compute_baud_rate(clocks: Hertz, freq: Hertz) -> u8 { | ||
| 120 | match clocks.0 / freq.0 { | ||
| 121 | 0 => unreachable!(), | ||
| 122 | 1..=2 => 0b000, | ||
| 123 | 3..=5 => 0b001, | ||
| 124 | 6..=11 => 0b010, | ||
| 125 | 12..=23 => 0b011, | ||
| 126 | 24..=39 => 0b100, | ||
| 127 | 40..=95 => 0b101, | ||
| 128 | 96..=191 => 0b110, | ||
| 129 | _ => 0b111, | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | fn set_word_size(&mut self, word_size: WordSize) { | 16 | fn set_word_size(&mut self, word_size: WordSize) { |
| 134 | if self.current_word_size == word_size { | 17 | if self.current_word_size == word_size { |
| 135 | return; | 18 | return; |
