diff options
68 files changed, 2916 insertions, 3591 deletions
diff --git a/docs/modules/ROOT/examples/layer-by-layer/blinky-irq/src/main.rs b/docs/modules/ROOT/examples/layer-by-layer/blinky-irq/src/main.rs index 743d0c342..aecba0755 100644 --- a/docs/modules/ROOT/examples/layer-by-layer/blinky-irq/src/main.rs +++ b/docs/modules/ROOT/examples/layer-by-layer/blinky-irq/src/main.rs | |||
| @@ -20,13 +20,13 @@ fn main() -> ! { | |||
| 20 | let led = Output::new(p.PB14, Level::Low, Speed::Low); | 20 | let led = Output::new(p.PB14, Level::Low, Speed::Low); |
| 21 | let mut button = Input::new(p.PC13, Pull::Up); | 21 | let mut button = Input::new(p.PC13, Pull::Up); |
| 22 | 22 | ||
| 23 | cortex_m::interrupt::free(|cs| unsafe { | 23 | cortex_m::interrupt::free(|cs| { |
| 24 | enable_interrupt(&mut button); | 24 | enable_interrupt(&mut button); |
| 25 | 25 | ||
| 26 | LED.borrow(cs).borrow_mut().replace(led); | 26 | LED.borrow(cs).borrow_mut().replace(led); |
| 27 | BUTTON.borrow(cs).borrow_mut().replace(button); | 27 | BUTTON.borrow(cs).borrow_mut().replace(button); |
| 28 | 28 | ||
| 29 | NVIC::unmask(pac::Interrupt::EXTI15_10); | 29 | unsafe { NVIC::unmask(pac::Interrupt::EXTI15_10) }; |
| 30 | }); | 30 | }); |
| 31 | 31 | ||
| 32 | loop { | 32 | loop { |
| @@ -64,25 +64,21 @@ const PORT: u8 = 2; | |||
| 64 | const PIN: usize = 13; | 64 | const PIN: usize = 13; |
| 65 | fn check_interrupt<P: Pin>(_pin: &mut Input<'static, P>) -> bool { | 65 | fn check_interrupt<P: Pin>(_pin: &mut Input<'static, P>) -> bool { |
| 66 | let exti = pac::EXTI; | 66 | let exti = pac::EXTI; |
| 67 | unsafe { | 67 | let pin = PIN; |
| 68 | let pin = PIN; | 68 | let lines = exti.pr(0).read(); |
| 69 | let lines = exti.pr(0).read(); | 69 | lines.line(pin) |
| 70 | lines.line(pin) | ||
| 71 | } | ||
| 72 | } | 70 | } |
| 73 | 71 | ||
| 74 | fn clear_interrupt<P: Pin>(_pin: &mut Input<'static, P>) { | 72 | fn clear_interrupt<P: Pin>(_pin: &mut Input<'static, P>) { |
| 75 | let exti = pac::EXTI; | 73 | let exti = pac::EXTI; |
| 76 | unsafe { | 74 | let pin = PIN; |
| 77 | let pin = PIN; | 75 | let mut lines = exti.pr(0).read(); |
| 78 | let mut lines = exti.pr(0).read(); | 76 | lines.set_line(pin, true); |
| 79 | lines.set_line(pin, true); | 77 | exti.pr(0).write_value(lines); |
| 80 | exti.pr(0).write_value(lines); | ||
| 81 | } | ||
| 82 | } | 78 | } |
| 83 | 79 | ||
| 84 | fn enable_interrupt<P: Pin>(_pin: &mut Input<'static, P>) { | 80 | fn enable_interrupt<P: Pin>(_pin: &mut Input<'static, P>) { |
| 85 | cortex_m::interrupt::free(|_| unsafe { | 81 | cortex_m::interrupt::free(|_| { |
| 86 | let rcc = pac::RCC; | 82 | let rcc = pac::RCC; |
| 87 | rcc.apb2enr().modify(|w| w.set_syscfgen(true)); | 83 | rcc.apb2enr().modify(|w| w.set_syscfgen(true)); |
| 88 | 84 | ||
diff --git a/embassy-lora/src/iv.rs b/embassy-lora/src/iv.rs index 2e0b68d1a..136973fe3 100644 --- a/embassy-lora/src/iv.rs +++ b/embassy-lora/src/iv.rs | |||
| @@ -68,29 +68,23 @@ where | |||
| 68 | } | 68 | } |
| 69 | async fn set_nss_low(&mut self) -> Result<(), RadioError> { | 69 | async fn set_nss_low(&mut self) -> Result<(), RadioError> { |
| 70 | let pwr = pac::PWR; | 70 | let pwr = pac::PWR; |
| 71 | unsafe { | 71 | pwr.subghzspicr().modify(|w| w.set_nss(pac::pwr::vals::Nss::LOW)); |
| 72 | pwr.subghzspicr().modify(|w| w.set_nss(pac::pwr::vals::Nss::LOW)); | ||
| 73 | } | ||
| 74 | Ok(()) | 72 | Ok(()) |
| 75 | } | 73 | } |
| 76 | async fn set_nss_high(&mut self) -> Result<(), RadioError> { | 74 | async fn set_nss_high(&mut self) -> Result<(), RadioError> { |
| 77 | let pwr = pac::PWR; | 75 | let pwr = pac::PWR; |
| 78 | unsafe { | 76 | pwr.subghzspicr().modify(|w| w.set_nss(pac::pwr::vals::Nss::HIGH)); |
| 79 | pwr.subghzspicr().modify(|w| w.set_nss(pac::pwr::vals::Nss::HIGH)); | ||
| 80 | } | ||
| 81 | Ok(()) | 77 | Ok(()) |
| 82 | } | 78 | } |
| 83 | async fn reset(&mut self, _delay: &mut impl DelayUs) -> Result<(), RadioError> { | 79 | async fn reset(&mut self, _delay: &mut impl DelayUs) -> Result<(), RadioError> { |
| 84 | let rcc = pac::RCC; | 80 | let rcc = pac::RCC; |
| 85 | unsafe { | 81 | rcc.csr().modify(|w| w.set_rfrst(true)); |
| 86 | rcc.csr().modify(|w| w.set_rfrst(true)); | 82 | rcc.csr().modify(|w| w.set_rfrst(false)); |
| 87 | rcc.csr().modify(|w| w.set_rfrst(false)); | ||
| 88 | } | ||
| 89 | Ok(()) | 83 | Ok(()) |
| 90 | } | 84 | } |
| 91 | async fn wait_on_busy(&mut self) -> Result<(), RadioError> { | 85 | async fn wait_on_busy(&mut self) -> Result<(), RadioError> { |
| 92 | let pwr = pac::PWR; | 86 | let pwr = pac::PWR; |
| 93 | while unsafe { pwr.sr2().read().rfbusys() == pac::pwr::vals::Rfbusys::BUSY } {} | 87 | while pwr.sr2().read().rfbusys() == pac::pwr::vals::Rfbusys::BUSY {} |
| 94 | Ok(()) | 88 | Ok(()) |
| 95 | } | 89 | } |
| 96 | 90 | ||
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index f876c7146..3d9ee8261 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml | |||
| @@ -57,7 +57,7 @@ sdio-host = "0.5.0" | |||
| 57 | embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } | 57 | embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } |
| 58 | critical-section = "1.1" | 58 | critical-section = "1.1" |
| 59 | atomic-polyfill = "1.0.1" | 59 | atomic-polyfill = "1.0.1" |
| 60 | stm32-metapac = "9" | 60 | stm32-metapac = "10" |
| 61 | vcell = "0.1.3" | 61 | vcell = "0.1.3" |
| 62 | bxcan = "0.7.0" | 62 | bxcan = "0.7.0" |
| 63 | nb = "1.0.0" | 63 | nb = "1.0.0" |
| @@ -74,7 +74,7 @@ critical-section = { version = "1.1", features = ["std"] } | |||
| 74 | [build-dependencies] | 74 | [build-dependencies] |
| 75 | proc-macro2 = "1.0.36" | 75 | proc-macro2 = "1.0.36" |
| 76 | quote = "1.0.15" | 76 | quote = "1.0.15" |
| 77 | stm32-metapac = { version = "9", default-features = false, features = ["metadata"]} | 77 | stm32-metapac = { version = "10", default-features = false, features = ["metadata"]} |
| 78 | 78 | ||
| 79 | [features] | 79 | [features] |
| 80 | default = ["rt"] | 80 | default = ["rt"] |
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 9e597f187..f71074bcf 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -322,7 +322,7 @@ fn main() { | |||
| 322 | let rst_reg = format_ident!("{}", rst.register.to_ascii_lowercase()); | 322 | let rst_reg = format_ident!("{}", rst.register.to_ascii_lowercase()); |
| 323 | let set_rst_field = format_ident!("set_{}", rst.field.to_ascii_lowercase()); | 323 | let set_rst_field = format_ident!("set_{}", rst.field.to_ascii_lowercase()); |
| 324 | quote! { | 324 | quote! { |
| 325 | critical_section::with(|_| unsafe { | 325 | critical_section::with(|_| { |
| 326 | crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(true)); | 326 | crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(true)); |
| 327 | crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(false)); | 327 | crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(false)); |
| 328 | }); | 328 | }); |
| @@ -353,13 +353,13 @@ fn main() { | |||
| 353 | }) | 353 | }) |
| 354 | } | 354 | } |
| 355 | fn enable() { | 355 | fn enable() { |
| 356 | critical_section::with(|_| unsafe { | 356 | critical_section::with(|_| { |
| 357 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); | 357 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); |
| 358 | #after_enable | 358 | #after_enable |
| 359 | }) | 359 | }) |
| 360 | } | 360 | } |
| 361 | fn disable() { | 361 | fn disable() { |
| 362 | critical_section::with(|_| unsafe { | 362 | critical_section::with(|_| { |
| 363 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); | 363 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); |
| 364 | }) | 364 | }) |
| 365 | } | 365 | } |
diff --git a/embassy-stm32/src/adc/f1.rs b/embassy-stm32/src/adc/f1.rs index d30ec001d..2322204d5 100644 --- a/embassy-stm32/src/adc/f1.rs +++ b/embassy-stm32/src/adc/f1.rs | |||
| @@ -32,26 +32,22 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 32 | into_ref!(adc); | 32 | into_ref!(adc); |
| 33 | T::enable(); | 33 | T::enable(); |
| 34 | T::reset(); | 34 | T::reset(); |
| 35 | unsafe { | 35 | T::regs().cr2().modify(|reg| reg.set_adon(true)); |
| 36 | T::regs().cr2().modify(|reg| reg.set_adon(true)); | ||
| 37 | } | ||
| 38 | 36 | ||
| 39 | // 11.4: Before starting a calibration, the ADC must have been in power-on state (ADON bit = ‘1’) | 37 | // 11.4: Before starting a calibration, the ADC must have been in power-on state (ADON bit = ‘1’) |
| 40 | // for at least two ADC clock cycles | 38 | // for at least two ADC clock cycles |
| 41 | delay.delay_us((1_000_000 * 2) / Self::freq().0 + 1); | 39 | delay.delay_us((1_000_000 * 2) / Self::freq().0 + 1); |
| 42 | 40 | ||
| 43 | unsafe { | 41 | // Reset calibration |
| 44 | // Reset calibration | 42 | T::regs().cr2().modify(|reg| reg.set_rstcal(true)); |
| 45 | T::regs().cr2().modify(|reg| reg.set_rstcal(true)); | 43 | while T::regs().cr2().read().rstcal() { |
| 46 | while T::regs().cr2().read().rstcal() { | 44 | // spin |
| 47 | // spin | 45 | } |
| 48 | } | 46 | |
| 49 | 47 | // Calibrate | |
| 50 | // Calibrate | 48 | T::regs().cr2().modify(|reg| reg.set_cal(true)); |
| 51 | T::regs().cr2().modify(|reg| reg.set_cal(true)); | 49 | while T::regs().cr2().read().cal() { |
| 52 | while T::regs().cr2().read().cal() { | 50 | // spin |
| 53 | // spin | ||
| 54 | } | ||
| 55 | } | 51 | } |
| 56 | 52 | ||
| 57 | // One cycle after calibration | 53 | // One cycle after calibration |
| @@ -81,20 +77,16 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 81 | } | 77 | } |
| 82 | 78 | ||
| 83 | pub fn enable_vref(&self, _delay: &mut impl DelayUs<u32>) -> Vref { | 79 | pub fn enable_vref(&self, _delay: &mut impl DelayUs<u32>) -> Vref { |
| 84 | unsafe { | 80 | T::regs().cr2().modify(|reg| { |
| 85 | T::regs().cr2().modify(|reg| { | 81 | reg.set_tsvrefe(true); |
| 86 | reg.set_tsvrefe(true); | 82 | }); |
| 87 | }) | ||
| 88 | } | ||
| 89 | Vref {} | 83 | Vref {} |
| 90 | } | 84 | } |
| 91 | 85 | ||
| 92 | pub fn enable_temperature(&self) -> Temperature { | 86 | pub fn enable_temperature(&self) -> Temperature { |
| 93 | unsafe { | 87 | T::regs().cr2().modify(|reg| { |
| 94 | T::regs().cr2().modify(|reg| { | 88 | reg.set_tsvrefe(true); |
| 95 | reg.set_tsvrefe(true); | 89 | }); |
| 96 | }) | ||
| 97 | } | ||
| 98 | Temperature {} | 90 | Temperature {} |
| 99 | } | 91 | } |
| 100 | 92 | ||
| @@ -104,41 +96,37 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 104 | 96 | ||
| 105 | /// Perform a single conversion. | 97 | /// Perform a single conversion. |
| 106 | fn convert(&mut self) -> u16 { | 98 | fn convert(&mut self) -> u16 { |
| 107 | unsafe { | 99 | T::regs().cr2().modify(|reg| { |
| 108 | T::regs().cr2().modify(|reg| { | 100 | reg.set_adon(true); |
| 109 | reg.set_adon(true); | 101 | reg.set_swstart(true); |
| 110 | reg.set_swstart(true); | 102 | }); |
| 111 | }); | 103 | while T::regs().cr2().read().swstart() {} |
| 112 | while T::regs().cr2().read().swstart() {} | 104 | while !T::regs().sr().read().eoc() {} |
| 113 | while !T::regs().sr().read().eoc() {} | 105 | |
| 114 | 106 | T::regs().dr().read().0 as u16 | |
| 115 | T::regs().dr().read().0 as u16 | ||
| 116 | } | ||
| 117 | } | 107 | } |
| 118 | 108 | ||
| 119 | pub fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 { | 109 | pub fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 { |
| 120 | unsafe { | 110 | Self::set_channel_sample_time(pin.channel(), self.sample_time); |
| 121 | Self::set_channel_sample_time(pin.channel(), self.sample_time); | 111 | T::regs().cr1().modify(|reg| { |
| 122 | T::regs().cr1().modify(|reg| { | 112 | reg.set_scan(false); |
| 123 | reg.set_scan(false); | 113 | reg.set_discen(false); |
| 124 | reg.set_discen(false); | 114 | }); |
| 125 | }); | 115 | T::regs().sqr1().modify(|reg| reg.set_l(0)); |
| 126 | T::regs().sqr1().modify(|reg| reg.set_l(0)); | 116 | |
| 127 | 117 | T::regs().cr2().modify(|reg| { | |
| 128 | T::regs().cr2().modify(|reg| { | 118 | reg.set_cont(false); |
| 129 | reg.set_cont(false); | 119 | reg.set_exttrig(true); |
| 130 | reg.set_exttrig(true); | 120 | reg.set_swstart(false); |
| 131 | reg.set_swstart(false); | 121 | reg.set_extsel(crate::pac::adc::vals::Extsel::SWSTART); |
| 132 | reg.set_extsel(crate::pac::adc::vals::Extsel::SWSTART); | 122 | }); |
| 133 | }); | ||
| 134 | } | ||
| 135 | 123 | ||
| 136 | // Configure the channel to sample | 124 | // Configure the channel to sample |
| 137 | unsafe { T::regs().sqr3().write(|reg| reg.set_sq(0, pin.channel())) } | 125 | T::regs().sqr3().write(|reg| reg.set_sq(0, pin.channel())); |
| 138 | self.convert() | 126 | self.convert() |
| 139 | } | 127 | } |
| 140 | 128 | ||
| 141 | unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { | 129 | fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { |
| 142 | let sample_time = sample_time.into(); | 130 | let sample_time = sample_time.into(); |
| 143 | if ch <= 9 { | 131 | if ch <= 9 { |
| 144 | T::regs().smpr2().modify(|reg| reg.set_smp(ch as _, sample_time)); | 132 | T::regs().smpr2().modify(|reg| reg.set_smp(ch as _, sample_time)); |
diff --git a/embassy-stm32/src/adc/v1.rs b/embassy-stm32/src/adc/v1.rs index 82a8c3efb..d9af0c55e 100644 --- a/embassy-stm32/src/adc/v1.rs +++ b/embassy-stm32/src/adc/v1.rs | |||
| @@ -57,18 +57,14 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 57 | // | 57 | // |
| 58 | // 6.3.20 Vbat monitoring characteristics | 58 | // 6.3.20 Vbat monitoring characteristics |
| 59 | // ts_vbat ≥ 4μs | 59 | // ts_vbat ≥ 4μs |
| 60 | unsafe { | 60 | T::regs().ccr().modify(|reg| reg.set_vbaten(true)); |
| 61 | T::regs().ccr().modify(|reg| reg.set_vbaten(true)); | ||
| 62 | } | ||
| 63 | Vbat | 61 | Vbat |
| 64 | } | 62 | } |
| 65 | 63 | ||
| 66 | pub fn enable_vref(&self, delay: &mut impl DelayUs<u32>) -> Vref { | 64 | pub fn enable_vref(&self, delay: &mut impl DelayUs<u32>) -> Vref { |
| 67 | // Table 28. Embedded internal reference voltage | 65 | // Table 28. Embedded internal reference voltage |
| 68 | // tstart = 10μs | 66 | // tstart = 10μs |
| 69 | unsafe { | 67 | T::regs().ccr().modify(|reg| reg.set_vrefen(true)); |
| 70 | T::regs().ccr().modify(|reg| reg.set_vrefen(true)); | ||
| 71 | } | ||
| 72 | delay.delay_us(10); | 68 | delay.delay_us(10); |
| 73 | Vref | 69 | Vref |
| 74 | } | 70 | } |
| @@ -79,27 +75,23 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 79 | // 6.3.19 Temperature sensor characteristics | 75 | // 6.3.19 Temperature sensor characteristics |
| 80 | // tstart ≤ 10μs | 76 | // tstart ≤ 10μs |
| 81 | // ts_temp ≥ 4μs | 77 | // ts_temp ≥ 4μs |
| 82 | unsafe { | 78 | T::regs().ccr().modify(|reg| reg.set_tsen(true)); |
| 83 | T::regs().ccr().modify(|reg| reg.set_tsen(true)); | ||
| 84 | } | ||
| 85 | delay.delay_us(10); | 79 | delay.delay_us(10); |
| 86 | Temperature | 80 | Temperature |
| 87 | } | 81 | } |
| 88 | 82 | ||
| 89 | fn calibrate(&self) { | 83 | fn calibrate(&self) { |
| 90 | unsafe { | 84 | // A.7.1 ADC calibration code example |
| 91 | // A.7.1 ADC calibration code example | 85 | if T::regs().cr().read().aden() { |
| 92 | if T::regs().cr().read().aden() { | 86 | T::regs().cr().modify(|reg| reg.set_addis(true)); |
| 93 | T::regs().cr().modify(|reg| reg.set_addis(true)); | 87 | } |
| 94 | } | 88 | while T::regs().cr().read().aden() { |
| 95 | while T::regs().cr().read().aden() { | 89 | // spin |
| 96 | // spin | 90 | } |
| 97 | } | 91 | T::regs().cfgr1().modify(|reg| reg.set_dmaen(false)); |
| 98 | T::regs().cfgr1().modify(|reg| reg.set_dmaen(false)); | 92 | T::regs().cr().modify(|reg| reg.set_adcal(true)); |
| 99 | T::regs().cr().modify(|reg| reg.set_adcal(true)); | 93 | while T::regs().cr().read().adcal() { |
| 100 | while T::regs().cr().read().adcal() { | 94 | // spin |
| 101 | // spin | ||
| 102 | } | ||
| 103 | } | 95 | } |
| 104 | } | 96 | } |
| 105 | 97 | ||
| @@ -108,9 +100,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 108 | } | 100 | } |
| 109 | 101 | ||
| 110 | pub fn set_resolution(&mut self, resolution: Resolution) { | 102 | pub fn set_resolution(&mut self, resolution: Resolution) { |
| 111 | unsafe { | 103 | T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into())); |
| 112 | T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into())); | ||
| 113 | } | ||
| 114 | } | 104 | } |
| 115 | 105 | ||
| 116 | pub fn read<P>(&mut self, pin: &mut P) -> u16 | 106 | pub fn read<P>(&mut self, pin: &mut P) -> u16 |
| @@ -118,18 +108,16 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 118 | P: AdcPin<T> + crate::gpio::sealed::Pin, | 108 | P: AdcPin<T> + crate::gpio::sealed::Pin, |
| 119 | { | 109 | { |
| 120 | let channel = pin.channel(); | 110 | let channel = pin.channel(); |
| 121 | unsafe { | 111 | pin.set_as_analog(); |
| 122 | pin.set_as_analog(); | 112 | self.read_channel(channel) |
| 123 | self.read_channel(channel) | ||
| 124 | } | ||
| 125 | } | 113 | } |
| 126 | 114 | ||
| 127 | pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 { | 115 | pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 { |
| 128 | let channel = channel.channel(); | 116 | let channel = channel.channel(); |
| 129 | unsafe { self.read_channel(channel) } | 117 | self.read_channel(channel) |
| 130 | } | 118 | } |
| 131 | 119 | ||
| 132 | unsafe fn read_channel(&mut self, channel: u8) -> u16 { | 120 | fn read_channel(&mut self, channel: u8) -> u16 { |
| 133 | // A.7.2 ADC enable sequence code example | 121 | // A.7.2 ADC enable sequence code example |
| 134 | if T::regs().isr().read().adrdy() { | 122 | if T::regs().isr().read().adrdy() { |
| 135 | T::regs().isr().modify(|reg| reg.set_adrdy(true)); | 123 | T::regs().isr().modify(|reg| reg.set_adrdy(true)); |
diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs index 11a51f993..091c1d447 100644 --- a/embassy-stm32/src/adc/v2.rs +++ b/embassy-stm32/src/adc/v2.rs | |||
| @@ -100,13 +100,10 @@ where | |||
| 100 | T::reset(); | 100 | T::reset(); |
| 101 | 101 | ||
| 102 | let presc = Prescaler::from_pclk2(T::frequency()); | 102 | let presc = Prescaler::from_pclk2(T::frequency()); |
| 103 | unsafe { | 103 | T::common_regs().ccr().modify(|w| w.set_adcpre(presc.adcpre())); |
| 104 | T::common_regs().ccr().modify(|w| w.set_adcpre(presc.adcpre())); | 104 | T::regs().cr2().modify(|reg| { |
| 105 | 105 | reg.set_adon(crate::pac::adc::vals::Adon::ENABLED); | |
| 106 | T::regs().cr2().modify(|reg| { | 106 | }); |
| 107 | reg.set_adon(crate::pac::adc::vals::Adon::ENABLED); | ||
| 108 | }); | ||
| 109 | } | ||
| 110 | 107 | ||
| 111 | delay.delay_us(ADC_POWERUP_TIME_US); | 108 | delay.delay_us(ADC_POWERUP_TIME_US); |
| 112 | 109 | ||
| @@ -121,19 +118,15 @@ where | |||
| 121 | } | 118 | } |
| 122 | 119 | ||
| 123 | pub fn set_resolution(&mut self, resolution: Resolution) { | 120 | pub fn set_resolution(&mut self, resolution: Resolution) { |
| 124 | unsafe { | 121 | T::regs().cr1().modify(|reg| reg.set_res(resolution.into())); |
| 125 | T::regs().cr1().modify(|reg| reg.set_res(resolution.into())); | ||
| 126 | } | ||
| 127 | } | 122 | } |
| 128 | 123 | ||
| 129 | /// Enables internal voltage reference and returns [VrefInt], which can be used in | 124 | /// Enables internal voltage reference and returns [VrefInt], which can be used in |
| 130 | /// [Adc::read_internal()] to perform conversion. | 125 | /// [Adc::read_internal()] to perform conversion. |
| 131 | pub fn enable_vrefint(&self) -> VrefInt { | 126 | pub fn enable_vrefint(&self) -> VrefInt { |
| 132 | unsafe { | 127 | T::common_regs().ccr().modify(|reg| { |
| 133 | T::common_regs().ccr().modify(|reg| { | 128 | reg.set_tsvrefe(crate::pac::adccommon::vals::Tsvrefe::ENABLED); |
| 134 | reg.set_tsvrefe(crate::pac::adccommon::vals::Tsvrefe::ENABLED); | 129 | }); |
| 135 | }); | ||
| 136 | } | ||
| 137 | 130 | ||
| 138 | VrefInt {} | 131 | VrefInt {} |
| 139 | } | 132 | } |
| @@ -144,11 +137,9 @@ where | |||
| 144 | /// On STM32F42 and STM32F43 this can not be used together with [Vbat]. If both are enabled, | 137 | /// On STM32F42 and STM32F43 this can not be used together with [Vbat]. If both are enabled, |
| 145 | /// temperature sensor will return vbat value. | 138 | /// temperature sensor will return vbat value. |
| 146 | pub fn enable_temperature(&self) -> Temperature { | 139 | pub fn enable_temperature(&self) -> Temperature { |
| 147 | unsafe { | 140 | T::common_regs().ccr().modify(|reg| { |
| 148 | T::common_regs().ccr().modify(|reg| { | 141 | reg.set_tsvrefe(crate::pac::adccommon::vals::Tsvrefe::ENABLED); |
| 149 | reg.set_tsvrefe(crate::pac::adccommon::vals::Tsvrefe::ENABLED); | 142 | }); |
| 150 | }); | ||
| 151 | } | ||
| 152 | 143 | ||
| 153 | Temperature {} | 144 | Temperature {} |
| 154 | } | 145 | } |
| @@ -156,37 +147,33 @@ where | |||
| 156 | /// Enables vbat input and returns [Vbat], which can be used in | 147 | /// Enables vbat input and returns [Vbat], which can be used in |
| 157 | /// [Adc::read_internal()] to perform conversion. | 148 | /// [Adc::read_internal()] to perform conversion. |
| 158 | pub fn enable_vbat(&self) -> Vbat { | 149 | pub fn enable_vbat(&self) -> Vbat { |
| 159 | unsafe { | 150 | T::common_regs().ccr().modify(|reg| { |
| 160 | T::common_regs().ccr().modify(|reg| { | 151 | reg.set_vbate(crate::pac::adccommon::vals::Vbate::ENABLED); |
| 161 | reg.set_vbate(crate::pac::adccommon::vals::Vbate::ENABLED); | 152 | }); |
| 162 | }); | ||
| 163 | } | ||
| 164 | 153 | ||
| 165 | Vbat {} | 154 | Vbat {} |
| 166 | } | 155 | } |
| 167 | 156 | ||
| 168 | /// Perform a single conversion. | 157 | /// Perform a single conversion. |
| 169 | fn convert(&mut self) -> u16 { | 158 | fn convert(&mut self) -> u16 { |
| 170 | unsafe { | 159 | // clear end of conversion flag |
| 171 | // clear end of conversion flag | 160 | T::regs().sr().modify(|reg| { |
| 172 | T::regs().sr().modify(|reg| { | 161 | reg.set_eoc(crate::pac::adc::vals::Eoc::NOTCOMPLETE); |
| 173 | reg.set_eoc(crate::pac::adc::vals::Eoc::NOTCOMPLETE); | 162 | }); |
| 174 | }); | 163 | |
| 175 | 164 | // Start conversion | |
| 176 | // Start conversion | 165 | T::regs().cr2().modify(|reg| { |
| 177 | T::regs().cr2().modify(|reg| { | 166 | reg.set_swstart(true); |
| 178 | reg.set_swstart(true); | 167 | }); |
| 179 | }); | 168 | |
| 180 | 169 | while T::regs().sr().read().strt() == crate::pac::adc::vals::Strt::NOTSTARTED { | |
| 181 | while T::regs().sr().read().strt() == crate::pac::adc::vals::Strt::NOTSTARTED { | 170 | // spin //wait for actual start |
| 182 | // spin //wait for actual start | ||
| 183 | } | ||
| 184 | while T::regs().sr().read().eoc() == crate::pac::adc::vals::Eoc::NOTCOMPLETE { | ||
| 185 | // spin //wait for finish | ||
| 186 | } | ||
| 187 | |||
| 188 | T::regs().dr().read().0 as u16 | ||
| 189 | } | 171 | } |
| 172 | while T::regs().sr().read().eoc() == crate::pac::adc::vals::Eoc::NOTCOMPLETE { | ||
| 173 | // spin //wait for finish | ||
| 174 | } | ||
| 175 | |||
| 176 | T::regs().dr().read().0 as u16 | ||
| 190 | } | 177 | } |
| 191 | 178 | ||
| 192 | pub fn read<P>(&mut self, pin: &mut P) -> u16 | 179 | pub fn read<P>(&mut self, pin: &mut P) -> u16 |
| @@ -194,18 +181,16 @@ where | |||
| 194 | P: AdcPin<T>, | 181 | P: AdcPin<T>, |
| 195 | P: crate::gpio::sealed::Pin, | 182 | P: crate::gpio::sealed::Pin, |
| 196 | { | 183 | { |
| 197 | unsafe { | 184 | pin.set_as_analog(); |
| 198 | pin.set_as_analog(); | ||
| 199 | 185 | ||
| 200 | self.read_channel(pin.channel()) | 186 | self.read_channel(pin.channel()) |
| 201 | } | ||
| 202 | } | 187 | } |
| 203 | 188 | ||
| 204 | pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 { | 189 | pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 { |
| 205 | unsafe { self.read_channel(channel.channel()) } | 190 | self.read_channel(channel.channel()) |
| 206 | } | 191 | } |
| 207 | 192 | ||
| 208 | unsafe fn read_channel(&mut self, channel: u8) -> u16 { | 193 | fn read_channel(&mut self, channel: u8) -> u16 { |
| 209 | // Configure ADC | 194 | // Configure ADC |
| 210 | 195 | ||
| 211 | // Select channel | 196 | // Select channel |
| @@ -219,7 +204,7 @@ where | |||
| 219 | val | 204 | val |
| 220 | } | 205 | } |
| 221 | 206 | ||
| 222 | unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { | 207 | fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { |
| 223 | let sample_time = sample_time.into(); | 208 | let sample_time = sample_time.into(); |
| 224 | if ch <= 9 { | 209 | if ch <= 9 { |
| 225 | T::regs().smpr2().modify(|reg| reg.set_smp(ch as _, sample_time)); | 210 | T::regs().smpr2().modify(|reg| reg.set_smp(ch as _, sample_time)); |
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs index 90aa7d3b9..94cdc86cd 100644 --- a/embassy-stm32/src/adc/v3.rs +++ b/embassy-stm32/src/adc/v3.rs | |||
| @@ -12,7 +12,7 @@ pub const VREF_CALIB_MV: u32 = 3000; | |||
| 12 | /// Sadly we cannot use `RccPeripheral::enable` since devices are quite inconsistent ADC clock | 12 | /// Sadly we cannot use `RccPeripheral::enable` since devices are quite inconsistent ADC clock |
| 13 | /// configuration. | 13 | /// configuration. |
| 14 | fn enable() { | 14 | fn enable() { |
| 15 | critical_section::with(|_| unsafe { | 15 | critical_section::with(|_| { |
| 16 | #[cfg(stm32h7)] | 16 | #[cfg(stm32h7)] |
| 17 | crate::pac::RCC.apb2enr().modify(|w| w.set_adcen(true)); | 17 | crate::pac::RCC.apb2enr().modify(|w| w.set_adcen(true)); |
| 18 | #[cfg(stm32g0)] | 18 | #[cfg(stm32g0)] |
| @@ -62,29 +62,25 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 62 | pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self { | 62 | pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self { |
| 63 | into_ref!(adc); | 63 | into_ref!(adc); |
| 64 | enable(); | 64 | enable(); |
| 65 | unsafe { | 65 | T::regs().cr().modify(|reg| { |
| 66 | T::regs().cr().modify(|reg| { | 66 | #[cfg(not(adc_g0))] |
| 67 | #[cfg(not(adc_g0))] | 67 | reg.set_deeppwd(false); |
| 68 | reg.set_deeppwd(false); | 68 | reg.set_advregen(true); |
| 69 | reg.set_advregen(true); | 69 | }); |
| 70 | }); | 70 | |
| 71 | 71 | #[cfg(adc_g0)] | |
| 72 | #[cfg(adc_g0)] | 72 | T::regs().cfgr1().modify(|reg| { |
| 73 | T::regs().cfgr1().modify(|reg| { | 73 | reg.set_chselrmod(false); |
| 74 | reg.set_chselrmod(false); | 74 | }); |
| 75 | }); | ||
| 76 | } | ||
| 77 | 75 | ||
| 78 | delay.delay_us(20); | 76 | delay.delay_us(20); |
| 79 | 77 | ||
| 80 | unsafe { | 78 | T::regs().cr().modify(|reg| { |
| 81 | T::regs().cr().modify(|reg| { | 79 | reg.set_adcal(true); |
| 82 | reg.set_adcal(true); | 80 | }); |
| 83 | }); | ||
| 84 | 81 | ||
| 85 | while T::regs().cr().read().adcal() { | 82 | while T::regs().cr().read().adcal() { |
| 86 | // spin | 83 | // spin |
| 87 | } | ||
| 88 | } | 84 | } |
| 89 | 85 | ||
| 90 | delay.delay_us(1); | 86 | delay.delay_us(1); |
| @@ -96,11 +92,9 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 96 | } | 92 | } |
| 97 | 93 | ||
| 98 | pub fn enable_vrefint(&self, delay: &mut impl DelayUs<u32>) -> VrefInt { | 94 | pub fn enable_vrefint(&self, delay: &mut impl DelayUs<u32>) -> VrefInt { |
| 99 | unsafe { | 95 | T::common_regs().ccr().modify(|reg| { |
| 100 | T::common_regs().ccr().modify(|reg| { | 96 | reg.set_vrefen(true); |
| 101 | reg.set_vrefen(true); | 97 | }); |
| 102 | }); | ||
| 103 | } | ||
| 104 | 98 | ||
| 105 | // "Table 24. Embedded internal voltage reference" states that it takes a maximum of 12 us | 99 | // "Table 24. Embedded internal voltage reference" states that it takes a maximum of 12 us |
| 106 | // to stabilize the internal voltage reference, we wait a little more. | 100 | // to stabilize the internal voltage reference, we wait a little more. |
| @@ -112,21 +106,17 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 112 | } | 106 | } |
| 113 | 107 | ||
| 114 | pub fn enable_temperature(&self) -> Temperature { | 108 | pub fn enable_temperature(&self) -> Temperature { |
| 115 | unsafe { | 109 | T::common_regs().ccr().modify(|reg| { |
| 116 | T::common_regs().ccr().modify(|reg| { | 110 | reg.set_ch17sel(true); |
| 117 | reg.set_ch17sel(true); | 111 | }); |
| 118 | }); | ||
| 119 | } | ||
| 120 | 112 | ||
| 121 | Temperature {} | 113 | Temperature {} |
| 122 | } | 114 | } |
| 123 | 115 | ||
| 124 | pub fn enable_vbat(&self) -> Vbat { | 116 | pub fn enable_vbat(&self) -> Vbat { |
| 125 | unsafe { | 117 | T::common_regs().ccr().modify(|reg| { |
| 126 | T::common_regs().ccr().modify(|reg| { | 118 | reg.set_ch18sel(true); |
| 127 | reg.set_ch18sel(true); | 119 | }); |
| 128 | }); | ||
| 129 | } | ||
| 130 | 120 | ||
| 131 | Vbat {} | 121 | Vbat {} |
| 132 | } | 122 | } |
| @@ -136,12 +126,10 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 136 | } | 126 | } |
| 137 | 127 | ||
| 138 | pub fn set_resolution(&mut self, resolution: Resolution) { | 128 | pub fn set_resolution(&mut self, resolution: Resolution) { |
| 139 | unsafe { | 129 | #[cfg(not(stm32g0))] |
| 140 | #[cfg(not(stm32g0))] | 130 | T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); |
| 141 | T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); | 131 | #[cfg(stm32g0)] |
| 142 | #[cfg(stm32g0)] | 132 | T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into())); |
| 143 | T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into())); | ||
| 144 | } | ||
| 145 | } | 133 | } |
| 146 | 134 | ||
| 147 | /* | 135 | /* |
| @@ -155,77 +143,73 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 155 | 143 | ||
| 156 | /// Perform a single conversion. | 144 | /// Perform a single conversion. |
| 157 | fn convert(&mut self) -> u16 { | 145 | fn convert(&mut self) -> u16 { |
| 158 | unsafe { | 146 | T::regs().isr().modify(|reg| { |
| 159 | T::regs().isr().modify(|reg| { | 147 | reg.set_eos(true); |
| 160 | reg.set_eos(true); | 148 | reg.set_eoc(true); |
| 161 | reg.set_eoc(true); | 149 | }); |
| 162 | }); | 150 | |
| 163 | 151 | // Start conversion | |
| 164 | // Start conversion | 152 | T::regs().cr().modify(|reg| { |
| 165 | T::regs().cr().modify(|reg| { | 153 | reg.set_adstart(true); |
| 166 | reg.set_adstart(true); | 154 | }); |
| 167 | }); | 155 | |
| 168 | 156 | while !T::regs().isr().read().eos() { | |
| 169 | while !T::regs().isr().read().eos() { | 157 | // spin |
| 170 | // spin | ||
| 171 | } | ||
| 172 | |||
| 173 | T::regs().dr().read().0 as u16 | ||
| 174 | } | 158 | } |
| 159 | |||
| 160 | T::regs().dr().read().0 as u16 | ||
| 175 | } | 161 | } |
| 176 | 162 | ||
| 177 | pub fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 { | 163 | pub fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 { |
| 178 | unsafe { | 164 | // Make sure bits are off |
| 179 | // Make sure bits are off | 165 | while T::regs().cr().read().addis() { |
| 180 | while T::regs().cr().read().addis() { | 166 | // spin |
| 181 | // spin | ||
| 182 | } | ||
| 183 | |||
| 184 | // Enable ADC | ||
| 185 | T::regs().isr().modify(|reg| { | ||
| 186 | reg.set_adrdy(true); | ||
| 187 | }); | ||
| 188 | T::regs().cr().modify(|reg| { | ||
| 189 | reg.set_aden(true); | ||
| 190 | }); | ||
| 191 | |||
| 192 | while !T::regs().isr().read().adrdy() { | ||
| 193 | // spin | ||
| 194 | } | ||
| 195 | |||
| 196 | // Configure channel | ||
| 197 | Self::set_channel_sample_time(pin.channel(), self.sample_time); | ||
| 198 | |||
| 199 | // Select channel | ||
| 200 | #[cfg(not(stm32g0))] | ||
| 201 | T::regs().sqr1().write(|reg| reg.set_sq(0, pin.channel())); | ||
| 202 | #[cfg(stm32g0)] | ||
| 203 | T::regs().chselr().write(|reg| reg.set_chsel(1 << pin.channel())); | ||
| 204 | |||
| 205 | // Some models are affected by an erratum: | ||
| 206 | // If we perform conversions slower than 1 kHz, the first read ADC value can be | ||
| 207 | // corrupted, so we discard it and measure again. | ||
| 208 | // | ||
| 209 | // STM32L471xx: Section 2.7.3 | ||
| 210 | // STM32G4: Section 2.7.3 | ||
| 211 | #[cfg(any(rcc_l4, rcc_g4))] | ||
| 212 | let _ = self.convert(); | ||
| 213 | |||
| 214 | let val = self.convert(); | ||
| 215 | |||
| 216 | T::regs().cr().modify(|reg| reg.set_addis(true)); | ||
| 217 | |||
| 218 | val | ||
| 219 | } | 167 | } |
| 168 | |||
| 169 | // Enable ADC | ||
| 170 | T::regs().isr().modify(|reg| { | ||
| 171 | reg.set_adrdy(true); | ||
| 172 | }); | ||
| 173 | T::regs().cr().modify(|reg| { | ||
| 174 | reg.set_aden(true); | ||
| 175 | }); | ||
| 176 | |||
| 177 | while !T::regs().isr().read().adrdy() { | ||
| 178 | // spin | ||
| 179 | } | ||
| 180 | |||
| 181 | // Configure channel | ||
| 182 | Self::set_channel_sample_time(pin.channel(), self.sample_time); | ||
| 183 | |||
| 184 | // Select channel | ||
| 185 | #[cfg(not(stm32g0))] | ||
| 186 | T::regs().sqr1().write(|reg| reg.set_sq(0, pin.channel())); | ||
| 187 | #[cfg(stm32g0)] | ||
| 188 | T::regs().chselr().write(|reg| reg.set_chsel(1 << pin.channel())); | ||
| 189 | |||
| 190 | // Some models are affected by an erratum: | ||
| 191 | // If we perform conversions slower than 1 kHz, the first read ADC value can be | ||
| 192 | // corrupted, so we discard it and measure again. | ||
| 193 | // | ||
| 194 | // STM32L471xx: Section 2.7.3 | ||
| 195 | // STM32G4: Section 2.7.3 | ||
| 196 | #[cfg(any(rcc_l4, rcc_g4))] | ||
| 197 | let _ = self.convert(); | ||
| 198 | |||
| 199 | let val = self.convert(); | ||
| 200 | |||
| 201 | T::regs().cr().modify(|reg| reg.set_addis(true)); | ||
| 202 | |||
| 203 | val | ||
| 220 | } | 204 | } |
| 221 | 205 | ||
| 222 | #[cfg(stm32g0)] | 206 | #[cfg(stm32g0)] |
| 223 | unsafe fn set_channel_sample_time(_ch: u8, sample_time: SampleTime) { | 207 | fn set_channel_sample_time(_ch: u8, sample_time: SampleTime) { |
| 224 | T::regs().smpr().modify(|reg| reg.set_smp1(sample_time.into())); | 208 | T::regs().smpr().modify(|reg| reg.set_smp1(sample_time.into())); |
| 225 | } | 209 | } |
| 226 | 210 | ||
| 227 | #[cfg(not(stm32g0))] | 211 | #[cfg(not(stm32g0))] |
| 228 | unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { | 212 | fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { |
| 229 | let sample_time = sample_time.into(); | 213 | let sample_time = sample_time.into(); |
| 230 | if ch <= 9 { | 214 | if ch <= 9 { |
| 231 | T::regs().smpr1().modify(|reg| reg.set_smp(ch as _, sample_time)); | 215 | T::regs().smpr1().modify(|reg| reg.set_smp(ch as _, sample_time)); |
diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs index 4707b7c95..c51c6840f 100644 --- a/embassy-stm32/src/adc/v4.rs +++ b/embassy-stm32/src/adc/v4.rs | |||
| @@ -46,8 +46,8 @@ foreach_peripheral!( | |||
| 46 | (adc, ADC1) => { | 46 | (adc, ADC1) => { |
| 47 | impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC1 { | 47 | impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC1 { |
| 48 | fn frequency() -> crate::time::Hertz { | 48 | fn frequency() -> crate::time::Hertz { |
| 49 | critical_section::with(|_| unsafe { | 49 | critical_section::with(|_| { |
| 50 | match crate::rcc::get_freqs().adc { | 50 | match unsafe { crate::rcc::get_freqs() }.adc { |
| 51 | Some(ck) => ck, | 51 | Some(ck) => ck, |
| 52 | None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.") | 52 | None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.") |
| 53 | } | 53 | } |
| @@ -55,7 +55,7 @@ foreach_peripheral!( | |||
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | fn enable() { | 57 | fn enable() { |
| 58 | critical_section::with(|_| unsafe { | 58 | critical_section::with(|_| { |
| 59 | crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(true)) | 59 | crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(true)) |
| 60 | }); | 60 | }); |
| 61 | ADC12_ENABLE_COUNTER.fetch_add(1, Ordering::SeqCst); | 61 | ADC12_ENABLE_COUNTER.fetch_add(1, Ordering::SeqCst); |
| @@ -63,7 +63,7 @@ foreach_peripheral!( | |||
| 63 | 63 | ||
| 64 | fn disable() { | 64 | fn disable() { |
| 65 | if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { | 65 | if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { |
| 66 | critical_section::with(|_| unsafe { | 66 | critical_section::with(|_| { |
| 67 | crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(false)); | 67 | crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(false)); |
| 68 | }) | 68 | }) |
| 69 | } | 69 | } |
| @@ -72,7 +72,7 @@ foreach_peripheral!( | |||
| 72 | 72 | ||
| 73 | fn reset() { | 73 | fn reset() { |
| 74 | if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { | 74 | if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { |
| 75 | critical_section::with(|_| unsafe { | 75 | critical_section::with(|_| { |
| 76 | crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(true)); | 76 | crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(true)); |
| 77 | crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(false)); | 77 | crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(false)); |
| 78 | }); | 78 | }); |
| @@ -85,8 +85,8 @@ foreach_peripheral!( | |||
| 85 | (adc, ADC2) => { | 85 | (adc, ADC2) => { |
| 86 | impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC2 { | 86 | impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC2 { |
| 87 | fn frequency() -> crate::time::Hertz { | 87 | fn frequency() -> crate::time::Hertz { |
| 88 | critical_section::with(|_| unsafe { | 88 | critical_section::with(|_| { |
| 89 | match crate::rcc::get_freqs().adc { | 89 | match unsafe { crate::rcc::get_freqs() }.adc { |
| 90 | Some(ck) => ck, | 90 | Some(ck) => ck, |
| 91 | None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.") | 91 | None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.") |
| 92 | } | 92 | } |
| @@ -94,7 +94,7 @@ foreach_peripheral!( | |||
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | fn enable() { | 96 | fn enable() { |
| 97 | critical_section::with(|_| unsafe { | 97 | critical_section::with(|_| { |
| 98 | crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(true)) | 98 | crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(true)) |
| 99 | }); | 99 | }); |
| 100 | ADC12_ENABLE_COUNTER.fetch_add(1, Ordering::SeqCst); | 100 | ADC12_ENABLE_COUNTER.fetch_add(1, Ordering::SeqCst); |
| @@ -102,7 +102,7 @@ foreach_peripheral!( | |||
| 102 | 102 | ||
| 103 | fn disable() { | 103 | fn disable() { |
| 104 | if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { | 104 | if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { |
| 105 | critical_section::with(|_| unsafe { | 105 | critical_section::with(|_| { |
| 106 | crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(false)); | 106 | crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(false)); |
| 107 | }) | 107 | }) |
| 108 | } | 108 | } |
| @@ -111,7 +111,7 @@ foreach_peripheral!( | |||
| 111 | 111 | ||
| 112 | fn reset() { | 112 | fn reset() { |
| 113 | if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { | 113 | if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { |
| 114 | critical_section::with(|_| unsafe { | 114 | critical_section::with(|_| { |
| 115 | crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(true)); | 115 | crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(true)); |
| 116 | crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(false)); | 116 | crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(false)); |
| 117 | }); | 117 | }); |
| @@ -124,8 +124,8 @@ foreach_peripheral!( | |||
| 124 | (adc, ADC3) => { | 124 | (adc, ADC3) => { |
| 125 | impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC3 { | 125 | impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC3 { |
| 126 | fn frequency() -> crate::time::Hertz { | 126 | fn frequency() -> crate::time::Hertz { |
| 127 | critical_section::with(|_| unsafe { | 127 | critical_section::with(|_| { |
| 128 | match crate::rcc::get_freqs().adc { | 128 | match unsafe { crate::rcc::get_freqs() }.adc { |
| 129 | Some(ck) => ck, | 129 | Some(ck) => ck, |
| 130 | None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.") | 130 | None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.") |
| 131 | } | 131 | } |
| @@ -133,22 +133,22 @@ foreach_peripheral!( | |||
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | fn enable() { | 135 | fn enable() { |
| 136 | critical_section::with(|_| unsafe { | 136 | critical_section::with(|_| { |
| 137 | crate::pac::RCC.ahb4enr().modify(|w| w.set_adc3en(true)) | 137 | crate::pac::RCC.ahb4enr().modify(|w| w.set_adc3en(true)) |
| 138 | }); | 138 | }); |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | fn disable() { | 141 | fn disable() { |
| 142 | critical_section::with(|_| unsafe { | 142 | critical_section::with(|_| { |
| 143 | crate::pac::RCC.ahb4enr().modify(|w| w.set_adc3en(false)); | 143 | crate::pac::RCC.ahb4enr().modify(|w| w.set_adc3en(false)); |
| 144 | }) | 144 | }) |
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | fn reset() { | 147 | fn reset() { |
| 148 | critical_section::with(|_| unsafe { | 148 | critical_section::with(|_| { |
| 149 | crate::pac::RCC.ahb4rstr().modify(|w| w.set_adc3rst(true)); | 149 | crate::pac::RCC.ahb4rstr().modify(|w| w.set_adc3rst(true)); |
| 150 | crate::pac::RCC.ahb4rstr().modify(|w| w.set_adc3rst(false)); | 150 | crate::pac::RCC.ahb4rstr().modify(|w| w.set_adc3rst(false)); |
| 151 | }); | 151 | }); |
| 152 | } | 152 | } |
| 153 | } | 153 | } |
| 154 | 154 | ||
| @@ -232,9 +232,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 232 | 232 | ||
| 233 | let prescaler = Prescaler::from_ker_ck(T::frequency()); | 233 | let prescaler = Prescaler::from_ker_ck(T::frequency()); |
| 234 | 234 | ||
| 235 | unsafe { | 235 | T::common_regs().ccr().modify(|w| w.set_presc(prescaler.presc())); |
| 236 | T::common_regs().ccr().modify(|w| w.set_presc(prescaler.presc())); | ||
| 237 | } | ||
| 238 | 236 | ||
| 239 | let frequency = Hertz(T::frequency().0 / prescaler.divisor()); | 237 | let frequency = Hertz(T::frequency().0 / prescaler.divisor()); |
| 240 | info!("ADC frequency set to {} Hz", frequency.0); | 238 | info!("ADC frequency set to {} Hz", frequency.0); |
| @@ -251,9 +249,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 251 | } else { | 249 | } else { |
| 252 | Boost::LT50 | 250 | Boost::LT50 |
| 253 | }; | 251 | }; |
| 254 | unsafe { | 252 | T::regs().cr().modify(|w| w.set_boost(boost)); |
| 255 | T::regs().cr().modify(|w| w.set_boost(boost)); | ||
| 256 | } | ||
| 257 | 253 | ||
| 258 | let mut s = Self { | 254 | let mut s = Self { |
| 259 | adc, | 255 | adc, |
| @@ -272,84 +268,68 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 272 | } | 268 | } |
| 273 | 269 | ||
| 274 | fn power_up(&mut self, delay: &mut impl DelayUs<u16>) { | 270 | fn power_up(&mut self, delay: &mut impl DelayUs<u16>) { |
| 275 | unsafe { | 271 | T::regs().cr().modify(|reg| { |
| 276 | T::regs().cr().modify(|reg| { | 272 | reg.set_deeppwd(false); |
| 277 | reg.set_deeppwd(false); | 273 | reg.set_advregen(true); |
| 278 | reg.set_advregen(true); | 274 | }); |
| 279 | }); | ||
| 280 | } | ||
| 281 | 275 | ||
| 282 | delay.delay_us(10); | 276 | delay.delay_us(10); |
| 283 | } | 277 | } |
| 284 | 278 | ||
| 285 | fn configure_differential_inputs(&mut self) { | 279 | fn configure_differential_inputs(&mut self) { |
| 286 | unsafe { | 280 | T::regs().difsel().modify(|w| { |
| 287 | T::regs().difsel().modify(|w| { | 281 | for n in 0..20 { |
| 288 | for n in 0..20 { | 282 | w.set_difsel(n, Difsel::SINGLEENDED); |
| 289 | w.set_difsel(n, Difsel::SINGLEENDED); | 283 | } |
| 290 | } | 284 | }); |
| 291 | }) | ||
| 292 | }; | ||
| 293 | } | 285 | } |
| 294 | 286 | ||
| 295 | fn calibrate(&mut self) { | 287 | fn calibrate(&mut self) { |
| 296 | unsafe { | 288 | T::regs().cr().modify(|w| { |
| 297 | T::regs().cr().modify(|w| { | 289 | w.set_adcaldif(Adcaldif::SINGLEENDED); |
| 298 | w.set_adcaldif(Adcaldif::SINGLEENDED); | 290 | w.set_adcallin(true); |
| 299 | w.set_adcallin(true); | 291 | }); |
| 300 | }); | ||
| 301 | 292 | ||
| 302 | T::regs().cr().modify(|w| w.set_adcal(true)); | 293 | T::regs().cr().modify(|w| w.set_adcal(true)); |
| 303 | 294 | ||
| 304 | while T::regs().cr().read().adcal() {} | 295 | while T::regs().cr().read().adcal() {} |
| 305 | } | ||
| 306 | } | 296 | } |
| 307 | 297 | ||
| 308 | fn enable(&mut self) { | 298 | fn enable(&mut self) { |
| 309 | unsafe { | 299 | T::regs().isr().write(|w| w.set_adrdy(true)); |
| 310 | T::regs().isr().write(|w| w.set_adrdy(true)); | 300 | T::regs().cr().modify(|w| w.set_aden(true)); |
| 311 | T::regs().cr().modify(|w| w.set_aden(true)); | 301 | while !T::regs().isr().read().adrdy() {} |
| 312 | while !T::regs().isr().read().adrdy() {} | 302 | T::regs().isr().write(|w| w.set_adrdy(true)); |
| 313 | T::regs().isr().write(|w| w.set_adrdy(true)); | ||
| 314 | } | ||
| 315 | } | 303 | } |
| 316 | 304 | ||
| 317 | fn configure(&mut self) { | 305 | fn configure(&mut self) { |
| 318 | // single conversion mode, software trigger | 306 | // single conversion mode, software trigger |
| 319 | unsafe { | 307 | T::regs().cfgr().modify(|w| { |
| 320 | T::regs().cfgr().modify(|w| { | 308 | w.set_cont(false); |
| 321 | w.set_cont(false); | 309 | w.set_exten(Exten::DISABLED); |
| 322 | w.set_exten(Exten::DISABLED); | 310 | }); |
| 323 | }) | ||
| 324 | } | ||
| 325 | } | 311 | } |
| 326 | 312 | ||
| 327 | pub fn enable_vrefint(&self) -> VrefInt { | 313 | pub fn enable_vrefint(&self) -> VrefInt { |
| 328 | unsafe { | 314 | T::common_regs().ccr().modify(|reg| { |
| 329 | T::common_regs().ccr().modify(|reg| { | 315 | reg.set_vrefen(true); |
| 330 | reg.set_vrefen(true); | 316 | }); |
| 331 | }); | ||
| 332 | } | ||
| 333 | 317 | ||
| 334 | VrefInt {} | 318 | VrefInt {} |
| 335 | } | 319 | } |
| 336 | 320 | ||
| 337 | pub fn enable_temperature(&self) -> Temperature { | 321 | pub fn enable_temperature(&self) -> Temperature { |
| 338 | unsafe { | 322 | T::common_regs().ccr().modify(|reg| { |
| 339 | T::common_regs().ccr().modify(|reg| { | 323 | reg.set_vsenseen(true); |
| 340 | reg.set_vsenseen(true); | 324 | }); |
| 341 | }); | ||
| 342 | } | ||
| 343 | 325 | ||
| 344 | Temperature {} | 326 | Temperature {} |
| 345 | } | 327 | } |
| 346 | 328 | ||
| 347 | pub fn enable_vbat(&self) -> Vbat { | 329 | pub fn enable_vbat(&self) -> Vbat { |
| 348 | unsafe { | 330 | T::common_regs().ccr().modify(|reg| { |
| 349 | T::common_regs().ccr().modify(|reg| { | 331 | reg.set_vbaten(true); |
| 350 | reg.set_vbaten(true); | 332 | }); |
| 351 | }); | ||
| 352 | } | ||
| 353 | 333 | ||
| 354 | Vbat {} | 334 | Vbat {} |
| 355 | } | 335 | } |
| @@ -359,30 +339,26 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 359 | } | 339 | } |
| 360 | 340 | ||
| 361 | pub fn set_resolution(&mut self, resolution: Resolution) { | 341 | pub fn set_resolution(&mut self, resolution: Resolution) { |
| 362 | unsafe { | 342 | T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); |
| 363 | T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); | ||
| 364 | } | ||
| 365 | } | 343 | } |
| 366 | 344 | ||
| 367 | /// Perform a single conversion. | 345 | /// Perform a single conversion. |
| 368 | fn convert(&mut self) -> u16 { | 346 | fn convert(&mut self) -> u16 { |
| 369 | unsafe { | 347 | T::regs().isr().modify(|reg| { |
| 370 | T::regs().isr().modify(|reg| { | 348 | reg.set_eos(true); |
| 371 | reg.set_eos(true); | 349 | reg.set_eoc(true); |
| 372 | reg.set_eoc(true); | 350 | }); |
| 373 | }); | ||
| 374 | |||
| 375 | // Start conversion | ||
| 376 | T::regs().cr().modify(|reg| { | ||
| 377 | reg.set_adstart(true); | ||
| 378 | }); | ||
| 379 | |||
| 380 | while !T::regs().isr().read().eos() { | ||
| 381 | // spin | ||
| 382 | } | ||
| 383 | 351 | ||
| 384 | T::regs().dr().read().0 as u16 | 352 | // Start conversion |
| 353 | T::regs().cr().modify(|reg| { | ||
| 354 | reg.set_adstart(true); | ||
| 355 | }); | ||
| 356 | |||
| 357 | while !T::regs().isr().read().eos() { | ||
| 358 | // spin | ||
| 385 | } | 359 | } |
| 360 | |||
| 361 | T::regs().dr().read().0 as u16 | ||
| 386 | } | 362 | } |
| 387 | 363 | ||
| 388 | pub fn read<P>(&mut self, pin: &mut P) -> u16 | 364 | pub fn read<P>(&mut self, pin: &mut P) -> u16 |
| @@ -390,18 +366,16 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 390 | P: AdcPin<T>, | 366 | P: AdcPin<T>, |
| 391 | P: crate::gpio::sealed::Pin, | 367 | P: crate::gpio::sealed::Pin, |
| 392 | { | 368 | { |
| 393 | unsafe { | 369 | pin.set_as_analog(); |
| 394 | pin.set_as_analog(); | ||
| 395 | 370 | ||
| 396 | self.read_channel(pin.channel()) | 371 | self.read_channel(pin.channel()) |
| 397 | } | ||
| 398 | } | 372 | } |
| 399 | 373 | ||
| 400 | pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 { | 374 | pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 { |
| 401 | unsafe { self.read_channel(channel.channel()) } | 375 | self.read_channel(channel.channel()) |
| 402 | } | 376 | } |
| 403 | 377 | ||
| 404 | unsafe fn read_channel(&mut self, channel: u8) -> u16 { | 378 | fn read_channel(&mut self, channel: u8) -> u16 { |
| 405 | // Configure channel | 379 | // Configure channel |
| 406 | Self::set_channel_sample_time(channel, self.sample_time); | 380 | Self::set_channel_sample_time(channel, self.sample_time); |
| 407 | 381 | ||
| @@ -417,7 +391,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 417 | self.convert() | 391 | self.convert() |
| 418 | } | 392 | } |
| 419 | 393 | ||
| 420 | unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { | 394 | fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { |
| 421 | let sample_time = sample_time.into(); | 395 | let sample_time = sample_time.into(); |
| 422 | if ch <= 9 { | 396 | if ch <= 9 { |
| 423 | T::regs().smpr(0).modify(|reg| reg.set_smp(ch as _, sample_time)); | 397 | T::regs().smpr(0).modify(|reg| reg.set_smp(ch as _, sample_time)); |
diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs index bd92b35a0..85f6e99ac 100644 --- a/embassy-stm32/src/can/bxcan.rs +++ b/embassy-stm32/src/can/bxcan.rs | |||
| @@ -20,10 +20,8 @@ impl<'d, T: Instance> Can<'d, T> { | |||
| 20 | ) -> Self { | 20 | ) -> Self { |
| 21 | into_ref!(peri, rx, tx); | 21 | into_ref!(peri, rx, tx); |
| 22 | 22 | ||
| 23 | unsafe { | 23 | rx.set_as_af(rx.af_num(), AFType::Input); |
| 24 | rx.set_as_af(rx.af_num(), AFType::Input); | 24 | tx.set_as_af(tx.af_num(), AFType::OutputPushPull); |
| 25 | tx.set_as_af(tx.af_num(), AFType::OutputPushPull); | ||
| 26 | } | ||
| 27 | 25 | ||
| 28 | T::enable(); | 26 | T::enable(); |
| 29 | T::reset(); | 27 | T::reset(); |
| @@ -42,10 +40,8 @@ impl<'d, T: Instance> Can<'d, T> { | |||
| 42 | ) -> Self { | 40 | ) -> Self { |
| 43 | into_ref!(peri, rx, tx); | 41 | into_ref!(peri, rx, tx); |
| 44 | 42 | ||
| 45 | unsafe { | 43 | rx.set_as_af(rx.af_num(), AFType::Input); |
| 46 | rx.set_as_af(rx.af_num(), AFType::Input); | 44 | tx.set_as_af(tx.af_num(), AFType::OutputPushPull); |
| 47 | tx.set_as_af(tx.af_num(), AFType::OutputPushPull); | ||
| 48 | } | ||
| 49 | 45 | ||
| 50 | T::enable(); | 46 | T::enable(); |
| 51 | T::reset(); | 47 | T::reset(); |
| @@ -60,7 +56,7 @@ impl<'d, T: Instance> Drop for Can<'d, T> { | |||
| 60 | fn drop(&mut self) { | 56 | fn drop(&mut self) { |
| 61 | // Cannot call `free()` because it moves the instance. | 57 | // Cannot call `free()` because it moves the instance. |
| 62 | // Manually reset the peripheral. | 58 | // Manually reset the peripheral. |
| 63 | unsafe { T::regs().mcr().write(|w| w.set_reset(true)) } | 59 | T::regs().mcr().write(|w| w.set_reset(true)); |
| 64 | T::disable(); | 60 | T::disable(); |
| 65 | } | 61 | } |
| 66 | } | 62 | } |
| @@ -98,7 +94,7 @@ unsafe impl<'d, T: Instance> bxcan::Instance for BxcanInstance<'d, T> { | |||
| 98 | foreach_peripheral!( | 94 | foreach_peripheral!( |
| 99 | (can, $inst:ident) => { | 95 | (can, $inst:ident) => { |
| 100 | impl sealed::Instance for peripherals::$inst { | 96 | impl sealed::Instance for peripherals::$inst { |
| 101 | const REGISTERS: *mut bxcan::RegisterBlock = crate::pac::$inst.0 as *mut _; | 97 | const REGISTERS: *mut bxcan::RegisterBlock = crate::pac::$inst.as_ptr() as *mut _; |
| 102 | 98 | ||
| 103 | fn regs() -> &'static crate::pac::can::Can { | 99 | fn regs() -> &'static crate::pac::can::Can { |
| 104 | &crate::pac::$inst | 100 | &crate::pac::$inst |
diff --git a/embassy-stm32/src/crc/v1.rs b/embassy-stm32/src/crc/v1.rs index 393089eed..3946a2d47 100644 --- a/embassy-stm32/src/crc/v1.rs +++ b/embassy-stm32/src/crc/v1.rs | |||
| @@ -27,26 +27,24 @@ impl<'d> Crc<'d> { | |||
| 27 | 27 | ||
| 28 | /// Resets the CRC unit to default value (0xFFFF_FFFF) | 28 | /// Resets the CRC unit to default value (0xFFFF_FFFF) |
| 29 | pub fn reset(&mut self) { | 29 | pub fn reset(&mut self) { |
| 30 | unsafe { PAC_CRC.cr().write(|w| w.set_reset(true)) }; | 30 | PAC_CRC.cr().write(|w| w.set_reset(true)); |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | /// Feeds a word to the peripheral and returns the current CRC value | 33 | /// Feeds a word to the peripheral and returns the current CRC value |
| 34 | pub fn feed_word(&mut self, word: u32) -> u32 { | 34 | pub fn feed_word(&mut self, word: u32) -> u32 { |
| 35 | // write a single byte to the device, and return the result | 35 | // write a single byte to the device, and return the result |
| 36 | unsafe { | 36 | PAC_CRC.dr().write_value(word); |
| 37 | PAC_CRC.dr().write_value(word); | ||
| 38 | } | ||
| 39 | self.read() | 37 | self.read() |
| 40 | } | 38 | } |
| 41 | /// Feed a slice of words to the peripheral and return the result. | 39 | /// Feed a slice of words to the peripheral and return the result. |
| 42 | pub fn feed_words(&mut self, words: &[u32]) -> u32 { | 40 | pub fn feed_words(&mut self, words: &[u32]) -> u32 { |
| 43 | for word in words { | 41 | for word in words { |
| 44 | unsafe { PAC_CRC.dr().write_value(*word) } | 42 | PAC_CRC.dr().write_value(*word); |
| 45 | } | 43 | } |
| 46 | 44 | ||
| 47 | self.read() | 45 | self.read() |
| 48 | } | 46 | } |
| 49 | pub fn read(&self) -> u32 { | 47 | pub fn read(&self) -> u32 { |
| 50 | unsafe { PAC_CRC.dr().read() } | 48 | PAC_CRC.dr().read() |
| 51 | } | 49 | } |
| 52 | } | 50 | } |
diff --git a/embassy-stm32/src/crc/v2v3.rs b/embassy-stm32/src/crc/v2v3.rs index 8acb3a770..f337055a7 100644 --- a/embassy-stm32/src/crc/v2v3.rs +++ b/embassy-stm32/src/crc/v2v3.rs | |||
| @@ -85,95 +85,79 @@ impl<'d> Crc<'d> { | |||
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | pub fn reset(&mut self) { | 87 | pub fn reset(&mut self) { |
| 88 | unsafe { | 88 | PAC_CRC.cr().modify(|w| w.set_reset(true)); |
| 89 | PAC_CRC.cr().modify(|w| w.set_reset(true)); | ||
| 90 | } | ||
| 91 | } | 89 | } |
| 92 | 90 | ||
| 93 | /// Reconfigures the CRC peripheral. Doesn't reset. | 91 | /// Reconfigures the CRC peripheral. Doesn't reset. |
| 94 | fn reconfigure(&mut self) { | 92 | fn reconfigure(&mut self) { |
| 95 | unsafe { | 93 | // Init CRC value |
| 96 | // Init CRC value | 94 | PAC_CRC.init().write_value(self._config.crc_init_value); |
| 97 | PAC_CRC.init().write_value(self._config.crc_init_value); | 95 | #[cfg(crc_v3)] |
| 98 | #[cfg(crc_v3)] | 96 | PAC_CRC.pol().write_value(self._config.crc_poly); |
| 99 | PAC_CRC.pol().write_value(self._config.crc_poly); | ||
| 100 | 97 | ||
| 101 | // configure CR components | 98 | // configure CR components |
| 102 | // (reverse I/O, polysize, poly) | 99 | // (reverse I/O, polysize, poly) |
| 103 | PAC_CRC.cr().write(|w| { | 100 | PAC_CRC.cr().write(|w| { |
| 104 | // configure reverse output | 101 | // configure reverse output |
| 105 | w.set_rev_out(match self._config.reverse_out { | 102 | w.set_rev_out(match self._config.reverse_out { |
| 106 | true => vals::RevOut::REVERSED, | 103 | true => vals::RevOut::REVERSED, |
| 107 | false => vals::RevOut::NORMAL, | 104 | false => vals::RevOut::NORMAL, |
| 108 | }); | 105 | }); |
| 109 | // configure reverse input | 106 | // configure reverse input |
| 110 | w.set_rev_in(match self._config.reverse_in { | 107 | w.set_rev_in(match self._config.reverse_in { |
| 111 | InputReverseConfig::None => vals::RevIn::NORMAL, | 108 | InputReverseConfig::None => vals::RevIn::NORMAL, |
| 112 | InputReverseConfig::Byte => vals::RevIn::BYTE, | 109 | InputReverseConfig::Byte => vals::RevIn::BYTE, |
| 113 | InputReverseConfig::Halfword => vals::RevIn::HALFWORD, | 110 | InputReverseConfig::Halfword => vals::RevIn::HALFWORD, |
| 114 | InputReverseConfig::Word => vals::RevIn::WORD, | 111 | InputReverseConfig::Word => vals::RevIn::WORD, |
| 115 | }); | 112 | }); |
| 116 | // configure the polynomial. | 113 | // configure the polynomial. |
| 117 | #[cfg(crc_v3)] | 114 | #[cfg(crc_v3)] |
| 118 | w.set_polysize(match self._config.poly_size { | 115 | w.set_polysize(match self._config.poly_size { |
| 119 | PolySize::Width7 => vals::Polysize::POLYSIZE7, | 116 | PolySize::Width7 => vals::Polysize::POLYSIZE7, |
| 120 | PolySize::Width8 => vals::Polysize::POLYSIZE8, | 117 | PolySize::Width8 => vals::Polysize::POLYSIZE8, |
| 121 | PolySize::Width16 => vals::Polysize::POLYSIZE16, | 118 | PolySize::Width16 => vals::Polysize::POLYSIZE16, |
| 122 | PolySize::Width32 => vals::Polysize::POLYSIZE32, | 119 | PolySize::Width32 => vals::Polysize::POLYSIZE32, |
| 123 | }); | 120 | }); |
| 124 | }) | 121 | }); |
| 125 | } | ||
| 126 | 122 | ||
| 127 | self.reset(); | 123 | self.reset(); |
| 128 | } | 124 | } |
| 129 | 125 | ||
| 130 | /// Feeds a byte into the CRC peripheral. Returns the computed checksum. | 126 | /// Feeds a byte into the CRC peripheral. Returns the computed checksum. |
| 131 | pub fn feed_byte(&mut self, byte: u8) -> u32 { | 127 | pub fn feed_byte(&mut self, byte: u8) -> u32 { |
| 132 | unsafe { | 128 | PAC_CRC.dr8().write_value(byte); |
| 133 | PAC_CRC.dr8().write_value(byte); | 129 | PAC_CRC.dr().read() |
| 134 | PAC_CRC.dr().read() | ||
| 135 | } | ||
| 136 | } | 130 | } |
| 137 | 131 | ||
| 138 | /// Feeds an slice of bytes into the CRC peripheral. Returns the computed checksum. | 132 | /// Feeds an slice of bytes into the CRC peripheral. Returns the computed checksum. |
| 139 | pub fn feed_bytes(&mut self, bytes: &[u8]) -> u32 { | 133 | pub fn feed_bytes(&mut self, bytes: &[u8]) -> u32 { |
| 140 | for byte in bytes { | 134 | for byte in bytes { |
| 141 | unsafe { | 135 | PAC_CRC.dr8().write_value(*byte); |
| 142 | PAC_CRC.dr8().write_value(*byte); | ||
| 143 | } | ||
| 144 | } | 136 | } |
| 145 | unsafe { PAC_CRC.dr().read() } | 137 | PAC_CRC.dr().read() |
| 146 | } | 138 | } |
| 147 | /// Feeds a halfword into the CRC peripheral. Returns the computed checksum. | 139 | /// Feeds a halfword into the CRC peripheral. Returns the computed checksum. |
| 148 | pub fn feed_halfword(&mut self, halfword: u16) -> u32 { | 140 | pub fn feed_halfword(&mut self, halfword: u16) -> u32 { |
| 149 | unsafe { | 141 | PAC_CRC.dr16().write_value(halfword); |
| 150 | PAC_CRC.dr16().write_value(halfword); | 142 | PAC_CRC.dr().read() |
| 151 | PAC_CRC.dr().read() | ||
| 152 | } | ||
| 153 | } | 143 | } |
| 154 | /// Feeds an slice of halfwords into the CRC peripheral. Returns the computed checksum. | 144 | /// Feeds an slice of halfwords into the CRC peripheral. Returns the computed checksum. |
| 155 | pub fn feed_halfwords(&mut self, halfwords: &[u16]) -> u32 { | 145 | pub fn feed_halfwords(&mut self, halfwords: &[u16]) -> u32 { |
| 156 | for halfword in halfwords { | 146 | for halfword in halfwords { |
| 157 | unsafe { | 147 | PAC_CRC.dr16().write_value(*halfword); |
| 158 | PAC_CRC.dr16().write_value(*halfword); | ||
| 159 | } | ||
| 160 | } | 148 | } |
| 161 | unsafe { PAC_CRC.dr().read() } | 149 | PAC_CRC.dr().read() |
| 162 | } | 150 | } |
| 163 | /// Feeds a words into the CRC peripheral. Returns the computed checksum. | 151 | /// Feeds a words into the CRC peripheral. Returns the computed checksum. |
| 164 | pub fn feed_word(&mut self, word: u32) -> u32 { | 152 | pub fn feed_word(&mut self, word: u32) -> u32 { |
| 165 | unsafe { | 153 | PAC_CRC.dr().write_value(word as u32); |
| 166 | PAC_CRC.dr().write_value(word as u32); | 154 | PAC_CRC.dr().read() |
| 167 | PAC_CRC.dr().read() | ||
| 168 | } | ||
| 169 | } | 155 | } |
| 170 | /// Feeds an slice of words into the CRC peripheral. Returns the computed checksum. | 156 | /// Feeds an slice of words into the CRC peripheral. Returns the computed checksum. |
| 171 | pub fn feed_words(&mut self, words: &[u32]) -> u32 { | 157 | pub fn feed_words(&mut self, words: &[u32]) -> u32 { |
| 172 | for word in words { | 158 | for word in words { |
| 173 | unsafe { | 159 | PAC_CRC.dr().write_value(*word as u32); |
| 174 | PAC_CRC.dr().write_value(*word as u32); | ||
| 175 | } | ||
| 176 | } | 160 | } |
| 177 | unsafe { PAC_CRC.dr().read() } | 161 | PAC_CRC.dr().read() |
| 178 | } | 162 | } |
| 179 | } | 163 | } |
diff --git a/embassy-stm32/src/dac.rs b/embassy-stm32/src/dac.rs index 60e856c78..631118877 100644 --- a/embassy-stm32/src/dac.rs +++ b/embassy-stm32/src/dac.rs | |||
| @@ -121,13 +121,11 @@ impl<'d, T: Instance> Dac<'d, T> { | |||
| 121 | T::enable(); | 121 | T::enable(); |
| 122 | T::reset(); | 122 | T::reset(); |
| 123 | 123 | ||
| 124 | unsafe { | 124 | T::regs().cr().modify(|reg| { |
| 125 | T::regs().cr().modify(|reg| { | 125 | for ch in 0..channels { |
| 126 | for ch in 0..channels { | 126 | reg.set_en(ch as usize, true); |
| 127 | reg.set_en(ch as usize, true); | 127 | } |
| 128 | } | 128 | }); |
| 129 | }); | ||
| 130 | } | ||
| 131 | 129 | ||
| 132 | Self { channels, _peri: peri } | 130 | Self { channels, _peri: peri } |
| 133 | } | 131 | } |
| @@ -143,11 +141,9 @@ impl<'d, T: Instance> Dac<'d, T> { | |||
| 143 | 141 | ||
| 144 | fn set_channel_enable(&mut self, ch: Channel, on: bool) -> Result<(), Error> { | 142 | fn set_channel_enable(&mut self, ch: Channel, on: bool) -> Result<(), Error> { |
| 145 | self.check_channel_exists(ch)?; | 143 | self.check_channel_exists(ch)?; |
| 146 | unsafe { | 144 | T::regs().cr().modify(|reg| { |
| 147 | T::regs().cr().modify(|reg| { | 145 | reg.set_en(ch.index(), on); |
| 148 | reg.set_en(ch.index(), on); | 146 | }); |
| 149 | }) | ||
| 150 | } | ||
| 151 | Ok(()) | 147 | Ok(()) |
| 152 | } | 148 | } |
| 153 | 149 | ||
| @@ -162,56 +158,42 @@ impl<'d, T: Instance> Dac<'d, T> { | |||
| 162 | pub fn select_trigger_ch1(&mut self, trigger: Ch1Trigger) -> Result<(), Error> { | 158 | pub fn select_trigger_ch1(&mut self, trigger: Ch1Trigger) -> Result<(), Error> { |
| 163 | self.check_channel_exists(Channel::Ch1)?; | 159 | self.check_channel_exists(Channel::Ch1)?; |
| 164 | unwrap!(self.disable_channel(Channel::Ch1)); | 160 | unwrap!(self.disable_channel(Channel::Ch1)); |
| 165 | unsafe { | 161 | T::regs().cr().modify(|reg| { |
| 166 | T::regs().cr().modify(|reg| { | 162 | reg.set_tsel1(trigger.tsel()); |
| 167 | reg.set_tsel1(trigger.tsel()); | 163 | }); |
| 168 | }) | ||
| 169 | } | ||
| 170 | Ok(()) | 164 | Ok(()) |
| 171 | } | 165 | } |
| 172 | 166 | ||
| 173 | pub fn select_trigger_ch2(&mut self, trigger: Ch2Trigger) -> Result<(), Error> { | 167 | pub fn select_trigger_ch2(&mut self, trigger: Ch2Trigger) -> Result<(), Error> { |
| 174 | self.check_channel_exists(Channel::Ch2)?; | 168 | self.check_channel_exists(Channel::Ch2)?; |
| 175 | unwrap!(self.disable_channel(Channel::Ch2)); | 169 | unwrap!(self.disable_channel(Channel::Ch2)); |
| 176 | unsafe { | 170 | T::regs().cr().modify(|reg| { |
| 177 | T::regs().cr().modify(|reg| { | 171 | reg.set_tsel2(trigger.tsel()); |
| 178 | reg.set_tsel2(trigger.tsel()); | 172 | }); |
| 179 | }) | ||
| 180 | } | ||
| 181 | Ok(()) | 173 | Ok(()) |
| 182 | } | 174 | } |
| 183 | 175 | ||
| 184 | pub fn trigger(&mut self, ch: Channel) -> Result<(), Error> { | 176 | pub fn trigger(&mut self, ch: Channel) -> Result<(), Error> { |
| 185 | self.check_channel_exists(ch)?; | 177 | self.check_channel_exists(ch)?; |
| 186 | unsafe { | 178 | T::regs().swtrigr().write(|reg| { |
| 187 | T::regs().swtrigr().write(|reg| { | 179 | reg.set_swtrig(ch.index(), true); |
| 188 | reg.set_swtrig(ch.index(), true); | 180 | }); |
| 189 | }); | ||
| 190 | } | ||
| 191 | Ok(()) | 181 | Ok(()) |
| 192 | } | 182 | } |
| 193 | 183 | ||
| 194 | pub fn trigger_all(&mut self) { | 184 | pub fn trigger_all(&mut self) { |
| 195 | unsafe { | 185 | T::regs().swtrigr().write(|reg| { |
| 196 | T::regs().swtrigr().write(|reg| { | 186 | reg.set_swtrig(Channel::Ch1.index(), true); |
| 197 | reg.set_swtrig(Channel::Ch1.index(), true); | 187 | reg.set_swtrig(Channel::Ch2.index(), true); |
| 198 | reg.set_swtrig(Channel::Ch2.index(), true); | 188 | }); |
| 199 | }) | ||
| 200 | } | ||
| 201 | } | 189 | } |
| 202 | 190 | ||
| 203 | pub fn set(&mut self, ch: Channel, value: Value) -> Result<(), Error> { | 191 | pub fn set(&mut self, ch: Channel, value: Value) -> Result<(), Error> { |
| 204 | self.check_channel_exists(ch)?; | 192 | self.check_channel_exists(ch)?; |
| 205 | match value { | 193 | match value { |
| 206 | Value::Bit8(v) => unsafe { | 194 | Value::Bit8(v) => T::regs().dhr8r(ch.index()).write(|reg| reg.set_dhr(v)), |
| 207 | T::regs().dhr8r(ch.index()).write(|reg| reg.set_dhr(v)); | 195 | Value::Bit12(v, Alignment::Left) => T::regs().dhr12l(ch.index()).write(|reg| reg.set_dhr(v)), |
| 208 | }, | 196 | Value::Bit12(v, Alignment::Right) => T::regs().dhr12r(ch.index()).write(|reg| reg.set_dhr(v)), |
| 209 | Value::Bit12(v, Alignment::Left) => unsafe { | ||
| 210 | T::regs().dhr12l(ch.index()).write(|reg| reg.set_dhr(v)); | ||
| 211 | }, | ||
| 212 | Value::Bit12(v, Alignment::Right) => unsafe { | ||
| 213 | T::regs().dhr12r(ch.index()).write(|reg| reg.set_dhr(v)); | ||
| 214 | }, | ||
| 215 | } | 197 | } |
| 216 | Ok(()) | 198 | Ok(()) |
| 217 | } | 199 | } |
| @@ -239,20 +221,20 @@ foreach_peripheral!( | |||
| 239 | } | 221 | } |
| 240 | 222 | ||
| 241 | fn reset() { | 223 | fn reset() { |
| 242 | critical_section::with(|_| unsafe { | 224 | critical_section::with(|_| { |
| 243 | crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(true)); | 225 | crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(true)); |
| 244 | crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(false)); | 226 | crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(false)); |
| 245 | }) | 227 | }) |
| 246 | } | 228 | } |
| 247 | 229 | ||
| 248 | fn enable() { | 230 | fn enable() { |
| 249 | critical_section::with(|_| unsafe { | 231 | critical_section::with(|_| { |
| 250 | crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true)); | 232 | crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true)); |
| 251 | }) | 233 | }) |
| 252 | } | 234 | } |
| 253 | 235 | ||
| 254 | fn disable() { | 236 | fn disable() { |
| 255 | critical_section::with(|_| unsafe { | 237 | critical_section::with(|_| { |
| 256 | crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(false)); | 238 | crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(false)); |
| 257 | }) | 239 | }) |
| 258 | } | 240 | } |
diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs index 41305d273..78b026cb6 100644 --- a/embassy-stm32/src/dcmi.rs +++ b/embassy-stm32/src/dcmi.rs | |||
| @@ -96,8 +96,7 @@ impl Default for Config { | |||
| 96 | macro_rules! config_pins { | 96 | macro_rules! config_pins { |
| 97 | ($($pin:ident),*) => { | 97 | ($($pin:ident),*) => { |
| 98 | into_ref!($($pin),*); | 98 | into_ref!($($pin),*); |
| 99 | // NOTE(unsafe) Exclusive access to the registers | 99 | critical_section::with(|_| { |
| 100 | critical_section::with(|_| unsafe { | ||
| 101 | $( | 100 | $( |
| 102 | $pin.set_as_af($pin.af_num(), AFType::Input); | 101 | $pin.set_as_af($pin.af_num(), AFType::Input); |
| 103 | $pin.set_speed(Speed::VeryHigh); | 102 | $pin.set_speed(Speed::VeryHigh); |
| @@ -334,17 +333,15 @@ where | |||
| 334 | T::reset(); | 333 | T::reset(); |
| 335 | T::enable(); | 334 | T::enable(); |
| 336 | 335 | ||
| 337 | unsafe { | 336 | peri.regs().cr().modify(|r| { |
| 338 | peri.regs().cr().modify(|r| { | 337 | r.set_cm(true); // disable continuous mode (snapshot mode) |
| 339 | r.set_cm(true); // disable continuous mode (snapshot mode) | 338 | r.set_ess(use_embedded_synchronization); |
| 340 | r.set_ess(use_embedded_synchronization); | 339 | r.set_pckpol(config.pixclk_polarity == PixelClockPolarity::RisingEdge); |
| 341 | r.set_pckpol(config.pixclk_polarity == PixelClockPolarity::RisingEdge); | 340 | r.set_vspol(config.vsync_level == VSyncDataInvalidLevel::High); |
| 342 | r.set_vspol(config.vsync_level == VSyncDataInvalidLevel::High); | 341 | r.set_hspol(config.hsync_level == HSyncDataInvalidLevel::High); |
| 343 | r.set_hspol(config.hsync_level == HSyncDataInvalidLevel::High); | 342 | r.set_fcrc(0x00); // capture every frame |
| 344 | r.set_fcrc(0x00); // capture every frame | 343 | r.set_edm(edm); // extended data mode |
| 345 | r.set_edm(edm); // extended data mode | 344 | }); |
| 346 | }); | ||
| 347 | } | ||
| 348 | 345 | ||
| 349 | T::Interrupt::unpend(); | 346 | T::Interrupt::unpend(); |
| 350 | unsafe { T::Interrupt::enable() }; | 347 | unsafe { T::Interrupt::enable() }; |
| @@ -352,7 +349,7 @@ where | |||
| 352 | Self { inner: peri, dma } | 349 | Self { inner: peri, dma } |
| 353 | } | 350 | } |
| 354 | 351 | ||
| 355 | unsafe fn toggle(enable: bool) { | 352 | fn toggle(enable: bool) { |
| 356 | crate::pac::DCMI.cr().modify(|r| { | 353 | crate::pac::DCMI.cr().modify(|r| { |
| 357 | r.set_enable(enable); | 354 | r.set_enable(enable); |
| 358 | r.set_capture(enable); | 355 | r.set_capture(enable); |
| @@ -360,23 +357,19 @@ where | |||
| 360 | } | 357 | } |
| 361 | 358 | ||
| 362 | fn enable_irqs() { | 359 | fn enable_irqs() { |
| 363 | unsafe { | 360 | crate::pac::DCMI.ier().modify(|r| { |
| 364 | crate::pac::DCMI.ier().modify(|r| { | 361 | r.set_err_ie(true); |
| 365 | r.set_err_ie(true); | 362 | r.set_ovr_ie(true); |
| 366 | r.set_ovr_ie(true); | 363 | r.set_frame_ie(true); |
| 367 | r.set_frame_ie(true); | 364 | }); |
| 368 | }); | ||
| 369 | } | ||
| 370 | } | 365 | } |
| 371 | 366 | ||
| 372 | fn clear_interrupt_flags() { | 367 | fn clear_interrupt_flags() { |
| 373 | unsafe { | 368 | crate::pac::DCMI.icr().write(|r| { |
| 374 | crate::pac::DCMI.icr().write(|r| { | 369 | r.set_ovr_isc(true); |
| 375 | r.set_ovr_isc(true); | 370 | r.set_err_isc(true); |
| 376 | r.set_err_isc(true); | 371 | r.set_frame_isc(true); |
| 377 | r.set_frame_isc(true); | 372 | }) |
| 378 | }) | ||
| 379 | } | ||
| 380 | } | 373 | } |
| 381 | 374 | ||
| 382 | /// This method starts the capture and finishes when both the dma transfer and DCMI finish the frame transfer. | 375 | /// This method starts the capture and finishes when both the dma transfer and DCMI finish the frame transfer. |
| @@ -392,41 +385,30 @@ where | |||
| 392 | return self.capture_giant(buffer).await; | 385 | return self.capture_giant(buffer).await; |
| 393 | } | 386 | } |
| 394 | } | 387 | } |
| 388 | |||
| 395 | async fn capture_small(&mut self, buffer: &mut [u32]) -> Result<(), Error> { | 389 | async fn capture_small(&mut self, buffer: &mut [u32]) -> Result<(), Error> { |
| 396 | let r = self.inner.regs(); | 390 | let r = self.inner.regs(); |
| 397 | let src = r.dr().ptr() as *mut u32; | 391 | let src = r.dr().as_ptr() as *mut u32; |
| 398 | let request = self.dma.request(); | 392 | let request = self.dma.request(); |
| 399 | let dma_read = unsafe { Transfer::new_read(&mut self.dma, request, src, buffer, Default::default()) }; | 393 | let dma_read = unsafe { Transfer::new_read(&mut self.dma, request, src, buffer, Default::default()) }; |
| 400 | 394 | ||
| 401 | Self::clear_interrupt_flags(); | 395 | Self::clear_interrupt_flags(); |
| 402 | Self::enable_irqs(); | 396 | Self::enable_irqs(); |
| 403 | 397 | ||
| 404 | unsafe { Self::toggle(true) }; | 398 | Self::toggle(true); |
| 405 | 399 | ||
| 406 | let result = poll_fn(|cx| { | 400 | let result = poll_fn(|cx| { |
| 407 | STATE.waker.register(cx.waker()); | 401 | STATE.waker.register(cx.waker()); |
| 408 | 402 | ||
| 409 | let ris = unsafe { crate::pac::DCMI.ris().read() }; | 403 | let ris = crate::pac::DCMI.ris().read(); |
| 410 | if ris.err_ris() { | 404 | if ris.err_ris() { |
| 411 | unsafe { | 405 | crate::pac::DCMI.icr().write(|r| r.set_err_isc(true)); |
| 412 | crate::pac::DCMI.icr().write(|r| { | ||
| 413 | r.set_err_isc(true); | ||
| 414 | }) | ||
| 415 | }; | ||
| 416 | Poll::Ready(Err(Error::PeripheralError)) | 406 | Poll::Ready(Err(Error::PeripheralError)) |
| 417 | } else if ris.ovr_ris() { | 407 | } else if ris.ovr_ris() { |
| 418 | unsafe { | 408 | crate::pac::DCMI.icr().write(|r| r.set_ovr_isc(true)); |
| 419 | crate::pac::DCMI.icr().write(|r| { | ||
| 420 | r.set_ovr_isc(true); | ||
| 421 | }) | ||
| 422 | }; | ||
| 423 | Poll::Ready(Err(Error::Overrun)) | 409 | Poll::Ready(Err(Error::Overrun)) |
| 424 | } else if ris.frame_ris() { | 410 | } else if ris.frame_ris() { |
| 425 | unsafe { | 411 | crate::pac::DCMI.icr().write(|r| r.set_frame_isc(true)); |
| 426 | crate::pac::DCMI.icr().write(|r| { | ||
| 427 | r.set_frame_isc(true); | ||
| 428 | }) | ||
| 429 | }; | ||
| 430 | Poll::Ready(Ok(())) | 412 | Poll::Ready(Ok(())) |
| 431 | } else { | 413 | } else { |
| 432 | Poll::Pending | 414 | Poll::Pending |
| @@ -435,7 +417,7 @@ where | |||
| 435 | 417 | ||
| 436 | let (_, result) = embassy_futures::join::join(dma_read, result).await; | 418 | let (_, result) = embassy_futures::join::join(dma_read, result).await; |
| 437 | 419 | ||
| 438 | unsafe { Self::toggle(false) }; | 420 | Self::toggle(false); |
| 439 | 421 | ||
| 440 | result | 422 | result |
| 441 | } | 423 | } |
| @@ -468,7 +450,7 @@ where | |||
| 468 | let request = channel.request(); | 450 | let request = channel.request(); |
| 469 | 451 | ||
| 470 | let r = self.inner.regs(); | 452 | let r = self.inner.regs(); |
| 471 | let src = r.dr().ptr() as *mut u32; | 453 | let src = r.dr().as_ptr() as *mut u32; |
| 472 | 454 | ||
| 473 | let mut transfer = unsafe { | 455 | let mut transfer = unsafe { |
| 474 | crate::dma::DoubleBuffered::new_read( | 456 | crate::dma::DoubleBuffered::new_read( |
| @@ -526,38 +508,26 @@ where | |||
| 526 | let result = poll_fn(|cx| { | 508 | let result = poll_fn(|cx| { |
| 527 | STATE.waker.register(cx.waker()); | 509 | STATE.waker.register(cx.waker()); |
| 528 | 510 | ||
| 529 | let ris = unsafe { crate::pac::DCMI.ris().read() }; | 511 | let ris = crate::pac::DCMI.ris().read(); |
| 530 | if ris.err_ris() { | 512 | if ris.err_ris() { |
| 531 | unsafe { | 513 | crate::pac::DCMI.icr().write(|r| r.set_err_isc(true)); |
| 532 | crate::pac::DCMI.icr().write(|r| { | ||
| 533 | r.set_err_isc(true); | ||
| 534 | }) | ||
| 535 | }; | ||
| 536 | Poll::Ready(Err(Error::PeripheralError)) | 514 | Poll::Ready(Err(Error::PeripheralError)) |
| 537 | } else if ris.ovr_ris() { | 515 | } else if ris.ovr_ris() { |
| 538 | unsafe { | 516 | crate::pac::DCMI.icr().write(|r| r.set_ovr_isc(true)); |
| 539 | crate::pac::DCMI.icr().write(|r| { | ||
| 540 | r.set_ovr_isc(true); | ||
| 541 | }) | ||
| 542 | }; | ||
| 543 | Poll::Ready(Err(Error::Overrun)) | 517 | Poll::Ready(Err(Error::Overrun)) |
| 544 | } else if ris.frame_ris() { | 518 | } else if ris.frame_ris() { |
| 545 | unsafe { | 519 | crate::pac::DCMI.icr().write(|r| r.set_frame_isc(true)); |
| 546 | crate::pac::DCMI.icr().write(|r| { | ||
| 547 | r.set_frame_isc(true); | ||
| 548 | }) | ||
| 549 | }; | ||
| 550 | Poll::Ready(Ok(())) | 520 | Poll::Ready(Ok(())) |
| 551 | } else { | 521 | } else { |
| 552 | Poll::Pending | 522 | Poll::Pending |
| 553 | } | 523 | } |
| 554 | }); | 524 | }); |
| 555 | 525 | ||
| 556 | unsafe { Self::toggle(true) }; | 526 | Self::toggle(true); |
| 557 | 527 | ||
| 558 | let (_, result) = embassy_futures::join::join(dma_result, result).await; | 528 | let (_, result) = embassy_futures::join::join(dma_result, result).await; |
| 559 | 529 | ||
| 560 | unsafe { Self::toggle(false) }; | 530 | Self::toggle(false); |
| 561 | 531 | ||
| 562 | result | 532 | result |
| 563 | } | 533 | } |
diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs index c0a503e25..5fcb30f65 100644 --- a/embassy-stm32/src/dma/bdma.rs +++ b/embassy-stm32/src/dma/bdma.rs | |||
| @@ -107,7 +107,7 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::bdma::Dma, channel_num: usize, index | |||
| 107 | let cr = dma.ch(channel_num).cr(); | 107 | let cr = dma.ch(channel_num).cr(); |
| 108 | 108 | ||
| 109 | if isr.teif(channel_num) { | 109 | if isr.teif(channel_num) { |
| 110 | panic!("DMA: error on BDMA@{:08x} channel {}", dma.0 as u32, channel_num); | 110 | panic!("DMA: error on BDMA@{:08x} channel {}", dma.as_ptr() as u32, channel_num); |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | if isr.htif(channel_num) && cr.read().htie() { | 113 | if isr.htif(channel_num) && cr.read().htie() { |
| @@ -291,29 +291,25 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 291 | } | 291 | } |
| 292 | 292 | ||
| 293 | fn clear_irqs(&mut self) { | 293 | fn clear_irqs(&mut self) { |
| 294 | unsafe { | 294 | self.channel.regs().ifcr().write(|w| { |
| 295 | self.channel.regs().ifcr().write(|w| { | 295 | w.set_tcif(self.channel.num(), true); |
| 296 | w.set_tcif(self.channel.num(), true); | 296 | w.set_teif(self.channel.num(), true); |
| 297 | w.set_teif(self.channel.num(), true); | 297 | }); |
| 298 | }) | ||
| 299 | } | ||
| 300 | } | 298 | } |
| 301 | 299 | ||
| 302 | pub fn request_stop(&mut self) { | 300 | pub fn request_stop(&mut self) { |
| 303 | let ch = self.channel.regs().ch(self.channel.num()); | 301 | let ch = self.channel.regs().ch(self.channel.num()); |
| 304 | 302 | ||
| 305 | // Disable the channel. Keep the IEs enabled so the irqs still fire. | 303 | // Disable the channel. Keep the IEs enabled so the irqs still fire. |
| 306 | unsafe { | 304 | ch.cr().write(|w| { |
| 307 | ch.cr().write(|w| { | 305 | w.set_teie(true); |
| 308 | w.set_teie(true); | 306 | w.set_tcie(true); |
| 309 | w.set_tcie(true); | 307 | }); |
| 310 | }) | ||
| 311 | } | ||
| 312 | } | 308 | } |
| 313 | 309 | ||
| 314 | pub fn is_running(&mut self) -> bool { | 310 | pub fn is_running(&mut self) -> bool { |
| 315 | let ch = self.channel.regs().ch(self.channel.num()); | 311 | let ch = self.channel.regs().ch(self.channel.num()); |
| 316 | let en = unsafe { ch.cr().read() }.en(); | 312 | let en = ch.cr().read().en(); |
| 317 | let tcif = STATE.complete_count[self.channel.index()].load(Ordering::Acquire) != 0; | 313 | let tcif = STATE.complete_count[self.channel.index()].load(Ordering::Acquire) != 0; |
| 318 | en && !tcif | 314 | en && !tcif |
| 319 | } | 315 | } |
| @@ -322,7 +318,7 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 322 | /// Note: this will be zero for transfers that completed without cancellation. | 318 | /// Note: this will be zero for transfers that completed without cancellation. |
| 323 | pub fn get_remaining_transfers(&self) -> u16 { | 319 | pub fn get_remaining_transfers(&self) -> u16 { |
| 324 | let ch = self.channel.regs().ch(self.channel.num()); | 320 | let ch = self.channel.regs().ch(self.channel.num()); |
| 325 | unsafe { ch.ndtr().read() }.ndt() | 321 | ch.ndtr().read().ndt() |
| 326 | } | 322 | } |
| 327 | 323 | ||
| 328 | pub fn blocking_wait(mut self) { | 324 | pub fn blocking_wait(mut self) { |
| @@ -366,7 +362,7 @@ struct DmaCtrlImpl<'a, C: Channel>(PeripheralRef<'a, C>); | |||
| 366 | impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> { | 362 | impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> { |
| 367 | fn get_remaining_transfers(&self) -> usize { | 363 | fn get_remaining_transfers(&self) -> usize { |
| 368 | let ch = self.0.regs().ch(self.0.num()); | 364 | let ch = self.0.regs().ch(self.0.num()); |
| 369 | unsafe { ch.ndtr().read() }.ndt() as usize | 365 | ch.ndtr().read().ndt() as usize |
| 370 | } | 366 | } |
| 371 | 367 | ||
| 372 | fn get_complete_count(&self) -> usize { | 368 | fn get_complete_count(&self) -> usize { |
| @@ -442,7 +438,7 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> { | |||
| 442 | 438 | ||
| 443 | pub fn start(&mut self) { | 439 | pub fn start(&mut self) { |
| 444 | let ch = self.channel.regs().ch(self.channel.num()); | 440 | let ch = self.channel.regs().ch(self.channel.num()); |
| 445 | unsafe { ch.cr().write_value(self.cr) } | 441 | ch.cr().write_value(self.cr) |
| 446 | } | 442 | } |
| 447 | 443 | ||
| 448 | pub fn clear(&mut self) { | 444 | pub fn clear(&mut self) { |
| @@ -469,31 +465,27 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> { | |||
| 469 | 465 | ||
| 470 | fn clear_irqs(&mut self) { | 466 | fn clear_irqs(&mut self) { |
| 471 | let dma = self.channel.regs(); | 467 | let dma = self.channel.regs(); |
| 472 | unsafe { | 468 | dma.ifcr().write(|w| { |
| 473 | dma.ifcr().write(|w| { | 469 | w.set_htif(self.channel.num(), true); |
| 474 | w.set_htif(self.channel.num(), true); | 470 | w.set_tcif(self.channel.num(), true); |
| 475 | w.set_tcif(self.channel.num(), true); | 471 | w.set_teif(self.channel.num(), true); |
| 476 | w.set_teif(self.channel.num(), true); | 472 | }); |
| 477 | }) | ||
| 478 | } | ||
| 479 | } | 473 | } |
| 480 | 474 | ||
| 481 | pub fn request_stop(&mut self) { | 475 | pub fn request_stop(&mut self) { |
| 482 | let ch = self.channel.regs().ch(self.channel.num()); | 476 | let ch = self.channel.regs().ch(self.channel.num()); |
| 483 | 477 | ||
| 484 | // Disable the channel. Keep the IEs enabled so the irqs still fire. | 478 | // Disable the channel. Keep the IEs enabled so the irqs still fire. |
| 485 | unsafe { | 479 | ch.cr().write(|w| { |
| 486 | ch.cr().write(|w| { | 480 | w.set_teie(true); |
| 487 | w.set_teie(true); | 481 | w.set_htie(true); |
| 488 | w.set_htie(true); | 482 | w.set_tcie(true); |
| 489 | w.set_tcie(true); | 483 | }); |
| 490 | }) | ||
| 491 | } | ||
| 492 | } | 484 | } |
| 493 | 485 | ||
| 494 | pub fn is_running(&mut self) -> bool { | 486 | pub fn is_running(&mut self) -> bool { |
| 495 | let ch = self.channel.regs().ch(self.channel.num()); | 487 | let ch = self.channel.regs().ch(self.channel.num()); |
| 496 | unsafe { ch.cr().read() }.en() | 488 | ch.cr().read().en() |
| 497 | } | 489 | } |
| 498 | } | 490 | } |
| 499 | 491 | ||
diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs index 874cb013a..8abe541d3 100644 --- a/embassy-stm32/src/dma/dma.rs +++ b/embassy-stm32/src/dma/dma.rs | |||
| @@ -183,7 +183,7 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::dma::Dma, channel_num: usize, index: | |||
| 183 | let isr = dma.isr(channel_num / 4).read(); | 183 | let isr = dma.isr(channel_num / 4).read(); |
| 184 | 184 | ||
| 185 | if isr.teif(channel_num % 4) { | 185 | if isr.teif(channel_num % 4) { |
| 186 | panic!("DMA: error on DMA@{:08x} channel {}", dma.0 as u32, channel_num); | 186 | panic!("DMA: error on DMA@{:08x} channel {}", dma.as_ptr() as u32, channel_num); |
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | if isr.htif(channel_num % 4) && cr.read().htie() { | 189 | if isr.htif(channel_num % 4) && cr.read().htie() { |
| @@ -387,36 +387,32 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 387 | let isrn = self.channel.num() / 4; | 387 | let isrn = self.channel.num() / 4; |
| 388 | let isrbit = self.channel.num() % 4; | 388 | let isrbit = self.channel.num() % 4; |
| 389 | 389 | ||
| 390 | unsafe { | 390 | self.channel.regs().ifcr(isrn).write(|w| { |
| 391 | self.channel.regs().ifcr(isrn).write(|w| { | 391 | w.set_tcif(isrbit, true); |
| 392 | w.set_tcif(isrbit, true); | 392 | w.set_teif(isrbit, true); |
| 393 | w.set_teif(isrbit, true); | 393 | }); |
| 394 | }) | ||
| 395 | } | ||
| 396 | } | 394 | } |
| 397 | 395 | ||
| 398 | pub fn request_stop(&mut self) { | 396 | pub fn request_stop(&mut self) { |
| 399 | let ch = self.channel.regs().st(self.channel.num()); | 397 | let ch = self.channel.regs().st(self.channel.num()); |
| 400 | 398 | ||
| 401 | // Disable the channel. Keep the IEs enabled so the irqs still fire. | 399 | // Disable the channel. Keep the IEs enabled so the irqs still fire. |
| 402 | unsafe { | 400 | ch.cr().write(|w| { |
| 403 | ch.cr().write(|w| { | 401 | w.set_teie(true); |
| 404 | w.set_teie(true); | 402 | w.set_tcie(true); |
| 405 | w.set_tcie(true); | 403 | }); |
| 406 | }) | ||
| 407 | } | ||
| 408 | } | 404 | } |
| 409 | 405 | ||
| 410 | pub fn is_running(&mut self) -> bool { | 406 | pub fn is_running(&mut self) -> bool { |
| 411 | let ch = self.channel.regs().st(self.channel.num()); | 407 | let ch = self.channel.regs().st(self.channel.num()); |
| 412 | unsafe { ch.cr().read() }.en() | 408 | ch.cr().read().en() |
| 413 | } | 409 | } |
| 414 | 410 | ||
| 415 | /// Gets the total remaining transfers for the channel | 411 | /// Gets the total remaining transfers for the channel |
| 416 | /// Note: this will be zero for transfers that completed without cancellation. | 412 | /// Note: this will be zero for transfers that completed without cancellation. |
| 417 | pub fn get_remaining_transfers(&self) -> u16 { | 413 | pub fn get_remaining_transfers(&self) -> u16 { |
| 418 | let ch = self.channel.regs().st(self.channel.num()); | 414 | let ch = self.channel.regs().st(self.channel.num()); |
| 419 | unsafe { ch.ndtr().read() }.ndt() | 415 | ch.ndtr().read().ndt() |
| 420 | } | 416 | } |
| 421 | 417 | ||
| 422 | pub fn blocking_wait(mut self) { | 418 | pub fn blocking_wait(mut self) { |
| @@ -537,13 +533,11 @@ impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> { | |||
| 537 | let isrn = channel_number / 4; | 533 | let isrn = channel_number / 4; |
| 538 | let isrbit = channel_number % 4; | 534 | let isrbit = channel_number % 4; |
| 539 | 535 | ||
| 540 | unsafe { | 536 | dma.ifcr(isrn).write(|w| { |
| 541 | dma.ifcr(isrn).write(|w| { | 537 | w.set_htif(isrbit, true); |
| 542 | w.set_htif(isrbit, true); | 538 | w.set_tcif(isrbit, true); |
| 543 | w.set_tcif(isrbit, true); | 539 | w.set_teif(isrbit, true); |
| 544 | w.set_teif(isrbit, true); | 540 | }); |
| 545 | }) | ||
| 546 | } | ||
| 547 | } | 541 | } |
| 548 | 542 | ||
| 549 | pub unsafe fn set_buffer0(&mut self, buffer: *mut W) { | 543 | pub unsafe fn set_buffer0(&mut self, buffer: *mut W) { |
| @@ -558,7 +552,7 @@ impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> { | |||
| 558 | 552 | ||
| 559 | pub fn is_buffer0_accessible(&mut self) -> bool { | 553 | pub fn is_buffer0_accessible(&mut self) -> bool { |
| 560 | let ch = self.channel.regs().st(self.channel.num()); | 554 | let ch = self.channel.regs().st(self.channel.num()); |
| 561 | unsafe { ch.cr().read() }.ct() == vals::Ct::MEMORY1 | 555 | ch.cr().read().ct() == vals::Ct::MEMORY1 |
| 562 | } | 556 | } |
| 563 | 557 | ||
| 564 | pub fn set_waker(&mut self, waker: &Waker) { | 558 | pub fn set_waker(&mut self, waker: &Waker) { |
| @@ -569,24 +563,22 @@ impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> { | |||
| 569 | let ch = self.channel.regs().st(self.channel.num()); | 563 | let ch = self.channel.regs().st(self.channel.num()); |
| 570 | 564 | ||
| 571 | // Disable the channel. Keep the IEs enabled so the irqs still fire. | 565 | // Disable the channel. Keep the IEs enabled so the irqs still fire. |
| 572 | unsafe { | 566 | ch.cr().write(|w| { |
| 573 | ch.cr().write(|w| { | 567 | w.set_teie(true); |
| 574 | w.set_teie(true); | 568 | w.set_tcie(true); |
| 575 | w.set_tcie(true); | 569 | }); |
| 576 | }) | ||
| 577 | } | ||
| 578 | } | 570 | } |
| 579 | 571 | ||
| 580 | pub fn is_running(&mut self) -> bool { | 572 | pub fn is_running(&mut self) -> bool { |
| 581 | let ch = self.channel.regs().st(self.channel.num()); | 573 | let ch = self.channel.regs().st(self.channel.num()); |
| 582 | unsafe { ch.cr().read() }.en() | 574 | ch.cr().read().en() |
| 583 | } | 575 | } |
| 584 | 576 | ||
| 585 | /// Gets the total remaining transfers for the channel | 577 | /// Gets the total remaining transfers for the channel |
| 586 | /// Note: this will be zero for transfers that completed without cancellation. | 578 | /// Note: this will be zero for transfers that completed without cancellation. |
| 587 | pub fn get_remaining_transfers(&self) -> u16 { | 579 | pub fn get_remaining_transfers(&self) -> u16 { |
| 588 | let ch = self.channel.regs().st(self.channel.num()); | 580 | let ch = self.channel.regs().st(self.channel.num()); |
| 589 | unsafe { ch.ndtr().read() }.ndt() | 581 | ch.ndtr().read().ndt() |
| 590 | } | 582 | } |
| 591 | } | 583 | } |
| 592 | 584 | ||
| @@ -607,7 +599,7 @@ struct DmaCtrlImpl<'a, C: Channel>(PeripheralRef<'a, C>); | |||
| 607 | impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> { | 599 | impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> { |
| 608 | fn get_remaining_transfers(&self) -> usize { | 600 | fn get_remaining_transfers(&self) -> usize { |
| 609 | let ch = self.0.regs().st(self.0.num()); | 601 | let ch = self.0.regs().st(self.0.num()); |
| 610 | unsafe { ch.ndtr().read() }.ndt() as usize | 602 | ch.ndtr().read().ndt() as usize |
| 611 | } | 603 | } |
| 612 | 604 | ||
| 613 | fn get_complete_count(&self) -> usize { | 605 | fn get_complete_count(&self) -> usize { |
| @@ -698,7 +690,7 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> { | |||
| 698 | 690 | ||
| 699 | pub fn start(&mut self) { | 691 | pub fn start(&mut self) { |
| 700 | let ch = self.channel.regs().st(self.channel.num()); | 692 | let ch = self.channel.regs().st(self.channel.num()); |
| 701 | unsafe { ch.cr().write_value(self.cr) } | 693 | ch.cr().write_value(self.cr); |
| 702 | } | 694 | } |
| 703 | 695 | ||
| 704 | pub fn clear(&mut self) { | 696 | pub fn clear(&mut self) { |
| @@ -729,31 +721,27 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> { | |||
| 729 | let isrn = channel_number / 4; | 721 | let isrn = channel_number / 4; |
| 730 | let isrbit = channel_number % 4; | 722 | let isrbit = channel_number % 4; |
| 731 | 723 | ||
| 732 | unsafe { | 724 | dma.ifcr(isrn).write(|w| { |
| 733 | dma.ifcr(isrn).write(|w| { | 725 | w.set_htif(isrbit, true); |
| 734 | w.set_htif(isrbit, true); | 726 | w.set_tcif(isrbit, true); |
| 735 | w.set_tcif(isrbit, true); | 727 | w.set_teif(isrbit, true); |
| 736 | w.set_teif(isrbit, true); | 728 | }); |
| 737 | }) | ||
| 738 | } | ||
| 739 | } | 729 | } |
| 740 | 730 | ||
| 741 | pub fn request_stop(&mut self) { | 731 | pub fn request_stop(&mut self) { |
| 742 | let ch = self.channel.regs().st(self.channel.num()); | 732 | let ch = self.channel.regs().st(self.channel.num()); |
| 743 | 733 | ||
| 744 | // Disable the channel. Keep the IEs enabled so the irqs still fire. | 734 | // Disable the channel. Keep the IEs enabled so the irqs still fire. |
| 745 | unsafe { | 735 | ch.cr().write(|w| { |
| 746 | ch.cr().write(|w| { | 736 | w.set_teie(true); |
| 747 | w.set_teie(true); | 737 | w.set_htie(true); |
| 748 | w.set_htie(true); | 738 | w.set_tcie(true); |
| 749 | w.set_tcie(true); | 739 | }); |
| 750 | }) | ||
| 751 | } | ||
| 752 | } | 740 | } |
| 753 | 741 | ||
| 754 | pub fn is_running(&mut self) -> bool { | 742 | pub fn is_running(&mut self) -> bool { |
| 755 | let ch = self.channel.regs().st(self.channel.num()); | 743 | let ch = self.channel.regs().st(self.channel.num()); |
| 756 | unsafe { ch.cr().read() }.en() | 744 | ch.cr().read().en() |
| 757 | } | 745 | } |
| 758 | } | 746 | } |
| 759 | 747 | ||
diff --git a/embassy-stm32/src/dma/dmamux.rs b/embassy-stm32/src/dma/dmamux.rs index a8c4c5827..36fc03403 100644 --- a/embassy-stm32/src/dma/dmamux.rs +++ b/embassy-stm32/src/dma/dmamux.rs | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | 2 | ||
| 3 | use crate::{pac, peripherals}; | 3 | use crate::{pac, peripherals}; |
| 4 | 4 | ||
| 5 | pub(crate) unsafe fn configure_dmamux<M: MuxChannel>(channel: &mut M, request: u8) { | 5 | pub(crate) fn configure_dmamux<M: MuxChannel>(channel: &mut M, request: u8) { |
| 6 | let ch_mux_regs = channel.mux_regs().ccr(channel.mux_num()); | 6 | let ch_mux_regs = channel.mux_regs().ccr(channel.mux_num()); |
| 7 | ch_mux_regs.write(|reg| { | 7 | ch_mux_regs.write(|reg| { |
| 8 | reg.set_nbreq(0); | 8 | reg.set_nbreq(0); |
diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs index 3f0d5e8fa..c600df92d 100644 --- a/embassy-stm32/src/dma/gpdma.rs +++ b/embassy-stm32/src/dma/gpdma.rs | |||
| @@ -92,13 +92,15 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::gpdma::Gpdma, channel_num: usize, in | |||
| 92 | if sr.dtef() { | 92 | if sr.dtef() { |
| 93 | panic!( | 93 | panic!( |
| 94 | "DMA: data transfer error on DMA@{:08x} channel {}", | 94 | "DMA: data transfer error on DMA@{:08x} channel {}", |
| 95 | dma.0 as u32, channel_num | 95 | dma.as_ptr() as u32, |
| 96 | channel_num | ||
| 96 | ); | 97 | ); |
| 97 | } | 98 | } |
| 98 | if sr.usef() { | 99 | if sr.usef() { |
| 99 | panic!( | 100 | panic!( |
| 100 | "DMA: user settings error on DMA@{:08x} channel {}", | 101 | "DMA: user settings error on DMA@{:08x} channel {}", |
| 101 | dma.0 as u32, channel_num | 102 | dma.as_ptr() as u32, |
| 103 | channel_num | ||
| 102 | ); | 104 | ); |
| 103 | } | 105 | } |
| 104 | 106 | ||
| @@ -298,26 +300,24 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 298 | let ch = self.channel.regs().ch(self.channel.num()); | 300 | let ch = self.channel.regs().ch(self.channel.num()); |
| 299 | 301 | ||
| 300 | // Disable the channel. Keep the IEs enabled so the irqs still fire. | 302 | // Disable the channel. Keep the IEs enabled so the irqs still fire. |
| 301 | unsafe { | 303 | ch.cr().write(|w| { |
| 302 | ch.cr().write(|w| { | 304 | w.set_tcie(true); |
| 303 | w.set_tcie(true); | 305 | w.set_useie(true); |
| 304 | w.set_useie(true); | 306 | w.set_dteie(true); |
| 305 | w.set_dteie(true); | 307 | w.set_suspie(true); |
| 306 | w.set_suspie(true); | 308 | }) |
| 307 | }) | ||
| 308 | } | ||
| 309 | } | 309 | } |
| 310 | 310 | ||
| 311 | pub fn is_running(&mut self) -> bool { | 311 | pub fn is_running(&mut self) -> bool { |
| 312 | let ch = self.channel.regs().ch(self.channel.num()); | 312 | let ch = self.channel.regs().ch(self.channel.num()); |
| 313 | !unsafe { ch.sr().read() }.tcf() | 313 | !ch.sr().read().tcf() |
| 314 | } | 314 | } |
| 315 | 315 | ||
| 316 | /// Gets the total remaining transfers for the channel | 316 | /// Gets the total remaining transfers for the channel |
| 317 | /// Note: this will be zero for transfers that completed without cancellation. | 317 | /// Note: this will be zero for transfers that completed without cancellation. |
| 318 | pub fn get_remaining_transfers(&self) -> u16 { | 318 | pub fn get_remaining_transfers(&self) -> u16 { |
| 319 | let ch = self.channel.regs().ch(self.channel.num()); | 319 | let ch = self.channel.regs().ch(self.channel.num()); |
| 320 | unsafe { ch.br1().read() }.bndt() | 320 | ch.br1().read().bndt() |
| 321 | } | 321 | } |
| 322 | 322 | ||
| 323 | pub fn blocking_wait(mut self) { | 323 | pub fn blocking_wait(mut self) { |
diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs index 540cdd027..b53c2d0fa 100644 --- a/embassy-stm32/src/eth/v1/mod.rs +++ b/embassy-stm32/src/eth/v1/mod.rs | |||
| @@ -29,18 +29,16 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::ETH> for InterruptHandl | |||
| 29 | WAKER.wake(); | 29 | WAKER.wake(); |
| 30 | 30 | ||
| 31 | // TODO: Check and clear more flags | 31 | // TODO: Check and clear more flags |
| 32 | unsafe { | 32 | let dma = ETH.ethernet_dma(); |
| 33 | let dma = ETH.ethernet_dma(); | 33 | |
| 34 | 34 | dma.dmasr().modify(|w| { | |
| 35 | dma.dmasr().modify(|w| { | 35 | w.set_ts(true); |
| 36 | w.set_ts(true); | 36 | w.set_rs(true); |
| 37 | w.set_rs(true); | 37 | w.set_nis(true); |
| 38 | w.set_nis(true); | 38 | }); |
| 39 | }); | 39 | // Delay two peripheral's clock |
| 40 | // Delay two peripheral's clock | 40 | dma.dmasr().read(); |
| 41 | dma.dmasr().read(); | 41 | dma.dmasr().read(); |
| 42 | dma.dmasr().read(); | ||
| 43 | } | ||
| 44 | } | 42 | } |
| 45 | } | 43 | } |
| 46 | 44 | ||
| @@ -59,7 +57,6 @@ pub struct Ethernet<'d, T: Instance, P: PHY> { | |||
| 59 | #[cfg(eth_v1a)] | 57 | #[cfg(eth_v1a)] |
| 60 | macro_rules! config_in_pins { | 58 | macro_rules! config_in_pins { |
| 61 | ($($pin:ident),*) => { | 59 | ($($pin:ident),*) => { |
| 62 | // NOTE(unsafe) Exclusive access to the registers | ||
| 63 | critical_section::with(|_| { | 60 | critical_section::with(|_| { |
| 64 | $( | 61 | $( |
| 65 | // TODO properly create a set_as_input function | 62 | // TODO properly create a set_as_input function |
| @@ -72,7 +69,6 @@ macro_rules! config_in_pins { | |||
| 72 | #[cfg(eth_v1a)] | 69 | #[cfg(eth_v1a)] |
| 73 | macro_rules! config_af_pins { | 70 | macro_rules! config_af_pins { |
| 74 | ($($pin:ident),*) => { | 71 | ($($pin:ident),*) => { |
| 75 | // NOTE(unsafe) Exclusive access to the registers | ||
| 76 | critical_section::with(|_| { | 72 | critical_section::with(|_| { |
| 77 | $( | 73 | $( |
| 78 | // We are lucky here, this configures to max speed (50MHz) | 74 | // We are lucky here, this configures to max speed (50MHz) |
| @@ -85,7 +81,6 @@ macro_rules! config_af_pins { | |||
| 85 | #[cfg(any(eth_v1b, eth_v1c))] | 81 | #[cfg(any(eth_v1b, eth_v1c))] |
| 86 | macro_rules! config_pins { | 82 | macro_rules! config_pins { |
| 87 | ($($pin:ident),*) => { | 83 | ($($pin:ident),*) => { |
| 88 | // NOTE(unsafe) Exclusive access to the registers | ||
| 89 | critical_section::with(|_| { | 84 | critical_section::with(|_| { |
| 90 | $( | 85 | $( |
| 91 | $pin.set_as_af($pin.af_num(), AFType::OutputPushPull); | 86 | $pin.set_as_af($pin.af_num(), AFType::OutputPushPull); |
| @@ -116,222 +111,208 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { | |||
| 116 | ) -> Self { | 111 | ) -> Self { |
| 117 | into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); | 112 | into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); |
| 118 | 113 | ||
| 119 | unsafe { | 114 | // Enable the necessary Clocks |
| 120 | // Enable the necessary Clocks | 115 | #[cfg(eth_v1a)] |
| 121 | // NOTE(unsafe) We have exclusive access to the registers | 116 | critical_section::with(|_| { |
| 122 | #[cfg(eth_v1a)] | 117 | RCC.apb2enr().modify(|w| w.set_afioen(true)); |
| 123 | critical_section::with(|_| { | ||
| 124 | RCC.apb2enr().modify(|w| w.set_afioen(true)); | ||
| 125 | |||
| 126 | // Select RMII (Reduced Media Independent Interface) | ||
| 127 | // Must be done prior to enabling peripheral clock | ||
| 128 | AFIO.mapr().modify(|w| w.set_mii_rmii_sel(true)); | ||
| 129 | |||
| 130 | RCC.ahbenr().modify(|w| { | ||
| 131 | w.set_ethen(true); | ||
| 132 | w.set_ethtxen(true); | ||
| 133 | w.set_ethrxen(true); | ||
| 134 | }); | ||
| 135 | }); | ||
| 136 | |||
| 137 | #[cfg(any(eth_v1b, eth_v1c))] | ||
| 138 | critical_section::with(|_| { | ||
| 139 | RCC.apb2enr().modify(|w| w.set_syscfgen(true)); | ||
| 140 | RCC.ahb1enr().modify(|w| { | ||
| 141 | w.set_ethen(true); | ||
| 142 | w.set_ethtxen(true); | ||
| 143 | w.set_ethrxen(true); | ||
| 144 | }); | ||
| 145 | |||
| 146 | // RMII (Reduced Media Independent Interface) | ||
| 147 | SYSCFG.pmc().modify(|w| w.set_mii_rmii_sel(true)); | ||
| 148 | }); | ||
| 149 | |||
| 150 | #[cfg(eth_v1a)] | ||
| 151 | { | ||
| 152 | config_in_pins!(ref_clk, rx_d0, rx_d1); | ||
| 153 | config_af_pins!(mdio, mdc, tx_d0, tx_d1, tx_en); | ||
| 154 | } | ||
| 155 | |||
| 156 | #[cfg(any(eth_v1b, eth_v1c))] | ||
| 157 | config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); | ||
| 158 | |||
| 159 | // NOTE(unsafe) We have exclusive access to the registers | ||
| 160 | let dma = ETH.ethernet_dma(); | ||
| 161 | let mac = ETH.ethernet_mac(); | ||
| 162 | |||
| 163 | // Reset and wait | ||
| 164 | dma.dmabmr().modify(|w| w.set_sr(true)); | ||
| 165 | while dma.dmabmr().read().sr() {} | ||
| 166 | |||
| 167 | mac.maccr().modify(|w| { | ||
| 168 | w.set_ifg(Ifg::IFG96); // inter frame gap 96 bit times | ||
| 169 | w.set_apcs(Apcs::STRIP); // automatic padding and crc stripping | ||
| 170 | w.set_fes(Fes::FES100); // fast ethernet speed | ||
| 171 | w.set_dm(Dm::FULLDUPLEX); // full duplex | ||
| 172 | // TODO: Carrier sense ? ECRSFD | ||
| 173 | }); | ||
| 174 | |||
| 175 | // Note: Writing to LR triggers synchronisation of both LR and HR into the MAC core, | ||
| 176 | // so the LR write must happen after the HR write. | ||
| 177 | mac.maca0hr() | ||
| 178 | .modify(|w| w.set_maca0h(u16::from(mac_addr[4]) | (u16::from(mac_addr[5]) << 8))); | ||
| 179 | mac.maca0lr().write(|w| { | ||
| 180 | w.set_maca0l( | ||
| 181 | u32::from(mac_addr[0]) | ||
| 182 | | (u32::from(mac_addr[1]) << 8) | ||
| 183 | | (u32::from(mac_addr[2]) << 16) | ||
| 184 | | (u32::from(mac_addr[3]) << 24), | ||
| 185 | ) | ||
| 186 | }); | ||
| 187 | |||
| 188 | // pause time | ||
| 189 | mac.macfcr().modify(|w| w.set_pt(0x100)); | ||
| 190 | |||
| 191 | // Transfer and Forward, Receive and Forward | ||
| 192 | dma.dmaomr().modify(|w| { | ||
| 193 | w.set_tsf(Tsf::STOREFORWARD); | ||
| 194 | w.set_rsf(Rsf::STOREFORWARD); | ||
| 195 | }); | ||
| 196 | 118 | ||
| 197 | dma.dmabmr().modify(|w| { | 119 | // Select RMII (Reduced Media Independent Interface) |
| 198 | w.set_pbl(Pbl::PBL32) // programmable burst length - 32 ? | 120 | // Must be done prior to enabling peripheral clock |
| 199 | }); | 121 | AFIO.mapr().modify(|w| w.set_mii_rmii_sel(true)); |
| 200 | 122 | ||
| 201 | // TODO MTU size setting not found for v1 ethernet, check if correct | 123 | RCC.ahbenr().modify(|w| { |
| 202 | 124 | w.set_ethen(true); | |
| 203 | // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called | 125 | w.set_ethtxen(true); |
| 204 | let hclk = crate::rcc::get_freqs().ahb1; | 126 | w.set_ethrxen(true); |
| 205 | let hclk_mhz = hclk.0 / 1_000_000; | ||
| 206 | |||
| 207 | // Set the MDC clock frequency in the range 1MHz - 2.5MHz | ||
| 208 | let clock_range = match hclk_mhz { | ||
| 209 | 0..=24 => panic!("Invalid HCLK frequency - should be at least 25 MHz."), | ||
| 210 | 25..=34 => Cr::CR_20_35, // Divide by 16 | ||
| 211 | 35..=59 => Cr::CR_35_60, // Divide by 26 | ||
| 212 | 60..=99 => Cr::CR_60_100, // Divide by 42 | ||
| 213 | 100..=149 => Cr::CR_100_150, // Divide by 62 | ||
| 214 | 150..=216 => Cr::CR_150_168, // Divide by 102 | ||
| 215 | _ => { | ||
| 216 | panic!("HCLK results in MDC clock > 2.5MHz even for the highest CSR clock divider") | ||
| 217 | } | ||
| 218 | }; | ||
| 219 | |||
| 220 | let pins = [ | ||
| 221 | ref_clk.map_into(), | ||
| 222 | mdio.map_into(), | ||
| 223 | mdc.map_into(), | ||
| 224 | crs.map_into(), | ||
| 225 | rx_d0.map_into(), | ||
| 226 | rx_d1.map_into(), | ||
| 227 | tx_d0.map_into(), | ||
| 228 | tx_d1.map_into(), | ||
| 229 | tx_en.map_into(), | ||
| 230 | ]; | ||
| 231 | |||
| 232 | let mut this = Self { | ||
| 233 | _peri: peri, | ||
| 234 | pins, | ||
| 235 | _phy: phy, | ||
| 236 | clock_range, | ||
| 237 | phy_addr, | ||
| 238 | mac_addr, | ||
| 239 | tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), | ||
| 240 | rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), | ||
| 241 | }; | ||
| 242 | |||
| 243 | fence(Ordering::SeqCst); | ||
| 244 | |||
| 245 | let mac = ETH.ethernet_mac(); | ||
| 246 | let dma = ETH.ethernet_dma(); | ||
| 247 | |||
| 248 | mac.maccr().modify(|w| { | ||
| 249 | w.set_re(true); | ||
| 250 | w.set_te(true); | ||
| 251 | }); | ||
| 252 | dma.dmaomr().modify(|w| { | ||
| 253 | w.set_ftf(Ftf::FLUSH); // flush transmit fifo (queue) | ||
| 254 | w.set_st(St::STARTED); // start transmitting channel | ||
| 255 | w.set_sr(DmaomrSr::STARTED); // start receiving channel | ||
| 256 | }); | 127 | }); |
| 128 | }); | ||
| 257 | 129 | ||
| 258 | this.rx.demand_poll(); | 130 | #[cfg(any(eth_v1b, eth_v1c))] |
| 259 | 131 | critical_section::with(|_| { | |
| 260 | // Enable interrupts | 132 | RCC.apb2enr().modify(|w| w.set_syscfgen(true)); |
| 261 | dma.dmaier().modify(|w| { | 133 | RCC.ahb1enr().modify(|w| { |
| 262 | w.set_nise(true); | 134 | w.set_ethen(true); |
| 263 | w.set_rie(true); | 135 | w.set_ethtxen(true); |
| 264 | w.set_tie(true); | 136 | w.set_ethrxen(true); |
| 265 | }); | 137 | }); |
| 266 | 138 | ||
| 267 | P::phy_reset(&mut this); | 139 | // RMII (Reduced Media Independent Interface) |
| 268 | P::phy_init(&mut this); | 140 | SYSCFG.pmc().modify(|w| w.set_mii_rmii_sel(true)); |
| 141 | }); | ||
| 269 | 142 | ||
| 270 | interrupt::ETH.unpend(); | 143 | #[cfg(eth_v1a)] |
| 271 | interrupt::ETH.enable(); | 144 | { |
| 272 | 145 | config_in_pins!(ref_clk, rx_d0, rx_d1); | |
| 273 | this | 146 | config_af_pins!(mdio, mdc, tx_d0, tx_d1, tx_en); |
| 274 | } | 147 | } |
| 148 | |||
| 149 | #[cfg(any(eth_v1b, eth_v1c))] | ||
| 150 | config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); | ||
| 151 | |||
| 152 | let dma = ETH.ethernet_dma(); | ||
| 153 | let mac = ETH.ethernet_mac(); | ||
| 154 | |||
| 155 | // Reset and wait | ||
| 156 | dma.dmabmr().modify(|w| w.set_sr(true)); | ||
| 157 | while dma.dmabmr().read().sr() {} | ||
| 158 | |||
| 159 | mac.maccr().modify(|w| { | ||
| 160 | w.set_ifg(Ifg::IFG96); // inter frame gap 96 bit times | ||
| 161 | w.set_apcs(Apcs::STRIP); // automatic padding and crc stripping | ||
| 162 | w.set_fes(Fes::FES100); // fast ethernet speed | ||
| 163 | w.set_dm(Dm::FULLDUPLEX); // full duplex | ||
| 164 | // TODO: Carrier sense ? ECRSFD | ||
| 165 | }); | ||
| 166 | |||
| 167 | // Note: Writing to LR triggers synchronisation of both LR and HR into the MAC core, | ||
| 168 | // so the LR write must happen after the HR write. | ||
| 169 | mac.maca0hr() | ||
| 170 | .modify(|w| w.set_maca0h(u16::from(mac_addr[4]) | (u16::from(mac_addr[5]) << 8))); | ||
| 171 | mac.maca0lr().write(|w| { | ||
| 172 | w.set_maca0l( | ||
| 173 | u32::from(mac_addr[0]) | ||
| 174 | | (u32::from(mac_addr[1]) << 8) | ||
| 175 | | (u32::from(mac_addr[2]) << 16) | ||
| 176 | | (u32::from(mac_addr[3]) << 24), | ||
| 177 | ) | ||
| 178 | }); | ||
| 179 | |||
| 180 | // pause time | ||
| 181 | mac.macfcr().modify(|w| w.set_pt(0x100)); | ||
| 182 | |||
| 183 | // Transfer and Forward, Receive and Forward | ||
| 184 | dma.dmaomr().modify(|w| { | ||
| 185 | w.set_tsf(Tsf::STOREFORWARD); | ||
| 186 | w.set_rsf(Rsf::STOREFORWARD); | ||
| 187 | }); | ||
| 188 | |||
| 189 | dma.dmabmr().modify(|w| { | ||
| 190 | w.set_pbl(Pbl::PBL32) // programmable burst length - 32 ? | ||
| 191 | }); | ||
| 192 | |||
| 193 | // TODO MTU size setting not found for v1 ethernet, check if correct | ||
| 194 | |||
| 195 | // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called | ||
| 196 | let hclk = unsafe { crate::rcc::get_freqs() }.ahb1; | ||
| 197 | let hclk_mhz = hclk.0 / 1_000_000; | ||
| 198 | |||
| 199 | // Set the MDC clock frequency in the range 1MHz - 2.5MHz | ||
| 200 | let clock_range = match hclk_mhz { | ||
| 201 | 0..=24 => panic!("Invalid HCLK frequency - should be at least 25 MHz."), | ||
| 202 | 25..=34 => Cr::CR_20_35, // Divide by 16 | ||
| 203 | 35..=59 => Cr::CR_35_60, // Divide by 26 | ||
| 204 | 60..=99 => Cr::CR_60_100, // Divide by 42 | ||
| 205 | 100..=149 => Cr::CR_100_150, // Divide by 62 | ||
| 206 | 150..=216 => Cr::CR_150_168, // Divide by 102 | ||
| 207 | _ => { | ||
| 208 | panic!("HCLK results in MDC clock > 2.5MHz even for the highest CSR clock divider") | ||
| 209 | } | ||
| 210 | }; | ||
| 211 | |||
| 212 | let pins = [ | ||
| 213 | ref_clk.map_into(), | ||
| 214 | mdio.map_into(), | ||
| 215 | mdc.map_into(), | ||
| 216 | crs.map_into(), | ||
| 217 | rx_d0.map_into(), | ||
| 218 | rx_d1.map_into(), | ||
| 219 | tx_d0.map_into(), | ||
| 220 | tx_d1.map_into(), | ||
| 221 | tx_en.map_into(), | ||
| 222 | ]; | ||
| 223 | |||
| 224 | let mut this = Self { | ||
| 225 | _peri: peri, | ||
| 226 | pins, | ||
| 227 | _phy: phy, | ||
| 228 | clock_range, | ||
| 229 | phy_addr, | ||
| 230 | mac_addr, | ||
| 231 | tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), | ||
| 232 | rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), | ||
| 233 | }; | ||
| 234 | |||
| 235 | fence(Ordering::SeqCst); | ||
| 236 | |||
| 237 | let mac = ETH.ethernet_mac(); | ||
| 238 | let dma = ETH.ethernet_dma(); | ||
| 239 | |||
| 240 | mac.maccr().modify(|w| { | ||
| 241 | w.set_re(true); | ||
| 242 | w.set_te(true); | ||
| 243 | }); | ||
| 244 | dma.dmaomr().modify(|w| { | ||
| 245 | w.set_ftf(Ftf::FLUSH); // flush transmit fifo (queue) | ||
| 246 | w.set_st(St::STARTED); // start transmitting channel | ||
| 247 | w.set_sr(DmaomrSr::STARTED); // start receiving channel | ||
| 248 | }); | ||
| 249 | |||
| 250 | this.rx.demand_poll(); | ||
| 251 | |||
| 252 | // Enable interrupts | ||
| 253 | dma.dmaier().modify(|w| { | ||
| 254 | w.set_nise(true); | ||
| 255 | w.set_rie(true); | ||
| 256 | w.set_tie(true); | ||
| 257 | }); | ||
| 258 | |||
| 259 | P::phy_reset(&mut this); | ||
| 260 | P::phy_init(&mut this); | ||
| 261 | |||
| 262 | interrupt::ETH.unpend(); | ||
| 263 | unsafe { interrupt::ETH.enable() }; | ||
| 264 | |||
| 265 | this | ||
| 275 | } | 266 | } |
| 276 | } | 267 | } |
| 277 | 268 | ||
| 278 | unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> { | 269 | unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> { |
| 279 | fn smi_read(&mut self, reg: u8) -> u16 { | 270 | fn smi_read(&mut self, reg: u8) -> u16 { |
| 280 | // NOTE(unsafe) These registers aren't used in the interrupt and we have `&mut self` | 271 | let mac = ETH.ethernet_mac(); |
| 281 | unsafe { | 272 | |
| 282 | let mac = ETH.ethernet_mac(); | 273 | mac.macmiiar().modify(|w| { |
| 283 | 274 | w.set_pa(self.phy_addr); | |
| 284 | mac.macmiiar().modify(|w| { | 275 | w.set_mr(reg); |
| 285 | w.set_pa(self.phy_addr); | 276 | w.set_mw(Mw::READ); // read operation |
| 286 | w.set_mr(reg); | 277 | w.set_cr(self.clock_range); |
| 287 | w.set_mw(Mw::READ); // read operation | 278 | w.set_mb(MbProgress::BUSY); // indicate that operation is in progress |
| 288 | w.set_cr(self.clock_range); | 279 | }); |
| 289 | w.set_mb(MbProgress::BUSY); // indicate that operation is in progress | 280 | while mac.macmiiar().read().mb() == MbProgress::BUSY {} |
| 290 | }); | 281 | mac.macmiidr().read().md() |
| 291 | while mac.macmiiar().read().mb() == MbProgress::BUSY {} | ||
| 292 | mac.macmiidr().read().md() | ||
| 293 | } | ||
| 294 | } | 282 | } |
| 295 | 283 | ||
| 296 | fn smi_write(&mut self, reg: u8, val: u16) { | 284 | fn smi_write(&mut self, reg: u8, val: u16) { |
| 297 | // NOTE(unsafe) These registers aren't used in the interrupt and we have `&mut self` | 285 | let mac = ETH.ethernet_mac(); |
| 298 | unsafe { | 286 | |
| 299 | let mac = ETH.ethernet_mac(); | 287 | mac.macmiidr().write(|w| w.set_md(val)); |
| 300 | 288 | mac.macmiiar().modify(|w| { | |
| 301 | mac.macmiidr().write(|w| w.set_md(val)); | 289 | w.set_pa(self.phy_addr); |
| 302 | mac.macmiiar().modify(|w| { | 290 | w.set_mr(reg); |
| 303 | w.set_pa(self.phy_addr); | 291 | w.set_mw(Mw::WRITE); // write |
| 304 | w.set_mr(reg); | 292 | w.set_cr(self.clock_range); |
| 305 | w.set_mw(Mw::WRITE); // write | 293 | w.set_mb(MbProgress::BUSY); |
| 306 | w.set_cr(self.clock_range); | 294 | }); |
| 307 | w.set_mb(MbProgress::BUSY); | 295 | while mac.macmiiar().read().mb() == MbProgress::BUSY {} |
| 308 | }); | ||
| 309 | while mac.macmiiar().read().mb() == MbProgress::BUSY {} | ||
| 310 | } | ||
| 311 | } | 296 | } |
| 312 | } | 297 | } |
| 313 | 298 | ||
| 314 | impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { | 299 | impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { |
| 315 | fn drop(&mut self) { | 300 | fn drop(&mut self) { |
| 316 | // NOTE(unsafe) We have `&mut self` and the interrupt doesn't use this registers | 301 | let dma = ETH.ethernet_dma(); |
| 317 | unsafe { | 302 | let mac = ETH.ethernet_mac(); |
| 318 | let dma = ETH.ethernet_dma(); | ||
| 319 | let mac = ETH.ethernet_mac(); | ||
| 320 | |||
| 321 | // Disable the TX DMA and wait for any previous transmissions to be completed | ||
| 322 | dma.dmaomr().modify(|w| w.set_st(St::STOPPED)); | ||
| 323 | |||
| 324 | // Disable MAC transmitter and receiver | ||
| 325 | mac.maccr().modify(|w| { | ||
| 326 | w.set_re(false); | ||
| 327 | w.set_te(false); | ||
| 328 | }); | ||
| 329 | 303 | ||
| 330 | dma.dmaomr().modify(|w| w.set_sr(DmaomrSr::STOPPED)); | 304 | // Disable the TX DMA and wait for any previous transmissions to be completed |
| 331 | } | 305 | dma.dmaomr().modify(|w| w.set_st(St::STOPPED)); |
| 306 | |||
| 307 | // Disable MAC transmitter and receiver | ||
| 308 | mac.maccr().modify(|w| { | ||
| 309 | w.set_re(false); | ||
| 310 | w.set_te(false); | ||
| 311 | }); | ||
| 332 | 312 | ||
| 333 | // NOTE(unsafe) Exclusive access to the regs | 313 | dma.dmaomr().modify(|w| w.set_sr(DmaomrSr::STOPPED)); |
| 334 | critical_section::with(|_| unsafe { | 314 | |
| 315 | critical_section::with(|_| { | ||
| 335 | for pin in self.pins.iter_mut() { | 316 | for pin in self.pins.iter_mut() { |
| 336 | pin.set_as_disconnected(); | 317 | pin.set_as_disconnected(); |
| 337 | } | 318 | } |
diff --git a/embassy-stm32/src/eth/v1/rx_desc.rs b/embassy-stm32/src/eth/v1/rx_desc.rs index 8b8566d92..01a073bb9 100644 --- a/embassy-stm32/src/eth/v1/rx_desc.rs +++ b/embassy-stm32/src/eth/v1/rx_desc.rs | |||
| @@ -146,12 +146,9 @@ impl<'a> RDesRing<'a> { | |||
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | // Register rx descriptor start | 148 | // Register rx descriptor start |
| 149 | // NOTE (unsafe) Used for atomic writes | 149 | ETH.ethernet_dma() |
| 150 | unsafe { | 150 | .dmardlar() |
| 151 | ETH.ethernet_dma() | 151 | .write(|w| w.0 = descriptors.as_ptr() as u32); |
| 152 | .dmardlar() | ||
| 153 | .write(|w| w.0 = descriptors.as_ptr() as u32); | ||
| 154 | }; | ||
| 155 | // We already have fences in `set_owned`, which is called in `setup` | 152 | // We already have fences in `set_owned`, which is called in `setup` |
| 156 | 153 | ||
| 157 | Self { | 154 | Self { |
| @@ -162,12 +159,12 @@ impl<'a> RDesRing<'a> { | |||
| 162 | } | 159 | } |
| 163 | 160 | ||
| 164 | pub(crate) fn demand_poll(&self) { | 161 | pub(crate) fn demand_poll(&self) { |
| 165 | unsafe { ETH.ethernet_dma().dmarpdr().write(|w| w.set_rpd(Rpd::POLL)) }; | 162 | ETH.ethernet_dma().dmarpdr().write(|w| w.set_rpd(Rpd::POLL)); |
| 166 | } | 163 | } |
| 167 | 164 | ||
| 168 | /// Get current `RunningState` | 165 | /// Get current `RunningState` |
| 169 | fn running_state(&self) -> RunningState { | 166 | fn running_state(&self) -> RunningState { |
| 170 | match unsafe { ETH.ethernet_dma().dmasr().read().rps() } { | 167 | match ETH.ethernet_dma().dmasr().read().rps() { |
| 171 | // Reset or Stop Receive Command issued | 168 | // Reset or Stop Receive Command issued |
| 172 | Rps::STOPPED => RunningState::Stopped, | 169 | Rps::STOPPED => RunningState::Stopped, |
| 173 | // Fetching receive transfer descriptor | 170 | // Fetching receive transfer descriptor |
diff --git a/embassy-stm32/src/eth/v1/tx_desc.rs b/embassy-stm32/src/eth/v1/tx_desc.rs index 0e63c5443..1317d20f4 100644 --- a/embassy-stm32/src/eth/v1/tx_desc.rs +++ b/embassy-stm32/src/eth/v1/tx_desc.rs | |||
| @@ -120,12 +120,9 @@ impl<'a> TDesRing<'a> { | |||
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | // Register txdescriptor start | 122 | // Register txdescriptor start |
| 123 | // NOTE (unsafe) Used for atomic writes | 123 | ETH.ethernet_dma() |
| 124 | unsafe { | 124 | .dmatdlar() |
| 125 | ETH.ethernet_dma() | 125 | .write(|w| w.0 = descriptors.as_ptr() as u32); |
| 126 | .dmatdlar() | ||
| 127 | .write(|w| w.0 = descriptors.as_ptr() as u32); | ||
| 128 | } | ||
| 129 | 126 | ||
| 130 | Self { | 127 | Self { |
| 131 | descriptors, | 128 | descriptors, |
| @@ -169,6 +166,6 @@ impl<'a> TDesRing<'a> { | |||
| 169 | self.index = 0 | 166 | self.index = 0 |
| 170 | } | 167 | } |
| 171 | // Request the DMA engine to poll the latest tx descriptor | 168 | // Request the DMA engine to poll the latest tx descriptor |
| 172 | unsafe { ETH.ethernet_dma().dmatpdr().modify(|w| w.0 = 1) } | 169 | ETH.ethernet_dma().dmatpdr().modify(|w| w.0 = 1) |
| 173 | } | 170 | } |
| 174 | } | 171 | } |
diff --git a/embassy-stm32/src/eth/v2/descriptors.rs b/embassy-stm32/src/eth/v2/descriptors.rs index 2426596fb..e9799adf1 100644 --- a/embassy-stm32/src/eth/v2/descriptors.rs +++ b/embassy-stm32/src/eth/v2/descriptors.rs | |||
| @@ -73,14 +73,10 @@ impl<'a> TDesRing<'a> { | |||
| 73 | 73 | ||
| 74 | // Initialize the pointers in the DMA engine. (There will be a memory barrier later | 74 | // Initialize the pointers in the DMA engine. (There will be a memory barrier later |
| 75 | // before the DMA engine is enabled.) | 75 | // before the DMA engine is enabled.) |
| 76 | // NOTE (unsafe) Used for atomic writes | 76 | let dma = ETH.ethernet_dma(); |
| 77 | unsafe { | 77 | dma.dmactx_dlar().write(|w| w.0 = descriptors.as_mut_ptr() as u32); |
| 78 | let dma = ETH.ethernet_dma(); | 78 | dma.dmactx_rlr().write(|w| w.set_tdrl((descriptors.len() as u16) - 1)); |
| 79 | 79 | dma.dmactx_dtpr().write(|w| w.0 = 0); | |
| 80 | dma.dmactx_dlar().write(|w| w.0 = descriptors.as_mut_ptr() as u32); | ||
| 81 | dma.dmactx_rlr().write(|w| w.set_tdrl((descriptors.len() as u16) - 1)); | ||
| 82 | dma.dmactx_dtpr().write(|w| w.0 = 0); | ||
| 83 | } | ||
| 84 | 80 | ||
| 85 | Self { | 81 | Self { |
| 86 | descriptors, | 82 | descriptors, |
| @@ -129,8 +125,7 @@ impl<'a> TDesRing<'a> { | |||
| 129 | } | 125 | } |
| 130 | 126 | ||
| 131 | // signal DMA it can try again. | 127 | // signal DMA it can try again. |
| 132 | // NOTE(unsafe) Atomic write | 128 | ETH.ethernet_dma().dmactx_dtpr().write(|w| w.0 = 0) |
| 133 | unsafe { ETH.ethernet_dma().dmactx_dtpr().write(|w| w.0 = 0) } | ||
| 134 | } | 129 | } |
| 135 | } | 130 | } |
| 136 | 131 | ||
| @@ -199,13 +194,10 @@ impl<'a> RDesRing<'a> { | |||
| 199 | desc.set_ready(buffers[i].0.as_mut_ptr()); | 194 | desc.set_ready(buffers[i].0.as_mut_ptr()); |
| 200 | } | 195 | } |
| 201 | 196 | ||
| 202 | unsafe { | 197 | let dma = ETH.ethernet_dma(); |
| 203 | let dma = ETH.ethernet_dma(); | 198 | dma.dmacrx_dlar().write(|w| w.0 = descriptors.as_mut_ptr() as u32); |
| 204 | 199 | dma.dmacrx_rlr().write(|w| w.set_rdrl((descriptors.len() as u16) - 1)); | |
| 205 | dma.dmacrx_dlar().write(|w| w.0 = descriptors.as_mut_ptr() as u32); | 200 | dma.dmacrx_dtpr().write(|w| w.0 = 0); |
| 206 | dma.dmacrx_rlr().write(|w| w.set_rdrl((descriptors.len() as u16) - 1)); | ||
| 207 | dma.dmacrx_dtpr().write(|w| w.0 = 0); | ||
| 208 | } | ||
| 209 | 201 | ||
| 210 | Self { | 202 | Self { |
| 211 | descriptors, | 203 | descriptors, |
| @@ -254,8 +246,7 @@ impl<'a> RDesRing<'a> { | |||
| 254 | fence(Ordering::Release); | 246 | fence(Ordering::Release); |
| 255 | 247 | ||
| 256 | // signal DMA it can try again. | 248 | // signal DMA it can try again. |
| 257 | // NOTE(unsafe) Atomic write | 249 | ETH.ethernet_dma().dmacrx_dtpr().write(|w| w.0 = 0); |
| 258 | unsafe { ETH.ethernet_dma().dmacrx_dtpr().write(|w| w.0 = 0) } | ||
| 259 | 250 | ||
| 260 | // Increment index. | 251 | // Increment index. |
| 261 | self.index += 1; | 252 | self.index += 1; |
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs index 3e45eafd5..600e1d3bc 100644 --- a/embassy-stm32/src/eth/v2/mod.rs +++ b/embassy-stm32/src/eth/v2/mod.rs | |||
| @@ -20,18 +20,16 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::ETH> for InterruptHandl | |||
| 20 | WAKER.wake(); | 20 | WAKER.wake(); |
| 21 | 21 | ||
| 22 | // TODO: Check and clear more flags | 22 | // TODO: Check and clear more flags |
| 23 | unsafe { | 23 | let dma = ETH.ethernet_dma(); |
| 24 | let dma = ETH.ethernet_dma(); | 24 | |
| 25 | 25 | dma.dmacsr().modify(|w| { | |
| 26 | dma.dmacsr().modify(|w| { | 26 | w.set_ti(true); |
| 27 | w.set_ti(true); | 27 | w.set_ri(true); |
| 28 | w.set_ri(true); | 28 | w.set_nis(true); |
| 29 | w.set_nis(true); | 29 | }); |
| 30 | }); | 30 | // Delay two peripheral's clock |
| 31 | // Delay two peripheral's clock | 31 | dma.dmacsr().read(); |
| 32 | dma.dmacsr().read(); | 32 | dma.dmacsr().read(); |
| 33 | dma.dmacsr().read(); | ||
| 34 | } | ||
| 35 | } | 33 | } |
| 36 | } | 34 | } |
| 37 | 35 | ||
| @@ -50,7 +48,6 @@ pub struct Ethernet<'d, T: Instance, P: PHY> { | |||
| 50 | 48 | ||
| 51 | macro_rules! config_pins { | 49 | macro_rules! config_pins { |
| 52 | ($($pin:ident),*) => { | 50 | ($($pin:ident),*) => { |
| 53 | // NOTE(unsafe) Exclusive access to the registers | ||
| 54 | critical_section::with(|_| { | 51 | critical_section::with(|_| { |
| 55 | $( | 52 | $( |
| 56 | $pin.set_as_af($pin.af_num(), AFType::OutputPushPull); | 53 | $pin.set_as_af($pin.af_num(), AFType::OutputPushPull); |
| @@ -80,239 +77,225 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { | |||
| 80 | ) -> Self { | 77 | ) -> Self { |
| 81 | into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); | 78 | into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); |
| 82 | 79 | ||
| 83 | unsafe { | 80 | // Enable the necessary Clocks |
| 84 | // Enable the necessary Clocks | 81 | #[cfg(not(rcc_h5))] |
| 85 | // NOTE(unsafe) We have exclusive access to the registers | 82 | critical_section::with(|_| { |
| 86 | #[cfg(not(rcc_h5))] | 83 | crate::pac::RCC.apb4enr().modify(|w| w.set_syscfgen(true)); |
| 87 | critical_section::with(|_| { | 84 | crate::pac::RCC.ahb1enr().modify(|w| { |
| 88 | crate::pac::RCC.apb4enr().modify(|w| w.set_syscfgen(true)); | 85 | w.set_eth1macen(true); |
| 89 | crate::pac::RCC.ahb1enr().modify(|w| { | 86 | w.set_eth1txen(true); |
| 90 | w.set_eth1macen(true); | 87 | w.set_eth1rxen(true); |
| 91 | w.set_eth1txen(true); | ||
| 92 | w.set_eth1rxen(true); | ||
| 93 | }); | ||
| 94 | |||
| 95 | // RMII | ||
| 96 | crate::pac::SYSCFG.pmcr().modify(|w| w.set_epis(0b100)); | ||
| 97 | }); | ||
| 98 | |||
| 99 | #[cfg(rcc_h5)] | ||
| 100 | critical_section::with(|_| { | ||
| 101 | crate::pac::RCC.apb3enr().modify(|w| w.set_sbsen(true)); | ||
| 102 | |||
| 103 | crate::pac::RCC.ahb1enr().modify(|w| { | ||
| 104 | w.set_ethen(true); | ||
| 105 | w.set_ethtxen(true); | ||
| 106 | w.set_ethrxen(true); | ||
| 107 | }); | ||
| 108 | |||
| 109 | // RMII | ||
| 110 | crate::pac::SBS | ||
| 111 | .pmcr() | ||
| 112 | .modify(|w| w.set_eth_sel_phy(crate::pac::sbs::vals::EthSelPhy::B_0X4)); | ||
| 113 | }); | ||
| 114 | |||
| 115 | config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); | ||
| 116 | |||
| 117 | // NOTE(unsafe) We have exclusive access to the registers | ||
| 118 | let dma = ETH.ethernet_dma(); | ||
| 119 | let mac = ETH.ethernet_mac(); | ||
| 120 | let mtl = ETH.ethernet_mtl(); | ||
| 121 | |||
| 122 | // Reset and wait | ||
| 123 | dma.dmamr().modify(|w| w.set_swr(true)); | ||
| 124 | while dma.dmamr().read().swr() {} | ||
| 125 | |||
| 126 | mac.maccr().modify(|w| { | ||
| 127 | w.set_ipg(0b000); // 96 bit times | ||
| 128 | w.set_acs(true); | ||
| 129 | w.set_fes(true); | ||
| 130 | w.set_dm(true); | ||
| 131 | // TODO: Carrier sense ? ECRSFD | ||
| 132 | }); | ||
| 133 | |||
| 134 | // Note: Writing to LR triggers synchronisation of both LR and HR into the MAC core, | ||
| 135 | // so the LR write must happen after the HR write. | ||
| 136 | mac.maca0hr() | ||
| 137 | .modify(|w| w.set_addrhi(u16::from(mac_addr[4]) | (u16::from(mac_addr[5]) << 8))); | ||
| 138 | mac.maca0lr().write(|w| { | ||
| 139 | w.set_addrlo( | ||
| 140 | u32::from(mac_addr[0]) | ||
| 141 | | (u32::from(mac_addr[1]) << 8) | ||
| 142 | | (u32::from(mac_addr[2]) << 16) | ||
| 143 | | (u32::from(mac_addr[3]) << 24), | ||
| 144 | ) | ||
| 145 | }); | ||
| 146 | |||
| 147 | mac.macqtx_fcr().modify(|w| w.set_pt(0x100)); | ||
| 148 | |||
| 149 | // disable all MMC RX interrupts | ||
| 150 | mac.mmc_rx_interrupt_mask().write(|w| { | ||
| 151 | w.set_rxcrcerpim(true); | ||
| 152 | w.set_rxalgnerpim(true); | ||
| 153 | w.set_rxucgpim(true); | ||
| 154 | w.set_rxlpiuscim(true); | ||
| 155 | w.set_rxlpitrcim(true) | ||
| 156 | }); | ||
| 157 | |||
| 158 | // disable all MMC TX interrupts | ||
| 159 | mac.mmc_tx_interrupt_mask().write(|w| { | ||
| 160 | w.set_txscolgpim(true); | ||
| 161 | w.set_txmcolgpim(true); | ||
| 162 | w.set_txgpktim(true); | ||
| 163 | w.set_txlpiuscim(true); | ||
| 164 | w.set_txlpitrcim(true); | ||
| 165 | }); | ||
| 166 | |||
| 167 | mtl.mtlrx_qomr().modify(|w| w.set_rsf(true)); | ||
| 168 | mtl.mtltx_qomr().modify(|w| w.set_tsf(true)); | ||
| 169 | |||
| 170 | dma.dmactx_cr().modify(|w| w.set_txpbl(1)); // 32 ? | ||
| 171 | dma.dmacrx_cr().modify(|w| { | ||
| 172 | w.set_rxpbl(1); // 32 ? | ||
| 173 | w.set_rbsz(MTU as u16); | ||
| 174 | }); | 88 | }); |
| 175 | 89 | ||
| 176 | // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called | 90 | // RMII |
| 177 | let hclk = crate::rcc::get_freqs().ahb1; | 91 | crate::pac::SYSCFG.pmcr().modify(|w| w.set_epis(0b100)); |
| 178 | let hclk_mhz = hclk.0 / 1_000_000; | 92 | }); |
| 179 | |||
| 180 | // Set the MDC clock frequency in the range 1MHz - 2.5MHz | ||
| 181 | let clock_range = match hclk_mhz { | ||
| 182 | 0..=34 => 2, // Divide by 16 | ||
| 183 | 35..=59 => 3, // Divide by 26 | ||
| 184 | 60..=99 => 0, // Divide by 42 | ||
| 185 | 100..=149 => 1, // Divide by 62 | ||
| 186 | 150..=249 => 4, // Divide by 102 | ||
| 187 | 250..=310 => 5, // Divide by 124 | ||
| 188 | _ => { | ||
| 189 | panic!("HCLK results in MDC clock > 2.5MHz even for the highest CSR clock divider") | ||
| 190 | } | ||
| 191 | }; | ||
| 192 | |||
| 193 | let pins = [ | ||
| 194 | ref_clk.map_into(), | ||
| 195 | mdio.map_into(), | ||
| 196 | mdc.map_into(), | ||
| 197 | crs.map_into(), | ||
| 198 | rx_d0.map_into(), | ||
| 199 | rx_d1.map_into(), | ||
| 200 | tx_d0.map_into(), | ||
| 201 | tx_d1.map_into(), | ||
| 202 | tx_en.map_into(), | ||
| 203 | ]; | ||
| 204 | |||
| 205 | let mut this = Self { | ||
| 206 | _peri: peri, | ||
| 207 | tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), | ||
| 208 | rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), | ||
| 209 | pins, | ||
| 210 | _phy: phy, | ||
| 211 | clock_range, | ||
| 212 | phy_addr, | ||
| 213 | mac_addr, | ||
| 214 | }; | ||
| 215 | |||
| 216 | fence(Ordering::SeqCst); | ||
| 217 | |||
| 218 | let mac = ETH.ethernet_mac(); | ||
| 219 | let mtl = ETH.ethernet_mtl(); | ||
| 220 | let dma = ETH.ethernet_dma(); | ||
| 221 | |||
| 222 | mac.maccr().modify(|w| { | ||
| 223 | w.set_re(true); | ||
| 224 | w.set_te(true); | ||
| 225 | }); | ||
| 226 | mtl.mtltx_qomr().modify(|w| w.set_ftq(true)); | ||
| 227 | 93 | ||
| 228 | dma.dmactx_cr().modify(|w| w.set_st(true)); | 94 | #[cfg(rcc_h5)] |
| 229 | dma.dmacrx_cr().modify(|w| w.set_sr(true)); | 95 | critical_section::with(|_| { |
| 96 | crate::pac::RCC.apb3enr().modify(|w| w.set_sbsen(true)); | ||
| 230 | 97 | ||
| 231 | // Enable interrupts | 98 | crate::pac::RCC.ahb1enr().modify(|w| { |
| 232 | dma.dmacier().modify(|w| { | 99 | w.set_ethen(true); |
| 233 | w.set_nie(true); | 100 | w.set_ethtxen(true); |
| 234 | w.set_rie(true); | 101 | w.set_ethrxen(true); |
| 235 | w.set_tie(true); | ||
| 236 | }); | 102 | }); |
| 237 | 103 | ||
| 238 | P::phy_reset(&mut this); | 104 | // RMII |
| 239 | P::phy_init(&mut this); | 105 | crate::pac::SBS |
| 240 | 106 | .pmcr() | |
| 241 | interrupt::ETH.unpend(); | 107 | .modify(|w| w.set_eth_sel_phy(crate::pac::sbs::vals::EthSelPhy::B_0X4)); |
| 242 | interrupt::ETH.enable(); | 108 | }); |
| 243 | 109 | ||
| 244 | this | 110 | config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); |
| 245 | } | 111 | |
| 112 | let dma = ETH.ethernet_dma(); | ||
| 113 | let mac = ETH.ethernet_mac(); | ||
| 114 | let mtl = ETH.ethernet_mtl(); | ||
| 115 | |||
| 116 | // Reset and wait | ||
| 117 | dma.dmamr().modify(|w| w.set_swr(true)); | ||
| 118 | while dma.dmamr().read().swr() {} | ||
| 119 | |||
| 120 | mac.maccr().modify(|w| { | ||
| 121 | w.set_ipg(0b000); // 96 bit times | ||
| 122 | w.set_acs(true); | ||
| 123 | w.set_fes(true); | ||
| 124 | w.set_dm(true); | ||
| 125 | // TODO: Carrier sense ? ECRSFD | ||
| 126 | }); | ||
| 127 | |||
| 128 | // Note: Writing to LR triggers synchronisation of both LR and HR into the MAC core, | ||
| 129 | // so the LR write must happen after the HR write. | ||
| 130 | mac.maca0hr() | ||
| 131 | .modify(|w| w.set_addrhi(u16::from(mac_addr[4]) | (u16::from(mac_addr[5]) << 8))); | ||
| 132 | mac.maca0lr().write(|w| { | ||
| 133 | w.set_addrlo( | ||
| 134 | u32::from(mac_addr[0]) | ||
| 135 | | (u32::from(mac_addr[1]) << 8) | ||
| 136 | | (u32::from(mac_addr[2]) << 16) | ||
| 137 | | (u32::from(mac_addr[3]) << 24), | ||
| 138 | ) | ||
| 139 | }); | ||
| 140 | |||
| 141 | mac.macqtx_fcr().modify(|w| w.set_pt(0x100)); | ||
| 142 | |||
| 143 | // disable all MMC RX interrupts | ||
| 144 | mac.mmc_rx_interrupt_mask().write(|w| { | ||
| 145 | w.set_rxcrcerpim(true); | ||
| 146 | w.set_rxalgnerpim(true); | ||
| 147 | w.set_rxucgpim(true); | ||
| 148 | w.set_rxlpiuscim(true); | ||
| 149 | w.set_rxlpitrcim(true) | ||
| 150 | }); | ||
| 151 | |||
| 152 | // disable all MMC TX interrupts | ||
| 153 | mac.mmc_tx_interrupt_mask().write(|w| { | ||
| 154 | w.set_txscolgpim(true); | ||
| 155 | w.set_txmcolgpim(true); | ||
| 156 | w.set_txgpktim(true); | ||
| 157 | w.set_txlpiuscim(true); | ||
| 158 | w.set_txlpitrcim(true); | ||
| 159 | }); | ||
| 160 | |||
| 161 | mtl.mtlrx_qomr().modify(|w| w.set_rsf(true)); | ||
| 162 | mtl.mtltx_qomr().modify(|w| w.set_tsf(true)); | ||
| 163 | |||
| 164 | dma.dmactx_cr().modify(|w| w.set_txpbl(1)); // 32 ? | ||
| 165 | dma.dmacrx_cr().modify(|w| { | ||
| 166 | w.set_rxpbl(1); // 32 ? | ||
| 167 | w.set_rbsz(MTU as u16); | ||
| 168 | }); | ||
| 169 | |||
| 170 | // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called | ||
| 171 | let hclk = unsafe { crate::rcc::get_freqs() }.ahb1; | ||
| 172 | let hclk_mhz = hclk.0 / 1_000_000; | ||
| 173 | |||
| 174 | // Set the MDC clock frequency in the range 1MHz - 2.5MHz | ||
| 175 | let clock_range = match hclk_mhz { | ||
| 176 | 0..=34 => 2, // Divide by 16 | ||
| 177 | 35..=59 => 3, // Divide by 26 | ||
| 178 | 60..=99 => 0, // Divide by 42 | ||
| 179 | 100..=149 => 1, // Divide by 62 | ||
| 180 | 150..=249 => 4, // Divide by 102 | ||
| 181 | 250..=310 => 5, // Divide by 124 | ||
| 182 | _ => { | ||
| 183 | panic!("HCLK results in MDC clock > 2.5MHz even for the highest CSR clock divider") | ||
| 184 | } | ||
| 185 | }; | ||
| 186 | |||
| 187 | let pins = [ | ||
| 188 | ref_clk.map_into(), | ||
| 189 | mdio.map_into(), | ||
| 190 | mdc.map_into(), | ||
| 191 | crs.map_into(), | ||
| 192 | rx_d0.map_into(), | ||
| 193 | rx_d1.map_into(), | ||
| 194 | tx_d0.map_into(), | ||
| 195 | tx_d1.map_into(), | ||
| 196 | tx_en.map_into(), | ||
| 197 | ]; | ||
| 198 | |||
| 199 | let mut this = Self { | ||
| 200 | _peri: peri, | ||
| 201 | tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), | ||
| 202 | rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), | ||
| 203 | pins, | ||
| 204 | _phy: phy, | ||
| 205 | clock_range, | ||
| 206 | phy_addr, | ||
| 207 | mac_addr, | ||
| 208 | }; | ||
| 209 | |||
| 210 | fence(Ordering::SeqCst); | ||
| 211 | |||
| 212 | let mac = ETH.ethernet_mac(); | ||
| 213 | let mtl = ETH.ethernet_mtl(); | ||
| 214 | let dma = ETH.ethernet_dma(); | ||
| 215 | |||
| 216 | mac.maccr().modify(|w| { | ||
| 217 | w.set_re(true); | ||
| 218 | w.set_te(true); | ||
| 219 | }); | ||
| 220 | mtl.mtltx_qomr().modify(|w| w.set_ftq(true)); | ||
| 221 | |||
| 222 | dma.dmactx_cr().modify(|w| w.set_st(true)); | ||
| 223 | dma.dmacrx_cr().modify(|w| w.set_sr(true)); | ||
| 224 | |||
| 225 | // Enable interrupts | ||
| 226 | dma.dmacier().modify(|w| { | ||
| 227 | w.set_nie(true); | ||
| 228 | w.set_rie(true); | ||
| 229 | w.set_tie(true); | ||
| 230 | }); | ||
| 231 | |||
| 232 | P::phy_reset(&mut this); | ||
| 233 | P::phy_init(&mut this); | ||
| 234 | |||
| 235 | interrupt::ETH.unpend(); | ||
| 236 | unsafe { interrupt::ETH.enable() }; | ||
| 237 | |||
| 238 | this | ||
| 246 | } | 239 | } |
| 247 | } | 240 | } |
| 248 | 241 | ||
| 249 | unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> { | 242 | unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> { |
| 250 | fn smi_read(&mut self, reg: u8) -> u16 { | 243 | fn smi_read(&mut self, reg: u8) -> u16 { |
| 251 | // NOTE(unsafe) These registers aren't used in the interrupt and we have `&mut self` | 244 | let mac = ETH.ethernet_mac(); |
| 252 | unsafe { | 245 | |
| 253 | let mac = ETH.ethernet_mac(); | 246 | mac.macmdioar().modify(|w| { |
| 254 | 247 | w.set_pa(self.phy_addr); | |
| 255 | mac.macmdioar().modify(|w| { | 248 | w.set_rda(reg); |
| 256 | w.set_pa(self.phy_addr); | 249 | w.set_goc(0b11); // read |
| 257 | w.set_rda(reg); | 250 | w.set_cr(self.clock_range); |
| 258 | w.set_goc(0b11); // read | 251 | w.set_mb(true); |
| 259 | w.set_cr(self.clock_range); | 252 | }); |
| 260 | w.set_mb(true); | 253 | while mac.macmdioar().read().mb() {} |
| 261 | }); | 254 | mac.macmdiodr().read().md() |
| 262 | while mac.macmdioar().read().mb() {} | ||
| 263 | mac.macmdiodr().read().md() | ||
| 264 | } | ||
| 265 | } | 255 | } |
| 266 | 256 | ||
| 267 | fn smi_write(&mut self, reg: u8, val: u16) { | 257 | fn smi_write(&mut self, reg: u8, val: u16) { |
| 268 | // NOTE(unsafe) These registers aren't used in the interrupt and we have `&mut self` | 258 | let mac = ETH.ethernet_mac(); |
| 269 | unsafe { | 259 | |
| 270 | let mac = ETH.ethernet_mac(); | 260 | mac.macmdiodr().write(|w| w.set_md(val)); |
| 271 | 261 | mac.macmdioar().modify(|w| { | |
| 272 | mac.macmdiodr().write(|w| w.set_md(val)); | 262 | w.set_pa(self.phy_addr); |
| 273 | mac.macmdioar().modify(|w| { | 263 | w.set_rda(reg); |
| 274 | w.set_pa(self.phy_addr); | 264 | w.set_goc(0b01); // write |
| 275 | w.set_rda(reg); | 265 | w.set_cr(self.clock_range); |
| 276 | w.set_goc(0b01); // write | 266 | w.set_mb(true); |
| 277 | w.set_cr(self.clock_range); | 267 | }); |
| 278 | w.set_mb(true); | 268 | while mac.macmdioar().read().mb() {} |
| 279 | }); | ||
| 280 | while mac.macmdioar().read().mb() {} | ||
| 281 | } | ||
| 282 | } | 269 | } |
| 283 | } | 270 | } |
| 284 | 271 | ||
| 285 | impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { | 272 | impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { |
| 286 | fn drop(&mut self) { | 273 | fn drop(&mut self) { |
| 287 | // NOTE(unsafe) We have `&mut self` and the interrupt doesn't use this registers | 274 | let dma = ETH.ethernet_dma(); |
| 288 | unsafe { | 275 | let mac = ETH.ethernet_mac(); |
| 289 | let dma = ETH.ethernet_dma(); | 276 | let mtl = ETH.ethernet_mtl(); |
| 290 | let mac = ETH.ethernet_mac(); | 277 | |
| 291 | let mtl = ETH.ethernet_mtl(); | 278 | // Disable the TX DMA and wait for any previous transmissions to be completed |
| 292 | 279 | dma.dmactx_cr().modify(|w| w.set_st(false)); | |
| 293 | // Disable the TX DMA and wait for any previous transmissions to be completed | 280 | while { |
| 294 | dma.dmactx_cr().modify(|w| w.set_st(false)); | 281 | let txqueue = mtl.mtltx_qdr().read(); |
| 295 | while { | 282 | txqueue.trcsts() == 0b01 || txqueue.txqsts() |
| 296 | let txqueue = mtl.mtltx_qdr().read(); | 283 | } {} |
| 297 | txqueue.trcsts() == 0b01 || txqueue.txqsts() | 284 | |
| 298 | } {} | 285 | // Disable MAC transmitter and receiver |
| 299 | 286 | mac.maccr().modify(|w| { | |
| 300 | // Disable MAC transmitter and receiver | 287 | w.set_re(false); |
| 301 | mac.maccr().modify(|w| { | 288 | w.set_te(false); |
| 302 | w.set_re(false); | 289 | }); |
| 303 | w.set_te(false); | 290 | |
| 304 | }); | 291 | // Wait for previous receiver transfers to be completed and then disable the RX DMA |
| 292 | while { | ||
| 293 | let rxqueue = mtl.mtlrx_qdr().read(); | ||
| 294 | rxqueue.rxqsts() != 0b00 || rxqueue.prxq() != 0 | ||
| 295 | } {} | ||
| 296 | dma.dmacrx_cr().modify(|w| w.set_sr(false)); | ||
| 305 | 297 | ||
| 306 | // Wait for previous receiver transfers to be completed and then disable the RX DMA | 298 | critical_section::with(|_| { |
| 307 | while { | ||
| 308 | let rxqueue = mtl.mtlrx_qdr().read(); | ||
| 309 | rxqueue.rxqsts() != 0b00 || rxqueue.prxq() != 0 | ||
| 310 | } {} | ||
| 311 | dma.dmacrx_cr().modify(|w| w.set_sr(false)); | ||
| 312 | } | ||
| 313 | |||
| 314 | // NOTE(unsafe) Exclusive access to the regs | ||
| 315 | critical_section::with(|_| unsafe { | ||
| 316 | for pin in self.pins.iter_mut() { | 299 | for pin in self.pins.iter_mut() { |
| 317 | pin.set_as_disconnected(); | 300 | pin.set_as_disconnected(); |
| 318 | } | 301 | } |
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs index 0631ae473..3ff92c9e6 100644 --- a/embassy-stm32/src/exti.rs +++ b/embassy-stm32/src/exti.rs | |||
| @@ -206,7 +206,7 @@ struct ExtiInputFuture<'a> { | |||
| 206 | 206 | ||
| 207 | impl<'a> ExtiInputFuture<'a> { | 207 | impl<'a> ExtiInputFuture<'a> { |
| 208 | fn new(pin: u8, port: u8, rising: bool, falling: bool) -> Self { | 208 | fn new(pin: u8, port: u8, rising: bool, falling: bool) -> Self { |
| 209 | critical_section::with(|_| unsafe { | 209 | critical_section::with(|_| { |
| 210 | let pin = pin as usize; | 210 | let pin = pin as usize; |
| 211 | exticr_regs().exticr(pin / 4).modify(|w| w.set_exti(pin % 4, port)); | 211 | exticr_regs().exticr(pin / 4).modify(|w| w.set_exti(pin % 4, port)); |
| 212 | EXTI.rtsr(0).modify(|w| w.set_line(pin, rising)); | 212 | EXTI.rtsr(0).modify(|w| w.set_line(pin, rising)); |
| @@ -233,7 +233,7 @@ impl<'a> ExtiInputFuture<'a> { | |||
| 233 | 233 | ||
| 234 | impl<'a> Drop for ExtiInputFuture<'a> { | 234 | impl<'a> Drop for ExtiInputFuture<'a> { |
| 235 | fn drop(&mut self) { | 235 | fn drop(&mut self) { |
| 236 | critical_section::with(|_| unsafe { | 236 | critical_section::with(|_| { |
| 237 | let pin = self.pin as _; | 237 | let pin = self.pin as _; |
| 238 | cpu_regs().imr(0).modify(|w| w.set_line(pin, false)); | 238 | cpu_regs().imr(0).modify(|w| w.set_line(pin, false)); |
| 239 | }); | 239 | }); |
| @@ -246,7 +246,7 @@ impl<'a> Future for ExtiInputFuture<'a> { | |||
| 246 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | 246 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
| 247 | EXTI_WAKERS[self.pin as usize].register(cx.waker()); | 247 | EXTI_WAKERS[self.pin as usize].register(cx.waker()); |
| 248 | 248 | ||
| 249 | let imr = unsafe { cpu_regs().imr(0).read() }; | 249 | let imr = cpu_regs().imr(0).read(); |
| 250 | if !imr.line(self.pin as _) { | 250 | if !imr.line(self.pin as _) { |
| 251 | Poll::Ready(()) | 251 | Poll::Ready(()) |
| 252 | } else { | 252 | } else { |
diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 5e1fc696f..242d99278 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs | |||
| @@ -192,7 +192,7 @@ impl FlashSector { | |||
| 192 | 192 | ||
| 193 | #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] | 193 | #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] |
| 194 | pub(crate) fn is_default_layout() -> bool { | 194 | pub(crate) fn is_default_layout() -> bool { |
| 195 | unsafe { !pac::FLASH.optcr().read().db1m() } | 195 | !pac::FLASH.optcr().read().db1m() |
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | #[cfg(not(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479)))] | 198 | #[cfg(not(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479)))] |
| @@ -336,7 +336,7 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E | |||
| 336 | ret | 336 | ret |
| 337 | } | 337 | } |
| 338 | 338 | ||
| 339 | pub(crate) unsafe fn clear_all_err() { | 339 | pub(crate) fn clear_all_err() { |
| 340 | pac::FLASH.sr().write(|w| { | 340 | pac::FLASH.sr().write(|w| { |
| 341 | w.set_pgserr(true); | 341 | w.set_pgserr(true); |
| 342 | w.set_pgperr(true); | 342 | w.set_pgperr(true); |
| @@ -345,7 +345,7 @@ pub(crate) unsafe fn clear_all_err() { | |||
| 345 | }); | 345 | }); |
| 346 | } | 346 | } |
| 347 | 347 | ||
| 348 | pub(crate) async unsafe fn wait_ready() -> Result<(), Error> { | 348 | pub(crate) async fn wait_ready() -> Result<(), Error> { |
| 349 | use core::task::Poll; | 349 | use core::task::Poll; |
| 350 | 350 | ||
| 351 | use futures::future::poll_fn; | 351 | use futures::future::poll_fn; |
| @@ -391,10 +391,10 @@ fn save_data_cache_state() { | |||
| 391 | let dual_bank = get_flash_regions().last().unwrap().bank == FlashBank::Bank2; | 391 | let dual_bank = get_flash_regions().last().unwrap().bank == FlashBank::Bank2; |
| 392 | if dual_bank { | 392 | if dual_bank { |
| 393 | // Disable data cache during write/erase if there are two banks, see errata 2.2.12 | 393 | // Disable data cache during write/erase if there are two banks, see errata 2.2.12 |
| 394 | let dcen = unsafe { pac::FLASH.acr().read().dcen() }; | 394 | let dcen = pac::FLASH.acr().read().dcen(); |
| 395 | DATA_CACHE_WAS_ENABLED.store(dcen, Ordering::Relaxed); | 395 | DATA_CACHE_WAS_ENABLED.store(dcen, Ordering::Relaxed); |
| 396 | if dcen { | 396 | if dcen { |
| 397 | unsafe { pac::FLASH.acr().modify(|w| w.set_dcen(false)) }; | 397 | pac::FLASH.acr().modify(|w| w.set_dcen(false)); |
| 398 | } | 398 | } |
| 399 | } | 399 | } |
| 400 | } | 400 | } |
| @@ -405,12 +405,10 @@ fn restore_data_cache_state() { | |||
| 405 | // Restore data cache if it was enabled | 405 | // Restore data cache if it was enabled |
| 406 | let dcen = DATA_CACHE_WAS_ENABLED.load(Ordering::Relaxed); | 406 | let dcen = DATA_CACHE_WAS_ENABLED.load(Ordering::Relaxed); |
| 407 | if dcen { | 407 | if dcen { |
| 408 | unsafe { | 408 | // Reset data cache before we enable it again |
| 409 | // Reset data cache before we enable it again | 409 | pac::FLASH.acr().modify(|w| w.set_dcrst(true)); |
| 410 | pac::FLASH.acr().modify(|w| w.set_dcrst(true)); | 410 | pac::FLASH.acr().modify(|w| w.set_dcrst(false)); |
| 411 | pac::FLASH.acr().modify(|w| w.set_dcrst(false)); | 411 | pac::FLASH.acr().modify(|w| w.set_dcen(true)) |
| 412 | pac::FLASH.acr().modify(|w| w.set_dcen(true)) | ||
| 413 | }; | ||
| 414 | } | 412 | } |
| 415 | } | 413 | } |
| 416 | } | 414 | } |
| @@ -445,7 +443,7 @@ pub(crate) fn assert_not_corrupted_read(end_address: u32) { | |||
| 445 | feature = "stm32f439vi", | 443 | feature = "stm32f439vi", |
| 446 | feature = "stm32f439zi", | 444 | feature = "stm32f439zi", |
| 447 | ))] | 445 | ))] |
| 448 | if second_bank_read && unsafe { pac::DBGMCU.idcode().read().rev_id() < REVISION_3 && !pa12_is_output_pull_low() } { | 446 | if second_bank_read && pac::DBGMCU.idcode().read().rev_id() < REVISION_3 && !pa12_is_output_pull_low() { |
| 449 | panic!("Read corruption for stm32f42xxI and stm32f43xxI when PA12 is in use for chips below revision 3, see errata 2.2.11"); | 447 | panic!("Read corruption for stm32f42xxI and stm32f43xxI when PA12 is in use for chips below revision 3, see errata 2.2.11"); |
| 450 | } | 448 | } |
| 451 | 449 | ||
| @@ -479,11 +477,9 @@ fn pa12_is_output_pull_low() -> bool { | |||
| 479 | use pac::gpio::vals; | 477 | use pac::gpio::vals; |
| 480 | use pac::GPIOA; | 478 | use pac::GPIOA; |
| 481 | const PIN: usize = 12; | 479 | const PIN: usize = 12; |
| 482 | unsafe { | 480 | GPIOA.moder().read().moder(PIN) == vals::Moder::OUTPUT |
| 483 | GPIOA.moder().read().moder(PIN) == vals::Moder::OUTPUT | 481 | && GPIOA.pupdr().read().pupdr(PIN) == vals::Pupdr::PULLDOWN |
| 484 | && GPIOA.pupdr().read().pupdr(PIN) == vals::Pupdr::PULLDOWN | 482 | && GPIOA.odr().read().odr(PIN) == vals::Odr::LOW |
| 485 | && GPIOA.odr().read().odr(PIN) == vals::Odr::LOW | ||
| 486 | } | ||
| 487 | } | 483 | } |
| 488 | 484 | ||
| 489 | #[cfg(test)] | 485 | #[cfg(test)] |
diff --git a/embassy-stm32/src/fmc.rs b/embassy-stm32/src/fmc.rs index b9129cb51..a4f3b9686 100644 --- a/embassy-stm32/src/fmc.rs +++ b/embassy-stm32/src/fmc.rs | |||
| @@ -16,7 +16,7 @@ unsafe impl<'d, T> stm32_fmc::FmcPeripheral for Fmc<'d, T> | |||
| 16 | where | 16 | where |
| 17 | T: Instance, | 17 | T: Instance, |
| 18 | { | 18 | { |
| 19 | const REGISTERS: *const () = T::REGS.0 as *const _; | 19 | const REGISTERS: *const () = T::REGS.as_ptr() as *const _; |
| 20 | 20 | ||
| 21 | fn enable(&mut self) { | 21 | fn enable(&mut self) { |
| 22 | <T as crate::rcc::sealed::RccPeripheral>::enable(); | 22 | <T as crate::rcc::sealed::RccPeripheral>::enable(); |
| @@ -28,9 +28,7 @@ where | |||
| 28 | // fsmc v1, v2 and v3 does not have the fmcen bit | 28 | // fsmc v1, v2 and v3 does not have the fmcen bit |
| 29 | // This is a "not" because it is expected that all future versions have this bit | 29 | // This is a "not" because it is expected that all future versions have this bit |
| 30 | #[cfg(not(any(fmc_v1x3, fmc_v2x1, fsmc_v1x0, fsmc_v1x3, fsmc_v2x3, fsmc_v3x1)))] | 30 | #[cfg(not(any(fmc_v1x3, fmc_v2x1, fsmc_v1x0, fsmc_v1x3, fsmc_v2x3, fsmc_v3x1)))] |
| 31 | unsafe { | 31 | T::REGS.bcr1().modify(|r| r.set_fmcen(true)); |
| 32 | T::REGS.bcr1().modify(|r| r.set_fmcen(true)) | ||
| 33 | }; | ||
| 34 | } | 32 | } |
| 35 | 33 | ||
| 36 | fn source_clock_hz(&self) -> u32 { | 34 | fn source_clock_hz(&self) -> u32 { |
| @@ -67,7 +65,7 @@ macro_rules! fmc_sdram_constructor { | |||
| 67 | chip: CHIP | 65 | chip: CHIP |
| 68 | ) -> stm32_fmc::Sdram<Fmc<'d, T>, CHIP> { | 66 | ) -> stm32_fmc::Sdram<Fmc<'d, T>, CHIP> { |
| 69 | 67 | ||
| 70 | critical_section::with(|_| unsafe { | 68 | critical_section::with(|_| { |
| 71 | config_pins!( | 69 | config_pins!( |
| 72 | $($addr_pin_name),*, | 70 | $($addr_pin_name),*, |
| 73 | $($ba_pin_name),*, | 71 | $($ba_pin_name),*, |
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs index 7a066a4ca..af3a8eaca 100644 --- a/embassy-stm32/src/gpio.rs +++ b/embassy-stm32/src/gpio.rs | |||
| @@ -46,7 +46,7 @@ impl<'d, T: Pin> Flex<'d, T> { | |||
| 46 | /// Put the pin into input mode. | 46 | /// Put the pin into input mode. |
| 47 | #[inline] | 47 | #[inline] |
| 48 | pub fn set_as_input(&mut self, pull: Pull) { | 48 | pub fn set_as_input(&mut self, pull: Pull) { |
| 49 | critical_section::with(|_| unsafe { | 49 | critical_section::with(|_| { |
| 50 | let r = self.pin.block(); | 50 | let r = self.pin.block(); |
| 51 | let n = self.pin.pin() as usize; | 51 | let n = self.pin.pin() as usize; |
| 52 | #[cfg(gpio_v1)] | 52 | #[cfg(gpio_v1)] |
| @@ -84,7 +84,7 @@ impl<'d, T: Pin> Flex<'d, T> { | |||
| 84 | /// at a specific level, call `set_high`/`set_low` on the pin first. | 84 | /// at a specific level, call `set_high`/`set_low` on the pin first. |
| 85 | #[inline] | 85 | #[inline] |
| 86 | pub fn set_as_output(&mut self, speed: Speed) { | 86 | pub fn set_as_output(&mut self, speed: Speed) { |
| 87 | critical_section::with(|_| unsafe { | 87 | critical_section::with(|_| { |
| 88 | let r = self.pin.block(); | 88 | let r = self.pin.block(); |
| 89 | let n = self.pin.pin() as usize; | 89 | let n = self.pin.pin() as usize; |
| 90 | #[cfg(gpio_v1)] | 90 | #[cfg(gpio_v1)] |
| @@ -116,7 +116,7 @@ impl<'d, T: Pin> Flex<'d, T> { | |||
| 116 | /// at a specific level, call `set_high`/`set_low` on the pin first. | 116 | /// at a specific level, call `set_high`/`set_low` on the pin first. |
| 117 | #[inline] | 117 | #[inline] |
| 118 | pub fn set_as_input_output(&mut self, speed: Speed, pull: Pull) { | 118 | pub fn set_as_input_output(&mut self, speed: Speed, pull: Pull) { |
| 119 | critical_section::with(|_| unsafe { | 119 | critical_section::with(|_| { |
| 120 | let r = self.pin.block(); | 120 | let r = self.pin.block(); |
| 121 | let n = self.pin.pin() as usize; | 121 | let n = self.pin.pin() as usize; |
| 122 | #[cfg(gpio_v1)] | 122 | #[cfg(gpio_v1)] |
| @@ -147,7 +147,7 @@ impl<'d, T: Pin> Flex<'d, T> { | |||
| 147 | 147 | ||
| 148 | #[inline] | 148 | #[inline] |
| 149 | pub fn is_low(&self) -> bool { | 149 | pub fn is_low(&self) -> bool { |
| 150 | let state = unsafe { self.pin.block().idr().read().idr(self.pin.pin() as _) }; | 150 | let state = self.pin.block().idr().read().idr(self.pin.pin() as _); |
| 151 | state == vals::Idr::LOW | 151 | state == vals::Idr::LOW |
| 152 | } | 152 | } |
| 153 | 153 | ||
| @@ -164,7 +164,7 @@ impl<'d, T: Pin> Flex<'d, T> { | |||
| 164 | /// Is the output pin set as low? | 164 | /// Is the output pin set as low? |
| 165 | #[inline] | 165 | #[inline] |
| 166 | pub fn is_set_low(&self) -> bool { | 166 | pub fn is_set_low(&self) -> bool { |
| 167 | let state = unsafe { self.pin.block().odr().read().odr(self.pin.pin() as _) }; | 167 | let state = self.pin.block().odr().read().odr(self.pin.pin() as _); |
| 168 | state == vals::Odr::LOW | 168 | state == vals::Odr::LOW |
| 169 | } | 169 | } |
| 170 | 170 | ||
| @@ -207,7 +207,7 @@ impl<'d, T: Pin> Flex<'d, T> { | |||
| 207 | impl<'d, T: Pin> Drop for Flex<'d, T> { | 207 | impl<'d, T: Pin> Drop for Flex<'d, T> { |
| 208 | #[inline] | 208 | #[inline] |
| 209 | fn drop(&mut self) { | 209 | fn drop(&mut self) { |
| 210 | critical_section::with(|_| unsafe { | 210 | critical_section::with(|_| { |
| 211 | let r = self.pin.block(); | 211 | let r = self.pin.block(); |
| 212 | let n = self.pin.pin() as usize; | 212 | let n = self.pin.pin() as usize; |
| 213 | #[cfg(gpio_v1)] | 213 | #[cfg(gpio_v1)] |
| @@ -534,29 +534,25 @@ pub(crate) mod sealed { | |||
| 534 | /// Set the output as high. | 534 | /// Set the output as high. |
| 535 | #[inline] | 535 | #[inline] |
| 536 | fn set_high(&self) { | 536 | fn set_high(&self) { |
| 537 | unsafe { | 537 | let n = self._pin() as _; |
| 538 | let n = self._pin() as _; | 538 | self.block().bsrr().write(|w| w.set_bs(n, true)); |
| 539 | self.block().bsrr().write(|w| w.set_bs(n, true)); | ||
| 540 | } | ||
| 541 | } | 539 | } |
| 542 | 540 | ||
| 543 | /// Set the output as low. | 541 | /// Set the output as low. |
| 544 | #[inline] | 542 | #[inline] |
| 545 | fn set_low(&self) { | 543 | fn set_low(&self) { |
| 546 | unsafe { | 544 | let n = self._pin() as _; |
| 547 | let n = self._pin() as _; | 545 | self.block().bsrr().write(|w| w.set_br(n, true)); |
| 548 | self.block().bsrr().write(|w| w.set_br(n, true)); | ||
| 549 | } | ||
| 550 | } | 546 | } |
| 551 | 547 | ||
| 552 | #[inline] | 548 | #[inline] |
| 553 | unsafe fn set_as_af(&self, af_num: u8, af_type: AFType) { | 549 | fn set_as_af(&self, af_num: u8, af_type: AFType) { |
| 554 | self.set_as_af_pull(af_num, af_type, Pull::None); | 550 | self.set_as_af_pull(af_num, af_type, Pull::None); |
| 555 | } | 551 | } |
| 556 | 552 | ||
| 557 | #[cfg(gpio_v1)] | 553 | #[cfg(gpio_v1)] |
| 558 | #[inline] | 554 | #[inline] |
| 559 | unsafe fn set_as_af_pull(&self, _af_num: u8, af_type: AFType, pull: Pull) { | 555 | fn set_as_af_pull(&self, _af_num: u8, af_type: AFType, pull: Pull) { |
| 560 | // F1 uses the AFIO register for remapping. | 556 | // F1 uses the AFIO register for remapping. |
| 561 | // For now, this is not implemented, so af_num is ignored | 557 | // For now, this is not implemented, so af_num is ignored |
| 562 | // _af_num should be zero here, since it is not set by stm32-data | 558 | // _af_num should be zero here, since it is not set by stm32-data |
| @@ -599,7 +595,7 @@ pub(crate) mod sealed { | |||
| 599 | 595 | ||
| 600 | #[cfg(gpio_v2)] | 596 | #[cfg(gpio_v2)] |
| 601 | #[inline] | 597 | #[inline] |
| 602 | unsafe fn set_as_af_pull(&self, af_num: u8, af_type: AFType, pull: Pull) { | 598 | fn set_as_af_pull(&self, af_num: u8, af_type: AFType, pull: Pull) { |
| 603 | let pin = self._pin() as usize; | 599 | let pin = self._pin() as usize; |
| 604 | let block = self.block(); | 600 | let block = self.block(); |
| 605 | block.afr(pin / 8).modify(|w| w.set_afr(pin % 8, af_num)); | 601 | block.afr(pin / 8).modify(|w| w.set_afr(pin % 8, af_num)); |
| @@ -614,7 +610,7 @@ pub(crate) mod sealed { | |||
| 614 | } | 610 | } |
| 615 | 611 | ||
| 616 | #[inline] | 612 | #[inline] |
| 617 | unsafe fn set_as_analog(&self) { | 613 | fn set_as_analog(&self) { |
| 618 | let pin = self._pin() as usize; | 614 | let pin = self._pin() as usize; |
| 619 | let block = self.block(); | 615 | let block = self.block(); |
| 620 | #[cfg(gpio_v1)] | 616 | #[cfg(gpio_v1)] |
| @@ -635,12 +631,12 @@ pub(crate) mod sealed { | |||
| 635 | /// This is currently the same as set_as_analog but is semantically different really. | 631 | /// This is currently the same as set_as_analog but is semantically different really. |
| 636 | /// Drivers should set_as_disconnected pins when dropped. | 632 | /// Drivers should set_as_disconnected pins when dropped. |
| 637 | #[inline] | 633 | #[inline] |
| 638 | unsafe fn set_as_disconnected(&self) { | 634 | fn set_as_disconnected(&self) { |
| 639 | self.set_as_analog(); | 635 | self.set_as_analog(); |
| 640 | } | 636 | } |
| 641 | 637 | ||
| 642 | #[inline] | 638 | #[inline] |
| 643 | unsafe fn set_speed(&self, speed: Speed) { | 639 | fn set_speed(&self, speed: Speed) { |
| 644 | let pin = self._pin() as usize; | 640 | let pin = self._pin() as usize; |
| 645 | 641 | ||
| 646 | #[cfg(gpio_v1)] | 642 | #[cfg(gpio_v1)] |
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index e04038886..aa485cd86 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs | |||
| @@ -68,53 +68,45 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 68 | T::enable(); | 68 | T::enable(); |
| 69 | T::reset(); | 69 | T::reset(); |
| 70 | 70 | ||
| 71 | unsafe { | 71 | scl.set_as_af_pull( |
| 72 | scl.set_as_af_pull( | 72 | scl.af_num(), |
| 73 | scl.af_num(), | 73 | AFType::OutputOpenDrain, |
| 74 | AFType::OutputOpenDrain, | 74 | match config.scl_pullup { |
| 75 | match config.scl_pullup { | 75 | true => Pull::Up, |
| 76 | true => Pull::Up, | 76 | false => Pull::None, |
| 77 | false => Pull::None, | 77 | }, |
| 78 | }, | 78 | ); |
| 79 | ); | 79 | sda.set_as_af_pull( |
| 80 | sda.set_as_af_pull( | 80 | sda.af_num(), |
| 81 | sda.af_num(), | 81 | AFType::OutputOpenDrain, |
| 82 | AFType::OutputOpenDrain, | 82 | match config.sda_pullup { |
| 83 | match config.sda_pullup { | 83 | true => Pull::Up, |
| 84 | true => Pull::Up, | 84 | false => Pull::None, |
| 85 | false => Pull::None, | 85 | }, |
| 86 | }, | 86 | ); |
| 87 | ); | ||
| 88 | } | ||
| 89 | 87 | ||
| 90 | unsafe { | 88 | T::regs().cr1().modify(|reg| { |
| 91 | T::regs().cr1().modify(|reg| { | 89 | reg.set_pe(false); |
| 92 | reg.set_pe(false); | 90 | //reg.set_anfoff(false); |
| 93 | //reg.set_anfoff(false); | 91 | }); |
| 94 | }); | ||
| 95 | } | ||
| 96 | 92 | ||
| 97 | let timings = Timings::new(T::frequency(), freq.into()); | 93 | let timings = Timings::new(T::frequency(), freq.into()); |
| 98 | 94 | ||
| 99 | unsafe { | 95 | T::regs().cr2().modify(|reg| { |
| 100 | T::regs().cr2().modify(|reg| { | 96 | reg.set_freq(timings.freq); |
| 101 | reg.set_freq(timings.freq); | 97 | }); |
| 102 | }); | 98 | T::regs().ccr().modify(|reg| { |
| 103 | T::regs().ccr().modify(|reg| { | 99 | reg.set_f_s(timings.mode.f_s()); |
| 104 | reg.set_f_s(timings.mode.f_s()); | 100 | reg.set_duty(timings.duty.duty()); |
| 105 | reg.set_duty(timings.duty.duty()); | 101 | reg.set_ccr(timings.ccr); |
| 106 | reg.set_ccr(timings.ccr); | 102 | }); |
| 107 | }); | 103 | T::regs().trise().modify(|reg| { |
| 108 | T::regs().trise().modify(|reg| { | 104 | reg.set_trise(timings.trise); |
| 109 | reg.set_trise(timings.trise); | 105 | }); |
| 110 | }); | ||
| 111 | } | ||
| 112 | 106 | ||
| 113 | unsafe { | 107 | T::regs().cr1().modify(|reg| { |
| 114 | T::regs().cr1().modify(|reg| { | 108 | reg.set_pe(true); |
| 115 | reg.set_pe(true); | 109 | }); |
| 116 | }); | ||
| 117 | } | ||
| 118 | 110 | ||
| 119 | Self { | 111 | Self { |
| 120 | phantom: PhantomData, | 112 | phantom: PhantomData, |
| @@ -123,7 +115,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 123 | } | 115 | } |
| 124 | } | 116 | } |
| 125 | 117 | ||
| 126 | unsafe fn check_and_clear_error_flags(&self) -> Result<i2c::regs::Sr1, Error> { | 118 | fn check_and_clear_error_flags(&self) -> Result<i2c::regs::Sr1, Error> { |
| 127 | // Note that flags should only be cleared once they have been registered. If flags are | 119 | // Note that flags should only be cleared once they have been registered. If flags are |
| 128 | // cleared otherwise, there may be an inherent race condition and flags may be missed. | 120 | // cleared otherwise, there may be an inherent race condition and flags may be missed. |
| 129 | let sr1 = T::regs().sr1().read(); | 121 | let sr1 = T::regs().sr1().read(); |
| @@ -162,7 +154,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 162 | Ok(sr1) | 154 | Ok(sr1) |
| 163 | } | 155 | } |
| 164 | 156 | ||
| 165 | unsafe fn write_bytes( | 157 | fn write_bytes( |
| 166 | &mut self, | 158 | &mut self, |
| 167 | addr: u8, | 159 | addr: u8, |
| 168 | bytes: &[u8], | 160 | bytes: &[u8], |
| @@ -211,7 +203,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 211 | Ok(()) | 203 | Ok(()) |
| 212 | } | 204 | } |
| 213 | 205 | ||
| 214 | unsafe fn send_byte(&self, byte: u8, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { | 206 | fn send_byte(&self, byte: u8, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { |
| 215 | // Wait until we're ready for sending | 207 | // Wait until we're ready for sending |
| 216 | while { | 208 | while { |
| 217 | // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. | 209 | // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. |
| @@ -234,7 +226,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 234 | Ok(()) | 226 | Ok(()) |
| 235 | } | 227 | } |
| 236 | 228 | ||
| 237 | unsafe fn recv_byte(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<u8, Error> { | 229 | fn recv_byte(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<u8, Error> { |
| 238 | while { | 230 | while { |
| 239 | // Check for any potential error conditions. | 231 | // Check for any potential error conditions. |
| 240 | self.check_and_clear_error_flags()?; | 232 | self.check_and_clear_error_flags()?; |
| @@ -256,56 +248,52 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 256 | ) -> Result<(), Error> { | 248 | ) -> Result<(), Error> { |
| 257 | if let Some((last, buffer)) = buffer.split_last_mut() { | 249 | if let Some((last, buffer)) = buffer.split_last_mut() { |
| 258 | // Send a START condition and set ACK bit | 250 | // Send a START condition and set ACK bit |
| 259 | unsafe { | 251 | T::regs().cr1().modify(|reg| { |
| 260 | T::regs().cr1().modify(|reg| { | 252 | reg.set_start(true); |
| 261 | reg.set_start(true); | 253 | reg.set_ack(true); |
| 262 | reg.set_ack(true); | 254 | }); |
| 263 | }); | ||
| 264 | } | ||
| 265 | 255 | ||
| 266 | // Wait until START condition was generated | 256 | // Wait until START condition was generated |
| 267 | while unsafe { !self.check_and_clear_error_flags()?.start() } { | 257 | while !self.check_and_clear_error_flags()?.start() { |
| 268 | check_timeout()?; | 258 | check_timeout()?; |
| 269 | } | 259 | } |
| 270 | 260 | ||
| 271 | // Also wait until signalled we're master and everything is waiting for us | 261 | // Also wait until signalled we're master and everything is waiting for us |
| 272 | while { | 262 | while { |
| 273 | let sr2 = unsafe { T::regs().sr2().read() }; | 263 | let sr2 = T::regs().sr2().read(); |
| 274 | !sr2.msl() && !sr2.busy() | 264 | !sr2.msl() && !sr2.busy() |
| 275 | } { | 265 | } { |
| 276 | check_timeout()?; | 266 | check_timeout()?; |
| 277 | } | 267 | } |
| 278 | 268 | ||
| 279 | // Set up current address, we're trying to talk to | 269 | // Set up current address, we're trying to talk to |
| 280 | unsafe { T::regs().dr().write(|reg| reg.set_dr((addr << 1) + 1)) } | 270 | T::regs().dr().write(|reg| reg.set_dr((addr << 1) + 1)); |
| 281 | 271 | ||
| 282 | // Wait until address was sent | 272 | // Wait until address was sent |
| 283 | // Wait for the address to be acknowledged | 273 | // Wait for the address to be acknowledged |
| 284 | while unsafe { !self.check_and_clear_error_flags()?.addr() } { | 274 | while !self.check_and_clear_error_flags()?.addr() { |
| 285 | check_timeout()?; | 275 | check_timeout()?; |
| 286 | } | 276 | } |
| 287 | 277 | ||
| 288 | // Clear condition by reading SR2 | 278 | // Clear condition by reading SR2 |
| 289 | let _ = unsafe { T::regs().sr2().read() }; | 279 | let _ = T::regs().sr2().read(); |
| 290 | 280 | ||
| 291 | // Receive bytes into buffer | 281 | // Receive bytes into buffer |
| 292 | for c in buffer { | 282 | for c in buffer { |
| 293 | *c = unsafe { self.recv_byte(&check_timeout)? }; | 283 | *c = self.recv_byte(&check_timeout)?; |
| 294 | } | 284 | } |
| 295 | 285 | ||
| 296 | // Prepare to send NACK then STOP after next byte | 286 | // Prepare to send NACK then STOP after next byte |
| 297 | unsafe { | 287 | T::regs().cr1().modify(|reg| { |
| 298 | T::regs().cr1().modify(|reg| { | 288 | reg.set_ack(false); |
| 299 | reg.set_ack(false); | 289 | reg.set_stop(true); |
| 300 | reg.set_stop(true); | 290 | }); |
| 301 | }) | ||
| 302 | } | ||
| 303 | 291 | ||
| 304 | // Receive last byte | 292 | // Receive last byte |
| 305 | *last = unsafe { self.recv_byte(&check_timeout)? }; | 293 | *last = self.recv_byte(&check_timeout)?; |
| 306 | 294 | ||
| 307 | // Wait for the STOP to be sent. | 295 | // Wait for the STOP to be sent. |
| 308 | while unsafe { T::regs().cr1().read().stop() } { | 296 | while T::regs().cr1().read().stop() { |
| 309 | check_timeout()?; | 297 | check_timeout()?; |
| 310 | } | 298 | } |
| 311 | 299 | ||
| @@ -326,15 +314,13 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 326 | write: &[u8], | 314 | write: &[u8], |
| 327 | check_timeout: impl Fn() -> Result<(), Error>, | 315 | check_timeout: impl Fn() -> Result<(), Error>, |
| 328 | ) -> Result<(), Error> { | 316 | ) -> Result<(), Error> { |
| 329 | unsafe { | 317 | self.write_bytes(addr, write, &check_timeout)?; |
| 330 | self.write_bytes(addr, write, &check_timeout)?; | 318 | // Send a STOP condition |
| 331 | // Send a STOP condition | 319 | T::regs().cr1().modify(|reg| reg.set_stop(true)); |
| 332 | T::regs().cr1().modify(|reg| reg.set_stop(true)); | 320 | // Wait for STOP condition to transmit. |
| 333 | // Wait for STOP condition to transmit. | 321 | while T::regs().cr1().read().stop() { |
| 334 | while T::regs().cr1().read().stop() { | 322 | check_timeout()?; |
| 335 | check_timeout()?; | 323 | } |
| 336 | } | ||
| 337 | }; | ||
| 338 | 324 | ||
| 339 | // Fallthrough is success | 325 | // Fallthrough is success |
| 340 | Ok(()) | 326 | Ok(()) |
| @@ -351,7 +337,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 351 | read: &mut [u8], | 337 | read: &mut [u8], |
| 352 | check_timeout: impl Fn() -> Result<(), Error>, | 338 | check_timeout: impl Fn() -> Result<(), Error>, |
| 353 | ) -> Result<(), Error> { | 339 | ) -> Result<(), Error> { |
| 354 | unsafe { self.write_bytes(addr, write, &check_timeout)? }; | 340 | self.write_bytes(addr, write, &check_timeout)?; |
| 355 | self.blocking_read_timeout(addr, read, &check_timeout)?; | 341 | self.blocking_read_timeout(addr, read, &check_timeout)?; |
| 356 | 342 | ||
| 357 | Ok(()) | 343 | Ok(()) |
| @@ -478,8 +464,6 @@ impl Timings { | |||
| 478 | assert!(freq >= 2 && freq <= 50); | 464 | assert!(freq >= 2 && freq <= 50); |
| 479 | 465 | ||
| 480 | // Configure bus frequency into I2C peripheral | 466 | // Configure bus frequency into I2C peripheral |
| 481 | //self.i2c.cr2.write(|w| unsafe { w.freq().bits(freq as u8) }); | ||
| 482 | |||
| 483 | let trise = if speed <= 100_000 { | 467 | let trise = if speed <= 100_000 { |
| 484 | freq + 1 | 468 | freq + 1 |
| 485 | } else { | 469 | } else { |
| @@ -539,18 +523,16 @@ impl<'d, T: Instance> SetConfig for I2c<'d, T> { | |||
| 539 | type Config = Hertz; | 523 | type Config = Hertz; |
| 540 | fn set_config(&mut self, config: &Self::Config) { | 524 | fn set_config(&mut self, config: &Self::Config) { |
| 541 | let timings = Timings::new(T::frequency(), *config); | 525 | let timings = Timings::new(T::frequency(), *config); |
| 542 | unsafe { | 526 | T::regs().cr2().modify(|reg| { |
| 543 | T::regs().cr2().modify(|reg| { | 527 | reg.set_freq(timings.freq); |
| 544 | reg.set_freq(timings.freq); | 528 | }); |
| 545 | }); | 529 | T::regs().ccr().modify(|reg| { |
| 546 | T::regs().ccr().modify(|reg| { | 530 | reg.set_f_s(timings.mode.f_s()); |
| 547 | reg.set_f_s(timings.mode.f_s()); | 531 | reg.set_duty(timings.duty.duty()); |
| 548 | reg.set_duty(timings.duty.duty()); | 532 | reg.set_ccr(timings.ccr); |
| 549 | reg.set_ccr(timings.ccr); | 533 | }); |
| 550 | }); | 534 | T::regs().trise().modify(|reg| { |
| 551 | T::regs().trise().modify(|reg| { | 535 | reg.set_trise(timings.trise); |
| 552 | reg.set_trise(timings.trise); | 536 | }); |
| 553 | }); | ||
| 554 | } | ||
| 555 | } | 537 | } |
| 556 | } | 538 | } |
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 1aaf2b46b..1f036d55c 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs | |||
| @@ -89,49 +89,41 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 89 | T::enable(); | 89 | T::enable(); |
| 90 | T::reset(); | 90 | T::reset(); |
| 91 | 91 | ||
| 92 | unsafe { | 92 | scl.set_as_af_pull( |
| 93 | scl.set_as_af_pull( | 93 | scl.af_num(), |
| 94 | scl.af_num(), | 94 | AFType::OutputOpenDrain, |
| 95 | AFType::OutputOpenDrain, | 95 | match config.scl_pullup { |
| 96 | match config.scl_pullup { | 96 | true => Pull::Up, |
| 97 | true => Pull::Up, | 97 | false => Pull::None, |
| 98 | false => Pull::None, | 98 | }, |
| 99 | }, | 99 | ); |
| 100 | ); | 100 | sda.set_as_af_pull( |
| 101 | sda.set_as_af_pull( | 101 | sda.af_num(), |
| 102 | sda.af_num(), | 102 | AFType::OutputOpenDrain, |
| 103 | AFType::OutputOpenDrain, | 103 | match config.sda_pullup { |
| 104 | match config.sda_pullup { | 104 | true => Pull::Up, |
| 105 | true => Pull::Up, | 105 | false => Pull::None, |
| 106 | false => Pull::None, | 106 | }, |
| 107 | }, | 107 | ); |
| 108 | ); | 108 | |
| 109 | } | 109 | T::regs().cr1().modify(|reg| { |
| 110 | 110 | reg.set_pe(false); | |
| 111 | unsafe { | 111 | reg.set_anfoff(false); |
| 112 | T::regs().cr1().modify(|reg| { | 112 | }); |
| 113 | reg.set_pe(false); | ||
| 114 | reg.set_anfoff(false); | ||
| 115 | }); | ||
| 116 | } | ||
| 117 | 113 | ||
| 118 | let timings = Timings::new(T::frequency(), freq.into()); | 114 | let timings = Timings::new(T::frequency(), freq.into()); |
| 119 | 115 | ||
| 120 | unsafe { | 116 | T::regs().timingr().write(|reg| { |
| 121 | T::regs().timingr().write(|reg| { | 117 | reg.set_presc(timings.prescale); |
| 122 | reg.set_presc(timings.prescale); | 118 | reg.set_scll(timings.scll); |
| 123 | reg.set_scll(timings.scll); | 119 | reg.set_sclh(timings.sclh); |
| 124 | reg.set_sclh(timings.sclh); | 120 | reg.set_sdadel(timings.sdadel); |
| 125 | reg.set_sdadel(timings.sdadel); | 121 | reg.set_scldel(timings.scldel); |
| 126 | reg.set_scldel(timings.scldel); | 122 | }); |
| 127 | }); | ||
| 128 | } | ||
| 129 | 123 | ||
| 130 | unsafe { | 124 | T::regs().cr1().modify(|reg| { |
| 131 | T::regs().cr1().modify(|reg| { | 125 | reg.set_pe(true); |
| 132 | reg.set_pe(true); | 126 | }); |
| 133 | }); | ||
| 134 | } | ||
| 135 | 127 | ||
| 136 | T::Interrupt::unpend(); | 128 | T::Interrupt::unpend(); |
| 137 | unsafe { T::Interrupt::enable() }; | 129 | unsafe { T::Interrupt::enable() }; |
| @@ -144,12 +136,10 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 144 | } | 136 | } |
| 145 | 137 | ||
| 146 | fn master_stop(&mut self) { | 138 | fn master_stop(&mut self) { |
| 147 | unsafe { | 139 | T::regs().cr2().write(|w| w.set_stop(true)); |
| 148 | T::regs().cr2().write(|w| w.set_stop(true)); | ||
| 149 | } | ||
| 150 | } | 140 | } |
| 151 | 141 | ||
| 152 | unsafe fn master_read( | 142 | fn master_read( |
| 153 | address: u8, | 143 | address: u8, |
| 154 | length: usize, | 144 | length: usize, |
| 155 | stop: Stop, | 145 | stop: Stop, |
| @@ -191,7 +181,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 191 | Ok(()) | 181 | Ok(()) |
| 192 | } | 182 | } |
| 193 | 183 | ||
| 194 | unsafe fn master_write( | 184 | fn master_write( |
| 195 | address: u8, | 185 | address: u8, |
| 196 | length: usize, | 186 | length: usize, |
| 197 | stop: Stop, | 187 | stop: Stop, |
| @@ -229,7 +219,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 229 | Ok(()) | 219 | Ok(()) |
| 230 | } | 220 | } |
| 231 | 221 | ||
| 232 | unsafe fn master_continue( | 222 | fn master_continue( |
| 233 | length: usize, | 223 | length: usize, |
| 234 | reload: bool, | 224 | reload: bool, |
| 235 | check_timeout: impl Fn() -> Result<(), Error>, | 225 | check_timeout: impl Fn() -> Result<(), Error>, |
| @@ -259,13 +249,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 259 | //$i2c.txdr.write(|w| w.txdata().bits(0)); | 249 | //$i2c.txdr.write(|w| w.txdata().bits(0)); |
| 260 | //} | 250 | //} |
| 261 | 251 | ||
| 262 | unsafe { | 252 | if T::regs().isr().read().txis() { |
| 263 | if T::regs().isr().read().txis() { | 253 | T::regs().txdr().write(|w| w.set_txdata(0)); |
| 264 | T::regs().txdr().write(|w| w.set_txdata(0)); | 254 | } |
| 265 | } | 255 | if !T::regs().isr().read().txe() { |
| 266 | if !T::regs().isr().read().txe() { | 256 | T::regs().isr().modify(|w| w.set_txe(true)) |
| 267 | T::regs().isr().modify(|w| w.set_txe(true)) | ||
| 268 | } | ||
| 269 | } | 257 | } |
| 270 | 258 | ||
| 271 | // If TXDR is not flagged as empty, write 1 to flush it | 259 | // If TXDR is not flagged as empty, write 1 to flush it |
| @@ -276,21 +264,19 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 276 | 264 | ||
| 277 | fn wait_txe(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { | 265 | fn wait_txe(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { |
| 278 | loop { | 266 | loop { |
| 279 | unsafe { | 267 | let isr = T::regs().isr().read(); |
| 280 | let isr = T::regs().isr().read(); | 268 | if isr.txe() { |
| 281 | if isr.txe() { | 269 | return Ok(()); |
| 282 | return Ok(()); | 270 | } else if isr.berr() { |
| 283 | } else if isr.berr() { | 271 | T::regs().icr().write(|reg| reg.set_berrcf(true)); |
| 284 | T::regs().icr().write(|reg| reg.set_berrcf(true)); | 272 | return Err(Error::Bus); |
| 285 | return Err(Error::Bus); | 273 | } else if isr.arlo() { |
| 286 | } else if isr.arlo() { | 274 | T::regs().icr().write(|reg| reg.set_arlocf(true)); |
| 287 | T::regs().icr().write(|reg| reg.set_arlocf(true)); | 275 | return Err(Error::Arbitration); |
| 288 | return Err(Error::Arbitration); | 276 | } else if isr.nackf() { |
| 289 | } else if isr.nackf() { | 277 | T::regs().icr().write(|reg| reg.set_nackcf(true)); |
| 290 | T::regs().icr().write(|reg| reg.set_nackcf(true)); | 278 | self.flush_txdr(); |
| 291 | self.flush_txdr(); | 279 | return Err(Error::Nack); |
| 292 | return Err(Error::Nack); | ||
| 293 | } | ||
| 294 | } | 280 | } |
| 295 | 281 | ||
| 296 | check_timeout()?; | 282 | check_timeout()?; |
| @@ -299,21 +285,19 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 299 | 285 | ||
| 300 | fn wait_rxne(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { | 286 | fn wait_rxne(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { |
| 301 | loop { | 287 | loop { |
| 302 | unsafe { | 288 | let isr = T::regs().isr().read(); |
| 303 | let isr = T::regs().isr().read(); | 289 | if isr.rxne() { |
| 304 | if isr.rxne() { | 290 | return Ok(()); |
| 305 | return Ok(()); | 291 | } else if isr.berr() { |
| 306 | } else if isr.berr() { | 292 | T::regs().icr().write(|reg| reg.set_berrcf(true)); |
| 307 | T::regs().icr().write(|reg| reg.set_berrcf(true)); | 293 | return Err(Error::Bus); |
| 308 | return Err(Error::Bus); | 294 | } else if isr.arlo() { |
| 309 | } else if isr.arlo() { | 295 | T::regs().icr().write(|reg| reg.set_arlocf(true)); |
| 310 | T::regs().icr().write(|reg| reg.set_arlocf(true)); | 296 | return Err(Error::Arbitration); |
| 311 | return Err(Error::Arbitration); | 297 | } else if isr.nackf() { |
| 312 | } else if isr.nackf() { | 298 | T::regs().icr().write(|reg| reg.set_nackcf(true)); |
| 313 | T::regs().icr().write(|reg| reg.set_nackcf(true)); | 299 | self.flush_txdr(); |
| 314 | self.flush_txdr(); | 300 | return Err(Error::Nack); |
| 315 | return Err(Error::Nack); | ||
| 316 | } | ||
| 317 | } | 301 | } |
| 318 | 302 | ||
| 319 | check_timeout()?; | 303 | check_timeout()?; |
| @@ -322,21 +306,19 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 322 | 306 | ||
| 323 | fn wait_tc(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { | 307 | fn wait_tc(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { |
| 324 | loop { | 308 | loop { |
| 325 | unsafe { | 309 | let isr = T::regs().isr().read(); |
| 326 | let isr = T::regs().isr().read(); | 310 | if isr.tc() { |
| 327 | if isr.tc() { | 311 | return Ok(()); |
| 328 | return Ok(()); | 312 | } else if isr.berr() { |
| 329 | } else if isr.berr() { | 313 | T::regs().icr().write(|reg| reg.set_berrcf(true)); |
| 330 | T::regs().icr().write(|reg| reg.set_berrcf(true)); | 314 | return Err(Error::Bus); |
| 331 | return Err(Error::Bus); | 315 | } else if isr.arlo() { |
| 332 | } else if isr.arlo() { | 316 | T::regs().icr().write(|reg| reg.set_arlocf(true)); |
| 333 | T::regs().icr().write(|reg| reg.set_arlocf(true)); | 317 | return Err(Error::Arbitration); |
| 334 | return Err(Error::Arbitration); | 318 | } else if isr.nackf() { |
| 335 | } else if isr.nackf() { | 319 | T::regs().icr().write(|reg| reg.set_nackcf(true)); |
| 336 | T::regs().icr().write(|reg| reg.set_nackcf(true)); | 320 | self.flush_txdr(); |
| 337 | self.flush_txdr(); | 321 | return Err(Error::Nack); |
| 338 | return Err(Error::Nack); | ||
| 339 | } | ||
| 340 | } | 322 | } |
| 341 | 323 | ||
| 342 | check_timeout()?; | 324 | check_timeout()?; |
| @@ -358,32 +340,25 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 358 | }; | 340 | }; |
| 359 | let last_chunk_idx = total_chunks.saturating_sub(1); | 341 | let last_chunk_idx = total_chunks.saturating_sub(1); |
| 360 | 342 | ||
| 361 | unsafe { | 343 | Self::master_read( |
| 362 | Self::master_read( | 344 | address, |
| 363 | address, | 345 | read.len().min(255), |
| 364 | read.len().min(255), | 346 | Stop::Automatic, |
| 365 | Stop::Automatic, | 347 | last_chunk_idx != 0, |
| 366 | last_chunk_idx != 0, | 348 | restart, |
| 367 | restart, | 349 | &check_timeout, |
| 368 | &check_timeout, | 350 | )?; |
| 369 | )?; | ||
| 370 | } | ||
| 371 | 351 | ||
| 372 | for (number, chunk) in read.chunks_mut(255).enumerate() { | 352 | for (number, chunk) in read.chunks_mut(255).enumerate() { |
| 373 | if number != 0 { | 353 | if number != 0 { |
| 374 | // NOTE(unsafe) We have &mut self | 354 | Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?; |
| 375 | unsafe { | ||
| 376 | Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?; | ||
| 377 | } | ||
| 378 | } | 355 | } |
| 379 | 356 | ||
| 380 | for byte in chunk { | 357 | for byte in chunk { |
| 381 | // Wait until we have received something | 358 | // Wait until we have received something |
| 382 | self.wait_rxne(&check_timeout)?; | 359 | self.wait_rxne(&check_timeout)?; |
| 383 | 360 | ||
| 384 | unsafe { | 361 | *byte = T::regs().rxdr().read().rxdata(); |
| 385 | *byte = T::regs().rxdr().read().rxdata(); | ||
| 386 | } | ||
| 387 | } | 362 | } |
| 388 | } | 363 | } |
| 389 | Ok(()) | 364 | Ok(()) |
| @@ -407,23 +382,17 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 407 | // I2C start | 382 | // I2C start |
| 408 | // | 383 | // |
| 409 | // ST SAD+W | 384 | // ST SAD+W |
| 410 | // NOTE(unsafe) We have &mut self | 385 | Self::master_write( |
| 411 | unsafe { | 386 | address, |
| 412 | Self::master_write( | 387 | write.len().min(255), |
| 413 | address, | 388 | Stop::Software, |
| 414 | write.len().min(255), | 389 | last_chunk_idx != 0, |
| 415 | Stop::Software, | 390 | &check_timeout, |
| 416 | last_chunk_idx != 0, | 391 | )?; |
| 417 | &check_timeout, | ||
| 418 | )?; | ||
| 419 | } | ||
| 420 | 392 | ||
| 421 | for (number, chunk) in write.chunks(255).enumerate() { | 393 | for (number, chunk) in write.chunks(255).enumerate() { |
| 422 | if number != 0 { | 394 | if number != 0 { |
| 423 | // NOTE(unsafe) We have &mut self | 395 | Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?; |
| 424 | unsafe { | ||
| 425 | Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?; | ||
| 426 | } | ||
| 427 | } | 396 | } |
| 428 | 397 | ||
| 429 | for byte in chunk { | 398 | for byte in chunk { |
| @@ -432,9 +401,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 432 | // through) | 401 | // through) |
| 433 | self.wait_txe(&check_timeout)?; | 402 | self.wait_txe(&check_timeout)?; |
| 434 | 403 | ||
| 435 | unsafe { | 404 | T::regs().txdr().write(|w| w.set_txdata(*byte)); |
| 436 | T::regs().txdr().write(|w| w.set_txdata(*byte)); | ||
| 437 | } | ||
| 438 | } | 405 | } |
| 439 | } | 406 | } |
| 440 | // Wait until the write finishes | 407 | // Wait until the write finishes |
| @@ -467,7 +434,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 467 | w.set_tcie(true); | 434 | w.set_tcie(true); |
| 468 | } | 435 | } |
| 469 | }); | 436 | }); |
| 470 | let dst = regs.txdr().ptr() as *mut u8; | 437 | let dst = regs.txdr().as_ptr() as *mut u8; |
| 471 | 438 | ||
| 472 | let ch = &mut self.tx_dma; | 439 | let ch = &mut self.tx_dma; |
| 473 | let request = ch.request(); | 440 | let request = ch.request(); |
| @@ -479,37 +446,30 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 479 | 446 | ||
| 480 | let on_drop = OnDrop::new(|| { | 447 | let on_drop = OnDrop::new(|| { |
| 481 | let regs = T::regs(); | 448 | let regs = T::regs(); |
| 482 | unsafe { | 449 | regs.cr1().modify(|w| { |
| 483 | regs.cr1().modify(|w| { | 450 | if last_slice { |
| 484 | if last_slice { | 451 | w.set_txdmaen(false); |
| 485 | w.set_txdmaen(false); | 452 | } |
| 486 | } | 453 | w.set_tcie(false); |
| 487 | w.set_tcie(false); | 454 | }) |
| 488 | }) | ||
| 489 | } | ||
| 490 | }); | 455 | }); |
| 491 | 456 | ||
| 492 | poll_fn(|cx| { | 457 | poll_fn(|cx| { |
| 493 | state.waker.register(cx.waker()); | 458 | state.waker.register(cx.waker()); |
| 494 | 459 | ||
| 495 | let isr = unsafe { T::regs().isr().read() }; | 460 | let isr = T::regs().isr().read(); |
| 496 | if remaining_len == total_len { | 461 | if remaining_len == total_len { |
| 497 | // NOTE(unsafe) self.tx_dma does not fiddle with the i2c registers | ||
| 498 | if first_slice { | 462 | if first_slice { |
| 499 | unsafe { | 463 | Self::master_write( |
| 500 | Self::master_write( | 464 | address, |
| 501 | address, | 465 | total_len.min(255), |
| 502 | total_len.min(255), | 466 | Stop::Software, |
| 503 | Stop::Software, | 467 | (total_len > 255) || !last_slice, |
| 504 | (total_len > 255) || !last_slice, | 468 | &check_timeout, |
| 505 | &check_timeout, | 469 | )?; |
| 506 | )?; | ||
| 507 | } | ||
| 508 | } else { | 470 | } else { |
| 509 | unsafe { | 471 | Self::master_continue(total_len.min(255), (total_len > 255) || !last_slice, &check_timeout)?; |
| 510 | Self::master_continue(total_len.min(255), (total_len > 255) || !last_slice, &check_timeout)?; | 472 | T::regs().cr1().modify(|w| w.set_tcie(true)); |
| 511 | T::regs().cr1().modify(|w| w.set_tcie(true)); | ||
| 512 | } | ||
| 513 | } | 473 | } |
| 514 | } else if !(isr.tcr() || isr.tc()) { | 474 | } else if !(isr.tcr() || isr.tc()) { |
| 515 | // poll_fn was woken without an interrupt present | 475 | // poll_fn was woken without an interrupt present |
| @@ -519,13 +479,10 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 519 | } else { | 479 | } else { |
| 520 | let last_piece = (remaining_len <= 255) && last_slice; | 480 | let last_piece = (remaining_len <= 255) && last_slice; |
| 521 | 481 | ||
| 522 | // NOTE(unsafe) self.tx_dma does not fiddle with the i2c registers | 482 | if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) { |
| 523 | unsafe { | 483 | return Poll::Ready(Err(e)); |
| 524 | if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) { | ||
| 525 | return Poll::Ready(Err(e)); | ||
| 526 | } | ||
| 527 | T::regs().cr1().modify(|w| w.set_tcie(true)); | ||
| 528 | } | 484 | } |
| 485 | T::regs().cr1().modify(|w| w.set_tcie(true)); | ||
| 529 | } | 486 | } |
| 530 | 487 | ||
| 531 | remaining_len = remaining_len.saturating_sub(255); | 488 | remaining_len = remaining_len.saturating_sub(255); |
| @@ -564,7 +521,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 564 | w.set_rxdmaen(true); | 521 | w.set_rxdmaen(true); |
| 565 | w.set_tcie(true); | 522 | w.set_tcie(true); |
| 566 | }); | 523 | }); |
| 567 | let src = regs.rxdr().ptr() as *mut u8; | 524 | let src = regs.rxdr().as_ptr() as *mut u8; |
| 568 | 525 | ||
| 569 | let ch = &mut self.rx_dma; | 526 | let ch = &mut self.rx_dma; |
| 570 | let request = ch.request(); | 527 | let request = ch.request(); |
| @@ -576,30 +533,25 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 576 | 533 | ||
| 577 | let on_drop = OnDrop::new(|| { | 534 | let on_drop = OnDrop::new(|| { |
| 578 | let regs = T::regs(); | 535 | let regs = T::regs(); |
| 579 | unsafe { | 536 | regs.cr1().modify(|w| { |
| 580 | regs.cr1().modify(|w| { | 537 | w.set_rxdmaen(false); |
| 581 | w.set_rxdmaen(false); | 538 | w.set_tcie(false); |
| 582 | w.set_tcie(false); | 539 | }) |
| 583 | }) | ||
| 584 | } | ||
| 585 | }); | 540 | }); |
| 586 | 541 | ||
| 587 | poll_fn(|cx| { | 542 | poll_fn(|cx| { |
| 588 | state.waker.register(cx.waker()); | 543 | state.waker.register(cx.waker()); |
| 589 | 544 | ||
| 590 | let isr = unsafe { T::regs().isr().read() }; | 545 | let isr = T::regs().isr().read(); |
| 591 | if remaining_len == total_len { | 546 | if remaining_len == total_len { |
| 592 | // NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers | 547 | Self::master_read( |
| 593 | unsafe { | 548 | address, |
| 594 | Self::master_read( | 549 | total_len.min(255), |
| 595 | address, | 550 | Stop::Software, |
| 596 | total_len.min(255), | 551 | total_len > 255, |
| 597 | Stop::Software, | 552 | restart, |
| 598 | total_len > 255, | 553 | &check_timeout, |
| 599 | restart, | 554 | )?; |
| 600 | &check_timeout, | ||
| 601 | )?; | ||
| 602 | } | ||
| 603 | } else if !(isr.tcr() || isr.tc()) { | 555 | } else if !(isr.tcr() || isr.tc()) { |
| 604 | // poll_fn was woken without an interrupt present | 556 | // poll_fn was woken without an interrupt present |
| 605 | return Poll::Pending; | 557 | return Poll::Pending; |
| @@ -608,13 +560,10 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 608 | } else { | 560 | } else { |
| 609 | let last_piece = remaining_len <= 255; | 561 | let last_piece = remaining_len <= 255; |
| 610 | 562 | ||
| 611 | // NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers | 563 | if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) { |
| 612 | unsafe { | 564 | return Poll::Ready(Err(e)); |
| 613 | if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) { | ||
| 614 | return Poll::Ready(Err(e)); | ||
| 615 | } | ||
| 616 | T::regs().cr1().modify(|w| w.set_tcie(true)); | ||
| 617 | } | 565 | } |
| 566 | T::regs().cr1().modify(|w| w.set_tcie(true)); | ||
| 618 | } | 567 | } |
| 619 | 568 | ||
| 620 | remaining_len = remaining_len.saturating_sub(255); | 569 | remaining_len = remaining_len.saturating_sub(255); |
| @@ -758,16 +707,13 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 758 | let first_length = write[0].len(); | 707 | let first_length = write[0].len(); |
| 759 | let last_slice_index = write.len() - 1; | 708 | let last_slice_index = write.len() - 1; |
| 760 | 709 | ||
| 761 | // NOTE(unsafe) We have &mut self | 710 | Self::master_write( |
| 762 | unsafe { | 711 | address, |
| 763 | Self::master_write( | 712 | first_length.min(255), |
| 764 | address, | 713 | Stop::Software, |
| 765 | first_length.min(255), | 714 | (first_length > 255) || (last_slice_index != 0), |
| 766 | Stop::Software, | 715 | &check_timeout, |
| 767 | (first_length > 255) || (last_slice_index != 0), | 716 | )?; |
| 768 | &check_timeout, | ||
| 769 | )?; | ||
| 770 | } | ||
| 771 | 717 | ||
| 772 | for (idx, slice) in write.iter().enumerate() { | 718 | for (idx, slice) in write.iter().enumerate() { |
| 773 | let slice_len = slice.len(); | 719 | let slice_len = slice.len(); |
| @@ -780,26 +726,20 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 780 | let last_chunk_idx = total_chunks.saturating_sub(1); | 726 | let last_chunk_idx = total_chunks.saturating_sub(1); |
| 781 | 727 | ||
| 782 | if idx != 0 { | 728 | if idx != 0 { |
| 783 | // NOTE(unsafe) We have &mut self | 729 | Self::master_continue( |
| 784 | unsafe { | 730 | slice_len.min(255), |
| 785 | Self::master_continue( | 731 | (idx != last_slice_index) || (slice_len > 255), |
| 786 | slice_len.min(255), | 732 | &check_timeout, |
| 787 | (idx != last_slice_index) || (slice_len > 255), | 733 | )?; |
| 788 | &check_timeout, | ||
| 789 | )?; | ||
| 790 | } | ||
| 791 | } | 734 | } |
| 792 | 735 | ||
| 793 | for (number, chunk) in slice.chunks(255).enumerate() { | 736 | for (number, chunk) in slice.chunks(255).enumerate() { |
| 794 | if number != 0 { | 737 | if number != 0 { |
| 795 | // NOTE(unsafe) We have &mut self | 738 | Self::master_continue( |
| 796 | unsafe { | 739 | chunk.len(), |
| 797 | Self::master_continue( | 740 | (number != last_chunk_idx) || (idx != last_slice_index), |
| 798 | chunk.len(), | 741 | &check_timeout, |
| 799 | (number != last_chunk_idx) || (idx != last_slice_index), | 742 | )?; |
| 800 | &check_timeout, | ||
| 801 | )?; | ||
| 802 | } | ||
| 803 | } | 743 | } |
| 804 | 744 | ||
| 805 | for byte in chunk { | 745 | for byte in chunk { |
| @@ -810,9 +750,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 810 | 750 | ||
| 811 | // Put byte on the wire | 751 | // Put byte on the wire |
| 812 | //self.i2c.txdr.write(|w| w.txdata().bits(*byte)); | 752 | //self.i2c.txdr.write(|w| w.txdata().bits(*byte)); |
| 813 | unsafe { | 753 | T::regs().txdr().write(|w| w.set_txdata(*byte)); |
| 814 | T::regs().txdr().write(|w| w.set_txdata(*byte)); | ||
| 815 | } | ||
| 816 | } | 754 | } |
| 817 | } | 755 | } |
| 818 | } | 756 | } |
| @@ -1061,14 +999,12 @@ impl<'d, T: Instance> SetConfig for I2c<'d, T> { | |||
| 1061 | type Config = Hertz; | 999 | type Config = Hertz; |
| 1062 | fn set_config(&mut self, config: &Self::Config) { | 1000 | fn set_config(&mut self, config: &Self::Config) { |
| 1063 | let timings = Timings::new(T::frequency(), *config); | 1001 | let timings = Timings::new(T::frequency(), *config); |
| 1064 | unsafe { | 1002 | T::regs().timingr().write(|reg| { |
| 1065 | T::regs().timingr().write(|reg| { | 1003 | reg.set_presc(timings.prescale); |
| 1066 | reg.set_presc(timings.prescale); | 1004 | reg.set_scll(timings.scll); |
| 1067 | reg.set_scll(timings.scll); | 1005 | reg.set_sclh(timings.sclh); |
| 1068 | reg.set_sclh(timings.sclh); | 1006 | reg.set_sdadel(timings.sdadel); |
| 1069 | reg.set_sdadel(timings.sdadel); | 1007 | reg.set_scldel(timings.scldel); |
| 1070 | reg.set_scldel(timings.scldel); | 1008 | }); |
| 1071 | }); | ||
| 1072 | } | ||
| 1073 | } | 1009 | } |
| 1074 | } | 1010 | } |
diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs index 2bb199f68..62dda69b4 100644 --- a/embassy-stm32/src/i2s.rs +++ b/embassy-stm32/src/i2s.rs | |||
| @@ -153,19 +153,17 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> { | |||
| 153 | ) -> Self { | 153 | ) -> Self { |
| 154 | into_ref!(sd, ws, ck, mck); | 154 | into_ref!(sd, ws, ck, mck); |
| 155 | 155 | ||
| 156 | unsafe { | 156 | sd.set_as_af(sd.af_num(), AFType::OutputPushPull); |
| 157 | sd.set_as_af(sd.af_num(), AFType::OutputPushPull); | 157 | sd.set_speed(crate::gpio::Speed::VeryHigh); |
| 158 | sd.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 159 | 158 | ||
| 160 | ws.set_as_af(ws.af_num(), AFType::OutputPushPull); | 159 | ws.set_as_af(ws.af_num(), AFType::OutputPushPull); |
| 161 | ws.set_speed(crate::gpio::Speed::VeryHigh); | 160 | ws.set_speed(crate::gpio::Speed::VeryHigh); |
| 162 | 161 | ||
| 163 | ck.set_as_af(ck.af_num(), AFType::OutputPushPull); | 162 | ck.set_as_af(ck.af_num(), AFType::OutputPushPull); |
| 164 | ck.set_speed(crate::gpio::Speed::VeryHigh); | 163 | ck.set_speed(crate::gpio::Speed::VeryHigh); |
| 165 | 164 | ||
| 166 | mck.set_as_af(mck.af_num(), AFType::OutputPushPull); | 165 | mck.set_as_af(mck.af_num(), AFType::OutputPushPull); |
| 167 | mck.set_speed(crate::gpio::Speed::VeryHigh); | 166 | mck.set_speed(crate::gpio::Speed::VeryHigh); |
| 168 | } | ||
| 169 | 167 | ||
| 170 | let spi = Spi::new_internal(peri, txdma, rxdma, freq, SpiConfig::default()); | 168 | let spi = Spi::new_internal(peri, txdma, rxdma, freq, SpiConfig::default()); |
| 171 | 169 | ||
| @@ -178,7 +176,7 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> { | |||
| 178 | let (odd, div) = compute_baud_rate(pclk, freq, config.master_clock, config.format); | 176 | let (odd, div) = compute_baud_rate(pclk, freq, config.master_clock, config.format); |
| 179 | 177 | ||
| 180 | #[cfg(any(spi_v1, spi_f1))] | 178 | #[cfg(any(spi_v1, spi_f1))] |
| 181 | unsafe { | 179 | { |
| 182 | use stm32_metapac::spi::vals::{I2scfg, Odd}; | 180 | use stm32_metapac::spi::vals::{I2scfg, Odd}; |
| 183 | 181 | ||
| 184 | // 1. Select the I2SDIV[7:0] bits in the SPI_I2SPR register to define the serial clock baud | 182 | // 1. Select the I2SDIV[7:0] bits in the SPI_I2SPR register to define the serial clock baud |
| @@ -232,10 +230,6 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> { | |||
| 232 | w.set_i2se(true) | 230 | w.set_i2se(true) |
| 233 | }); | 231 | }); |
| 234 | } | 232 | } |
| 235 | #[cfg(spi_v2)] | ||
| 236 | unsafe {} | ||
| 237 | #[cfg(any(spi_v3, spi_v4))] | ||
| 238 | unsafe {} | ||
| 239 | 233 | ||
| 240 | Self { | 234 | Self { |
| 241 | _peri: spi, | 235 | _peri: spi, |
| @@ -264,12 +258,10 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> { | |||
| 264 | 258 | ||
| 265 | impl<'d, T: Instance, Tx, Rx> Drop for I2S<'d, T, Tx, Rx> { | 259 | impl<'d, T: Instance, Tx, Rx> Drop for I2S<'d, T, Tx, Rx> { |
| 266 | fn drop(&mut self) { | 260 | fn drop(&mut self) { |
| 267 | unsafe { | 261 | self.sd.as_ref().map(|x| x.set_as_disconnected()); |
| 268 | self.sd.as_ref().map(|x| x.set_as_disconnected()); | 262 | self.ws.as_ref().map(|x| x.set_as_disconnected()); |
| 269 | self.ws.as_ref().map(|x| x.set_as_disconnected()); | 263 | self.ck.as_ref().map(|x| x.set_as_disconnected()); |
| 270 | self.ck.as_ref().map(|x| x.set_as_disconnected()); | 264 | self.mck.as_ref().map(|x| x.set_as_disconnected()); |
| 271 | self.mck.as_ref().map(|x| x.set_as_disconnected()); | ||
| 272 | } | ||
| 273 | } | 265 | } |
| 274 | } | 266 | } |
| 275 | 267 | ||
diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs index 609c4d2c3..3062226c7 100644 --- a/embassy-stm32/src/ipcc.rs +++ b/embassy-stm32/src/ipcc.rs | |||
| @@ -26,7 +26,7 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::IPCC_C1_RX> for Receive | |||
| 26 | ]; | 26 | ]; |
| 27 | 27 | ||
| 28 | // Status register gives channel occupied status. For rx, use cpu1. | 28 | // Status register gives channel occupied status. For rx, use cpu1. |
| 29 | let sr = unsafe { regs.cpu(1).sr().read() }; | 29 | let sr = regs.cpu(1).sr().read(); |
| 30 | regs.cpu(0).mr().modify(|w| { | 30 | regs.cpu(0).mr().modify(|w| { |
| 31 | for channel in channels { | 31 | for channel in channels { |
| 32 | if sr.chf(channel as usize) { | 32 | if sr.chf(channel as usize) { |
| @@ -57,7 +57,7 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::IPCC_C1_TX> for Transmi | |||
| 57 | ]; | 57 | ]; |
| 58 | 58 | ||
| 59 | // Status register gives channel occupied status. For tx, use cpu0. | 59 | // Status register gives channel occupied status. For tx, use cpu0. |
| 60 | let sr = unsafe { regs.cpu(0).sr().read() }; | 60 | let sr = regs.cpu(0).sr().read(); |
| 61 | regs.cpu(0).mr().modify(|w| { | 61 | regs.cpu(0).mr().modify(|w| { |
| 62 | for channel in channels { | 62 | for channel in channels { |
| 63 | if !sr.chf(channel as usize) { | 63 | if !sr.chf(channel as usize) { |
| @@ -98,16 +98,14 @@ impl Ipcc { | |||
| 98 | IPCC::reset(); | 98 | IPCC::reset(); |
| 99 | IPCC::set_cpu2(true); | 99 | IPCC::set_cpu2(true); |
| 100 | 100 | ||
| 101 | unsafe { _configure_pwr() }; | 101 | _configure_pwr(); |
| 102 | 102 | ||
| 103 | let regs = IPCC::regs(); | 103 | let regs = IPCC::regs(); |
| 104 | 104 | ||
| 105 | unsafe { | 105 | regs.cpu(0).cr().modify(|w| { |
| 106 | regs.cpu(0).cr().modify(|w| { | 106 | w.set_rxoie(true); |
| 107 | w.set_rxoie(true); | 107 | w.set_txfie(true); |
| 108 | w.set_txfie(true); | 108 | }); |
| 109 | }) | ||
| 110 | } | ||
| 111 | 109 | ||
| 112 | // enable interrupts | 110 | // enable interrupts |
| 113 | crate::interrupt::typelevel::IPCC_C1_RX::unpend(); | 111 | crate::interrupt::typelevel::IPCC_C1_RX::unpend(); |
| @@ -129,7 +127,7 @@ impl Ipcc { | |||
| 129 | compiler_fence(Ordering::SeqCst); | 127 | compiler_fence(Ordering::SeqCst); |
| 130 | 128 | ||
| 131 | trace!("ipcc: ch {}: send data", channel as u8); | 129 | trace!("ipcc: ch {}: send data", channel as u8); |
| 132 | unsafe { regs.cpu(0).scr().write(|w| w.set_chs(channel as usize, true)) } | 130 | regs.cpu(0).scr().write(|w| w.set_chs(channel as usize, true)); |
| 133 | } | 131 | } |
| 134 | 132 | ||
| 135 | /// Wait for the tx channel to become clear | 133 | /// Wait for the tx channel to become clear |
| @@ -137,20 +135,20 @@ impl Ipcc { | |||
| 137 | let regs = IPCC::regs(); | 135 | let regs = IPCC::regs(); |
| 138 | 136 | ||
| 139 | // This is a race, but is nice for debugging | 137 | // This is a race, but is nice for debugging |
| 140 | if unsafe { regs.cpu(0).sr().read() }.chf(channel as usize) { | 138 | if regs.cpu(0).sr().read().chf(channel as usize) { |
| 141 | trace!("ipcc: ch {}: wait for tx free", channel as u8); | 139 | trace!("ipcc: ch {}: wait for tx free", channel as u8); |
| 142 | } | 140 | } |
| 143 | 141 | ||
| 144 | poll_fn(|cx| { | 142 | poll_fn(|cx| { |
| 145 | IPCC::state().tx_waker_for(channel).register(cx.waker()); | 143 | IPCC::state().tx_waker_for(channel).register(cx.waker()); |
| 146 | // If bit is set to 1 then interrupt is disabled; we want to enable the interrupt | 144 | // If bit is set to 1 then interrupt is disabled; we want to enable the interrupt |
| 147 | unsafe { regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, false)) } | 145 | regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, false)); |
| 148 | 146 | ||
| 149 | compiler_fence(Ordering::SeqCst); | 147 | compiler_fence(Ordering::SeqCst); |
| 150 | 148 | ||
| 151 | if !unsafe { regs.cpu(0).sr().read() }.chf(channel as usize) { | 149 | if !regs.cpu(0).sr().read().chf(channel as usize) { |
| 152 | // If bit is set to 1 then interrupt is disabled; we want to disable the interrupt | 150 | // If bit is set to 1 then interrupt is disabled; we want to disable the interrupt |
| 153 | unsafe { regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, true)) } | 151 | regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, true)); |
| 154 | 152 | ||
| 155 | Poll::Ready(()) | 153 | Poll::Ready(()) |
| 156 | } else { | 154 | } else { |
| @@ -166,20 +164,20 @@ impl Ipcc { | |||
| 166 | 164 | ||
| 167 | loop { | 165 | loop { |
| 168 | // This is a race, but is nice for debugging | 166 | // This is a race, but is nice for debugging |
| 169 | if !unsafe { regs.cpu(1).sr().read() }.chf(channel as usize) { | 167 | if !regs.cpu(1).sr().read().chf(channel as usize) { |
| 170 | trace!("ipcc: ch {}: wait for rx occupied", channel as u8); | 168 | trace!("ipcc: ch {}: wait for rx occupied", channel as u8); |
| 171 | } | 169 | } |
| 172 | 170 | ||
| 173 | poll_fn(|cx| { | 171 | poll_fn(|cx| { |
| 174 | IPCC::state().rx_waker_for(channel).register(cx.waker()); | 172 | IPCC::state().rx_waker_for(channel).register(cx.waker()); |
| 175 | // If bit is set to 1 then interrupt is disabled; we want to enable the interrupt | 173 | // If bit is set to 1 then interrupt is disabled; we want to enable the interrupt |
| 176 | unsafe { regs.cpu(0).mr().modify(|w| w.set_chom(channel as usize, false)) } | 174 | regs.cpu(0).mr().modify(|w| w.set_chom(channel as usize, false)); |
| 177 | 175 | ||
| 178 | compiler_fence(Ordering::SeqCst); | 176 | compiler_fence(Ordering::SeqCst); |
| 179 | 177 | ||
| 180 | if unsafe { regs.cpu(1).sr().read() }.chf(channel as usize) { | 178 | if regs.cpu(1).sr().read().chf(channel as usize) { |
| 181 | // If bit is set to 1 then interrupt is disabled; we want to disable the interrupt | 179 | // If bit is set to 1 then interrupt is disabled; we want to disable the interrupt |
| 182 | unsafe { regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, true)) } | 180 | regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, true)); |
| 183 | 181 | ||
| 184 | Poll::Ready(()) | 182 | Poll::Ready(()) |
| 185 | } else { | 183 | } else { |
| @@ -199,7 +197,7 @@ impl Ipcc { | |||
| 199 | trace!("ipcc: ch {}: clear rx", channel as u8); | 197 | trace!("ipcc: ch {}: clear rx", channel as u8); |
| 200 | compiler_fence(Ordering::SeqCst); | 198 | compiler_fence(Ordering::SeqCst); |
| 201 | // If the channel is clear and the read function returns none, fetch more data | 199 | // If the channel is clear and the read function returns none, fetch more data |
| 202 | unsafe { regs.cpu(0).scr().write(|w| w.set_chc(channel as usize, true)) } | 200 | regs.cpu(0).scr().write(|w| w.set_chc(channel as usize, true)); |
| 203 | } | 201 | } |
| 204 | } | 202 | } |
| 205 | } | 203 | } |
| @@ -210,7 +208,7 @@ impl sealed::Instance for crate::peripherals::IPCC { | |||
| 210 | } | 208 | } |
| 211 | 209 | ||
| 212 | fn set_cpu2(enabled: bool) { | 210 | fn set_cpu2(enabled: bool) { |
| 213 | unsafe { crate::pac::PWR.cr4().modify(|w| w.set_c2boot(enabled)) } | 211 | crate::pac::PWR.cr4().modify(|w| w.set_c2boot(enabled)); |
| 214 | } | 212 | } |
| 215 | 213 | ||
| 216 | fn state() -> &'static self::sealed::State { | 214 | fn state() -> &'static self::sealed::State { |
| @@ -269,7 +267,7 @@ pub(crate) mod sealed { | |||
| 269 | } | 267 | } |
| 270 | } | 268 | } |
| 271 | 269 | ||
| 272 | unsafe fn _configure_pwr() { | 270 | fn _configure_pwr() { |
| 273 | // TODO: move this to RCC | 271 | // TODO: move this to RCC |
| 274 | 272 | ||
| 275 | let pwr = crate::pac::PWR; | 273 | let pwr = crate::pac::PWR; |
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 6fde61c06..45a7b5476 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs | |||
| @@ -146,35 +146,35 @@ impl Default for Config { | |||
| 146 | pub fn init(config: Config) -> Peripherals { | 146 | pub fn init(config: Config) -> Peripherals { |
| 147 | let p = Peripherals::take(); | 147 | let p = Peripherals::take(); |
| 148 | 148 | ||
| 149 | unsafe { | 149 | #[cfg(dbgmcu)] |
| 150 | #[cfg(dbgmcu)] | 150 | if config.enable_debug_during_sleep { |
| 151 | if config.enable_debug_during_sleep { | 151 | crate::pac::DBGMCU.cr().modify(|cr| { |
| 152 | crate::pac::DBGMCU.cr().modify(|cr| { | 152 | #[cfg(any(dbgmcu_f0, dbgmcu_c0, dbgmcu_g0, dbgmcu_u5))] |
| 153 | #[cfg(any(dbgmcu_f0, dbgmcu_c0, dbgmcu_g0, dbgmcu_u5))] | 153 | { |
| 154 | { | 154 | cr.set_dbg_stop(true); |
| 155 | cr.set_dbg_stop(true); | 155 | cr.set_dbg_standby(true); |
| 156 | cr.set_dbg_standby(true); | 156 | } |
| 157 | } | 157 | #[cfg(any( |
| 158 | #[cfg(any( | 158 | dbgmcu_f1, dbgmcu_f2, dbgmcu_f3, dbgmcu_f4, dbgmcu_f7, dbgmcu_g4, dbgmcu_f7, dbgmcu_l0, dbgmcu_l1, |
| 159 | dbgmcu_f1, dbgmcu_f2, dbgmcu_f3, dbgmcu_f4, dbgmcu_f7, dbgmcu_g4, dbgmcu_f7, dbgmcu_l0, dbgmcu_l1, | 159 | dbgmcu_l4, dbgmcu_wb, dbgmcu_wl |
| 160 | dbgmcu_l4, dbgmcu_wb, dbgmcu_wl | 160 | ))] |
| 161 | ))] | 161 | { |
| 162 | { | 162 | cr.set_dbg_sleep(true); |
| 163 | cr.set_dbg_sleep(true); | 163 | cr.set_dbg_stop(true); |
| 164 | cr.set_dbg_stop(true); | 164 | cr.set_dbg_standby(true); |
| 165 | cr.set_dbg_standby(true); | 165 | } |
| 166 | } | 166 | #[cfg(dbgmcu_h7)] |
| 167 | #[cfg(dbgmcu_h7)] | 167 | { |
| 168 | { | 168 | cr.set_d1dbgcken(true); |
| 169 | cr.set_d1dbgcken(true); | 169 | cr.set_d3dbgcken(true); |
| 170 | cr.set_d3dbgcken(true); | 170 | cr.set_dbgsleep_d1(true); |
| 171 | cr.set_dbgsleep_d1(true); | 171 | cr.set_dbgstby_d1(true); |
| 172 | cr.set_dbgstby_d1(true); | 172 | cr.set_dbgstop_d1(true); |
| 173 | cr.set_dbgstop_d1(true); | 173 | } |
| 174 | } | 174 | }); |
| 175 | }); | 175 | } |
| 176 | } | ||
| 177 | 176 | ||
| 177 | unsafe { | ||
| 178 | gpio::init(); | 178 | gpio::init(); |
| 179 | dma::init( | 179 | dma::init( |
| 180 | #[cfg(bdma)] | 180 | #[cfg(bdma)] |
diff --git a/embassy-stm32/src/pwm/complementary_pwm.rs b/embassy-stm32/src/pwm/complementary_pwm.rs index cfb79947c..0e153202e 100644 --- a/embassy-stm32/src/pwm/complementary_pwm.rs +++ b/embassy-stm32/src/pwm/complementary_pwm.rs | |||
| @@ -21,7 +21,7 @@ macro_rules! complementary_channel_impl { | |||
| 21 | impl<'d, Perip: CaptureCompare16bitInstance> ComplementaryPwmPin<'d, Perip, $channel> { | 21 | impl<'d, Perip: CaptureCompare16bitInstance> ComplementaryPwmPin<'d, Perip, $channel> { |
| 22 | pub fn $new_chx(pin: impl Peripheral<P = impl $complementary_pin_trait<Perip>> + 'd) -> Self { | 22 | pub fn $new_chx(pin: impl Peripheral<P = impl $complementary_pin_trait<Perip>> + 'd) -> Self { |
| 23 | into_ref!(pin); | 23 | into_ref!(pin); |
| 24 | critical_section::with(|_| unsafe { | 24 | critical_section::with(|_| { |
| 25 | pin.set_low(); | 25 | pin.set_low(); |
| 26 | pin.set_as_af(pin.af_num(), AFType::OutputPushPull); | 26 | pin.set_as_af(pin.af_num(), AFType::OutputPushPull); |
| 27 | #[cfg(gpio_v2)] | 27 | #[cfg(gpio_v2)] |
| @@ -72,33 +72,27 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { | |||
| 72 | this.inner.set_frequency(freq); | 72 | this.inner.set_frequency(freq); |
| 73 | this.inner.start(); | 73 | this.inner.start(); |
| 74 | 74 | ||
| 75 | unsafe { | 75 | this.inner.enable_outputs(true); |
| 76 | this.inner.enable_outputs(true); | 76 | |
| 77 | 77 | this.inner | |
| 78 | this.inner | 78 | .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1); |
| 79 | .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1); | 79 | this.inner |
| 80 | this.inner | 80 | .set_output_compare_mode(Channel::Ch2, OutputCompareMode::PwmMode1); |
| 81 | .set_output_compare_mode(Channel::Ch2, OutputCompareMode::PwmMode1); | 81 | this.inner |
| 82 | this.inner | 82 | .set_output_compare_mode(Channel::Ch3, OutputCompareMode::PwmMode1); |
| 83 | .set_output_compare_mode(Channel::Ch3, OutputCompareMode::PwmMode1); | 83 | this.inner |
| 84 | this.inner | 84 | .set_output_compare_mode(Channel::Ch4, OutputCompareMode::PwmMode1); |
| 85 | .set_output_compare_mode(Channel::Ch4, OutputCompareMode::PwmMode1); | ||
| 86 | } | ||
| 87 | this | 85 | this |
| 88 | } | 86 | } |
| 89 | 87 | ||
| 90 | pub fn enable(&mut self, channel: Channel) { | 88 | pub fn enable(&mut self, channel: Channel) { |
| 91 | unsafe { | 89 | self.inner.enable_channel(channel, true); |
| 92 | self.inner.enable_channel(channel, true); | 90 | self.inner.enable_complementary_channel(channel, true); |
| 93 | self.inner.enable_complementary_channel(channel, true); | ||
| 94 | } | ||
| 95 | } | 91 | } |
| 96 | 92 | ||
| 97 | pub fn disable(&mut self, channel: Channel) { | 93 | pub fn disable(&mut self, channel: Channel) { |
| 98 | unsafe { | 94 | self.inner.enable_complementary_channel(channel, false); |
| 99 | self.inner.enable_complementary_channel(channel, false); | 95 | self.inner.enable_channel(channel, false); |
| 100 | self.inner.enable_channel(channel, false); | ||
| 101 | } | ||
| 102 | } | 96 | } |
| 103 | 97 | ||
| 104 | pub fn set_freq(&mut self, freq: Hertz) { | 98 | pub fn set_freq(&mut self, freq: Hertz) { |
| @@ -106,22 +100,20 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { | |||
| 106 | } | 100 | } |
| 107 | 101 | ||
| 108 | pub fn get_max_duty(&self) -> u16 { | 102 | pub fn get_max_duty(&self) -> u16 { |
| 109 | unsafe { self.inner.get_max_compare_value() } | 103 | self.inner.get_max_compare_value() |
| 110 | } | 104 | } |
| 111 | 105 | ||
| 112 | pub fn set_duty(&mut self, channel: Channel, duty: u16) { | 106 | pub fn set_duty(&mut self, channel: Channel, duty: u16) { |
| 113 | assert!(duty < self.get_max_duty()); | 107 | assert!(duty < self.get_max_duty()); |
| 114 | unsafe { self.inner.set_compare_value(channel, duty) } | 108 | self.inner.set_compare_value(channel, duty) |
| 115 | } | 109 | } |
| 116 | 110 | ||
| 117 | /// Set the dead time as a proportion of max_duty | 111 | /// Set the dead time as a proportion of max_duty |
| 118 | pub fn set_dead_time(&mut self, value: u16) { | 112 | pub fn set_dead_time(&mut self, value: u16) { |
| 119 | let (ckd, value) = compute_dead_time_value(value); | 113 | let (ckd, value) = compute_dead_time_value(value); |
| 120 | 114 | ||
| 121 | unsafe { | 115 | self.inner.set_dead_time_clock_division(ckd); |
| 122 | self.inner.set_dead_time_clock_division(ckd); | 116 | self.inner.set_dead_time_value(value); |
| 123 | self.inner.set_dead_time_value(value); | ||
| 124 | } | ||
| 125 | } | 117 | } |
| 126 | } | 118 | } |
| 127 | 119 | ||
diff --git a/embassy-stm32/src/pwm/mod.rs b/embassy-stm32/src/pwm/mod.rs index 0bef07089..5aba2663e 100644 --- a/embassy-stm32/src/pwm/mod.rs +++ b/embassy-stm32/src/pwm/mod.rs | |||
| @@ -59,33 +59,33 @@ pub(crate) mod sealed { | |||
| 59 | 59 | ||
| 60 | pub trait CaptureCompare16bitInstance: crate::timer::sealed::GeneralPurpose16bitInstance { | 60 | pub trait CaptureCompare16bitInstance: crate::timer::sealed::GeneralPurpose16bitInstance { |
| 61 | /// Global output enable. Does not do anything on non-advanced timers. | 61 | /// Global output enable. Does not do anything on non-advanced timers. |
| 62 | unsafe fn enable_outputs(&mut self, enable: bool); | 62 | fn enable_outputs(&mut self, enable: bool); |
| 63 | 63 | ||
| 64 | unsafe fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); | 64 | fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); |
| 65 | 65 | ||
| 66 | unsafe fn enable_channel(&mut self, channel: Channel, enable: bool); | 66 | fn enable_channel(&mut self, channel: Channel, enable: bool); |
| 67 | 67 | ||
| 68 | unsafe fn set_compare_value(&mut self, channel: Channel, value: u16); | 68 | fn set_compare_value(&mut self, channel: Channel, value: u16); |
| 69 | 69 | ||
| 70 | unsafe fn get_max_compare_value(&self) -> u16; | 70 | fn get_max_compare_value(&self) -> u16; |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance { | 73 | pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance { |
| 74 | unsafe fn set_dead_time_clock_division(&mut self, value: Ckd); | 74 | fn set_dead_time_clock_division(&mut self, value: Ckd); |
| 75 | 75 | ||
| 76 | unsafe fn set_dead_time_value(&mut self, value: u8); | 76 | fn set_dead_time_value(&mut self, value: u8); |
| 77 | 77 | ||
| 78 | unsafe fn enable_complementary_channel(&mut self, channel: Channel, enable: bool); | 78 | fn enable_complementary_channel(&mut self, channel: Channel, enable: bool); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | pub trait CaptureCompare32bitInstance: crate::timer::sealed::GeneralPurpose32bitInstance { | 81 | pub trait CaptureCompare32bitInstance: crate::timer::sealed::GeneralPurpose32bitInstance { |
| 82 | unsafe fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); | 82 | fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); |
| 83 | 83 | ||
| 84 | unsafe fn enable_channel(&mut self, channel: Channel, enable: bool); | 84 | fn enable_channel(&mut self, channel: Channel, enable: bool); |
| 85 | 85 | ||
| 86 | unsafe fn set_compare_value(&mut self, channel: Channel, value: u32); | 86 | fn set_compare_value(&mut self, channel: Channel, value: u32); |
| 87 | 87 | ||
| 88 | unsafe fn get_max_compare_value(&self) -> u32; | 88 | fn get_max_compare_value(&self) -> u32; |
| 89 | } | 89 | } |
| 90 | } | 90 | } |
| 91 | 91 | ||
| @@ -108,9 +108,9 @@ pub trait CaptureCompare32bitInstance: | |||
| 108 | macro_rules! impl_compare_capable_16bit { | 108 | macro_rules! impl_compare_capable_16bit { |
| 109 | ($inst:ident) => { | 109 | ($inst:ident) => { |
| 110 | impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { | 110 | impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { |
| 111 | unsafe fn enable_outputs(&mut self, _enable: bool) {} | 111 | fn enable_outputs(&mut self, _enable: bool) {} |
| 112 | 112 | ||
| 113 | unsafe fn set_output_compare_mode(&mut self, channel: crate::pwm::Channel, mode: OutputCompareMode) { | 113 | fn set_output_compare_mode(&mut self, channel: crate::pwm::Channel, mode: OutputCompareMode) { |
| 114 | use crate::timer::sealed::GeneralPurpose16bitInstance; | 114 | use crate::timer::sealed::GeneralPurpose16bitInstance; |
| 115 | let r = Self::regs_gp16(); | 115 | let r = Self::regs_gp16(); |
| 116 | let raw_channel: usize = channel.raw(); | 116 | let raw_channel: usize = channel.raw(); |
| @@ -118,19 +118,19 @@ macro_rules! impl_compare_capable_16bit { | |||
| 118 | .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); | 118 | .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | unsafe fn enable_channel(&mut self, channel: Channel, enable: bool) { | 121 | fn enable_channel(&mut self, channel: Channel, enable: bool) { |
| 122 | use crate::timer::sealed::GeneralPurpose16bitInstance; | 122 | use crate::timer::sealed::GeneralPurpose16bitInstance; |
| 123 | Self::regs_gp16() | 123 | Self::regs_gp16() |
| 124 | .ccer() | 124 | .ccer() |
| 125 | .modify(|w| w.set_cce(channel.raw(), enable)); | 125 | .modify(|w| w.set_cce(channel.raw(), enable)); |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | unsafe fn set_compare_value(&mut self, channel: Channel, value: u16) { | 128 | fn set_compare_value(&mut self, channel: Channel, value: u16) { |
| 129 | use crate::timer::sealed::GeneralPurpose16bitInstance; | 129 | use crate::timer::sealed::GeneralPurpose16bitInstance; |
| 130 | Self::regs_gp16().ccr(channel.raw()).modify(|w| w.set_ccr(value)); | 130 | Self::regs_gp16().ccr(channel.raw()).modify(|w| w.set_ccr(value)); |
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | unsafe fn get_max_compare_value(&self) -> u16 { | 133 | fn get_max_compare_value(&self) -> u16 { |
| 134 | use crate::timer::sealed::GeneralPurpose16bitInstance; | 134 | use crate::timer::sealed::GeneralPurpose16bitInstance; |
| 135 | Self::regs_gp16().arr().read().arr() | 135 | Self::regs_gp16().arr().read().arr() |
| 136 | } | 136 | } |
| @@ -150,7 +150,7 @@ foreach_interrupt! { | |||
| 150 | ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => { | 150 | ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => { |
| 151 | impl_compare_capable_16bit!($inst); | 151 | impl_compare_capable_16bit!($inst); |
| 152 | impl crate::pwm::sealed::CaptureCompare32bitInstance for crate::peripherals::$inst { | 152 | impl crate::pwm::sealed::CaptureCompare32bitInstance for crate::peripherals::$inst { |
| 153 | unsafe fn set_output_compare_mode( | 153 | fn set_output_compare_mode( |
| 154 | &mut self, | 154 | &mut self, |
| 155 | channel: crate::pwm::Channel, | 155 | channel: crate::pwm::Channel, |
| 156 | mode: OutputCompareMode, | 156 | mode: OutputCompareMode, |
| @@ -160,17 +160,17 @@ foreach_interrupt! { | |||
| 160 | Self::regs_gp32().ccmr_output(raw_channel / 2).modify(|w| w.set_ocm(raw_channel % 2, mode.into())); | 160 | Self::regs_gp32().ccmr_output(raw_channel / 2).modify(|w| w.set_ocm(raw_channel % 2, mode.into())); |
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | unsafe fn enable_channel(&mut self, channel: Channel, enable: bool) { | 163 | fn enable_channel(&mut self, channel: Channel, enable: bool) { |
| 164 | use crate::timer::sealed::GeneralPurpose32bitInstance; | 164 | use crate::timer::sealed::GeneralPurpose32bitInstance; |
| 165 | Self::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), enable)); | 165 | Self::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), enable)); |
| 166 | } | 166 | } |
| 167 | 167 | ||
| 168 | unsafe fn set_compare_value(&mut self, channel: Channel, value: u32) { | 168 | fn set_compare_value(&mut self, channel: Channel, value: u32) { |
| 169 | use crate::timer::sealed::GeneralPurpose32bitInstance; | 169 | use crate::timer::sealed::GeneralPurpose32bitInstance; |
| 170 | Self::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(value)); | 170 | Self::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(value)); |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | unsafe fn get_max_compare_value(&self) -> u32 { | 173 | fn get_max_compare_value(&self) -> u32 { |
| 174 | use crate::timer::sealed::GeneralPurpose32bitInstance; | 174 | use crate::timer::sealed::GeneralPurpose32bitInstance; |
| 175 | Self::regs_gp32().arr().read().arr() as u32 | 175 | Self::regs_gp32().arr().read().arr() as u32 |
| 176 | } | 176 | } |
| @@ -185,13 +185,13 @@ foreach_interrupt! { | |||
| 185 | 185 | ||
| 186 | ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => { | 186 | ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => { |
| 187 | impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { | 187 | impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { |
| 188 | unsafe fn enable_outputs(&mut self, enable: bool) { | 188 | fn enable_outputs(&mut self, enable: bool) { |
| 189 | use crate::timer::sealed::AdvancedControlInstance; | 189 | use crate::timer::sealed::AdvancedControlInstance; |
| 190 | let r = Self::regs_advanced(); | 190 | let r = Self::regs_advanced(); |
| 191 | r.bdtr().modify(|w| w.set_moe(enable)); | 191 | r.bdtr().modify(|w| w.set_moe(enable)); |
| 192 | } | 192 | } |
| 193 | 193 | ||
| 194 | unsafe fn set_output_compare_mode( | 194 | fn set_output_compare_mode( |
| 195 | &mut self, | 195 | &mut self, |
| 196 | channel: crate::pwm::Channel, | 196 | channel: crate::pwm::Channel, |
| 197 | mode: OutputCompareMode, | 197 | mode: OutputCompareMode, |
| @@ -203,21 +203,21 @@ foreach_interrupt! { | |||
| 203 | .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); | 203 | .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); |
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | unsafe fn enable_channel(&mut self, channel: Channel, enable: bool) { | 206 | fn enable_channel(&mut self, channel: Channel, enable: bool) { |
| 207 | use crate::timer::sealed::AdvancedControlInstance; | 207 | use crate::timer::sealed::AdvancedControlInstance; |
| 208 | Self::regs_advanced() | 208 | Self::regs_advanced() |
| 209 | .ccer() | 209 | .ccer() |
| 210 | .modify(|w| w.set_cce(channel.raw(), enable)); | 210 | .modify(|w| w.set_cce(channel.raw(), enable)); |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | unsafe fn set_compare_value(&mut self, channel: Channel, value: u16) { | 213 | fn set_compare_value(&mut self, channel: Channel, value: u16) { |
| 214 | use crate::timer::sealed::AdvancedControlInstance; | 214 | use crate::timer::sealed::AdvancedControlInstance; |
| 215 | Self::regs_advanced() | 215 | Self::regs_advanced() |
| 216 | .ccr(channel.raw()) | 216 | .ccr(channel.raw()) |
| 217 | .modify(|w| w.set_ccr(value)); | 217 | .modify(|w| w.set_ccr(value)); |
| 218 | } | 218 | } |
| 219 | 219 | ||
| 220 | unsafe fn get_max_compare_value(&self) -> u16 { | 220 | fn get_max_compare_value(&self) -> u16 { |
| 221 | use crate::timer::sealed::AdvancedControlInstance; | 221 | use crate::timer::sealed::AdvancedControlInstance; |
| 222 | Self::regs_advanced().arr().read().arr() | 222 | Self::regs_advanced().arr().read().arr() |
| 223 | } | 223 | } |
| @@ -228,17 +228,17 @@ foreach_interrupt! { | |||
| 228 | } | 228 | } |
| 229 | 229 | ||
| 230 | impl crate::pwm::sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst { | 230 | impl crate::pwm::sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst { |
| 231 | unsafe fn set_dead_time_clock_division(&mut self, value: Ckd) { | 231 | fn set_dead_time_clock_division(&mut self, value: Ckd) { |
| 232 | use crate::timer::sealed::AdvancedControlInstance; | 232 | use crate::timer::sealed::AdvancedControlInstance; |
| 233 | Self::regs_advanced().cr1().modify(|w| w.set_ckd(value)); | 233 | Self::regs_advanced().cr1().modify(|w| w.set_ckd(value)); |
| 234 | } | 234 | } |
| 235 | 235 | ||
| 236 | unsafe fn set_dead_time_value(&mut self, value: u8) { | 236 | fn set_dead_time_value(&mut self, value: u8) { |
| 237 | use crate::timer::sealed::AdvancedControlInstance; | 237 | use crate::timer::sealed::AdvancedControlInstance; |
| 238 | Self::regs_advanced().bdtr().modify(|w| w.set_dtg(value)); | 238 | Self::regs_advanced().bdtr().modify(|w| w.set_dtg(value)); |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | unsafe fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) { | 241 | fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) { |
| 242 | use crate::timer::sealed::AdvancedControlInstance; | 242 | use crate::timer::sealed::AdvancedControlInstance; |
| 243 | Self::regs_advanced() | 243 | Self::regs_advanced() |
| 244 | .ccer() | 244 | .ccer() |
diff --git a/embassy-stm32/src/pwm/simple_pwm.rs b/embassy-stm32/src/pwm/simple_pwm.rs index b045a2d78..995f59c23 100644 --- a/embassy-stm32/src/pwm/simple_pwm.rs +++ b/embassy-stm32/src/pwm/simple_pwm.rs | |||
| @@ -24,7 +24,7 @@ macro_rules! channel_impl { | |||
| 24 | impl<'d, Perip: CaptureCompare16bitInstance> PwmPin<'d, Perip, $channel> { | 24 | impl<'d, Perip: CaptureCompare16bitInstance> PwmPin<'d, Perip, $channel> { |
| 25 | pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd) -> Self { | 25 | pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd) -> Self { |
| 26 | into_ref!(pin); | 26 | into_ref!(pin); |
| 27 | critical_section::with(|_| unsafe { | 27 | critical_section::with(|_| { |
| 28 | pin.set_low(); | 28 | pin.set_low(); |
| 29 | pin.set_as_af(pin.af_num(), AFType::OutputPushPull); | 29 | pin.set_as_af(pin.af_num(), AFType::OutputPushPull); |
| 30 | #[cfg(gpio_v2)] | 30 | #[cfg(gpio_v2)] |
| @@ -71,31 +71,25 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { | |||
| 71 | this.inner.set_frequency(freq); | 71 | this.inner.set_frequency(freq); |
| 72 | this.inner.start(); | 72 | this.inner.start(); |
| 73 | 73 | ||
| 74 | unsafe { | 74 | this.inner.enable_outputs(true); |
| 75 | this.inner.enable_outputs(true); | 75 | |
| 76 | 76 | this.inner | |
| 77 | this.inner | 77 | .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1); |
| 78 | .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1); | 78 | this.inner |
| 79 | this.inner | 79 | .set_output_compare_mode(Channel::Ch2, OutputCompareMode::PwmMode1); |
| 80 | .set_output_compare_mode(Channel::Ch2, OutputCompareMode::PwmMode1); | 80 | this.inner |
| 81 | this.inner | 81 | .set_output_compare_mode(Channel::Ch3, OutputCompareMode::PwmMode1); |
| 82 | .set_output_compare_mode(Channel::Ch3, OutputCompareMode::PwmMode1); | 82 | this.inner |
| 83 | this.inner | 83 | .set_output_compare_mode(Channel::Ch4, OutputCompareMode::PwmMode1); |
| 84 | .set_output_compare_mode(Channel::Ch4, OutputCompareMode::PwmMode1); | ||
| 85 | } | ||
| 86 | this | 84 | this |
| 87 | } | 85 | } |
| 88 | 86 | ||
| 89 | pub fn enable(&mut self, channel: Channel) { | 87 | pub fn enable(&mut self, channel: Channel) { |
| 90 | unsafe { | 88 | self.inner.enable_channel(channel, true); |
| 91 | self.inner.enable_channel(channel, true); | ||
| 92 | } | ||
| 93 | } | 89 | } |
| 94 | 90 | ||
| 95 | pub fn disable(&mut self, channel: Channel) { | 91 | pub fn disable(&mut self, channel: Channel) { |
| 96 | unsafe { | 92 | self.inner.enable_channel(channel, false); |
| 97 | self.inner.enable_channel(channel, false); | ||
| 98 | } | ||
| 99 | } | 93 | } |
| 100 | 94 | ||
| 101 | pub fn set_freq(&mut self, freq: Hertz) { | 95 | pub fn set_freq(&mut self, freq: Hertz) { |
| @@ -103,11 +97,11 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { | |||
| 103 | } | 97 | } |
| 104 | 98 | ||
| 105 | pub fn get_max_duty(&self) -> u16 { | 99 | pub fn get_max_duty(&self) -> u16 { |
| 106 | unsafe { self.inner.get_max_compare_value() } | 100 | self.inner.get_max_compare_value() |
| 107 | } | 101 | } |
| 108 | 102 | ||
| 109 | pub fn set_duty(&mut self, channel: Channel, duty: u16) { | 103 | pub fn set_duty(&mut self, channel: Channel, duty: u16) { |
| 110 | assert!(duty < self.get_max_duty()); | 104 | assert!(duty < self.get_max_duty()); |
| 111 | unsafe { self.inner.set_compare_value(channel, duty) } | 105 | self.inner.set_compare_value(channel, duty) |
| 112 | } | 106 | } |
| 113 | } | 107 | } |
diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs index c3126b37f..e9db934bf 100644 --- a/embassy-stm32/src/qspi/mod.rs +++ b/embassy-stm32/src/qspi/mod.rs | |||
| @@ -96,20 +96,18 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { | |||
| 96 | ) -> Self { | 96 | ) -> Self { |
| 97 | into_ref!(peri, d0, d1, d2, d3, sck, nss); | 97 | into_ref!(peri, d0, d1, d2, d3, sck, nss); |
| 98 | 98 | ||
| 99 | unsafe { | 99 | sck.set_as_af(sck.af_num(), AFType::OutputPushPull); |
| 100 | sck.set_as_af(sck.af_num(), AFType::OutputPushPull); | 100 | sck.set_speed(crate::gpio::Speed::VeryHigh); |
| 101 | sck.set_speed(crate::gpio::Speed::VeryHigh); | 101 | nss.set_as_af(nss.af_num(), AFType::OutputPushPull); |
| 102 | nss.set_as_af(nss.af_num(), AFType::OutputPushPull); | 102 | nss.set_speed(crate::gpio::Speed::VeryHigh); |
| 103 | nss.set_speed(crate::gpio::Speed::VeryHigh); | 103 | d0.set_as_af(d0.af_num(), AFType::OutputPushPull); |
| 104 | d0.set_as_af(d0.af_num(), AFType::OutputPushPull); | 104 | d0.set_speed(crate::gpio::Speed::VeryHigh); |
| 105 | d0.set_speed(crate::gpio::Speed::VeryHigh); | 105 | d1.set_as_af(d1.af_num(), AFType::OutputPushPull); |
| 106 | d1.set_as_af(d1.af_num(), AFType::OutputPushPull); | 106 | d1.set_speed(crate::gpio::Speed::VeryHigh); |
| 107 | d1.set_speed(crate::gpio::Speed::VeryHigh); | 107 | d2.set_as_af(d2.af_num(), AFType::OutputPushPull); |
| 108 | d2.set_as_af(d2.af_num(), AFType::OutputPushPull); | 108 | d2.set_speed(crate::gpio::Speed::VeryHigh); |
| 109 | d2.set_speed(crate::gpio::Speed::VeryHigh); | 109 | d3.set_as_af(d3.af_num(), AFType::OutputPushPull); |
| 110 | d3.set_as_af(d3.af_num(), AFType::OutputPushPull); | 110 | d3.set_speed(crate::gpio::Speed::VeryHigh); |
| 111 | d3.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 112 | } | ||
| 113 | 111 | ||
| 114 | Self::new_inner( | 112 | Self::new_inner( |
| 115 | peri, | 113 | peri, |
| @@ -138,21 +136,19 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { | |||
| 138 | into_ref!(peri, dma); | 136 | into_ref!(peri, dma); |
| 139 | 137 | ||
| 140 | T::enable(); | 138 | T::enable(); |
| 141 | unsafe { | 139 | T::REGS.cr().write(|w| w.set_fthres(config.fifo_threshold.into())); |
| 142 | T::REGS.cr().write(|w| w.set_fthres(config.fifo_threshold.into())); | ||
| 143 | 140 | ||
| 144 | while T::REGS.sr().read().busy() {} | 141 | while T::REGS.sr().read().busy() {} |
| 145 | 142 | ||
| 146 | T::REGS.cr().write(|w| { | 143 | T::REGS.cr().write(|w| { |
| 147 | w.set_prescaler(config.prescaler); | 144 | w.set_prescaler(config.prescaler); |
| 148 | w.set_en(true); | 145 | w.set_en(true); |
| 149 | }); | 146 | }); |
| 150 | T::REGS.dcr().write(|w| { | 147 | T::REGS.dcr().write(|w| { |
| 151 | w.set_fsize(config.memory_size.into()); | 148 | w.set_fsize(config.memory_size.into()); |
| 152 | w.set_csht(config.cs_high_time.into()); | 149 | w.set_csht(config.cs_high_time.into()); |
| 153 | w.set_ckmode(false); | 150 | w.set_ckmode(false); |
| 154 | }); | 151 | }); |
| 155 | } | ||
| 156 | 152 | ||
| 157 | Self { | 153 | Self { |
| 158 | _peri: peri, | 154 | _peri: peri, |
| @@ -168,148 +164,140 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { | |||
| 168 | } | 164 | } |
| 169 | 165 | ||
| 170 | pub fn command(&mut self, transaction: TransferConfig) { | 166 | pub fn command(&mut self, transaction: TransferConfig) { |
| 171 | unsafe { | 167 | T::REGS.cr().modify(|v| v.set_dmaen(false)); |
| 172 | T::REGS.cr().modify(|v| v.set_dmaen(false)); | 168 | self.setup_transaction(QspiMode::IndirectWrite, &transaction); |
| 173 | self.setup_transaction(QspiMode::IndirectWrite, &transaction); | ||
| 174 | 169 | ||
| 175 | while !T::REGS.sr().read().tcf() {} | 170 | while !T::REGS.sr().read().tcf() {} |
| 176 | T::REGS.fcr().modify(|v| v.set_ctcf(true)); | 171 | T::REGS.fcr().modify(|v| v.set_ctcf(true)); |
| 177 | } | ||
| 178 | } | 172 | } |
| 179 | 173 | ||
| 180 | pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) { | 174 | pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) { |
| 181 | unsafe { | 175 | T::REGS.cr().modify(|v| v.set_dmaen(false)); |
| 182 | T::REGS.cr().modify(|v| v.set_dmaen(false)); | 176 | self.setup_transaction(QspiMode::IndirectWrite, &transaction); |
| 183 | self.setup_transaction(QspiMode::IndirectWrite, &transaction); | 177 | |
| 184 | 178 | if let Some(len) = transaction.data_len { | |
| 185 | if let Some(len) = transaction.data_len { | 179 | let current_ar = T::REGS.ar().read().address(); |
| 186 | let current_ar = T::REGS.ar().read().address(); | 180 | T::REGS.ccr().modify(|v| { |
| 187 | T::REGS.ccr().modify(|v| { | 181 | v.set_fmode(QspiMode::IndirectRead.into()); |
| 188 | v.set_fmode(QspiMode::IndirectRead.into()); | 182 | }); |
| 189 | }); | 183 | T::REGS.ar().write(|v| { |
| 190 | T::REGS.ar().write(|v| { | 184 | v.set_address(current_ar); |
| 191 | v.set_address(current_ar); | 185 | }); |
| 192 | }); | ||
| 193 | |||
| 194 | for idx in 0..len { | ||
| 195 | while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {} | ||
| 196 | buf[idx] = *(T::REGS.dr().ptr() as *mut u8); | ||
| 197 | } | ||
| 198 | } | ||
| 199 | 186 | ||
| 200 | while !T::REGS.sr().read().tcf() {} | 187 | for idx in 0..len { |
| 201 | T::REGS.fcr().modify(|v| v.set_ctcf(true)); | 188 | while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {} |
| 189 | buf[idx] = unsafe { (T::REGS.dr().as_ptr() as *mut u8).read_volatile() }; | ||
| 190 | } | ||
| 202 | } | 191 | } |
| 192 | |||
| 193 | while !T::REGS.sr().read().tcf() {} | ||
| 194 | T::REGS.fcr().modify(|v| v.set_ctcf(true)); | ||
| 203 | } | 195 | } |
| 204 | 196 | ||
| 205 | pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) { | 197 | pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) { |
| 206 | unsafe { | 198 | T::REGS.cr().modify(|v| v.set_dmaen(false)); |
| 207 | T::REGS.cr().modify(|v| v.set_dmaen(false)); | 199 | self.setup_transaction(QspiMode::IndirectWrite, &transaction); |
| 208 | self.setup_transaction(QspiMode::IndirectWrite, &transaction); | ||
| 209 | |||
| 210 | if let Some(len) = transaction.data_len { | ||
| 211 | T::REGS.ccr().modify(|v| { | ||
| 212 | v.set_fmode(QspiMode::IndirectWrite.into()); | ||
| 213 | }); | ||
| 214 | |||
| 215 | for idx in 0..len { | ||
| 216 | while !T::REGS.sr().read().ftf() {} | ||
| 217 | *(T::REGS.dr().ptr() as *mut u8) = buf[idx]; | ||
| 218 | } | ||
| 219 | } | ||
| 220 | 200 | ||
| 221 | while !T::REGS.sr().read().tcf() {} | 201 | if let Some(len) = transaction.data_len { |
| 222 | T::REGS.fcr().modify(|v| v.set_ctcf(true)); | 202 | T::REGS.ccr().modify(|v| { |
| 203 | v.set_fmode(QspiMode::IndirectWrite.into()); | ||
| 204 | }); | ||
| 205 | |||
| 206 | for idx in 0..len { | ||
| 207 | while !T::REGS.sr().read().ftf() {} | ||
| 208 | unsafe { (T::REGS.dr().as_ptr() as *mut u8).write_volatile(buf[idx]) }; | ||
| 209 | } | ||
| 223 | } | 210 | } |
| 211 | |||
| 212 | while !T::REGS.sr().read().tcf() {} | ||
| 213 | T::REGS.fcr().modify(|v| v.set_ctcf(true)); | ||
| 224 | } | 214 | } |
| 225 | 215 | ||
| 226 | pub fn blocking_read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig) | 216 | pub fn blocking_read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig) |
| 227 | where | 217 | where |
| 228 | Dma: QuadDma<T>, | 218 | Dma: QuadDma<T>, |
| 229 | { | 219 | { |
| 230 | unsafe { | 220 | self.setup_transaction(QspiMode::IndirectWrite, &transaction); |
| 231 | self.setup_transaction(QspiMode::IndirectWrite, &transaction); | 221 | |
| 232 | 222 | T::REGS.ccr().modify(|v| { | |
| 233 | T::REGS.ccr().modify(|v| { | 223 | v.set_fmode(QspiMode::IndirectRead.into()); |
| 234 | v.set_fmode(QspiMode::IndirectRead.into()); | 224 | }); |
| 235 | }); | 225 | let current_ar = T::REGS.ar().read().address(); |
| 236 | let current_ar = T::REGS.ar().read().address(); | 226 | T::REGS.ar().write(|v| { |
| 237 | T::REGS.ar().write(|v| { | 227 | v.set_address(current_ar); |
| 238 | v.set_address(current_ar); | 228 | }); |
| 239 | }); | 229 | |
| 240 | 230 | let request = self.dma.request(); | |
| 241 | let request = self.dma.request(); | 231 | let transfer = unsafe { |
| 242 | let transfer = Transfer::new_read( | 232 | Transfer::new_read( |
| 243 | &mut self.dma, | 233 | &mut self.dma, |
| 244 | request, | 234 | request, |
| 245 | T::REGS.dr().ptr() as *mut u8, | 235 | T::REGS.dr().as_ptr() as *mut u8, |
| 246 | buf, | 236 | buf, |
| 247 | Default::default(), | 237 | Default::default(), |
| 248 | ); | 238 | ) |
| 239 | }; | ||
| 249 | 240 | ||
| 250 | T::REGS.cr().modify(|v| v.set_dmaen(true)); | 241 | T::REGS.cr().modify(|v| v.set_dmaen(true)); |
| 251 | 242 | ||
| 252 | transfer.blocking_wait(); | 243 | transfer.blocking_wait(); |
| 253 | } | ||
| 254 | } | 244 | } |
| 255 | 245 | ||
| 256 | pub fn blocking_write_dma(&mut self, buf: &[u8], transaction: TransferConfig) | 246 | pub fn blocking_write_dma(&mut self, buf: &[u8], transaction: TransferConfig) |
| 257 | where | 247 | where |
| 258 | Dma: QuadDma<T>, | 248 | Dma: QuadDma<T>, |
| 259 | { | 249 | { |
| 260 | unsafe { | 250 | self.setup_transaction(QspiMode::IndirectWrite, &transaction); |
| 261 | self.setup_transaction(QspiMode::IndirectWrite, &transaction); | ||
| 262 | 251 | ||
| 263 | T::REGS.ccr().modify(|v| { | 252 | T::REGS.ccr().modify(|v| { |
| 264 | v.set_fmode(QspiMode::IndirectWrite.into()); | 253 | v.set_fmode(QspiMode::IndirectWrite.into()); |
| 265 | }); | 254 | }); |
| 266 | 255 | ||
| 267 | let request = self.dma.request(); | 256 | let request = self.dma.request(); |
| 268 | let transfer = Transfer::new_write( | 257 | let transfer = unsafe { |
| 258 | Transfer::new_write( | ||
| 269 | &mut self.dma, | 259 | &mut self.dma, |
| 270 | request, | 260 | request, |
| 271 | buf, | 261 | buf, |
| 272 | T::REGS.dr().ptr() as *mut u8, | 262 | T::REGS.dr().as_ptr() as *mut u8, |
| 273 | Default::default(), | 263 | Default::default(), |
| 274 | ); | 264 | ) |
| 265 | }; | ||
| 275 | 266 | ||
| 276 | T::REGS.cr().modify(|v| v.set_dmaen(true)); | 267 | T::REGS.cr().modify(|v| v.set_dmaen(true)); |
| 277 | 268 | ||
| 278 | transfer.blocking_wait(); | 269 | transfer.blocking_wait(); |
| 279 | } | ||
| 280 | } | 270 | } |
| 281 | 271 | ||
| 282 | fn setup_transaction(&mut self, fmode: QspiMode, transaction: &TransferConfig) { | 272 | fn setup_transaction(&mut self, fmode: QspiMode, transaction: &TransferConfig) { |
| 283 | unsafe { | 273 | T::REGS.fcr().modify(|v| { |
| 284 | T::REGS.fcr().modify(|v| { | 274 | v.set_csmf(true); |
| 285 | v.set_csmf(true); | 275 | v.set_ctcf(true); |
| 286 | v.set_ctcf(true); | 276 | v.set_ctef(true); |
| 287 | v.set_ctef(true); | 277 | v.set_ctof(true); |
| 288 | v.set_ctof(true); | 278 | }); |
| 289 | }); | ||
| 290 | 279 | ||
| 291 | while T::REGS.sr().read().busy() {} | 280 | while T::REGS.sr().read().busy() {} |
| 292 | 281 | ||
| 293 | if let Some(len) = transaction.data_len { | 282 | if let Some(len) = transaction.data_len { |
| 294 | T::REGS.dlr().write(|v| v.set_dl(len as u32 - 1)); | 283 | T::REGS.dlr().write(|v| v.set_dl(len as u32 - 1)); |
| 295 | } | 284 | } |
| 296 | 285 | ||
| 297 | T::REGS.ccr().write(|v| { | 286 | T::REGS.ccr().write(|v| { |
| 298 | v.set_fmode(fmode.into()); | 287 | v.set_fmode(fmode.into()); |
| 299 | v.set_imode(transaction.iwidth.into()); | 288 | v.set_imode(transaction.iwidth.into()); |
| 300 | v.set_instruction(transaction.instruction); | 289 | v.set_instruction(transaction.instruction); |
| 301 | v.set_admode(transaction.awidth.into()); | 290 | v.set_admode(transaction.awidth.into()); |
| 302 | v.set_adsize(self.config.address_size.into()); | 291 | v.set_adsize(self.config.address_size.into()); |
| 303 | v.set_dmode(transaction.dwidth.into()); | 292 | v.set_dmode(transaction.dwidth.into()); |
| 304 | v.set_abmode(QspiWidth::NONE.into()); | 293 | v.set_abmode(QspiWidth::NONE.into()); |
| 305 | v.set_dcyc(transaction.dummy.into()); | 294 | v.set_dcyc(transaction.dummy.into()); |
| 295 | }); | ||
| 296 | |||
| 297 | if let Some(addr) = transaction.address { | ||
| 298 | T::REGS.ar().write(|v| { | ||
| 299 | v.set_address(addr); | ||
| 306 | }); | 300 | }); |
| 307 | |||
| 308 | if let Some(addr) = transaction.address { | ||
| 309 | T::REGS.ar().write(|v| { | ||
| 310 | v.set_address(addr); | ||
| 311 | }); | ||
| 312 | } | ||
| 313 | } | 301 | } |
| 314 | } | 302 | } |
| 315 | } | 303 | } |
diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index e0929ca49..bc430afb2 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs | |||
| @@ -36,18 +36,18 @@ pub struct Config { | |||
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | #[cfg(stm32f410)] | 38 | #[cfg(stm32f410)] |
| 39 | unsafe fn setup_i2s_pll(_vco_in: u32, _plli2s: Option<u32>) -> Option<u32> { | 39 | fn setup_i2s_pll(_vco_in: u32, _plli2s: Option<u32>) -> Option<u32> { |
| 40 | None | 40 | None |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | // Not currently implemented, but will be in the future | 43 | // Not currently implemented, but will be in the future |
| 44 | #[cfg(any(stm32f411, stm32f412, stm32f413, stm32f423, stm32f446))] | 44 | #[cfg(any(stm32f411, stm32f412, stm32f413, stm32f423, stm32f446))] |
| 45 | unsafe fn setup_i2s_pll(_vco_in: u32, _plli2s: Option<u32>) -> Option<u32> { | 45 | fn setup_i2s_pll(_vco_in: u32, _plli2s: Option<u32>) -> Option<u32> { |
| 46 | None | 46 | None |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | #[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))] | 49 | #[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))] |
| 50 | unsafe fn setup_i2s_pll(vco_in: u32, plli2s: Option<u32>) -> Option<u32> { | 50 | fn setup_i2s_pll(vco_in: u32, plli2s: Option<u32>) -> Option<u32> { |
| 51 | let min_div = 2; | 51 | let min_div = 2; |
| 52 | let max_div = 7; | 52 | let max_div = 7; |
| 53 | let target = match plli2s { | 53 | let target = match plli2s { |
| @@ -82,13 +82,7 @@ unsafe fn setup_i2s_pll(vco_in: u32, plli2s: Option<u32>) -> Option<u32> { | |||
| 82 | Some(output) | 82 | Some(output) |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | unsafe fn setup_pll( | 85 | fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, plli2s: Option<u32>, pll48clk: bool) -> PllResults { |
| 86 | pllsrcclk: u32, | ||
| 87 | use_hse: bool, | ||
| 88 | pllsysclk: Option<u32>, | ||
| 89 | plli2s: Option<u32>, | ||
| 90 | pll48clk: bool, | ||
| 91 | ) -> PllResults { | ||
| 92 | use crate::pac::rcc::vals::{Pllp, Pllsrc}; | 86 | use crate::pac::rcc::vals::{Pllp, Pllsrc}; |
| 93 | 87 | ||
| 94 | let sysclk = pllsysclk.unwrap_or(pllsrcclk); | 88 | let sysclk = pllsysclk.unwrap_or(pllsrcclk); |
| @@ -320,7 +314,7 @@ impl<'d, T: McoInstance> Mco<'d, T> { | |||
| 320 | } | 314 | } |
| 321 | } | 315 | } |
| 322 | 316 | ||
| 323 | unsafe fn flash_setup(sysclk: u32) { | 317 | fn flash_setup(sysclk: u32) { |
| 324 | use crate::pac::flash::vals::Latency; | 318 | use crate::pac::flash::vals::Latency; |
| 325 | 319 | ||
| 326 | // Be conservative with voltage ranges | 320 | // Be conservative with voltage ranges |
diff --git a/embassy-stm32/src/rcc/f7.rs b/embassy-stm32/src/rcc/f7.rs index 2d21326a3..71215cac5 100644 --- a/embassy-stm32/src/rcc/f7.rs +++ b/embassy-stm32/src/rcc/f7.rs | |||
| @@ -25,7 +25,7 @@ pub struct Config { | |||
| 25 | pub pll48: bool, | 25 | pub pll48: bool, |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | unsafe fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, pll48clk: bool) -> PllResults { | 28 | fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, pll48clk: bool) -> PllResults { |
| 29 | use crate::pac::rcc::vals::{Pllp, Pllsrc}; | 29 | use crate::pac::rcc::vals::{Pllp, Pllsrc}; |
| 30 | 30 | ||
| 31 | let sysclk = pllsysclk.unwrap_or(pllsrcclk); | 31 | let sysclk = pllsysclk.unwrap_or(pllsrcclk); |
| @@ -97,7 +97,7 @@ unsafe fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, pll48 | |||
| 97 | } | 97 | } |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | unsafe fn flash_setup(sysclk: u32) { | 100 | fn flash_setup(sysclk: u32) { |
| 101 | use crate::pac::flash::vals::Latency; | 101 | use crate::pac::flash::vals::Latency; |
| 102 | 102 | ||
| 103 | // Be conservative with voltage ranges | 103 | // Be conservative with voltage ranges |
diff --git a/embassy-stm32/src/rcc/g0.rs b/embassy-stm32/src/rcc/g0.rs index 3e138c7ab..17c73c36b 100644 --- a/embassy-stm32/src/rcc/g0.rs +++ b/embassy-stm32/src/rcc/g0.rs | |||
| @@ -245,7 +245,7 @@ impl Default for Config { | |||
| 245 | } | 245 | } |
| 246 | 246 | ||
| 247 | impl PllConfig { | 247 | impl PllConfig { |
| 248 | pub(crate) unsafe fn init(self) -> u32 { | 248 | pub(crate) fn init(self) -> u32 { |
| 249 | assert!(self.n >= 8 && self.n <= 86); | 249 | assert!(self.n >= 8 && self.n <= 86); |
| 250 | let (src, input_freq) = match self.source { | 250 | let (src, input_freq) = match self.source { |
| 251 | PllSrc::HSI16 => (vals::Pllsrc::HSI16, HSI_FREQ.0), | 251 | PllSrc::HSI16 => (vals::Pllsrc::HSI16, HSI_FREQ.0), |
diff --git a/embassy-stm32/src/rcc/h5.rs b/embassy-stm32/src/rcc/h5.rs index 17fbc6056..4025a4e05 100644 --- a/embassy-stm32/src/rcc/h5.rs +++ b/embassy-stm32/src/rcc/h5.rs | |||
| @@ -462,7 +462,7 @@ struct PllOutput { | |||
| 462 | r: Option<Hertz>, | 462 | r: Option<Hertz>, |
| 463 | } | 463 | } |
| 464 | 464 | ||
| 465 | unsafe fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput { | 465 | fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput { |
| 466 | let Some(config) = config else { | 466 | let Some(config) = config else { |
| 467 | // Stop PLL | 467 | // Stop PLL |
| 468 | RCC.cr().modify(|w| w.set_pllon(num, false)); | 468 | RCC.cr().modify(|w| w.set_pllon(num, false)); |
| @@ -595,12 +595,9 @@ fn flash_setup(clk: Hertz, vos: VoltageScale) { | |||
| 595 | 595 | ||
| 596 | defmt::debug!("flash: latency={} wrhighfreq={}", latency, wrhighfreq); | 596 | defmt::debug!("flash: latency={} wrhighfreq={}", latency, wrhighfreq); |
| 597 | 597 | ||
| 598 | // NOTE(unsafe) Atomic write | 598 | FLASH.acr().write(|w| { |
| 599 | unsafe { | 599 | w.set_wrhighfreq(wrhighfreq); |
| 600 | FLASH.acr().write(|w| { | 600 | w.set_latency(latency); |
| 601 | w.set_wrhighfreq(wrhighfreq); | 601 | }); |
| 602 | w.set_latency(latency); | 602 | while FLASH.acr().read().latency() != latency {} |
| 603 | }); | ||
| 604 | while FLASH.acr().read().latency() != latency {} | ||
| 605 | } | ||
| 606 | } | 603 | } |
diff --git a/embassy-stm32/src/rcc/h7.rs b/embassy-stm32/src/rcc/h7.rs index 0185f7ae8..daa1cd61f 100644 --- a/embassy-stm32/src/rcc/h7.rs +++ b/embassy-stm32/src/rcc/h7.rs | |||
| @@ -253,14 +253,11 @@ fn flash_setup(rcc_aclk: u32, vos: VoltageScale) { | |||
| 253 | }, | 253 | }, |
| 254 | }; | 254 | }; |
| 255 | 255 | ||
| 256 | // NOTE(unsafe) Atomic write | 256 | FLASH.acr().write(|w| { |
| 257 | unsafe { | 257 | w.set_wrhighfreq(progr_delay); |
| 258 | FLASH.acr().write(|w| { | 258 | w.set_latency(wait_states) |
| 259 | w.set_wrhighfreq(progr_delay); | 259 | }); |
| 260 | w.set_latency(wait_states) | 260 | while FLASH.acr().read().latency() != wait_states {} |
| 261 | }); | ||
| 262 | while FLASH.acr().read().latency() != wait_states {} | ||
| 263 | } | ||
| 264 | } | 261 | } |
| 265 | 262 | ||
| 266 | pub enum McoClock { | 263 | pub enum McoClock { |
| @@ -474,7 +471,6 @@ pub(crate) unsafe fn init(mut config: Config) { | |||
| 474 | // Configure traceclk from PLL if needed | 471 | // Configure traceclk from PLL if needed |
| 475 | traceclk_setup(&mut config, sys_use_pll1_p); | 472 | traceclk_setup(&mut config, sys_use_pll1_p); |
| 476 | 473 | ||
| 477 | // NOTE(unsafe) We have exclusive access to the RCC | ||
| 478 | let (pll1_p_ck, pll1_q_ck, pll1_r_ck) = pll::pll_setup(srcclk.0, &config.pll1, 0); | 474 | let (pll1_p_ck, pll1_q_ck, pll1_r_ck) = pll::pll_setup(srcclk.0, &config.pll1, 0); |
| 479 | let (pll2_p_ck, pll2_q_ck, pll2_r_ck) = pll::pll_setup(srcclk.0, &config.pll2, 1); | 475 | let (pll2_p_ck, pll2_q_ck, pll2_r_ck) = pll::pll_setup(srcclk.0, &config.pll2, 1); |
| 480 | let (pll3_p_ck, pll3_q_ck, pll3_r_ck) = pll::pll_setup(srcclk.0, &config.pll3, 2); | 476 | let (pll3_p_ck, pll3_q_ck, pll3_r_ck) = pll::pll_setup(srcclk.0, &config.pll3, 2); |
| @@ -756,7 +752,7 @@ mod pll { | |||
| 756 | /// # Safety | 752 | /// # Safety |
| 757 | /// | 753 | /// |
| 758 | /// Must have exclusive access to the RCC register block | 754 | /// Must have exclusive access to the RCC register block |
| 759 | unsafe fn vco_setup(pll_src: u32, requested_output: u32, plln: usize) -> PllConfigResults { | 755 | fn vco_setup(pll_src: u32, requested_output: u32, plln: usize) -> PllConfigResults { |
| 760 | use crate::pac::rcc::vals::{Pllrge, Pllvcosel}; | 756 | use crate::pac::rcc::vals::{Pllrge, Pllvcosel}; |
| 761 | 757 | ||
| 762 | let (vco_ck_target, pll_x_p) = vco_output_divider_setup(requested_output, plln); | 758 | let (vco_ck_target, pll_x_p) = vco_output_divider_setup(requested_output, plln); |
| @@ -785,11 +781,7 @@ mod pll { | |||
| 785 | /// # Safety | 781 | /// # Safety |
| 786 | /// | 782 | /// |
| 787 | /// Must have exclusive access to the RCC register block | 783 | /// Must have exclusive access to the RCC register block |
| 788 | pub(super) unsafe fn pll_setup( | 784 | pub(super) fn pll_setup(pll_src: u32, config: &PllConfig, plln: usize) -> (Option<u32>, Option<u32>, Option<u32>) { |
| 789 | pll_src: u32, | ||
| 790 | config: &PllConfig, | ||
| 791 | plln: usize, | ||
| 792 | ) -> (Option<u32>, Option<u32>, Option<u32>) { | ||
| 793 | use crate::pac::rcc::vals::Divp; | 785 | use crate::pac::rcc::vals::Divp; |
| 794 | 786 | ||
| 795 | match config.p_ck { | 787 | match config.p_ck { |
diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs index c657bf70e..b2faec53d 100644 --- a/embassy-stm32/src/rng.rs +++ b/embassy-stm32/src/rng.rs | |||
| @@ -34,40 +34,34 @@ impl<'d, T: Instance> Rng<'d, T> { | |||
| 34 | pub fn reset(&mut self) { | 34 | pub fn reset(&mut self) { |
| 35 | // rng_v2 locks up on seed error, needs reset | 35 | // rng_v2 locks up on seed error, needs reset |
| 36 | #[cfg(rng_v2)] | 36 | #[cfg(rng_v2)] |
| 37 | if unsafe { T::regs().sr().read().seis() } { | 37 | if T::regs().sr().read().seis() { |
| 38 | T::reset(); | 38 | T::reset(); |
| 39 | } | 39 | } |
| 40 | unsafe { | 40 | T::regs().cr().modify(|reg| { |
| 41 | T::regs().cr().modify(|reg| { | 41 | reg.set_rngen(true); |
| 42 | reg.set_rngen(true); | 42 | reg.set_ie(true); |
| 43 | reg.set_ie(true); | 43 | }); |
| 44 | }); | 44 | T::regs().sr().modify(|reg| { |
| 45 | T::regs().sr().modify(|reg| { | 45 | reg.set_seis(false); |
| 46 | reg.set_seis(false); | 46 | reg.set_ceis(false); |
| 47 | reg.set_ceis(false); | 47 | }); |
| 48 | }); | ||
| 49 | } | ||
| 50 | // Reference manual says to discard the first. | 48 | // Reference manual says to discard the first. |
| 51 | let _ = self.next_u32(); | 49 | let _ = self.next_u32(); |
| 52 | } | 50 | } |
| 53 | 51 | ||
| 54 | pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { | 52 | pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { |
| 55 | unsafe { | 53 | T::regs().cr().modify(|reg| { |
| 56 | T::regs().cr().modify(|reg| { | 54 | reg.set_rngen(true); |
| 57 | reg.set_rngen(true); | 55 | }); |
| 58 | }) | ||
| 59 | } | ||
| 60 | 56 | ||
| 61 | for chunk in dest.chunks_mut(4) { | 57 | for chunk in dest.chunks_mut(4) { |
| 62 | poll_fn(|cx| { | 58 | poll_fn(|cx| { |
| 63 | RNG_WAKER.register(cx.waker()); | 59 | RNG_WAKER.register(cx.waker()); |
| 64 | unsafe { | 60 | T::regs().cr().modify(|reg| { |
| 65 | T::regs().cr().modify(|reg| { | 61 | reg.set_ie(true); |
| 66 | reg.set_ie(true); | 62 | }); |
| 67 | }); | ||
| 68 | } | ||
| 69 | 63 | ||
| 70 | let bits = unsafe { T::regs().sr().read() }; | 64 | let bits = T::regs().sr().read(); |
| 71 | 65 | ||
| 72 | if bits.drdy() { | 66 | if bits.drdy() { |
| 73 | Poll::Ready(Ok(())) | 67 | Poll::Ready(Ok(())) |
| @@ -82,7 +76,7 @@ impl<'d, T: Instance> Rng<'d, T> { | |||
| 82 | } | 76 | } |
| 83 | }) | 77 | }) |
| 84 | .await?; | 78 | .await?; |
| 85 | let random_bytes = unsafe { T::regs().dr().read() }.to_be_bytes(); | 79 | let random_bytes = T::regs().dr().read().to_be_bytes(); |
| 86 | for (dest, src) in chunk.iter_mut().zip(random_bytes.iter()) { | 80 | for (dest, src) in chunk.iter_mut().zip(random_bytes.iter()) { |
| 87 | *dest = *src | 81 | *dest = *src |
| 88 | } | 82 | } |
| @@ -95,11 +89,11 @@ impl<'d, T: Instance> Rng<'d, T> { | |||
| 95 | impl<'d, T: Instance> RngCore for Rng<'d, T> { | 89 | impl<'d, T: Instance> RngCore for Rng<'d, T> { |
| 96 | fn next_u32(&mut self) -> u32 { | 90 | fn next_u32(&mut self) -> u32 { |
| 97 | loop { | 91 | loop { |
| 98 | let sr = unsafe { T::regs().sr().read() }; | 92 | let sr = T::regs().sr().read(); |
| 99 | if sr.seis() | sr.ceis() { | 93 | if sr.seis() | sr.ceis() { |
| 100 | self.reset(); | 94 | self.reset(); |
| 101 | } else if sr.drdy() { | 95 | } else if sr.drdy() { |
| 102 | return unsafe { T::regs().dr().read() }; | 96 | return T::regs().dr().read(); |
| 103 | } | 97 | } |
| 104 | } | 98 | } |
| 105 | } | 99 | } |
diff --git a/embassy-stm32/src/rtc/datetime.rs b/embassy-stm32/src/rtc/datetime.rs index 0a590c1bb..a9c48d88d 100644 --- a/embassy-stm32/src/rtc/datetime.rs +++ b/embassy-stm32/src/rtc/datetime.rs | |||
| @@ -154,29 +154,27 @@ pub(super) fn write_date_time(rtc: &Rtc, t: DateTime) { | |||
| 154 | let yr_offset = (yr - 1970_u16) as u8; | 154 | let yr_offset = (yr - 1970_u16) as u8; |
| 155 | let (yt, yu) = byte_to_bcd2(yr_offset); | 155 | let (yt, yu) = byte_to_bcd2(yr_offset); |
| 156 | 156 | ||
| 157 | unsafe { | 157 | use crate::pac::rtc::vals::Ampm; |
| 158 | use crate::pac::rtc::vals::Ampm; | 158 | |
| 159 | 159 | rtc.tr().write(|w| { | |
| 160 | rtc.tr().write(|w| { | 160 | w.set_ht(ht); |
| 161 | w.set_ht(ht); | 161 | w.set_hu(hu); |
| 162 | w.set_hu(hu); | 162 | w.set_mnt(mnt); |
| 163 | w.set_mnt(mnt); | 163 | w.set_mnu(mnu); |
| 164 | w.set_mnu(mnu); | 164 | w.set_st(st); |
| 165 | w.set_st(st); | 165 | w.set_su(su); |
| 166 | w.set_su(su); | 166 | w.set_pm(Ampm::AM); |
| 167 | w.set_pm(Ampm::AM); | 167 | }); |
| 168 | }); | 168 | |
| 169 | 169 | rtc.dr().write(|w| { | |
| 170 | rtc.dr().write(|w| { | 170 | w.set_dt(dt); |
| 171 | w.set_dt(dt); | 171 | w.set_du(du); |
| 172 | w.set_du(du); | 172 | w.set_mt(mt > 0); |
| 173 | w.set_mt(mt > 0); | 173 | w.set_mu(mu); |
| 174 | w.set_mu(mu); | 174 | w.set_yt(yt); |
| 175 | w.set_yt(yt); | 175 | w.set_yu(yu); |
| 176 | w.set_yu(yu); | 176 | w.set_wdu(day_of_week_to_u8(t.day_of_week)); |
| 177 | w.set_wdu(day_of_week_to_u8(t.day_of_week)); | 177 | }); |
| 178 | }); | ||
| 179 | } | ||
| 180 | } | 178 | } |
| 181 | 179 | ||
| 182 | pub(super) fn datetime( | 180 | pub(super) fn datetime( |
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 962927fb1..12a2ac795 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs | |||
| @@ -113,7 +113,7 @@ impl Default for RtcCalibrationCyclePeriod { | |||
| 113 | 113 | ||
| 114 | impl<'d, T: Instance> Rtc<'d, T> { | 114 | impl<'d, T: Instance> Rtc<'d, T> { |
| 115 | pub fn new(_rtc: impl Peripheral<P = T> + 'd, rtc_config: RtcConfig) -> Self { | 115 | pub fn new(_rtc: impl Peripheral<P = T> + 'd, rtc_config: RtcConfig) -> Self { |
| 116 | unsafe { T::enable_peripheral_clk() }; | 116 | T::enable_peripheral_clk(); |
| 117 | 117 | ||
| 118 | let mut rtc_struct = Self { | 118 | let mut rtc_struct = Self { |
| 119 | phantom: PhantomData, | 119 | phantom: PhantomData, |
| @@ -144,34 +144,32 @@ impl<'d, T: Instance> Rtc<'d, T> { | |||
| 144 | /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`]. | 144 | /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`]. |
| 145 | pub fn now(&self) -> Result<DateTime, RtcError> { | 145 | pub fn now(&self) -> Result<DateTime, RtcError> { |
| 146 | let r = T::regs(); | 146 | let r = T::regs(); |
| 147 | unsafe { | 147 | let tr = r.tr().read(); |
| 148 | let tr = r.tr().read(); | 148 | let second = bcd2_to_byte((tr.st(), tr.su())); |
| 149 | let second = bcd2_to_byte((tr.st(), tr.su())); | 149 | let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); |
| 150 | let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); | 150 | let hour = bcd2_to_byte((tr.ht(), tr.hu())); |
| 151 | let hour = bcd2_to_byte((tr.ht(), tr.hu())); | 151 | // Reading either RTC_SSR or RTC_TR locks the values in the higher-order |
| 152 | // Reading either RTC_SSR or RTC_TR locks the values in the higher-order | 152 | // calendar shadow registers until RTC_DR is read. |
| 153 | // calendar shadow registers until RTC_DR is read. | 153 | let dr = r.dr().read(); |
| 154 | let dr = r.dr().read(); | 154 | |
| 155 | 155 | let weekday = dr.wdu(); | |
| 156 | let weekday = dr.wdu(); | 156 | let day = bcd2_to_byte((dr.dt(), dr.du())); |
| 157 | let day = bcd2_to_byte((dr.dt(), dr.du())); | 157 | let month = bcd2_to_byte((dr.mt() as u8, dr.mu())); |
| 158 | let month = bcd2_to_byte((dr.mt() as u8, dr.mu())); | 158 | let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16; |
| 159 | let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16; | 159 | |
| 160 | 160 | self::datetime::datetime(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime) | |
| 161 | self::datetime::datetime(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime) | ||
| 162 | } | ||
| 163 | } | 161 | } |
| 164 | 162 | ||
| 165 | /// Check if daylight savings time is active. | 163 | /// Check if daylight savings time is active. |
| 166 | pub fn get_daylight_savings(&self) -> bool { | 164 | pub fn get_daylight_savings(&self) -> bool { |
| 167 | let cr = unsafe { T::regs().cr().read() }; | 165 | let cr = T::regs().cr().read(); |
| 168 | cr.bkp() | 166 | cr.bkp() |
| 169 | } | 167 | } |
| 170 | 168 | ||
| 171 | /// Enable/disable daylight savings time. | 169 | /// Enable/disable daylight savings time. |
| 172 | pub fn set_daylight_savings(&mut self, daylight_savings: bool) { | 170 | pub fn set_daylight_savings(&mut self, daylight_savings: bool) { |
| 173 | self.write(true, |rtc| { | 171 | self.write(true, |rtc| { |
| 174 | unsafe { rtc.cr().modify(|w| w.set_bkp(daylight_savings)) }; | 172 | rtc.cr().modify(|w| w.set_bkp(daylight_savings)); |
| 175 | }) | 173 | }) |
| 176 | } | 174 | } |
| 177 | 175 | ||
| @@ -228,7 +226,7 @@ pub(crate) mod sealed { | |||
| 228 | crate::pac::RTC | 226 | crate::pac::RTC |
| 229 | } | 227 | } |
| 230 | 228 | ||
| 231 | unsafe fn enable_peripheral_clk() {} | 229 | fn enable_peripheral_clk() {} |
| 232 | 230 | ||
| 233 | /// Read content of the backup register. | 231 | /// Read content of the backup register. |
| 234 | /// | 232 | /// |
diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index adaafe67a..e1615b34c 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs | |||
| @@ -8,74 +8,72 @@ impl<'d, T: Instance> super::Rtc<'d, T> { | |||
| 8 | /// It this changes the RTC clock source the time will be reset | 8 | /// It this changes the RTC clock source the time will be reset |
| 9 | pub(super) fn apply_config(&mut self, rtc_config: RtcConfig) { | 9 | pub(super) fn apply_config(&mut self, rtc_config: RtcConfig) { |
| 10 | // Unlock the backup domain | 10 | // Unlock the backup domain |
| 11 | unsafe { | 11 | let clock_config = rtc_config.clock_config as u8; |
| 12 | let clock_config = rtc_config.clock_config as u8; | ||
| 13 | 12 | ||
| 14 | #[cfg(not(rtc_v2wb))] | 13 | #[cfg(not(rtc_v2wb))] |
| 15 | use stm32_metapac::rcc::vals::Rtcsel; | 14 | use stm32_metapac::rcc::vals::Rtcsel; |
| 16 | 15 | ||
| 17 | #[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1))] | 16 | #[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1))] |
| 18 | let cr = crate::pac::PWR.cr(); | 17 | let cr = crate::pac::PWR.cr(); |
| 19 | #[cfg(any(rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] | 18 | #[cfg(any(rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] |
| 20 | let cr = crate::pac::PWR.cr1(); | 19 | let cr = crate::pac::PWR.cr1(); |
| 21 | 20 | ||
| 22 | // TODO: Missing from PAC for l0 and f0? | 21 | // TODO: Missing from PAC for l0 and f0? |
| 23 | #[cfg(not(any(rtc_v2f0, rtc_v2l0)))] | 22 | #[cfg(not(any(rtc_v2f0, rtc_v2l0)))] |
| 24 | { | 23 | { |
| 25 | cr.modify(|w| w.set_dbp(true)); | 24 | cr.modify(|w| w.set_dbp(true)); |
| 26 | while !cr.read().dbp() {} | 25 | while !cr.read().dbp() {} |
| 27 | } | 26 | } |
| 28 | 27 | ||
| 29 | #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] | 28 | #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] |
| 30 | let reg = crate::pac::RCC.bdcr().read(); | 29 | let reg = crate::pac::RCC.bdcr().read(); |
| 31 | #[cfg(any(rtc_v2l0, rtc_v2l1))] | 30 | #[cfg(any(rtc_v2l0, rtc_v2l1))] |
| 32 | let reg = crate::pac::RCC.csr().read(); | 31 | let reg = crate::pac::RCC.csr().read(); |
| 33 | 32 | ||
| 34 | #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb))] | 33 | #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb))] |
| 35 | assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); | 34 | assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); |
| 36 | 35 | ||
| 37 | #[cfg(rtc_v2wb)] | 36 | #[cfg(rtc_v2wb)] |
| 38 | let rtcsel = reg.rtcsel(); | 37 | let rtcsel = reg.rtcsel(); |
| 39 | #[cfg(not(rtc_v2wb))] | 38 | #[cfg(not(rtc_v2wb))] |
| 40 | let rtcsel = reg.rtcsel().0; | 39 | let rtcsel = reg.rtcsel().0; |
| 41 | 40 | ||
| 42 | if !reg.rtcen() || rtcsel != clock_config { | 41 | if !reg.rtcen() || rtcsel != clock_config { |
| 43 | #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] | 42 | #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] |
| 44 | crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); | 43 | crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); |
| 45 | 44 | ||
| 45 | #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] | ||
| 46 | let cr = crate::pac::RCC.bdcr(); | ||
| 47 | #[cfg(any(rtc_v2l0, rtc_v2l1))] | ||
| 48 | let cr = crate::pac::RCC.csr(); | ||
| 49 | |||
| 50 | cr.modify(|w| { | ||
| 51 | // Reset | ||
| 46 | #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] | 52 | #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] |
| 47 | let cr = crate::pac::RCC.bdcr(); | 53 | w.set_bdrst(false); |
| 48 | #[cfg(any(rtc_v2l0, rtc_v2l1))] | 54 | |
| 49 | let cr = crate::pac::RCC.csr(); | 55 | // Select RTC source |
| 50 | 56 | #[cfg(not(rtc_v2wb))] | |
| 51 | cr.modify(|w| { | 57 | w.set_rtcsel(Rtcsel(clock_config)); |
| 52 | // Reset | 58 | #[cfg(rtc_v2wb)] |
| 53 | #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] | 59 | w.set_rtcsel(clock_config); |
| 54 | w.set_bdrst(false); | 60 | w.set_rtcen(true); |
| 55 | 61 | ||
| 56 | // Select RTC source | 62 | // Restore bcdr |
| 57 | #[cfg(not(rtc_v2wb))] | 63 | #[cfg(any(rtc_v2l4, rtc_v2wb))] |
| 58 | w.set_rtcsel(Rtcsel(clock_config)); | 64 | w.set_lscosel(reg.lscosel()); |
| 59 | #[cfg(rtc_v2wb)] | 65 | #[cfg(any(rtc_v2l4, rtc_v2wb))] |
| 60 | w.set_rtcsel(clock_config); | 66 | w.set_lscoen(reg.lscoen()); |
| 61 | w.set_rtcen(true); | 67 | |
| 62 | 68 | w.set_lseon(reg.lseon()); | |
| 63 | // Restore bcdr | 69 | |
| 64 | #[cfg(any(rtc_v2l4, rtc_v2wb))] | 70 | #[cfg(any(rtc_v2f0, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] |
| 65 | w.set_lscosel(reg.lscosel()); | 71 | w.set_lsedrv(reg.lsedrv()); |
| 66 | #[cfg(any(rtc_v2l4, rtc_v2wb))] | 72 | w.set_lsebyp(reg.lsebyp()); |
| 67 | w.set_lscoen(reg.lscoen()); | 73 | }); |
| 68 | |||
| 69 | w.set_lseon(reg.lseon()); | ||
| 70 | |||
| 71 | #[cfg(any(rtc_v2f0, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] | ||
| 72 | w.set_lsedrv(reg.lsedrv()); | ||
| 73 | w.set_lsebyp(reg.lsebyp()); | ||
| 74 | }); | ||
| 75 | } | ||
| 76 | } | 74 | } |
| 77 | 75 | ||
| 78 | self.write(true, |rtc| unsafe { | 76 | self.write(true, |rtc| { |
| 79 | rtc.cr().modify(|w| { | 77 | rtc.cr().modify(|w| { |
| 80 | #[cfg(rtc_v2f2)] | 78 | #[cfg(rtc_v2f2)] |
| 81 | w.set_fmt(false); | 79 | w.set_fmt(false); |
| @@ -117,47 +115,45 @@ impl<'d, T: Instance> super::Rtc<'d, T> { | |||
| 117 | clock_drift = clock_drift / RTC_CALR_RESOLUTION_PPM; | 115 | clock_drift = clock_drift / RTC_CALR_RESOLUTION_PPM; |
| 118 | 116 | ||
| 119 | self.write(false, |rtc| { | 117 | self.write(false, |rtc| { |
| 120 | unsafe { | 118 | rtc.calr().write(|w| { |
| 121 | rtc.calr().write(|w| { | 119 | match period { |
| 122 | match period { | 120 | super::RtcCalibrationCyclePeriod::Seconds8 => { |
| 123 | super::RtcCalibrationCyclePeriod::Seconds8 => { | 121 | w.set_calw8(stm32_metapac::rtc::vals::Calw8::EIGHT_SECOND); |
| 124 | w.set_calw8(stm32_metapac::rtc::vals::Calw8::EIGHT_SECOND); | ||
| 125 | } | ||
| 126 | super::RtcCalibrationCyclePeriod::Seconds16 => { | ||
| 127 | w.set_calw16(stm32_metapac::rtc::vals::Calw16::SIXTEEN_SECOND); | ||
| 128 | } | ||
| 129 | super::RtcCalibrationCyclePeriod::Seconds32 => { | ||
| 130 | // Set neither `calw8` nor `calw16` to use 32 seconds | ||
| 131 | } | ||
| 132 | } | 122 | } |
| 133 | 123 | super::RtcCalibrationCyclePeriod::Seconds16 => { | |
| 134 | // Extra pulses during calibration cycle period: CALP * 512 - CALM | 124 | w.set_calw16(stm32_metapac::rtc::vals::Calw16::SIXTEEN_SECOND); |
| 135 | // | 125 | } |
| 136 | // CALP sets whether pulses are added or omitted. | 126 | super::RtcCalibrationCyclePeriod::Seconds32 => { |
| 137 | // | 127 | // Set neither `calw8` nor `calw16` to use 32 seconds |
| 138 | // CALM contains how many pulses (out of 512) are masked in a | ||
| 139 | // given calibration cycle period. | ||
| 140 | if clock_drift > 0.0 { | ||
| 141 | // Maximum (about 512.2) rounds to 512. | ||
| 142 | clock_drift += 0.5; | ||
| 143 | |||
| 144 | // When the offset is positive (0 to 512), the opposite of | ||
| 145 | // the offset (512 - offset) is masked, i.e. for the | ||
| 146 | // maximum offset (512), 0 pulses are masked. | ||
| 147 | w.set_calp(stm32_metapac::rtc::vals::Calp::INCREASEFREQ); | ||
| 148 | w.set_calm(512 - clock_drift as u16); | ||
| 149 | } else { | ||
| 150 | // Minimum (about -510.7) rounds to -511. | ||
| 151 | clock_drift -= 0.5; | ||
| 152 | |||
| 153 | // When the offset is negative or zero (-511 to 0), | ||
| 154 | // the absolute offset is masked, i.e. for the minimum | ||
| 155 | // offset (-511), 511 pulses are masked. | ||
| 156 | w.set_calp(stm32_metapac::rtc::vals::Calp::NOCHANGE); | ||
| 157 | w.set_calm((clock_drift * -1.0) as u16); | ||
| 158 | } | 128 | } |
| 159 | }); | 129 | } |
| 160 | } | 130 | |
| 131 | // Extra pulses during calibration cycle period: CALP * 512 - CALM | ||
| 132 | // | ||
| 133 | // CALP sets whether pulses are added or omitted. | ||
| 134 | // | ||
| 135 | // CALM contains how many pulses (out of 512) are masked in a | ||
| 136 | // given calibration cycle period. | ||
| 137 | if clock_drift > 0.0 { | ||
| 138 | // Maximum (about 512.2) rounds to 512. | ||
| 139 | clock_drift += 0.5; | ||
| 140 | |||
| 141 | // When the offset is positive (0 to 512), the opposite of | ||
| 142 | // the offset (512 - offset) is masked, i.e. for the | ||
| 143 | // maximum offset (512), 0 pulses are masked. | ||
| 144 | w.set_calp(stm32_metapac::rtc::vals::Calp::INCREASEFREQ); | ||
| 145 | w.set_calm(512 - clock_drift as u16); | ||
| 146 | } else { | ||
| 147 | // Minimum (about -510.7) rounds to -511. | ||
| 148 | clock_drift -= 0.5; | ||
| 149 | |||
| 150 | // When the offset is negative or zero (-511 to 0), | ||
| 151 | // the absolute offset is masked, i.e. for the minimum | ||
| 152 | // offset (-511), 511 pulses are masked. | ||
| 153 | w.set_calp(stm32_metapac::rtc::vals::Calp::NOCHANGE); | ||
| 154 | w.set_calm((clock_drift * -1.0) as u16); | ||
| 155 | } | ||
| 156 | }); | ||
| 161 | }) | 157 | }) |
| 162 | } | 158 | } |
| 163 | 159 | ||
| @@ -168,31 +164,27 @@ impl<'d, T: Instance> super::Rtc<'d, T> { | |||
| 168 | let r = T::regs(); | 164 | let r = T::regs(); |
| 169 | // Disable write protection. | 165 | // Disable write protection. |
| 170 | // This is safe, as we're only writin the correct and expected values. | 166 | // This is safe, as we're only writin the correct and expected values. |
| 171 | unsafe { | 167 | r.wpr().write(|w| w.set_key(0xca)); |
| 172 | r.wpr().write(|w| w.set_key(0xca)); | 168 | r.wpr().write(|w| w.set_key(0x53)); |
| 173 | r.wpr().write(|w| w.set_key(0x53)); | 169 | |
| 174 | 170 | // true if initf bit indicates RTC peripheral is in init mode | |
| 175 | // true if initf bit indicates RTC peripheral is in init mode | 171 | if init_mode && !r.isr().read().initf() { |
| 176 | if init_mode && !r.isr().read().initf() { | 172 | // to update calendar date/time, time format, and prescaler configuration, RTC must be in init mode |
| 177 | // to update calendar date/time, time format, and prescaler configuration, RTC must be in init mode | 173 | r.isr().modify(|w| w.set_init(Init::INITMODE)); |
| 178 | r.isr().modify(|w| w.set_init(Init::INITMODE)); | 174 | // wait till init state entered |
| 179 | // wait till init state entered | 175 | // ~2 RTCCLK cycles |
| 180 | // ~2 RTCCLK cycles | 176 | while !r.isr().read().initf() {} |
| 181 | while !r.isr().read().initf() {} | ||
| 182 | } | ||
| 183 | } | 177 | } |
| 184 | 178 | ||
| 185 | let result = f(&r); | 179 | let result = f(&r); |
| 186 | 180 | ||
| 187 | unsafe { | 181 | if init_mode { |
| 188 | if init_mode { | 182 | r.isr().modify(|w| w.set_init(Init::FREERUNNINGMODE)); // Exits init mode |
| 189 | r.isr().modify(|w| w.set_init(Init::FREERUNNINGMODE)); // Exits init mode | ||
| 190 | } | ||
| 191 | |||
| 192 | // Re-enable write protection. | ||
| 193 | // This is safe, as the field accepts the full range of 8-bit values. | ||
| 194 | r.wpr().write(|w| w.set_key(0xff)); | ||
| 195 | } | 183 | } |
| 184 | |||
| 185 | // Re-enable write protection. | ||
| 186 | // This is safe, as the field accepts the full range of 8-bit values. | ||
| 187 | r.wpr().write(|w| w.set_key(0xff)); | ||
| 196 | result | 188 | result |
| 197 | } | 189 | } |
| 198 | } | 190 | } |
| @@ -200,7 +192,7 @@ impl<'d, T: Instance> super::Rtc<'d, T> { | |||
| 200 | impl sealed::Instance for crate::peripherals::RTC { | 192 | impl sealed::Instance for crate::peripherals::RTC { |
| 201 | const BACKUP_REGISTER_COUNT: usize = 20; | 193 | const BACKUP_REGISTER_COUNT: usize = 20; |
| 202 | 194 | ||
| 203 | unsafe fn enable_peripheral_clk() { | 195 | fn enable_peripheral_clk() { |
| 204 | #[cfg(any(rtc_v2l4, rtc_v2wb))] | 196 | #[cfg(any(rtc_v2l4, rtc_v2wb))] |
| 205 | { | 197 | { |
| 206 | // enable peripheral clock for communication | 198 | // enable peripheral clock for communication |
| @@ -213,7 +205,7 @@ impl sealed::Instance for crate::peripherals::RTC { | |||
| 213 | 205 | ||
| 214 | fn read_backup_register(rtc: &Rtc, register: usize) -> Option<u32> { | 206 | fn read_backup_register(rtc: &Rtc, register: usize) -> Option<u32> { |
| 215 | if register < Self::BACKUP_REGISTER_COUNT { | 207 | if register < Self::BACKUP_REGISTER_COUNT { |
| 216 | Some(unsafe { rtc.bkpr(register).read().bkp() }) | 208 | Some(rtc.bkpr(register).read().bkp()) |
| 217 | } else { | 209 | } else { |
| 218 | None | 210 | None |
| 219 | } | 211 | } |
| @@ -221,7 +213,7 @@ impl sealed::Instance for crate::peripherals::RTC { | |||
| 221 | 213 | ||
| 222 | fn write_backup_register(rtc: &Rtc, register: usize, value: u32) { | 214 | fn write_backup_register(rtc: &Rtc, register: usize, value: u32) { |
| 223 | if register < Self::BACKUP_REGISTER_COUNT { | 215 | if register < Self::BACKUP_REGISTER_COUNT { |
| 224 | unsafe { rtc.bkpr(register).write(|w| w.set_bkp(value)) } | 216 | rtc.bkpr(register).write(|w| w.set_bkp(value)); |
| 225 | } | 217 | } |
| 226 | } | 218 | } |
| 227 | } | 219 | } |
diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index 24f6496a6..7c91046a2 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs | |||
| @@ -8,70 +8,66 @@ impl<'d, T: Instance> super::Rtc<'d, T> { | |||
| 8 | /// It this changes the RTC clock source the time will be reset | 8 | /// It this changes the RTC clock source the time will be reset |
| 9 | pub(super) fn apply_config(&mut self, rtc_config: RtcConfig) { | 9 | pub(super) fn apply_config(&mut self, rtc_config: RtcConfig) { |
| 10 | // Unlock the backup domain | 10 | // Unlock the backup domain |
| 11 | unsafe { | 11 | #[cfg(not(any(rtc_v3u5, rcc_wl5, rcc_wle)))] |
| 12 | #[cfg(not(any(rtc_v3u5, rcc_wl5, rcc_wle)))] | 12 | { |
| 13 | { | 13 | crate::pac::PWR.cr1().modify(|w| w.set_dbp(true)); |
| 14 | crate::pac::PWR.cr1().modify(|w| w.set_dbp(true)); | 14 | while !crate::pac::PWR.cr1().read().dbp() {} |
| 15 | while !crate::pac::PWR.cr1().read().dbp() {} | 15 | } |
| 16 | } | 16 | #[cfg(any(rcc_wl5, rcc_wle))] |
| 17 | #[cfg(any(rcc_wl5, rcc_wle))] | 17 | { |
| 18 | { | 18 | use crate::pac::pwr::vals::Dbp; |
| 19 | use crate::pac::pwr::vals::Dbp; | 19 | |
| 20 | 20 | crate::pac::PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED)); | |
| 21 | crate::pac::PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED)); | 21 | while crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED {} |
| 22 | while crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED {} | 22 | } |
| 23 | } | 23 | |
| 24 | 24 | let reg = crate::pac::RCC.bdcr().read(); | |
| 25 | let reg = crate::pac::RCC.bdcr().read(); | 25 | assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); |
| 26 | assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); | 26 | |
| 27 | 27 | let config_rtcsel = rtc_config.clock_config as u8; | |
| 28 | let config_rtcsel = rtc_config.clock_config as u8; | 28 | #[cfg(not(any(rcc_wl5, rcc_wle)))] |
| 29 | #[cfg(not(any(rcc_wl5, rcc_wle)))] | 29 | let config_rtcsel = crate::pac::rcc::vals::Rtcsel(config_rtcsel); |
| 30 | let config_rtcsel = crate::pac::rcc::vals::Rtcsel(config_rtcsel); | 30 | |
| 31 | 31 | if !reg.rtcen() || reg.rtcsel() != config_rtcsel { | |
| 32 | if !reg.rtcen() || reg.rtcsel() != config_rtcsel { | 32 | crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); |
| 33 | crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); | 33 | |
| 34 | 34 | crate::pac::RCC.bdcr().modify(|w| { | |
| 35 | crate::pac::RCC.bdcr().modify(|w| { | 35 | // Reset |
| 36 | // Reset | 36 | w.set_bdrst(false); |
| 37 | w.set_bdrst(false); | 37 | |
| 38 | 38 | // Select RTC source | |
| 39 | // Select RTC source | 39 | w.set_rtcsel(config_rtcsel); |
| 40 | w.set_rtcsel(config_rtcsel); | 40 | |
| 41 | 41 | w.set_rtcen(true); | |
| 42 | w.set_rtcen(true); | 42 | |
| 43 | 43 | // Restore bcdr | |
| 44 | // Restore bcdr | 44 | w.set_lscosel(reg.lscosel()); |
| 45 | w.set_lscosel(reg.lscosel()); | 45 | w.set_lscoen(reg.lscoen()); |
| 46 | w.set_lscoen(reg.lscoen()); | 46 | |
| 47 | 47 | w.set_lseon(reg.lseon()); | |
| 48 | w.set_lseon(reg.lseon()); | 48 | w.set_lsedrv(reg.lsedrv()); |
| 49 | w.set_lsedrv(reg.lsedrv()); | 49 | w.set_lsebyp(reg.lsebyp()); |
| 50 | w.set_lsebyp(reg.lsebyp()); | 50 | }); |
| 51 | }); | ||
| 52 | } | ||
| 53 | } | 51 | } |
| 54 | 52 | ||
| 55 | self.write(true, |rtc| { | 53 | self.write(true, |rtc| { |
| 56 | unsafe { | 54 | rtc.cr().modify(|w| { |
| 57 | rtc.cr().modify(|w| { | 55 | w.set_fmt(Fmt::TWENTYFOURHOUR); |
| 58 | w.set_fmt(Fmt::TWENTYFOURHOUR); | 56 | w.set_osel(Osel::DISABLED); |
| 59 | w.set_osel(Osel::DISABLED); | 57 | w.set_pol(Pol::HIGH); |
| 60 | w.set_pol(Pol::HIGH); | 58 | }); |
| 61 | }); | 59 | |
| 62 | 60 | rtc.prer().modify(|w| { | |
| 63 | rtc.prer().modify(|w| { | 61 | w.set_prediv_s(rtc_config.sync_prescaler); |
| 64 | w.set_prediv_s(rtc_config.sync_prescaler); | 62 | w.set_prediv_a(rtc_config.async_prescaler); |
| 65 | w.set_prediv_a(rtc_config.async_prescaler); | 63 | }); |
| 66 | }); | 64 | |
| 67 | 65 | // TODO: configuration for output pins | |
| 68 | // TODO: configuration for output pins | 66 | rtc.cr().modify(|w| { |
| 69 | rtc.cr().modify(|w| { | 67 | w.set_out2en(false); |
| 70 | w.set_out2en(false); | 68 | w.set_tampalrm_type(TampalrmType::PUSHPULL); |
| 71 | w.set_tampalrm_type(TampalrmType::PUSHPULL); | 69 | w.set_tampalrm_pu(TampalrmPu::NOPULLUP); |
| 72 | w.set_tampalrm_pu(TampalrmPu::NOPULLUP); | 70 | }); |
| 73 | }); | ||
| 74 | } | ||
| 75 | }); | 71 | }); |
| 76 | 72 | ||
| 77 | self.rtc_config = rtc_config; | 73 | self.rtc_config = rtc_config; |
| @@ -99,47 +95,45 @@ impl<'d, T: Instance> super::Rtc<'d, T> { | |||
| 99 | clock_drift = clock_drift / Self::RTC_CALR_RESOLUTION_PPM; | 95 | clock_drift = clock_drift / Self::RTC_CALR_RESOLUTION_PPM; |
| 100 | 96 | ||
| 101 | self.write(false, |rtc| { | 97 | self.write(false, |rtc| { |
| 102 | unsafe { | 98 | rtc.calr().write(|w| { |
| 103 | rtc.calr().write(|w| { | 99 | match period { |
| 104 | match period { | 100 | RtcCalibrationCyclePeriod::Seconds8 => { |
| 105 | RtcCalibrationCyclePeriod::Seconds8 => { | 101 | w.set_calw8(Calw8::EIGHTSECONDS); |
| 106 | w.set_calw8(Calw8::EIGHTSECONDS); | ||
| 107 | } | ||
| 108 | RtcCalibrationCyclePeriod::Seconds16 => { | ||
| 109 | w.set_calw16(Calw16::SIXTEENSECONDS); | ||
| 110 | } | ||
| 111 | RtcCalibrationCyclePeriod::Seconds32 => { | ||
| 112 | // Set neither `calw8` nor `calw16` to use 32 seconds | ||
| 113 | } | ||
| 114 | } | 102 | } |
| 115 | 103 | RtcCalibrationCyclePeriod::Seconds16 => { | |
| 116 | // Extra pulses during calibration cycle period: CALP * 512 - CALM | 104 | w.set_calw16(Calw16::SIXTEENSECONDS); |
| 117 | // | ||
| 118 | // CALP sets whether pulses are added or omitted. | ||
| 119 | // | ||
| 120 | // CALM contains how many pulses (out of 512) are masked in a | ||
| 121 | // given calibration cycle period. | ||
| 122 | if clock_drift > 0.0 { | ||
| 123 | // Maximum (about 512.2) rounds to 512. | ||
| 124 | clock_drift += 0.5; | ||
| 125 | |||
| 126 | // When the offset is positive (0 to 512), the opposite of | ||
| 127 | // the offset (512 - offset) is masked, i.e. for the | ||
| 128 | // maximum offset (512), 0 pulses are masked. | ||
| 129 | w.set_calp(Calp::INCREASEFREQ); | ||
| 130 | w.set_calm(512 - clock_drift as u16); | ||
| 131 | } else { | ||
| 132 | // Minimum (about -510.7) rounds to -511. | ||
| 133 | clock_drift -= 0.5; | ||
| 134 | |||
| 135 | // When the offset is negative or zero (-511 to 0), | ||
| 136 | // the absolute offset is masked, i.e. for the minimum | ||
| 137 | // offset (-511), 511 pulses are masked. | ||
| 138 | w.set_calp(Calp::NOCHANGE); | ||
| 139 | w.set_calm((clock_drift * -1.0) as u16); | ||
| 140 | } | 105 | } |
| 141 | }); | 106 | RtcCalibrationCyclePeriod::Seconds32 => { |
| 142 | } | 107 | // Set neither `calw8` nor `calw16` to use 32 seconds |
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | // Extra pulses during calibration cycle period: CALP * 512 - CALM | ||
| 112 | // | ||
| 113 | // CALP sets whether pulses are added or omitted. | ||
| 114 | // | ||
| 115 | // CALM contains how many pulses (out of 512) are masked in a | ||
| 116 | // given calibration cycle period. | ||
| 117 | if clock_drift > 0.0 { | ||
| 118 | // Maximum (about 512.2) rounds to 512. | ||
| 119 | clock_drift += 0.5; | ||
| 120 | |||
| 121 | // When the offset is positive (0 to 512), the opposite of | ||
| 122 | // the offset (512 - offset) is masked, i.e. for the | ||
| 123 | // maximum offset (512), 0 pulses are masked. | ||
| 124 | w.set_calp(Calp::INCREASEFREQ); | ||
| 125 | w.set_calm(512 - clock_drift as u16); | ||
| 126 | } else { | ||
| 127 | // Minimum (about -510.7) rounds to -511. | ||
| 128 | clock_drift -= 0.5; | ||
| 129 | |||
| 130 | // When the offset is negative or zero (-511 to 0), | ||
| 131 | // the absolute offset is masked, i.e. for the minimum | ||
| 132 | // offset (-511), 511 pulses are masked. | ||
| 133 | w.set_calp(Calp::NOCHANGE); | ||
| 134 | w.set_calm((clock_drift * -1.0) as u16); | ||
| 135 | } | ||
| 136 | }); | ||
| 143 | }) | 137 | }) |
| 144 | } | 138 | } |
| 145 | 139 | ||
| @@ -150,29 +144,26 @@ impl<'d, T: Instance> super::Rtc<'d, T> { | |||
| 150 | let r = T::regs(); | 144 | let r = T::regs(); |
| 151 | // Disable write protection. | 145 | // Disable write protection. |
| 152 | // This is safe, as we're only writin the correct and expected values. | 146 | // This is safe, as we're only writin the correct and expected values. |
| 153 | unsafe { | 147 | r.wpr().write(|w| w.set_key(Key::DEACTIVATE1)); |
| 154 | r.wpr().write(|w| w.set_key(Key::DEACTIVATE1)); | 148 | r.wpr().write(|w| w.set_key(Key::DEACTIVATE2)); |
| 155 | r.wpr().write(|w| w.set_key(Key::DEACTIVATE2)); | 149 | |
| 156 | 150 | if init_mode && !r.icsr().read().initf() { | |
| 157 | if init_mode && !r.icsr().read().initf() { | 151 | r.icsr().modify(|w| w.set_init(Init::INITMODE)); |
| 158 | r.icsr().modify(|w| w.set_init(Init::INITMODE)); | 152 | // wait till init state entered |
| 159 | // wait till init state entered | 153 | // ~2 RTCCLK cycles |
| 160 | // ~2 RTCCLK cycles | 154 | while !r.icsr().read().initf() {} |
| 161 | while !r.icsr().read().initf() {} | ||
| 162 | } | ||
| 163 | } | 155 | } |
| 164 | 156 | ||
| 165 | let result = f(&r); | 157 | let result = f(&r); |
| 166 | 158 | ||
| 167 | unsafe { | 159 | if init_mode { |
| 168 | if init_mode { | 160 | r.icsr().modify(|w| w.set_init(Init::FREERUNNINGMODE)); // Exits init mode |
| 169 | r.icsr().modify(|w| w.set_init(Init::FREERUNNINGMODE)); // Exits init mode | ||
| 170 | } | ||
| 171 | |||
| 172 | // Re-enable write protection. | ||
| 173 | // This is safe, as the field accepts the full range of 8-bit values. | ||
| 174 | r.wpr().write(|w| w.set_key(Key::ACTIVATE)); | ||
| 175 | } | 161 | } |
| 162 | |||
| 163 | // Re-enable write protection. | ||
| 164 | // This is safe, as the field accepts the full range of 8-bit values. | ||
| 165 | r.wpr().write(|w| w.set_key(Key::ACTIVATE)); | ||
| 166 | |||
| 176 | result | 167 | result |
| 177 | } | 168 | } |
| 178 | } | 169 | } |
| @@ -192,7 +183,7 @@ impl sealed::Instance for crate::peripherals::RTC { | |||
| 192 | fn write_backup_register(_rtc: &Rtc, register: usize, _value: u32) { | 183 | fn write_backup_register(_rtc: &Rtc, register: usize, _value: u32) { |
| 193 | if register < Self::BACKUP_REGISTER_COUNT { | 184 | if register < Self::BACKUP_REGISTER_COUNT { |
| 194 | // RTC3 backup registers come from the TAMP peripe=heral, not RTC. Not() even in the L412 PAC | 185 | // RTC3 backup registers come from the TAMP peripe=heral, not RTC. Not() even in the L412 PAC |
| 195 | //unsafe { self.rtc.bkpr()[register].write(|w| w.bits(value)) } | 186 | //self.rtc.bkpr()[register].write(|w| w.bits(value)) |
| 196 | } | 187 | } |
| 197 | } | 188 | } |
| 198 | } | 189 | } |
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index 28eb49ab6..80a336a48 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs | |||
| @@ -28,17 +28,14 @@ pub struct InterruptHandler<T: Instance> { | |||
| 28 | impl<T: Instance> InterruptHandler<T> { | 28 | impl<T: Instance> InterruptHandler<T> { |
| 29 | fn data_interrupts(enable: bool) { | 29 | fn data_interrupts(enable: bool) { |
| 30 | let regs = T::regs(); | 30 | let regs = T::regs(); |
| 31 | // NOTE(unsafe) Atomic write | 31 | regs.maskr().write(|w| { |
| 32 | unsafe { | 32 | w.set_dcrcfailie(enable); |
| 33 | regs.maskr().write(|w| { | 33 | w.set_dtimeoutie(enable); |
| 34 | w.set_dcrcfailie(enable); | 34 | w.set_dataendie(enable); |
| 35 | w.set_dtimeoutie(enable); | ||
| 36 | w.set_dataendie(enable); | ||
| 37 | 35 | ||
| 38 | #[cfg(sdmmc_v2)] | 36 | #[cfg(sdmmc_v2)] |
| 39 | w.set_dabortie(enable); | 37 | w.set_dabortie(enable); |
| 40 | }); | 38 | }); |
| 41 | } | ||
| 42 | } | 39 | } |
| 43 | } | 40 | } |
| 44 | 41 | ||
| @@ -285,7 +282,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { | |||
| 285 | ) -> Self { | 282 | ) -> Self { |
| 286 | into_ref!(clk, cmd, d0); | 283 | into_ref!(clk, cmd, d0); |
| 287 | 284 | ||
| 288 | critical_section::with(|_| unsafe { | 285 | critical_section::with(|_| { |
| 289 | clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None); | 286 | clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None); |
| 290 | cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up); | 287 | cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up); |
| 291 | d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up); | 288 | d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up); |
| @@ -322,7 +319,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { | |||
| 322 | ) -> Self { | 319 | ) -> Self { |
| 323 | into_ref!(clk, cmd, d0, d1, d2, d3); | 320 | into_ref!(clk, cmd, d0, d1, d2, d3); |
| 324 | 321 | ||
| 325 | critical_section::with(|_| unsafe { | 322 | critical_section::with(|_| { |
| 326 | clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None); | 323 | clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None); |
| 327 | cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up); | 324 | cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up); |
| 328 | d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up); | 325 | d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up); |
| @@ -364,7 +361,7 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { | |||
| 364 | ) -> Self { | 361 | ) -> Self { |
| 365 | into_ref!(clk, cmd, d0); | 362 | into_ref!(clk, cmd, d0); |
| 366 | 363 | ||
| 367 | critical_section::with(|_| unsafe { | 364 | critical_section::with(|_| { |
| 368 | clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None); | 365 | clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None); |
| 369 | cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up); | 366 | cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up); |
| 370 | d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up); | 367 | d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up); |
| @@ -400,7 +397,7 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { | |||
| 400 | ) -> Self { | 397 | ) -> Self { |
| 401 | into_ref!(clk, cmd, d0, d1, d2, d3); | 398 | into_ref!(clk, cmd, d0, d1, d2, d3); |
| 402 | 399 | ||
| 403 | critical_section::with(|_| unsafe { | 400 | critical_section::with(|_| { |
| 404 | clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None); | 401 | clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None); |
| 405 | cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up); | 402 | cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up); |
| 406 | d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up); | 403 | d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up); |
| @@ -451,26 +448,24 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 451 | unsafe { T::Interrupt::enable() }; | 448 | unsafe { T::Interrupt::enable() }; |
| 452 | 449 | ||
| 453 | let regs = T::regs(); | 450 | let regs = T::regs(); |
| 454 | unsafe { | 451 | regs.clkcr().write(|w| { |
| 455 | regs.clkcr().write(|w| { | 452 | w.set_pwrsav(false); |
| 456 | w.set_pwrsav(false); | 453 | w.set_negedge(false); |
| 457 | w.set_negedge(false); | ||
| 458 | |||
| 459 | // Hardware flow control is broken on SDIOv1 and causes clock glitches, which result in CRC errors. | ||
| 460 | // See chip erratas for more details. | ||
| 461 | #[cfg(sdmmc_v1)] | ||
| 462 | w.set_hwfc_en(false); | ||
| 463 | #[cfg(sdmmc_v2)] | ||
| 464 | w.set_hwfc_en(true); | ||
| 465 | 454 | ||
| 466 | #[cfg(sdmmc_v1)] | 455 | // Hardware flow control is broken on SDIOv1 and causes clock glitches, which result in CRC errors. |
| 467 | w.set_clken(true); | 456 | // See chip erratas for more details. |
| 468 | }); | 457 | #[cfg(sdmmc_v1)] |
| 458 | w.set_hwfc_en(false); | ||
| 459 | #[cfg(sdmmc_v2)] | ||
| 460 | w.set_hwfc_en(true); | ||
| 469 | 461 | ||
| 470 | // Power off, writen 00: Clock to the card is stopped; | 462 | #[cfg(sdmmc_v1)] |
| 471 | // D[7:0], CMD, and CK are driven high. | 463 | w.set_clken(true); |
| 472 | regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::Off as u8)); | 464 | }); |
| 473 | } | 465 | |
| 466 | // Power off, writen 00: Clock to the card is stopped; | ||
| 467 | // D[7:0], CMD, and CK are driven high. | ||
| 468 | regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::Off as u8)); | ||
| 474 | 469 | ||
| 475 | Self { | 470 | Self { |
| 476 | _peri: sdmmc, | 471 | _peri: sdmmc, |
| @@ -495,14 +490,11 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 495 | fn data_active() -> bool { | 490 | fn data_active() -> bool { |
| 496 | let regs = T::regs(); | 491 | let regs = T::regs(); |
| 497 | 492 | ||
| 498 | // NOTE(unsafe) Atomic read with no side-effects | 493 | let status = regs.star().read(); |
| 499 | unsafe { | 494 | #[cfg(sdmmc_v1)] |
| 500 | let status = regs.star().read(); | 495 | return status.rxact() || status.txact(); |
| 501 | #[cfg(sdmmc_v1)] | 496 | #[cfg(sdmmc_v2)] |
| 502 | return status.rxact() || status.txact(); | 497 | return status.dpsmact(); |
| 503 | #[cfg(sdmmc_v2)] | ||
| 504 | return status.dpsmact(); | ||
| 505 | } | ||
| 506 | } | 498 | } |
| 507 | 499 | ||
| 508 | /// Coammand transfer is in progress | 500 | /// Coammand transfer is in progress |
| @@ -510,14 +502,11 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 510 | fn cmd_active() -> bool { | 502 | fn cmd_active() -> bool { |
| 511 | let regs = T::regs(); | 503 | let regs = T::regs(); |
| 512 | 504 | ||
| 513 | // NOTE(unsafe) Atomic read with no side-effects | 505 | let status = regs.star().read(); |
| 514 | unsafe { | 506 | #[cfg(sdmmc_v1)] |
| 515 | let status = regs.star().read(); | 507 | return status.cmdact(); |
| 516 | #[cfg(sdmmc_v1)] | 508 | #[cfg(sdmmc_v2)] |
| 517 | return status.cmdact(); | 509 | return status.cpsmact(); |
| 518 | #[cfg(sdmmc_v2)] | ||
| 519 | return status.cpsmact(); | ||
| 520 | } | ||
| 521 | } | 510 | } |
| 522 | 511 | ||
| 523 | /// Wait idle on CMDACT, RXACT and TXACT (v1) or DOSNACT and CPSMACT (v2) | 512 | /// Wait idle on CMDACT, RXACT and TXACT (v1) or DOSNACT and CPSMACT (v2) |
| @@ -542,44 +531,41 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 542 | Self::wait_idle(); | 531 | Self::wait_idle(); |
| 543 | Self::clear_interrupt_flags(); | 532 | Self::clear_interrupt_flags(); |
| 544 | 533 | ||
| 545 | // NOTE(unsafe) We have exclusive access to the regisers | 534 | regs.dtimer() |
| 546 | unsafe { | 535 | .write(|w| w.set_datatime(self.config.data_transfer_timeout)); |
| 547 | regs.dtimer() | 536 | regs.dlenr().write(|w| w.set_datalength(length_bytes)); |
| 548 | .write(|w| w.set_datatime(self.config.data_transfer_timeout)); | ||
| 549 | regs.dlenr().write(|w| w.set_datalength(length_bytes)); | ||
| 550 | 537 | ||
| 551 | #[cfg(sdmmc_v1)] | 538 | #[cfg(sdmmc_v1)] |
| 552 | let transfer = { | 539 | let transfer = unsafe { |
| 553 | let request = self.dma.request(); | 540 | let request = self.dma.request(); |
| 554 | Transfer::new_read( | 541 | Transfer::new_read( |
| 555 | &mut self.dma, | 542 | &mut self.dma, |
| 556 | request, | 543 | request, |
| 557 | regs.fifor().ptr() as *mut u32, | 544 | regs.fifor().as_ptr() as *mut u32, |
| 558 | buffer, | 545 | buffer, |
| 559 | DMA_TRANSFER_OPTIONS, | 546 | DMA_TRANSFER_OPTIONS, |
| 560 | ) | 547 | ) |
| 561 | }; | 548 | }; |
| 562 | #[cfg(sdmmc_v2)] | 549 | #[cfg(sdmmc_v2)] |
| 563 | let transfer = { | 550 | let transfer = { |
| 564 | regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_mut_ptr() as u32)); | 551 | regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_mut_ptr() as u32)); |
| 565 | regs.idmactrlr().modify(|w| w.set_idmaen(true)); | 552 | regs.idmactrlr().modify(|w| w.set_idmaen(true)); |
| 566 | Transfer { | 553 | Transfer { |
| 567 | _dummy: core::marker::PhantomData, | 554 | _dummy: core::marker::PhantomData, |
| 568 | } | 555 | } |
| 569 | }; | 556 | }; |
| 570 | 557 | ||
| 571 | regs.dctrl().modify(|w| { | 558 | regs.dctrl().modify(|w| { |
| 572 | w.set_dblocksize(block_size); | 559 | w.set_dblocksize(block_size); |
| 573 | w.set_dtdir(true); | 560 | w.set_dtdir(true); |
| 574 | #[cfg(sdmmc_v1)] | 561 | #[cfg(sdmmc_v1)] |
| 575 | { | 562 | { |
| 576 | w.set_dmaen(true); | 563 | w.set_dmaen(true); |
| 577 | w.set_dten(true); | 564 | w.set_dten(true); |
| 578 | } | 565 | } |
| 579 | }); | 566 | }); |
| 580 | 567 | ||
| 581 | transfer | 568 | transfer |
| 582 | } | ||
| 583 | } | 569 | } |
| 584 | 570 | ||
| 585 | /// # Safety | 571 | /// # Safety |
| @@ -598,59 +584,54 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 598 | Self::wait_idle(); | 584 | Self::wait_idle(); |
| 599 | Self::clear_interrupt_flags(); | 585 | Self::clear_interrupt_flags(); |
| 600 | 586 | ||
| 601 | // NOTE(unsafe) We have exclusive access to the regisers | 587 | regs.dtimer() |
| 602 | unsafe { | 588 | .write(|w| w.set_datatime(self.config.data_transfer_timeout)); |
| 603 | regs.dtimer() | 589 | regs.dlenr().write(|w| w.set_datalength(length_bytes)); |
| 604 | .write(|w| w.set_datatime(self.config.data_transfer_timeout)); | ||
| 605 | regs.dlenr().write(|w| w.set_datalength(length_bytes)); | ||
| 606 | 590 | ||
| 607 | #[cfg(sdmmc_v1)] | 591 | #[cfg(sdmmc_v1)] |
| 608 | let transfer = { | 592 | let transfer = unsafe { |
| 609 | let request = self.dma.request(); | 593 | let request = self.dma.request(); |
| 610 | Transfer::new_write( | 594 | Transfer::new_write( |
| 611 | &mut self.dma, | 595 | &mut self.dma, |
| 612 | request, | 596 | request, |
| 613 | buffer, | 597 | buffer, |
| 614 | regs.fifor().ptr() as *mut u32, | 598 | regs.fifor().as_ptr() as *mut u32, |
| 615 | DMA_TRANSFER_OPTIONS, | 599 | DMA_TRANSFER_OPTIONS, |
| 616 | ) | 600 | ) |
| 617 | }; | 601 | }; |
| 618 | #[cfg(sdmmc_v2)] | 602 | #[cfg(sdmmc_v2)] |
| 619 | let transfer = { | 603 | let transfer = { |
| 620 | regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_ptr() as u32)); | 604 | regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_ptr() as u32)); |
| 621 | regs.idmactrlr().modify(|w| w.set_idmaen(true)); | 605 | regs.idmactrlr().modify(|w| w.set_idmaen(true)); |
| 622 | Transfer { | 606 | Transfer { |
| 623 | _dummy: core::marker::PhantomData, | 607 | _dummy: core::marker::PhantomData, |
| 624 | } | 608 | } |
| 625 | }; | 609 | }; |
| 626 | 610 | ||
| 627 | regs.dctrl().modify(|w| { | 611 | regs.dctrl().modify(|w| { |
| 628 | w.set_dblocksize(block_size); | 612 | w.set_dblocksize(block_size); |
| 629 | w.set_dtdir(false); | 613 | w.set_dtdir(false); |
| 630 | #[cfg(sdmmc_v1)] | 614 | #[cfg(sdmmc_v1)] |
| 631 | { | 615 | { |
| 632 | w.set_dmaen(true); | 616 | w.set_dmaen(true); |
| 633 | w.set_dten(true); | 617 | w.set_dten(true); |
| 634 | } | 618 | } |
| 635 | }); | 619 | }); |
| 636 | 620 | ||
| 637 | transfer | 621 | transfer |
| 638 | } | ||
| 639 | } | 622 | } |
| 640 | 623 | ||
| 641 | /// Stops the DMA datapath | 624 | /// Stops the DMA datapath |
| 642 | fn stop_datapath() { | 625 | fn stop_datapath() { |
| 643 | let regs = T::regs(); | 626 | let regs = T::regs(); |
| 644 | 627 | ||
| 645 | unsafe { | 628 | #[cfg(sdmmc_v1)] |
| 646 | #[cfg(sdmmc_v1)] | 629 | regs.dctrl().modify(|w| { |
| 647 | regs.dctrl().modify(|w| { | 630 | w.set_dmaen(false); |
| 648 | w.set_dmaen(false); | 631 | w.set_dten(false); |
| 649 | w.set_dten(false); | 632 | }); |
| 650 | }); | 633 | #[cfg(sdmmc_v2)] |
| 651 | #[cfg(sdmmc_v2)] | 634 | regs.idmactrlr().modify(|w| w.set_idmaen(false)); |
| 652 | regs.idmactrlr().modify(|w| w.set_idmaen(false)); | ||
| 653 | } | ||
| 654 | } | 635 | } |
| 655 | 636 | ||
| 656 | /// Sets the CLKDIV field in CLKCR. Updates clock field in self | 637 | /// Sets the CLKDIV field in CLKCR. Updates clock field in self |
| @@ -673,16 +654,13 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 673 | assert!(ker_ck.0 > 3 * sdmmc_bus_bandwidth / 32); | 654 | assert!(ker_ck.0 > 3 * sdmmc_bus_bandwidth / 32); |
| 674 | self.clock = new_clock; | 655 | self.clock = new_clock; |
| 675 | 656 | ||
| 676 | // NOTE(unsafe) We have exclusive access to the regblock | 657 | // CPSMACT and DPSMACT must be 0 to set CLKDIV |
| 677 | unsafe { | 658 | Self::wait_idle(); |
| 678 | // CPSMACT and DPSMACT must be 0 to set CLKDIV | 659 | regs.clkcr().modify(|w| { |
| 679 | Self::wait_idle(); | 660 | w.set_clkdiv(clkdiv); |
| 680 | regs.clkcr().modify(|w| { | 661 | #[cfg(sdmmc_v1)] |
| 681 | w.set_clkdiv(clkdiv); | 662 | w.set_bypass(_bypass); |
| 682 | #[cfg(sdmmc_v1)] | 663 | }); |
| 683 | w.set_bypass(_bypass); | ||
| 684 | }); | ||
| 685 | } | ||
| 686 | 664 | ||
| 687 | Ok(()) | 665 | Ok(()) |
| 688 | } | 666 | } |
| @@ -710,7 +688,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 710 | 688 | ||
| 711 | // Arm `OnDrop` after the buffer, so it will be dropped first | 689 | // Arm `OnDrop` after the buffer, so it will be dropped first |
| 712 | let regs = T::regs(); | 690 | let regs = T::regs(); |
| 713 | let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); | 691 | let on_drop = OnDrop::new(|| Self::on_drop()); |
| 714 | 692 | ||
| 715 | let transfer = self.prepare_datapath_read(&mut status, 64, 6); | 693 | let transfer = self.prepare_datapath_read(&mut status, 64, 6); |
| 716 | InterruptHandler::<T>::data_interrupts(true); | 694 | InterruptHandler::<T>::data_interrupts(true); |
| @@ -718,7 +696,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 718 | 696 | ||
| 719 | let res = poll_fn(|cx| { | 697 | let res = poll_fn(|cx| { |
| 720 | T::state().register(cx.waker()); | 698 | T::state().register(cx.waker()); |
| 721 | let status = unsafe { regs.star().read() }; | 699 | let status = regs.star().read(); |
| 722 | 700 | ||
| 723 | if status.dcrcfail() { | 701 | if status.dcrcfail() { |
| 724 | return Poll::Ready(Err(Error::Crc)); | 702 | return Poll::Ready(Err(Error::Crc)); |
| @@ -769,8 +747,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 769 | 747 | ||
| 770 | Self::cmd(Cmd::card_status(rca << 16), false)?; // CMD13 | 748 | Self::cmd(Cmd::card_status(rca << 16), false)?; // CMD13 |
| 771 | 749 | ||
| 772 | // NOTE(unsafe) Atomic read with no side-effects | 750 | let r1 = regs.respr(0).read().cardstatus(); |
| 773 | let r1 = unsafe { regs.respr(0).read().cardstatus() }; | ||
| 774 | Ok(r1.into()) | 751 | Ok(r1.into()) |
| 775 | } | 752 | } |
| 776 | 753 | ||
| @@ -786,7 +763,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 786 | 763 | ||
| 787 | // Arm `OnDrop` after the buffer, so it will be dropped first | 764 | // Arm `OnDrop` after the buffer, so it will be dropped first |
| 788 | let regs = T::regs(); | 765 | let regs = T::regs(); |
| 789 | let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); | 766 | let on_drop = OnDrop::new(|| Self::on_drop()); |
| 790 | 767 | ||
| 791 | let transfer = self.prepare_datapath_read(&mut status, 64, 6); | 768 | let transfer = self.prepare_datapath_read(&mut status, 64, 6); |
| 792 | InterruptHandler::<T>::data_interrupts(true); | 769 | InterruptHandler::<T>::data_interrupts(true); |
| @@ -794,7 +771,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 794 | 771 | ||
| 795 | let res = poll_fn(|cx| { | 772 | let res = poll_fn(|cx| { |
| 796 | T::state().register(cx.waker()); | 773 | T::state().register(cx.waker()); |
| 797 | let status = unsafe { regs.star().read() }; | 774 | let status = regs.star().read(); |
| 798 | 775 | ||
| 799 | if status.dcrcfail() { | 776 | if status.dcrcfail() { |
| 800 | return Poll::Ready(Err(Error::Crc)); | 777 | return Poll::Ready(Err(Error::Crc)); |
| @@ -840,35 +817,32 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 840 | #[inline(always)] | 817 | #[inline(always)] |
| 841 | fn clear_interrupt_flags() { | 818 | fn clear_interrupt_flags() { |
| 842 | let regs = T::regs(); | 819 | let regs = T::regs(); |
| 843 | // NOTE(unsafe) Atomic write | 820 | regs.icr().write(|w| { |
| 844 | unsafe { | 821 | w.set_ccrcfailc(true); |
| 845 | regs.icr().write(|w| { | 822 | w.set_dcrcfailc(true); |
| 846 | w.set_ccrcfailc(true); | 823 | w.set_ctimeoutc(true); |
| 847 | w.set_dcrcfailc(true); | 824 | w.set_dtimeoutc(true); |
| 848 | w.set_ctimeoutc(true); | 825 | w.set_txunderrc(true); |
| 849 | w.set_dtimeoutc(true); | 826 | w.set_rxoverrc(true); |
| 850 | w.set_txunderrc(true); | 827 | w.set_cmdrendc(true); |
| 851 | w.set_rxoverrc(true); | 828 | w.set_cmdsentc(true); |
| 852 | w.set_cmdrendc(true); | 829 | w.set_dataendc(true); |
| 853 | w.set_cmdsentc(true); | 830 | w.set_dbckendc(true); |
| 854 | w.set_dataendc(true); | 831 | w.set_sdioitc(true); |
| 855 | w.set_dbckendc(true); | ||
| 856 | w.set_sdioitc(true); | ||
| 857 | 832 | ||
| 858 | #[cfg(sdmmc_v2)] | 833 | #[cfg(sdmmc_v2)] |
| 859 | { | 834 | { |
| 860 | w.set_dholdc(true); | 835 | w.set_dholdc(true); |
| 861 | w.set_dabortc(true); | 836 | w.set_dabortc(true); |
| 862 | w.set_busyd0endc(true); | 837 | w.set_busyd0endc(true); |
| 863 | w.set_ackfailc(true); | 838 | w.set_ackfailc(true); |
| 864 | w.set_acktimeoutc(true); | 839 | w.set_acktimeoutc(true); |
| 865 | w.set_vswendc(true); | 840 | w.set_vswendc(true); |
| 866 | w.set_ckstopc(true); | 841 | w.set_ckstopc(true); |
| 867 | w.set_idmatec(true); | 842 | w.set_idmatec(true); |
| 868 | w.set_idmabtcc(true); | 843 | w.set_idmabtcc(true); |
| 869 | } | 844 | } |
| 870 | }); | 845 | }); |
| 871 | } | ||
| 872 | } | 846 | } |
| 873 | 847 | ||
| 874 | async fn get_scr(&mut self, card: &mut Card) -> Result<(), Error> { | 848 | async fn get_scr(&mut self, card: &mut Card) -> Result<(), Error> { |
| @@ -880,7 +854,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 880 | 854 | ||
| 881 | // Arm `OnDrop` after the buffer, so it will be dropped first | 855 | // Arm `OnDrop` after the buffer, so it will be dropped first |
| 882 | let regs = T::regs(); | 856 | let regs = T::regs(); |
| 883 | let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); | 857 | let on_drop = OnDrop::new(|| Self::on_drop()); |
| 884 | 858 | ||
| 885 | let transfer = self.prepare_datapath_read(&mut scr[..], 8, 3); | 859 | let transfer = self.prepare_datapath_read(&mut scr[..], 8, 3); |
| 886 | InterruptHandler::<T>::data_interrupts(true); | 860 | InterruptHandler::<T>::data_interrupts(true); |
| @@ -888,7 +862,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 888 | 862 | ||
| 889 | let res = poll_fn(|cx| { | 863 | let res = poll_fn(|cx| { |
| 890 | T::state().register(cx.waker()); | 864 | T::state().register(cx.waker()); |
| 891 | let status = unsafe { regs.star().read() }; | 865 | let status = regs.star().read(); |
| 892 | 866 | ||
| 893 | if status.dcrcfail() { | 867 | if status.dcrcfail() { |
| 894 | return Poll::Ready(Err(Error::Crc)); | 868 | return Poll::Ready(Err(Error::Crc)); |
| @@ -921,59 +895,53 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 921 | let regs = T::regs(); | 895 | let regs = T::regs(); |
| 922 | 896 | ||
| 923 | Self::clear_interrupt_flags(); | 897 | Self::clear_interrupt_flags(); |
| 924 | // NOTE(safety) Atomic operations | 898 | // CP state machine must be idle |
| 925 | unsafe { | 899 | while Self::cmd_active() {} |
| 926 | // CP state machine must be idle | ||
| 927 | while Self::cmd_active() {} | ||
| 928 | 900 | ||
| 929 | // Command arg | 901 | // Command arg |
| 930 | regs.argr().write(|w| w.set_cmdarg(cmd.arg)); | 902 | regs.argr().write(|w| w.set_cmdarg(cmd.arg)); |
| 931 | |||
| 932 | // Command index and start CP State Machine | ||
| 933 | regs.cmdr().write(|w| { | ||
| 934 | w.set_waitint(false); | ||
| 935 | w.set_waitresp(cmd.resp as u8); | ||
| 936 | w.set_cmdindex(cmd.cmd); | ||
| 937 | w.set_cpsmen(true); | ||
| 938 | 903 | ||
| 939 | #[cfg(sdmmc_v2)] | 904 | // Command index and start CP State Machine |
| 940 | { | 905 | regs.cmdr().write(|w| { |
| 941 | // Special mode in CP State Machine | 906 | w.set_waitint(false); |
| 942 | // CMD12: Stop Transmission | 907 | w.set_waitresp(cmd.resp as u8); |
| 943 | let cpsm_stop_transmission = cmd.cmd == 12; | 908 | w.set_cmdindex(cmd.cmd); |
| 944 | w.set_cmdstop(cpsm_stop_transmission); | 909 | w.set_cpsmen(true); |
| 945 | w.set_cmdtrans(data); | ||
| 946 | } | ||
| 947 | }); | ||
| 948 | 910 | ||
| 949 | let mut status; | 911 | #[cfg(sdmmc_v2)] |
| 950 | if cmd.resp == Response::None { | 912 | { |
| 951 | // Wait for CMDSENT or a timeout | 913 | // Special mode in CP State Machine |
| 952 | while { | 914 | // CMD12: Stop Transmission |
| 953 | status = regs.star().read(); | 915 | let cpsm_stop_transmission = cmd.cmd == 12; |
| 954 | !(status.ctimeout() || status.cmdsent()) | 916 | w.set_cmdstop(cpsm_stop_transmission); |
| 955 | } {} | 917 | w.set_cmdtrans(data); |
| 956 | } else { | ||
| 957 | // Wait for CMDREND or CCRCFAIL or a timeout | ||
| 958 | while { | ||
| 959 | status = regs.star().read(); | ||
| 960 | !(status.ctimeout() || status.cmdrend() || status.ccrcfail()) | ||
| 961 | } {} | ||
| 962 | } | 918 | } |
| 919 | }); | ||
| 963 | 920 | ||
| 964 | if status.ctimeout() { | 921 | let mut status; |
| 965 | return Err(Error::Timeout); | 922 | if cmd.resp == Response::None { |
| 966 | } else if status.ccrcfail() { | 923 | // Wait for CMDSENT or a timeout |
| 967 | return Err(Error::Crc); | 924 | while { |
| 968 | } | 925 | status = regs.star().read(); |
| 969 | Ok(()) | 926 | !(status.ctimeout() || status.cmdsent()) |
| 927 | } {} | ||
| 928 | } else { | ||
| 929 | // Wait for CMDREND or CCRCFAIL or a timeout | ||
| 930 | while { | ||
| 931 | status = regs.star().read(); | ||
| 932 | !(status.ctimeout() || status.cmdrend() || status.ccrcfail()) | ||
| 933 | } {} | ||
| 934 | } | ||
| 935 | |||
| 936 | if status.ctimeout() { | ||
| 937 | return Err(Error::Timeout); | ||
| 938 | } else if status.ccrcfail() { | ||
| 939 | return Err(Error::Crc); | ||
| 970 | } | 940 | } |
| 941 | Ok(()) | ||
| 971 | } | 942 | } |
| 972 | 943 | ||
| 973 | /// # Safety | 944 | fn on_drop() { |
| 974 | /// | ||
| 975 | /// Ensure that `regs` has exclusive access to the regblocks | ||
| 976 | unsafe fn on_drop() { | ||
| 977 | let regs = T::regs(); | 945 | let regs = T::regs(); |
| 978 | if Self::data_active() { | 946 | if Self::data_active() { |
| 979 | Self::clear_interrupt_flags(); | 947 | Self::clear_interrupt_flags(); |
| @@ -1017,141 +985,138 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 1017 | false => BusWidth::One, | 985 | false => BusWidth::One, |
| 1018 | }; | 986 | }; |
| 1019 | 987 | ||
| 1020 | // NOTE(unsafe) We have exclusive access to the peripheral | 988 | // While the SD/SDIO card or eMMC is in identification mode, |
| 1021 | unsafe { | 989 | // the SDMMC_CK frequency must be no more than 400 kHz. |
| 1022 | // While the SD/SDIO card or eMMC is in identification mode, | 990 | let (_bypass, clkdiv, init_clock) = unwrap!(clk_div(ker_ck, SD_INIT_FREQ.0)); |
| 1023 | // the SDMMC_CK frequency must be no more than 400 kHz. | 991 | self.clock = init_clock; |
| 1024 | let (_bypass, clkdiv, init_clock) = unwrap!(clk_div(ker_ck, SD_INIT_FREQ.0)); | ||
| 1025 | self.clock = init_clock; | ||
| 1026 | |||
| 1027 | // CPSMACT and DPSMACT must be 0 to set WIDBUS | ||
| 1028 | Self::wait_idle(); | ||
| 1029 | |||
| 1030 | regs.clkcr().modify(|w| { | ||
| 1031 | w.set_widbus(0); | ||
| 1032 | w.set_clkdiv(clkdiv); | ||
| 1033 | #[cfg(sdmmc_v1)] | ||
| 1034 | w.set_bypass(_bypass); | ||
| 1035 | }); | ||
| 1036 | 992 | ||
| 1037 | regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8)); | 993 | // CPSMACT and DPSMACT must be 0 to set WIDBUS |
| 1038 | Self::cmd(Cmd::idle(), false)?; | 994 | Self::wait_idle(); |
| 1039 | 995 | ||
| 1040 | // Check if cards supports CMD8 (with pattern) | 996 | regs.clkcr().modify(|w| { |
| 1041 | Self::cmd(Cmd::hs_send_ext_csd(0x1AA), false)?; | 997 | w.set_widbus(0); |
| 1042 | let r1 = regs.respr(0).read().cardstatus(); | 998 | w.set_clkdiv(clkdiv); |
| 999 | #[cfg(sdmmc_v1)] | ||
| 1000 | w.set_bypass(_bypass); | ||
| 1001 | }); | ||
| 1043 | 1002 | ||
| 1044 | let mut card = if r1 == 0x1AA { | 1003 | regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8)); |
| 1045 | // Card echoed back the pattern. Must be at least v2 | 1004 | Self::cmd(Cmd::idle(), false)?; |
| 1046 | Card::default() | ||
| 1047 | } else { | ||
| 1048 | return Err(Error::UnsupportedCardVersion); | ||
| 1049 | }; | ||
| 1050 | 1005 | ||
| 1051 | let ocr = loop { | 1006 | // Check if cards supports CMD8 (with pattern) |
| 1052 | // Signal that next command is a app command | 1007 | Self::cmd(Cmd::hs_send_ext_csd(0x1AA), false)?; |
| 1053 | Self::cmd(Cmd::app_cmd(0), false)?; // CMD55 | 1008 | let r1 = regs.respr(0).read().cardstatus(); |
| 1054 | 1009 | ||
| 1055 | let arg = CmdAppOper::VOLTAGE_WINDOW_SD as u32 | 1010 | let mut card = if r1 == 0x1AA { |
| 1056 | | CmdAppOper::HIGH_CAPACITY as u32 | 1011 | // Card echoed back the pattern. Must be at least v2 |
| 1057 | | CmdAppOper::SD_SWITCH_1_8V_CAPACITY as u32; | 1012 | Card::default() |
| 1013 | } else { | ||
| 1014 | return Err(Error::UnsupportedCardVersion); | ||
| 1015 | }; | ||
| 1058 | 1016 | ||
| 1059 | // Initialize card | 1017 | let ocr = loop { |
| 1060 | match Self::cmd(Cmd::app_op_cmd(arg), false) { | 1018 | // Signal that next command is a app command |
| 1061 | // ACMD41 | 1019 | Self::cmd(Cmd::app_cmd(0), false)?; // CMD55 |
| 1062 | Ok(_) => (), | ||
| 1063 | Err(Error::Crc) => (), | ||
| 1064 | Err(err) => return Err(err), | ||
| 1065 | } | ||
| 1066 | let ocr: OCR = regs.respr(0).read().cardstatus().into(); | ||
| 1067 | if !ocr.is_busy() { | ||
| 1068 | // Power up done | ||
| 1069 | break ocr; | ||
| 1070 | } | ||
| 1071 | }; | ||
| 1072 | 1020 | ||
| 1073 | if ocr.high_capacity() { | 1021 | let arg = CmdAppOper::VOLTAGE_WINDOW_SD as u32 |
| 1074 | // Card is SDHC or SDXC or SDUC | 1022 | | CmdAppOper::HIGH_CAPACITY as u32 |
| 1075 | card.card_type = CardCapacity::SDHC; | 1023 | | CmdAppOper::SD_SWITCH_1_8V_CAPACITY as u32; |
| 1076 | } else { | ||
| 1077 | card.card_type = CardCapacity::SDSC; | ||
| 1078 | } | ||
| 1079 | card.ocr = ocr; | ||
| 1080 | |||
| 1081 | Self::cmd(Cmd::all_send_cid(), false)?; // CMD2 | ||
| 1082 | let cid0 = regs.respr(0).read().cardstatus() as u128; | ||
| 1083 | let cid1 = regs.respr(1).read().cardstatus() as u128; | ||
| 1084 | let cid2 = regs.respr(2).read().cardstatus() as u128; | ||
| 1085 | let cid3 = regs.respr(3).read().cardstatus() as u128; | ||
| 1086 | let cid = (cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3); | ||
| 1087 | card.cid = cid.into(); | ||
| 1088 | |||
| 1089 | Self::cmd(Cmd::send_rel_addr(), false)?; | ||
| 1090 | card.rca = regs.respr(0).read().cardstatus() >> 16; | ||
| 1091 | |||
| 1092 | Self::cmd(Cmd::send_csd(card.rca << 16), false)?; | ||
| 1093 | let csd0 = regs.respr(0).read().cardstatus() as u128; | ||
| 1094 | let csd1 = regs.respr(1).read().cardstatus() as u128; | ||
| 1095 | let csd2 = regs.respr(2).read().cardstatus() as u128; | ||
| 1096 | let csd3 = regs.respr(3).read().cardstatus() as u128; | ||
| 1097 | let csd = (csd0 << 96) | (csd1 << 64) | (csd2 << 32) | (csd3); | ||
| 1098 | card.csd = csd.into(); | ||
| 1099 | |||
| 1100 | self.select_card(Some(&card))?; | ||
| 1101 | |||
| 1102 | self.get_scr(&mut card).await?; | ||
| 1103 | |||
| 1104 | // Set bus width | ||
| 1105 | let (width, acmd_arg) = match bus_width { | ||
| 1106 | BusWidth::Eight => unimplemented!(), | ||
| 1107 | BusWidth::Four if card.scr.bus_width_four() => (BusWidth::Four, 2), | ||
| 1108 | _ => (BusWidth::One, 0), | ||
| 1109 | }; | ||
| 1110 | Self::cmd(Cmd::app_cmd(card.rca << 16), false)?; | ||
| 1111 | Self::cmd(Cmd::cmd6(acmd_arg), false)?; | ||
| 1112 | |||
| 1113 | // CPSMACT and DPSMACT must be 0 to set WIDBUS | ||
| 1114 | Self::wait_idle(); | ||
| 1115 | |||
| 1116 | regs.clkcr().modify(|w| { | ||
| 1117 | w.set_widbus(match width { | ||
| 1118 | BusWidth::One => 0, | ||
| 1119 | BusWidth::Four => 1, | ||
| 1120 | BusWidth::Eight => 2, | ||
| 1121 | _ => panic!("Invalid Bus Width"), | ||
| 1122 | }) | ||
| 1123 | }); | ||
| 1124 | 1024 | ||
| 1125 | // Set Clock | 1025 | // Initialize card |
| 1126 | if freq.0 <= 25_000_000 { | 1026 | match Self::cmd(Cmd::app_op_cmd(arg), false) { |
| 1127 | // Final clock frequency | 1027 | // ACMD41 |
| 1128 | self.clkcr_set_clkdiv(freq.0, width)?; | 1028 | Ok(_) => (), |
| 1129 | } else { | 1029 | Err(Error::Crc) => (), |
| 1130 | // Switch to max clock for SDR12 | 1030 | Err(err) => return Err(err), |
| 1131 | self.clkcr_set_clkdiv(25_000_000, width)?; | ||
| 1132 | } | 1031 | } |
| 1032 | let ocr: OCR = regs.respr(0).read().cardstatus().into(); | ||
| 1033 | if !ocr.is_busy() { | ||
| 1034 | // Power up done | ||
| 1035 | break ocr; | ||
| 1036 | } | ||
| 1037 | }; | ||
| 1038 | |||
| 1039 | if ocr.high_capacity() { | ||
| 1040 | // Card is SDHC or SDXC or SDUC | ||
| 1041 | card.card_type = CardCapacity::SDHC; | ||
| 1042 | } else { | ||
| 1043 | card.card_type = CardCapacity::SDSC; | ||
| 1044 | } | ||
| 1045 | card.ocr = ocr; | ||
| 1046 | |||
| 1047 | Self::cmd(Cmd::all_send_cid(), false)?; // CMD2 | ||
| 1048 | let cid0 = regs.respr(0).read().cardstatus() as u128; | ||
| 1049 | let cid1 = regs.respr(1).read().cardstatus() as u128; | ||
| 1050 | let cid2 = regs.respr(2).read().cardstatus() as u128; | ||
| 1051 | let cid3 = regs.respr(3).read().cardstatus() as u128; | ||
| 1052 | let cid = (cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3); | ||
| 1053 | card.cid = cid.into(); | ||
| 1054 | |||
| 1055 | Self::cmd(Cmd::send_rel_addr(), false)?; | ||
| 1056 | card.rca = regs.respr(0).read().cardstatus() >> 16; | ||
| 1057 | |||
| 1058 | Self::cmd(Cmd::send_csd(card.rca << 16), false)?; | ||
| 1059 | let csd0 = regs.respr(0).read().cardstatus() as u128; | ||
| 1060 | let csd1 = regs.respr(1).read().cardstatus() as u128; | ||
| 1061 | let csd2 = regs.respr(2).read().cardstatus() as u128; | ||
| 1062 | let csd3 = regs.respr(3).read().cardstatus() as u128; | ||
| 1063 | let csd = (csd0 << 96) | (csd1 << 64) | (csd2 << 32) | (csd3); | ||
| 1064 | card.csd = csd.into(); | ||
| 1065 | |||
| 1066 | self.select_card(Some(&card))?; | ||
| 1067 | |||
| 1068 | self.get_scr(&mut card).await?; | ||
| 1069 | |||
| 1070 | // Set bus width | ||
| 1071 | let (width, acmd_arg) = match bus_width { | ||
| 1072 | BusWidth::Eight => unimplemented!(), | ||
| 1073 | BusWidth::Four if card.scr.bus_width_four() => (BusWidth::Four, 2), | ||
| 1074 | _ => (BusWidth::One, 0), | ||
| 1075 | }; | ||
| 1076 | Self::cmd(Cmd::app_cmd(card.rca << 16), false)?; | ||
| 1077 | Self::cmd(Cmd::cmd6(acmd_arg), false)?; | ||
| 1078 | |||
| 1079 | // CPSMACT and DPSMACT must be 0 to set WIDBUS | ||
| 1080 | Self::wait_idle(); | ||
| 1133 | 1081 | ||
| 1134 | self.card = Some(card); | 1082 | regs.clkcr().modify(|w| { |
| 1083 | w.set_widbus(match width { | ||
| 1084 | BusWidth::One => 0, | ||
| 1085 | BusWidth::Four => 1, | ||
| 1086 | BusWidth::Eight => 2, | ||
| 1087 | _ => panic!("Invalid Bus Width"), | ||
| 1088 | }) | ||
| 1089 | }); | ||
| 1090 | |||
| 1091 | // Set Clock | ||
| 1092 | if freq.0 <= 25_000_000 { | ||
| 1093 | // Final clock frequency | ||
| 1094 | self.clkcr_set_clkdiv(freq.0, width)?; | ||
| 1095 | } else { | ||
| 1096 | // Switch to max clock for SDR12 | ||
| 1097 | self.clkcr_set_clkdiv(25_000_000, width)?; | ||
| 1098 | } | ||
| 1135 | 1099 | ||
| 1136 | // Read status | 1100 | self.card = Some(card); |
| 1137 | self.read_sd_status().await?; | ||
| 1138 | 1101 | ||
| 1139 | if freq.0 > 25_000_000 { | 1102 | // Read status |
| 1140 | // Switch to SDR25 | 1103 | self.read_sd_status().await?; |
| 1141 | self.signalling = self.switch_signalling_mode(Signalling::SDR25).await?; | ||
| 1142 | 1104 | ||
| 1143 | if self.signalling == Signalling::SDR25 { | 1105 | if freq.0 > 25_000_000 { |
| 1144 | // Set final clock frequency | 1106 | // Switch to SDR25 |
| 1145 | self.clkcr_set_clkdiv(freq.0, width)?; | 1107 | self.signalling = self.switch_signalling_mode(Signalling::SDR25).await?; |
| 1146 | 1108 | ||
| 1147 | if self.read_status(&card)?.state() != CurrentState::Transfer { | 1109 | if self.signalling == Signalling::SDR25 { |
| 1148 | return Err(Error::SignalingSwitchFailed); | 1110 | // Set final clock frequency |
| 1149 | } | 1111 | self.clkcr_set_clkdiv(freq.0, width)?; |
| 1112 | |||
| 1113 | if self.read_status(&card)?.state() != CurrentState::Transfer { | ||
| 1114 | return Err(Error::SignalingSwitchFailed); | ||
| 1150 | } | 1115 | } |
| 1151 | } | 1116 | } |
| 1152 | // Read status after signalling change | ||
| 1153 | self.read_sd_status().await?; | ||
| 1154 | } | 1117 | } |
| 1118 | // Read status after signalling change | ||
| 1119 | self.read_sd_status().await?; | ||
| 1155 | 1120 | ||
| 1156 | Ok(()) | 1121 | Ok(()) |
| 1157 | } | 1122 | } |
| @@ -1172,7 +1137,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 1172 | Self::cmd(Cmd::set_block_length(512), false)?; // CMD16 | 1137 | Self::cmd(Cmd::set_block_length(512), false)?; // CMD16 |
| 1173 | 1138 | ||
| 1174 | let regs = T::regs(); | 1139 | let regs = T::regs(); |
| 1175 | let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); | 1140 | let on_drop = OnDrop::new(|| Self::on_drop()); |
| 1176 | 1141 | ||
| 1177 | let transfer = self.prepare_datapath_read(buffer, 512, 9); | 1142 | let transfer = self.prepare_datapath_read(buffer, 512, 9); |
| 1178 | InterruptHandler::<T>::data_interrupts(true); | 1143 | InterruptHandler::<T>::data_interrupts(true); |
| @@ -1180,7 +1145,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 1180 | 1145 | ||
| 1181 | let res = poll_fn(|cx| { | 1146 | let res = poll_fn(|cx| { |
| 1182 | T::state().register(cx.waker()); | 1147 | T::state().register(cx.waker()); |
| 1183 | let status = unsafe { regs.star().read() }; | 1148 | let status = regs.star().read(); |
| 1184 | 1149 | ||
| 1185 | if status.dcrcfail() { | 1150 | if status.dcrcfail() { |
| 1186 | return Poll::Ready(Err(Error::Crc)); | 1151 | return Poll::Ready(Err(Error::Crc)); |
| @@ -1217,7 +1182,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 1217 | Self::cmd(Cmd::set_block_length(512), false)?; // CMD16 | 1182 | Self::cmd(Cmd::set_block_length(512), false)?; // CMD16 |
| 1218 | 1183 | ||
| 1219 | let regs = T::regs(); | 1184 | let regs = T::regs(); |
| 1220 | let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); | 1185 | let on_drop = OnDrop::new(|| Self::on_drop()); |
| 1221 | 1186 | ||
| 1222 | // sdmmc_v1 uses different cmd/dma order than v2, but only for writes | 1187 | // sdmmc_v1 uses different cmd/dma order than v2, but only for writes |
| 1223 | #[cfg(sdmmc_v1)] | 1188 | #[cfg(sdmmc_v1)] |
| @@ -1231,7 +1196,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 1231 | 1196 | ||
| 1232 | let res = poll_fn(|cx| { | 1197 | let res = poll_fn(|cx| { |
| 1233 | T::state().register(cx.waker()); | 1198 | T::state().register(cx.waker()); |
| 1234 | let status = unsafe { regs.star().read() }; | 1199 | let status = regs.star().read(); |
| 1235 | 1200 | ||
| 1236 | if status.dcrcfail() { | 1201 | if status.dcrcfail() { |
| 1237 | return Poll::Ready(Err(Error::Crc)); | 1202 | return Poll::Ready(Err(Error::Crc)); |
| @@ -1289,9 +1254,9 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 1289 | impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Drop for Sdmmc<'d, T, Dma> { | 1254 | impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Drop for Sdmmc<'d, T, Dma> { |
| 1290 | fn drop(&mut self) { | 1255 | fn drop(&mut self) { |
| 1291 | T::Interrupt::disable(); | 1256 | T::Interrupt::disable(); |
| 1292 | unsafe { Self::on_drop() }; | 1257 | Self::on_drop(); |
| 1293 | 1258 | ||
| 1294 | critical_section::with(|_| unsafe { | 1259 | critical_section::with(|_| { |
| 1295 | self.clk.set_as_disconnected(); | 1260 | self.clk.set_as_disconnected(); |
| 1296 | self.cmd.set_as_disconnected(); | 1261 | self.cmd.set_as_disconnected(); |
| 1297 | self.d0.set_as_disconnected(); | 1262 | self.d0.set_as_disconnected(); |
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 580971e45..1cddac992 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs | |||
| @@ -98,14 +98,12 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 98 | Polarity::IdleHigh => Pull::Up, | 98 | Polarity::IdleHigh => Pull::Up, |
| 99 | }; | 99 | }; |
| 100 | 100 | ||
| 101 | unsafe { | 101 | sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, sck_pull_mode); |
| 102 | sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, sck_pull_mode); | 102 | sck.set_speed(crate::gpio::Speed::VeryHigh); |
| 103 | sck.set_speed(crate::gpio::Speed::VeryHigh); | 103 | mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); |
| 104 | mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); | 104 | mosi.set_speed(crate::gpio::Speed::VeryHigh); |
| 105 | mosi.set_speed(crate::gpio::Speed::VeryHigh); | 105 | miso.set_as_af(miso.af_num(), AFType::Input); |
| 106 | miso.set_as_af(miso.af_num(), AFType::Input); | 106 | miso.set_speed(crate::gpio::Speed::VeryHigh); |
| 107 | miso.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 108 | } | ||
| 109 | 107 | ||
| 110 | Self::new_inner( | 108 | Self::new_inner( |
| 111 | peri, | 109 | peri, |
| @@ -129,12 +127,10 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 129 | config: Config, | 127 | config: Config, |
| 130 | ) -> Self { | 128 | ) -> Self { |
| 131 | into_ref!(sck, miso); | 129 | into_ref!(sck, miso); |
| 132 | unsafe { | 130 | sck.set_as_af(sck.af_num(), AFType::OutputPushPull); |
| 133 | sck.set_as_af(sck.af_num(), AFType::OutputPushPull); | 131 | sck.set_speed(crate::gpio::Speed::VeryHigh); |
| 134 | sck.set_speed(crate::gpio::Speed::VeryHigh); | 132 | miso.set_as_af(miso.af_num(), AFType::Input); |
| 135 | miso.set_as_af(miso.af_num(), AFType::Input); | 133 | miso.set_speed(crate::gpio::Speed::VeryHigh); |
| 136 | miso.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 137 | } | ||
| 138 | 134 | ||
| 139 | Self::new_inner( | 135 | Self::new_inner( |
| 140 | peri, | 136 | peri, |
| @@ -158,12 +154,10 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 158 | config: Config, | 154 | config: Config, |
| 159 | ) -> Self { | 155 | ) -> Self { |
| 160 | into_ref!(sck, mosi); | 156 | into_ref!(sck, mosi); |
| 161 | unsafe { | 157 | sck.set_as_af(sck.af_num(), AFType::OutputPushPull); |
| 162 | sck.set_as_af(sck.af_num(), AFType::OutputPushPull); | 158 | sck.set_speed(crate::gpio::Speed::VeryHigh); |
| 163 | sck.set_speed(crate::gpio::Speed::VeryHigh); | 159 | mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); |
| 164 | mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); | 160 | mosi.set_speed(crate::gpio::Speed::VeryHigh); |
| 165 | mosi.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 166 | } | ||
| 167 | 161 | ||
| 168 | Self::new_inner( | 162 | Self::new_inner( |
| 169 | peri, | 163 | peri, |
| @@ -186,10 +180,8 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 186 | config: Config, | 180 | config: Config, |
| 187 | ) -> Self { | 181 | ) -> Self { |
| 188 | into_ref!(mosi); | 182 | into_ref!(mosi); |
| 189 | unsafe { | 183 | mosi.set_as_af_pull(mosi.af_num(), AFType::OutputPushPull, Pull::Down); |
| 190 | mosi.set_as_af_pull(mosi.af_num(), AFType::OutputPushPull, Pull::Down); | 184 | mosi.set_speed(crate::gpio::Speed::Medium); |
| 191 | mosi.set_speed(crate::gpio::Speed::Medium); | ||
| 192 | } | ||
| 193 | 185 | ||
| 194 | Self::new_inner(peri, None, Some(mosi.map_into()), None, txdma, rxdma, freq, config) | 186 | Self::new_inner(peri, None, Some(mosi.map_into()), None, txdma, rxdma, freq, config) |
| 195 | } | 187 | } |
| @@ -247,7 +239,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 247 | T::reset(); | 239 | T::reset(); |
| 248 | 240 | ||
| 249 | #[cfg(any(spi_v1, spi_f1))] | 241 | #[cfg(any(spi_v1, spi_f1))] |
| 250 | unsafe { | 242 | { |
| 251 | T::REGS.cr2().modify(|w| { | 243 | T::REGS.cr2().modify(|w| { |
| 252 | w.set_ssoe(false); | 244 | w.set_ssoe(false); |
| 253 | }); | 245 | }); |
| @@ -270,7 +262,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 270 | }); | 262 | }); |
| 271 | } | 263 | } |
| 272 | #[cfg(spi_v2)] | 264 | #[cfg(spi_v2)] |
| 273 | unsafe { | 265 | { |
| 274 | T::REGS.cr2().modify(|w| { | 266 | T::REGS.cr2().modify(|w| { |
| 275 | let (ds, frxth) = <u8 as sealed::Word>::CONFIG; | 267 | let (ds, frxth) = <u8 as sealed::Word>::CONFIG; |
| 276 | w.set_frxth(frxth); | 268 | w.set_frxth(frxth); |
| @@ -292,7 +284,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 292 | }); | 284 | }); |
| 293 | } | 285 | } |
| 294 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 286 | #[cfg(any(spi_v3, spi_v4, spi_v5))] |
| 295 | unsafe { | 287 | { |
| 296 | T::REGS.ifcr().write(|w| w.0 = 0xffff_ffff); | 288 | T::REGS.ifcr().write(|w| w.0 = 0xffff_ffff); |
| 297 | T::REGS.cfg2().modify(|w| { | 289 | T::REGS.cfg2().modify(|w| { |
| 298 | //w.set_ssoe(true); | 290 | //w.set_ssoe(true); |
| @@ -343,29 +335,25 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 343 | let lsbfirst = config.raw_byte_order(); | 335 | let lsbfirst = config.raw_byte_order(); |
| 344 | 336 | ||
| 345 | #[cfg(any(spi_v1, spi_f1, spi_v2))] | 337 | #[cfg(any(spi_v1, spi_f1, spi_v2))] |
| 346 | unsafe { | 338 | T::REGS.cr1().modify(|w| { |
| 347 | T::REGS.cr1().modify(|w| { | 339 | w.set_cpha(cpha); |
| 348 | w.set_cpha(cpha); | 340 | w.set_cpol(cpol); |
| 349 | w.set_cpol(cpol); | 341 | w.set_lsbfirst(lsbfirst); |
| 350 | w.set_lsbfirst(lsbfirst); | 342 | }); |
| 351 | }); | ||
| 352 | } | ||
| 353 | 343 | ||
| 354 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 344 | #[cfg(any(spi_v3, spi_v4, spi_v5))] |
| 355 | unsafe { | 345 | T::REGS.cfg2().modify(|w| { |
| 356 | T::REGS.cfg2().modify(|w| { | 346 | w.set_cpha(cpha); |
| 357 | w.set_cpha(cpha); | 347 | w.set_cpol(cpol); |
| 358 | w.set_cpol(cpol); | 348 | w.set_lsbfirst(lsbfirst); |
| 359 | w.set_lsbfirst(lsbfirst); | 349 | }); |
| 360 | }); | ||
| 361 | } | ||
| 362 | } | 350 | } |
| 363 | 351 | ||
| 364 | pub fn get_current_config(&self) -> Config { | 352 | pub fn get_current_config(&self) -> Config { |
| 365 | #[cfg(any(spi_v1, spi_f1, spi_v2))] | 353 | #[cfg(any(spi_v1, spi_f1, spi_v2))] |
| 366 | let cfg = unsafe { T::REGS.cr1().read() }; | 354 | let cfg = T::REGS.cr1().read(); |
| 367 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 355 | #[cfg(any(spi_v3, spi_v4, spi_v5))] |
| 368 | let cfg = unsafe { T::REGS.cfg2().read() }; | 356 | let cfg = T::REGS.cfg2().read(); |
| 369 | let polarity = if cfg.cpol() == vals::Cpol::IDLELOW { | 357 | let polarity = if cfg.cpol() == vals::Cpol::IDLELOW { |
| 370 | Polarity::IdleLow | 358 | Polarity::IdleLow |
| 371 | } else { | 359 | } else { |
| @@ -395,7 +383,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 395 | } | 383 | } |
| 396 | 384 | ||
| 397 | #[cfg(any(spi_v1, spi_f1))] | 385 | #[cfg(any(spi_v1, spi_f1))] |
| 398 | unsafe { | 386 | { |
| 399 | T::REGS.cr1().modify(|reg| { | 387 | T::REGS.cr1().modify(|reg| { |
| 400 | reg.set_spe(false); | 388 | reg.set_spe(false); |
| 401 | reg.set_dff(word_size) | 389 | reg.set_dff(word_size) |
| @@ -405,7 +393,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 405 | }); | 393 | }); |
| 406 | } | 394 | } |
| 407 | #[cfg(spi_v2)] | 395 | #[cfg(spi_v2)] |
| 408 | unsafe { | 396 | { |
| 409 | T::REGS.cr1().modify(|w| { | 397 | T::REGS.cr1().modify(|w| { |
| 410 | w.set_spe(false); | 398 | w.set_spe(false); |
| 411 | }); | 399 | }); |
| @@ -418,7 +406,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 418 | }); | 406 | }); |
| 419 | } | 407 | } |
| 420 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 408 | #[cfg(any(spi_v3, spi_v4, spi_v5))] |
| 421 | unsafe { | 409 | { |
| 422 | T::REGS.cr1().modify(|w| { | 410 | T::REGS.cr1().modify(|w| { |
| 423 | w.set_csusp(true); | 411 | w.set_csusp(true); |
| 424 | }); | 412 | }); |
| @@ -447,26 +435,22 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 447 | } | 435 | } |
| 448 | 436 | ||
| 449 | self.set_word_size(W::CONFIG); | 437 | self.set_word_size(W::CONFIG); |
| 450 | unsafe { | 438 | T::REGS.cr1().modify(|w| { |
| 451 | T::REGS.cr1().modify(|w| { | 439 | w.set_spe(false); |
| 452 | w.set_spe(false); | 440 | }); |
| 453 | }); | ||
| 454 | } | ||
| 455 | 441 | ||
| 456 | let tx_request = self.txdma.request(); | 442 | let tx_request = self.txdma.request(); |
| 457 | let tx_dst = T::REGS.tx_ptr(); | 443 | let tx_dst = T::REGS.tx_ptr(); |
| 458 | let tx_f = unsafe { Transfer::new_write(&mut self.txdma, tx_request, data, tx_dst, Default::default()) }; | 444 | let tx_f = unsafe { Transfer::new_write(&mut self.txdma, tx_request, data, tx_dst, Default::default()) }; |
| 459 | 445 | ||
| 460 | unsafe { | 446 | set_txdmaen(T::REGS, true); |
| 461 | set_txdmaen(T::REGS, true); | 447 | T::REGS.cr1().modify(|w| { |
| 462 | T::REGS.cr1().modify(|w| { | 448 | w.set_spe(true); |
| 463 | w.set_spe(true); | 449 | }); |
| 464 | }); | 450 | #[cfg(any(spi_v3, spi_v4, spi_v5))] |
| 465 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 451 | T::REGS.cr1().modify(|w| { |
| 466 | T::REGS.cr1().modify(|w| { | 452 | w.set_cstart(true); |
| 467 | w.set_cstart(true); | 453 | }); |
| 468 | }); | ||
| 469 | } | ||
| 470 | 454 | ||
| 471 | tx_f.await; | 455 | tx_f.await; |
| 472 | 456 | ||
| @@ -485,11 +469,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 485 | } | 469 | } |
| 486 | 470 | ||
| 487 | self.set_word_size(W::CONFIG); | 471 | self.set_word_size(W::CONFIG); |
| 488 | unsafe { | 472 | T::REGS.cr1().modify(|w| { |
| 489 | T::REGS.cr1().modify(|w| { | 473 | w.set_spe(false); |
| 490 | w.set_spe(false); | 474 | }); |
| 491 | }); | ||
| 492 | } | ||
| 493 | 475 | ||
| 494 | // SPIv3 clears rxfifo on SPE=0 | 476 | // SPIv3 clears rxfifo on SPE=0 |
| 495 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] | 477 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] |
| @@ -517,16 +499,14 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 517 | ) | 499 | ) |
| 518 | }; | 500 | }; |
| 519 | 501 | ||
| 520 | unsafe { | 502 | set_txdmaen(T::REGS, true); |
| 521 | set_txdmaen(T::REGS, true); | 503 | T::REGS.cr1().modify(|w| { |
| 522 | T::REGS.cr1().modify(|w| { | 504 | w.set_spe(true); |
| 523 | w.set_spe(true); | 505 | }); |
| 524 | }); | 506 | #[cfg(any(spi_v3, spi_v4, spi_v5))] |
| 525 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 507 | T::REGS.cr1().modify(|w| { |
| 526 | T::REGS.cr1().modify(|w| { | 508 | w.set_cstart(true); |
| 527 | w.set_cstart(true); | 509 | }); |
| 528 | }); | ||
| 529 | } | ||
| 530 | 510 | ||
| 531 | join(tx_f, rx_f).await; | 511 | join(tx_f, rx_f).await; |
| 532 | 512 | ||
| @@ -548,11 +528,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 548 | } | 528 | } |
| 549 | 529 | ||
| 550 | self.set_word_size(W::CONFIG); | 530 | self.set_word_size(W::CONFIG); |
| 551 | unsafe { | 531 | T::REGS.cr1().modify(|w| { |
| 552 | T::REGS.cr1().modify(|w| { | 532 | w.set_spe(false); |
| 553 | w.set_spe(false); | 533 | }); |
| 554 | }); | ||
| 555 | } | ||
| 556 | 534 | ||
| 557 | // SPIv3 clears rxfifo on SPE=0 | 535 | // SPIv3 clears rxfifo on SPE=0 |
| 558 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] | 536 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] |
| @@ -568,16 +546,14 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 568 | let tx_dst = T::REGS.tx_ptr(); | 546 | let tx_dst = T::REGS.tx_ptr(); |
| 569 | let tx_f = unsafe { Transfer::new_write_raw(&mut self.txdma, tx_request, write, tx_dst, Default::default()) }; | 547 | let tx_f = unsafe { Transfer::new_write_raw(&mut self.txdma, tx_request, write, tx_dst, Default::default()) }; |
| 570 | 548 | ||
| 571 | unsafe { | 549 | set_txdmaen(T::REGS, true); |
| 572 | set_txdmaen(T::REGS, true); | 550 | T::REGS.cr1().modify(|w| { |
| 573 | T::REGS.cr1().modify(|w| { | 551 | w.set_spe(true); |
| 574 | w.set_spe(true); | 552 | }); |
| 575 | }); | 553 | #[cfg(any(spi_v3, spi_v4, spi_v5))] |
| 576 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 554 | T::REGS.cr1().modify(|w| { |
| 577 | T::REGS.cr1().modify(|w| { | 555 | w.set_cstart(true); |
| 578 | w.set_cstart(true); | 556 | }); |
| 579 | }); | ||
| 580 | } | ||
| 581 | 557 | ||
| 582 | join(tx_f, rx_f).await; | 558 | join(tx_f, rx_f).await; |
| 583 | 559 | ||
| @@ -603,7 +579,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 603 | } | 579 | } |
| 604 | 580 | ||
| 605 | pub fn blocking_write<W: Word>(&mut self, words: &[W]) -> Result<(), Error> { | 581 | pub fn blocking_write<W: Word>(&mut self, words: &[W]) -> Result<(), Error> { |
| 606 | unsafe { T::REGS.cr1().modify(|w| w.set_spe(true)) } | 582 | T::REGS.cr1().modify(|w| w.set_spe(true)); |
| 607 | flush_rx_fifo(T::REGS); | 583 | flush_rx_fifo(T::REGS); |
| 608 | self.set_word_size(W::CONFIG); | 584 | self.set_word_size(W::CONFIG); |
| 609 | for word in words.iter() { | 585 | for word in words.iter() { |
| @@ -613,7 +589,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 613 | } | 589 | } |
| 614 | 590 | ||
| 615 | pub fn blocking_read<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> { | 591 | pub fn blocking_read<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> { |
| 616 | unsafe { T::REGS.cr1().modify(|w| w.set_spe(true)) } | 592 | T::REGS.cr1().modify(|w| w.set_spe(true)); |
| 617 | flush_rx_fifo(T::REGS); | 593 | flush_rx_fifo(T::REGS); |
| 618 | self.set_word_size(W::CONFIG); | 594 | self.set_word_size(W::CONFIG); |
| 619 | for word in words.iter_mut() { | 595 | for word in words.iter_mut() { |
| @@ -623,7 +599,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 623 | } | 599 | } |
| 624 | 600 | ||
| 625 | pub fn blocking_transfer_in_place<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> { | 601 | pub fn blocking_transfer_in_place<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> { |
| 626 | unsafe { T::REGS.cr1().modify(|w| w.set_spe(true)) } | 602 | T::REGS.cr1().modify(|w| w.set_spe(true)); |
| 627 | flush_rx_fifo(T::REGS); | 603 | flush_rx_fifo(T::REGS); |
| 628 | self.set_word_size(W::CONFIG); | 604 | self.set_word_size(W::CONFIG); |
| 629 | for word in words.iter_mut() { | 605 | for word in words.iter_mut() { |
| @@ -633,7 +609,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 633 | } | 609 | } |
| 634 | 610 | ||
| 635 | pub fn blocking_transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> { | 611 | pub fn blocking_transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> { |
| 636 | unsafe { T::REGS.cr1().modify(|w| w.set_spe(true)) } | 612 | T::REGS.cr1().modify(|w| w.set_spe(true)); |
| 637 | flush_rx_fifo(T::REGS); | 613 | flush_rx_fifo(T::REGS); |
| 638 | self.set_word_size(W::CONFIG); | 614 | self.set_word_size(W::CONFIG); |
| 639 | let len = read.len().max(write.len()); | 615 | let len = read.len().max(write.len()); |
| @@ -650,11 +626,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 650 | 626 | ||
| 651 | impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> { | 627 | impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> { |
| 652 | fn drop(&mut self) { | 628 | fn drop(&mut self) { |
| 653 | unsafe { | 629 | self.sck.as_ref().map(|x| x.set_as_disconnected()); |
| 654 | self.sck.as_ref().map(|x| x.set_as_disconnected()); | 630 | self.mosi.as_ref().map(|x| x.set_as_disconnected()); |
| 655 | self.mosi.as_ref().map(|x| x.set_as_disconnected()); | 631 | self.miso.as_ref().map(|x| x.set_as_disconnected()); |
| 656 | self.miso.as_ref().map(|x| x.set_as_disconnected()); | ||
| 657 | } | ||
| 658 | } | 632 | } |
| 659 | } | 633 | } |
| 660 | 634 | ||
| @@ -690,7 +664,7 @@ impl RegsExt for Regs { | |||
| 690 | let dr = self.dr(); | 664 | let dr = self.dr(); |
| 691 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 665 | #[cfg(any(spi_v3, spi_v4, spi_v5))] |
| 692 | let dr = self.txdr(); | 666 | let dr = self.txdr(); |
| 693 | dr.ptr() as *mut W | 667 | dr.as_ptr() as *mut W |
| 694 | } | 668 | } |
| 695 | 669 | ||
| 696 | fn rx_ptr<W>(&self) -> *mut W { | 670 | fn rx_ptr<W>(&self) -> *mut W { |
| @@ -698,7 +672,7 @@ impl RegsExt for Regs { | |||
| 698 | let dr = self.dr(); | 672 | let dr = self.dr(); |
| 699 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 673 | #[cfg(any(spi_v3, spi_v4, spi_v5))] |
| 700 | let dr = self.rxdr(); | 674 | let dr = self.rxdr(); |
| 701 | dr.ptr() as *mut W | 675 | dr.as_ptr() as *mut W |
| 702 | } | 676 | } |
| 703 | } | 677 | } |
| 704 | 678 | ||
| @@ -731,7 +705,7 @@ fn check_error_flags(sr: regs::Sr) -> Result<(), Error> { | |||
| 731 | 705 | ||
| 732 | fn spin_until_tx_ready(regs: Regs) -> Result<(), Error> { | 706 | fn spin_until_tx_ready(regs: Regs) -> Result<(), Error> { |
| 733 | loop { | 707 | loop { |
| 734 | let sr = unsafe { regs.sr().read() }; | 708 | let sr = regs.sr().read(); |
| 735 | 709 | ||
| 736 | check_error_flags(sr)?; | 710 | check_error_flags(sr)?; |
| 737 | 711 | ||
| @@ -748,7 +722,7 @@ fn spin_until_tx_ready(regs: Regs) -> Result<(), Error> { | |||
| 748 | 722 | ||
| 749 | fn spin_until_rx_ready(regs: Regs) -> Result<(), Error> { | 723 | fn spin_until_rx_ready(regs: Regs) -> Result<(), Error> { |
| 750 | loop { | 724 | loop { |
| 751 | let sr = unsafe { regs.sr().read() }; | 725 | let sr = regs.sr().read(); |
| 752 | 726 | ||
| 753 | check_error_flags(sr)?; | 727 | check_error_flags(sr)?; |
| 754 | 728 | ||
| @@ -764,72 +738,64 @@ fn spin_until_rx_ready(regs: Regs) -> Result<(), Error> { | |||
| 764 | } | 738 | } |
| 765 | 739 | ||
| 766 | fn flush_rx_fifo(regs: Regs) { | 740 | fn flush_rx_fifo(regs: Regs) { |
| 767 | unsafe { | 741 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] |
| 768 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] | 742 | while regs.sr().read().rxne() { |
| 769 | while regs.sr().read().rxne() { | 743 | let _ = regs.dr().read(); |
| 770 | let _ = regs.dr().read(); | 744 | } |
| 771 | } | 745 | #[cfg(any(spi_v3, spi_v4, spi_v5))] |
| 772 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 746 | while regs.sr().read().rxp() { |
| 773 | while regs.sr().read().rxp() { | 747 | let _ = regs.rxdr().read(); |
| 774 | let _ = regs.rxdr().read(); | ||
| 775 | } | ||
| 776 | } | 748 | } |
| 777 | } | 749 | } |
| 778 | 750 | ||
| 779 | fn set_txdmaen(regs: Regs, val: bool) { | 751 | fn set_txdmaen(regs: Regs, val: bool) { |
| 780 | unsafe { | 752 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] |
| 781 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] | 753 | regs.cr2().modify(|reg| { |
| 782 | regs.cr2().modify(|reg| { | 754 | reg.set_txdmaen(val); |
| 783 | reg.set_txdmaen(val); | 755 | }); |
| 784 | }); | 756 | #[cfg(any(spi_v3, spi_v4, spi_v5))] |
| 785 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 757 | regs.cfg1().modify(|reg| { |
| 786 | regs.cfg1().modify(|reg| { | 758 | reg.set_txdmaen(val); |
| 787 | reg.set_txdmaen(val); | 759 | }); |
| 788 | }); | ||
| 789 | } | ||
| 790 | } | 760 | } |
| 791 | 761 | ||
| 792 | fn set_rxdmaen(regs: Regs, val: bool) { | 762 | fn set_rxdmaen(regs: Regs, val: bool) { |
| 793 | unsafe { | 763 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] |
| 794 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] | 764 | regs.cr2().modify(|reg| { |
| 795 | regs.cr2().modify(|reg| { | 765 | reg.set_rxdmaen(val); |
| 796 | reg.set_rxdmaen(val); | 766 | }); |
| 797 | }); | 767 | #[cfg(any(spi_v3, spi_v4, spi_v5))] |
| 798 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 768 | regs.cfg1().modify(|reg| { |
| 799 | regs.cfg1().modify(|reg| { | 769 | reg.set_rxdmaen(val); |
| 800 | reg.set_rxdmaen(val); | 770 | }); |
| 801 | }); | ||
| 802 | } | ||
| 803 | } | 771 | } |
| 804 | 772 | ||
| 805 | fn finish_dma(regs: Regs) { | 773 | fn finish_dma(regs: Regs) { |
| 806 | unsafe { | 774 | #[cfg(spi_v2)] |
| 807 | #[cfg(spi_v2)] | 775 | while regs.sr().read().ftlvl() > 0 {} |
| 808 | while regs.sr().read().ftlvl() > 0 {} | ||
| 809 | 776 | ||
| 810 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 777 | #[cfg(any(spi_v3, spi_v4, spi_v5))] |
| 811 | while !regs.sr().read().txc() {} | 778 | while !regs.sr().read().txc() {} |
| 812 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] | 779 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] |
| 813 | while regs.sr().read().bsy() {} | 780 | while regs.sr().read().bsy() {} |
| 814 | 781 | ||
| 815 | // Disable the spi peripheral | 782 | // Disable the spi peripheral |
| 816 | regs.cr1().modify(|w| { | 783 | regs.cr1().modify(|w| { |
| 817 | w.set_spe(false); | 784 | w.set_spe(false); |
| 818 | }); | 785 | }); |
| 819 | 786 | ||
| 820 | // The peripheral automatically disables the DMA stream on completion without error, | 787 | // The peripheral automatically disables the DMA stream on completion without error, |
| 821 | // but it does not clear the RXDMAEN/TXDMAEN flag in CR2. | 788 | // but it does not clear the RXDMAEN/TXDMAEN flag in CR2. |
| 822 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] | 789 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] |
| 823 | regs.cr2().modify(|reg| { | 790 | regs.cr2().modify(|reg| { |
| 824 | reg.set_txdmaen(false); | 791 | reg.set_txdmaen(false); |
| 825 | reg.set_rxdmaen(false); | 792 | reg.set_rxdmaen(false); |
| 826 | }); | 793 | }); |
| 827 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 794 | #[cfg(any(spi_v3, spi_v4, spi_v5))] |
| 828 | regs.cfg1().modify(|reg| { | 795 | regs.cfg1().modify(|reg| { |
| 829 | reg.set_txdmaen(false); | 796 | reg.set_txdmaen(false); |
| 830 | reg.set_rxdmaen(false); | 797 | reg.set_rxdmaen(false); |
| 831 | }); | 798 | }); |
| 832 | } | ||
| 833 | } | 799 | } |
| 834 | 800 | ||
| 835 | fn transfer_word<W: Word>(regs: Regs, tx_word: W) -> Result<W, Error> { | 801 | fn transfer_word<W: Word>(regs: Regs, tx_word: W) -> Result<W, Error> { |
diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs index e82501a45..2622442f4 100644 --- a/embassy-stm32/src/time_driver.rs +++ b/embassy-stm32/src/time_driver.rs | |||
| @@ -155,8 +155,7 @@ impl RtcDriver { | |||
| 155 | 155 | ||
| 156 | let timer_freq = T::frequency(); | 156 | let timer_freq = T::frequency(); |
| 157 | 157 | ||
| 158 | // NOTE(unsafe) Critical section to use the unsafe methods | 158 | critical_section::with(|_| { |
| 159 | critical_section::with(|_| unsafe { | ||
| 160 | r.cr1().modify(|w| w.set_cen(false)); | 159 | r.cr1().modify(|w| w.set_cen(false)); |
| 161 | r.cnt().write(|w| w.set_cnt(0)); | 160 | r.cnt().write(|w| w.set_cnt(0)); |
| 162 | 161 | ||
| @@ -184,7 +183,7 @@ impl RtcDriver { | |||
| 184 | }); | 183 | }); |
| 185 | 184 | ||
| 186 | <T as BasicInstance>::Interrupt::unpend(); | 185 | <T as BasicInstance>::Interrupt::unpend(); |
| 187 | <T as BasicInstance>::Interrupt::enable(); | 186 | unsafe { <T as BasicInstance>::Interrupt::enable() }; |
| 188 | 187 | ||
| 189 | r.cr1().modify(|w| w.set_cen(true)); | 188 | r.cr1().modify(|w| w.set_cen(true)); |
| 190 | }) | 189 | }) |
| @@ -193,9 +192,8 @@ impl RtcDriver { | |||
| 193 | fn on_interrupt(&self) { | 192 | fn on_interrupt(&self) { |
| 194 | let r = T::regs_gp16(); | 193 | let r = T::regs_gp16(); |
| 195 | 194 | ||
| 196 | // NOTE(unsafe) Use critical section to access the methods | ||
| 197 | // XXX: reduce the size of this critical section ? | 195 | // XXX: reduce the size of this critical section ? |
| 198 | critical_section::with(|cs| unsafe { | 196 | critical_section::with(|cs| { |
| 199 | let sr = r.sr().read(); | 197 | let sr = r.sr().read(); |
| 200 | let dier = r.dier().read(); | 198 | let dier = r.dier().read(); |
| 201 | 199 | ||
| @@ -228,7 +226,7 @@ impl RtcDriver { | |||
| 228 | let period = self.period.fetch_add(1, Ordering::Relaxed) + 1; | 226 | let period = self.period.fetch_add(1, Ordering::Relaxed) + 1; |
| 229 | let t = (period as u64) << 15; | 227 | let t = (period as u64) << 15; |
| 230 | 228 | ||
| 231 | critical_section::with(move |cs| unsafe { | 229 | critical_section::with(move |cs| { |
| 232 | r.dier().modify(move |w| { | 230 | r.dier().modify(move |w| { |
| 233 | for n in 0..ALARM_COUNT { | 231 | for n in 0..ALARM_COUNT { |
| 234 | let alarm = &self.alarms.borrow(cs)[n]; | 232 | let alarm = &self.alarms.borrow(cs)[n]; |
| @@ -269,8 +267,7 @@ impl Driver for RtcDriver { | |||
| 269 | 267 | ||
| 270 | let period = self.period.load(Ordering::Relaxed); | 268 | let period = self.period.load(Ordering::Relaxed); |
| 271 | compiler_fence(Ordering::Acquire); | 269 | compiler_fence(Ordering::Acquire); |
| 272 | // NOTE(unsafe) Atomic read with no side-effects | 270 | let counter = r.cnt().read().cnt(); |
| 273 | let counter = unsafe { r.cnt().read().cnt() }; | ||
| 274 | calc_now(period, counter) | 271 | calc_now(period, counter) |
| 275 | } | 272 | } |
| 276 | 273 | ||
| @@ -310,7 +307,7 @@ impl Driver for RtcDriver { | |||
| 310 | if timestamp <= t { | 307 | if timestamp <= t { |
| 311 | // If alarm timestamp has passed the alarm will not fire. | 308 | // If alarm timestamp has passed the alarm will not fire. |
| 312 | // Disarm the alarm and return `false` to indicate that. | 309 | // Disarm the alarm and return `false` to indicate that. |
| 313 | unsafe { r.dier().modify(|w| w.set_ccie(n + 1, false)) }; | 310 | r.dier().modify(|w| w.set_ccie(n + 1, false)); |
| 314 | 311 | ||
| 315 | alarm.timestamp.set(u64::MAX); | 312 | alarm.timestamp.set(u64::MAX); |
| 316 | 313 | ||
| @@ -321,12 +318,11 @@ impl Driver for RtcDriver { | |||
| 321 | 318 | ||
| 322 | // Write the CCR value regardless of whether we're going to enable it now or not. | 319 | // Write the CCR value regardless of whether we're going to enable it now or not. |
| 323 | // This way, when we enable it later, the right value is already set. | 320 | // This way, when we enable it later, the right value is already set. |
| 324 | unsafe { r.ccr(n + 1).write(|w| w.set_ccr(safe_timestamp as u16)) }; | 321 | r.ccr(n + 1).write(|w| w.set_ccr(safe_timestamp as u16)); |
| 325 | 322 | ||
| 326 | // Enable it if it'll happen soon. Otherwise, `next_period` will enable it. | 323 | // Enable it if it'll happen soon. Otherwise, `next_period` will enable it. |
| 327 | let diff = timestamp - t; | 324 | let diff = timestamp - t; |
| 328 | // NOTE(unsafe) We're in a critical section | 325 | r.dier().modify(|w| w.set_ccie(n + 1, diff < 0xc000)); |
| 329 | unsafe { r.dier().modify(|w| w.set_ccie(n + 1, diff < 0xc000)) }; | ||
| 330 | 326 | ||
| 331 | true | 327 | true |
| 332 | }) | 328 | }) |
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 14db97024..09b7a3776 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs | |||
| @@ -60,25 +60,19 @@ macro_rules! impl_basic_16bit_timer { | |||
| 60 | type Interrupt = crate::interrupt::typelevel::$irq; | 60 | type Interrupt = crate::interrupt::typelevel::$irq; |
| 61 | 61 | ||
| 62 | fn regs() -> crate::pac::timer::TimBasic { | 62 | fn regs() -> crate::pac::timer::TimBasic { |
| 63 | crate::pac::timer::TimBasic(crate::pac::$inst.0) | 63 | unsafe { crate::pac::timer::TimBasic::from_ptr(crate::pac::$inst.as_ptr()) } |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | fn start(&mut self) { | 66 | fn start(&mut self) { |
| 67 | unsafe { | 67 | Self::regs().cr1().modify(|r| r.set_cen(true)); |
| 68 | Self::regs().cr1().modify(|r| r.set_cen(true)); | ||
| 69 | } | ||
| 70 | } | 68 | } |
| 71 | 69 | ||
| 72 | fn stop(&mut self) { | 70 | fn stop(&mut self) { |
| 73 | unsafe { | 71 | Self::regs().cr1().modify(|r| r.set_cen(false)); |
| 74 | Self::regs().cr1().modify(|r| r.set_cen(false)); | ||
| 75 | } | ||
| 76 | } | 72 | } |
| 77 | 73 | ||
| 78 | fn reset(&mut self) { | 74 | fn reset(&mut self) { |
| 79 | unsafe { | 75 | Self::regs().cnt().write(|r| r.set_cnt(0)); |
| 80 | Self::regs().cnt().write(|r| r.set_cnt(0)); | ||
| 81 | } | ||
| 82 | } | 76 | } |
| 83 | 77 | ||
| 84 | fn set_frequency(&mut self, frequency: Hertz) { | 78 | fn set_frequency(&mut self, frequency: Hertz) { |
| @@ -90,35 +84,29 @@ macro_rules! impl_basic_16bit_timer { | |||
| 90 | let arr: u16 = unwrap!((pclk_ticks_per_timer_period / (u32::from(psc) + 1)).try_into()); | 84 | let arr: u16 = unwrap!((pclk_ticks_per_timer_period / (u32::from(psc) + 1)).try_into()); |
| 91 | 85 | ||
| 92 | let regs = Self::regs(); | 86 | let regs = Self::regs(); |
| 93 | unsafe { | 87 | regs.psc().write(|r| r.set_psc(psc)); |
| 94 | regs.psc().write(|r| r.set_psc(psc)); | 88 | regs.arr().write(|r| r.set_arr(arr)); |
| 95 | regs.arr().write(|r| r.set_arr(arr)); | ||
| 96 | 89 | ||
| 97 | regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); | 90 | regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); |
| 98 | regs.egr().write(|r| r.set_ug(true)); | 91 | regs.egr().write(|r| r.set_ug(true)); |
| 99 | regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); | 92 | regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); |
| 100 | } | ||
| 101 | } | 93 | } |
| 102 | 94 | ||
| 103 | fn clear_update_interrupt(&mut self) -> bool { | 95 | fn clear_update_interrupt(&mut self) -> bool { |
| 104 | let regs = Self::regs(); | 96 | let regs = Self::regs(); |
| 105 | unsafe { | 97 | let sr = regs.sr().read(); |
| 106 | let sr = regs.sr().read(); | 98 | if sr.uif() { |
| 107 | if sr.uif() { | 99 | regs.sr().modify(|r| { |
| 108 | regs.sr().modify(|r| { | 100 | r.set_uif(false); |
| 109 | r.set_uif(false); | 101 | }); |
| 110 | }); | 102 | true |
| 111 | true | 103 | } else { |
| 112 | } else { | 104 | false |
| 113 | false | ||
| 114 | } | ||
| 115 | } | 105 | } |
| 116 | } | 106 | } |
| 117 | 107 | ||
| 118 | fn enable_update_interrupt(&mut self, enable: bool) { | 108 | fn enable_update_interrupt(&mut self, enable: bool) { |
| 119 | unsafe { | 109 | Self::regs().dier().write(|r| r.set_uie(enable)); |
| 120 | Self::regs().dier().write(|r| r.set_uie(enable)); | ||
| 121 | } | ||
| 122 | } | 110 | } |
| 123 | } | 111 | } |
| 124 | }; | 112 | }; |
| @@ -141,14 +129,12 @@ macro_rules! impl_32bit_timer { | |||
| 141 | let arr: u32 = unwrap!(((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into())); | 129 | let arr: u32 = unwrap!(((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into())); |
| 142 | 130 | ||
| 143 | let regs = Self::regs_gp32(); | 131 | let regs = Self::regs_gp32(); |
| 144 | unsafe { | 132 | regs.psc().write(|r| r.set_psc(psc)); |
| 145 | regs.psc().write(|r| r.set_psc(psc)); | 133 | regs.arr().write(|r| r.set_arr(arr)); |
| 146 | regs.arr().write(|r| r.set_arr(arr)); | ||
| 147 | 134 | ||
| 148 | regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); | 135 | regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); |
| 149 | regs.egr().write(|r| r.set_ug(true)); | 136 | regs.egr().write(|r| r.set_ug(true)); |
| 150 | regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); | 137 | regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); |
| 151 | } | ||
| 152 | } | 138 | } |
| 153 | } | 139 | } |
| 154 | }; | 140 | }; |
| @@ -185,7 +171,7 @@ foreach_interrupt! { | |||
| 185 | 171 | ||
| 186 | impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { | 172 | impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { |
| 187 | fn regs_gp16() -> crate::pac::timer::TimGp16 { | 173 | fn regs_gp16() -> crate::pac::timer::TimGp16 { |
| 188 | crate::pac::timer::TimGp16(crate::pac::$inst.0) | 174 | unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } |
| 189 | } | 175 | } |
| 190 | } | 176 | } |
| 191 | 177 | ||
| @@ -206,7 +192,7 @@ foreach_interrupt! { | |||
| 206 | 192 | ||
| 207 | impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { | 193 | impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { |
| 208 | fn regs_gp16() -> crate::pac::timer::TimGp16 { | 194 | fn regs_gp16() -> crate::pac::timer::TimGp16 { |
| 209 | crate::pac::timer::TimGp16(crate::pac::$inst.0) | 195 | unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } |
| 210 | } | 196 | } |
| 211 | } | 197 | } |
| 212 | 198 | ||
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index 086196a2c..433ad299c 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs | |||
| @@ -19,68 +19,64 @@ impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for Interrupt | |||
| 19 | let state = T::buffered_state(); | 19 | let state = T::buffered_state(); |
| 20 | 20 | ||
| 21 | // RX | 21 | // RX |
| 22 | unsafe { | 22 | let sr_val = sr(r).read(); |
| 23 | let sr = sr(r).read(); | 23 | // On v1 & v2, reading DR clears the rxne, error and idle interrupt |
| 24 | // On v1 & v2, reading DR clears the rxne, error and idle interrupt | 24 | // flags. Keep this close to the SR read to reduce the chance of a |
| 25 | // flags. Keep this close to the SR read to reduce the chance of a | 25 | // flag being set in-between. |
| 26 | // flag being set in-between. | 26 | let dr = if sr_val.rxne() || cfg!(any(usart_v1, usart_v2)) && (sr_val.ore() || sr_val.idle()) { |
| 27 | let dr = if sr.rxne() || cfg!(any(usart_v1, usart_v2)) && (sr.ore() || sr.idle()) { | 27 | Some(rdr(r).read_volatile()) |
| 28 | Some(rdr(r).read_volatile()) | 28 | } else { |
| 29 | None | ||
| 30 | }; | ||
| 31 | clear_interrupt_flags(r, sr_val); | ||
| 32 | |||
| 33 | if sr_val.pe() { | ||
| 34 | warn!("Parity error"); | ||
| 35 | } | ||
| 36 | if sr_val.fe() { | ||
| 37 | warn!("Framing error"); | ||
| 38 | } | ||
| 39 | if sr_val.ne() { | ||
| 40 | warn!("Noise error"); | ||
| 41 | } | ||
| 42 | if sr_val.ore() { | ||
| 43 | warn!("Overrun error"); | ||
| 44 | } | ||
| 45 | if sr_val.rxne() { | ||
| 46 | let mut rx_writer = state.rx_buf.writer(); | ||
| 47 | let buf = rx_writer.push_slice(); | ||
| 48 | if !buf.is_empty() { | ||
| 49 | buf[0] = dr.unwrap(); | ||
| 50 | rx_writer.push_done(1); | ||
| 29 | } else { | 51 | } else { |
| 30 | None | 52 | // FIXME: Should we disable any further RX interrupts when the buffer becomes full. |
| 31 | }; | ||
| 32 | clear_interrupt_flags(r, sr); | ||
| 33 | |||
| 34 | if sr.pe() { | ||
| 35 | warn!("Parity error"); | ||
| 36 | } | ||
| 37 | if sr.fe() { | ||
| 38 | warn!("Framing error"); | ||
| 39 | } | ||
| 40 | if sr.ne() { | ||
| 41 | warn!("Noise error"); | ||
| 42 | } | ||
| 43 | if sr.ore() { | ||
| 44 | warn!("Overrun error"); | ||
| 45 | } | ||
| 46 | if sr.rxne() { | ||
| 47 | let mut rx_writer = state.rx_buf.writer(); | ||
| 48 | let buf = rx_writer.push_slice(); | ||
| 49 | if !buf.is_empty() { | ||
| 50 | buf[0] = dr.unwrap(); | ||
| 51 | rx_writer.push_done(1); | ||
| 52 | } else { | ||
| 53 | // FIXME: Should we disable any further RX interrupts when the buffer becomes full. | ||
| 54 | } | ||
| 55 | |||
| 56 | if state.rx_buf.is_full() { | ||
| 57 | state.rx_waker.wake(); | ||
| 58 | } | ||
| 59 | } | 53 | } |
| 60 | 54 | ||
| 61 | if sr.idle() { | 55 | if state.rx_buf.is_full() { |
| 62 | state.rx_waker.wake(); | 56 | state.rx_waker.wake(); |
| 63 | } | 57 | } |
| 64 | } | 58 | } |
| 65 | 59 | ||
| 60 | if sr_val.idle() { | ||
| 61 | state.rx_waker.wake(); | ||
| 62 | } | ||
| 63 | |||
| 66 | // TX | 64 | // TX |
| 67 | unsafe { | 65 | if sr(r).read().txe() { |
| 68 | if sr(r).read().txe() { | 66 | let mut tx_reader = state.tx_buf.reader(); |
| 69 | let mut tx_reader = state.tx_buf.reader(); | 67 | let buf = tx_reader.pop_slice(); |
| 70 | let buf = tx_reader.pop_slice(); | 68 | if !buf.is_empty() { |
| 71 | if !buf.is_empty() { | 69 | r.cr1().modify(|w| { |
| 72 | r.cr1().modify(|w| { | 70 | w.set_txeie(true); |
| 73 | w.set_txeie(true); | 71 | }); |
| 74 | }); | 72 | tdr(r).write_volatile(buf[0].into()); |
| 75 | tdr(r).write_volatile(buf[0].into()); | 73 | tx_reader.pop_done(1); |
| 76 | tx_reader.pop_done(1); | 74 | state.tx_waker.wake(); |
| 77 | state.tx_waker.wake(); | 75 | } else { |
| 78 | } else { | 76 | // Disable interrupt until we have something to transmit again |
| 79 | // Disable interrupt until we have something to transmit again | 77 | r.cr1().modify(|w| { |
| 80 | r.cr1().modify(|w| { | 78 | w.set_txeie(false); |
| 81 | w.set_txeie(false); | 79 | }); |
| 82 | }); | ||
| 83 | } | ||
| 84 | } | 80 | } |
| 85 | } | 81 | } |
| 86 | } | 82 | } |
| @@ -150,14 +146,12 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { | |||
| 150 | T::enable(); | 146 | T::enable(); |
| 151 | T::reset(); | 147 | T::reset(); |
| 152 | 148 | ||
| 153 | unsafe { | 149 | rts.set_as_af(rts.af_num(), AFType::OutputPushPull); |
| 154 | rts.set_as_af(rts.af_num(), AFType::OutputPushPull); | 150 | cts.set_as_af(cts.af_num(), AFType::Input); |
| 155 | cts.set_as_af(cts.af_num(), AFType::Input); | 151 | T::regs().cr3().write(|w| { |
| 156 | T::regs().cr3().write(|w| { | 152 | w.set_rtse(true); |
| 157 | w.set_rtse(true); | 153 | w.set_ctse(true); |
| 158 | w.set_ctse(true); | 154 | }); |
| 159 | }); | ||
| 160 | } | ||
| 161 | 155 | ||
| 162 | Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) | 156 | Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) |
| 163 | } | 157 | } |
| @@ -178,12 +172,10 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { | |||
| 178 | T::enable(); | 172 | T::enable(); |
| 179 | T::reset(); | 173 | T::reset(); |
| 180 | 174 | ||
| 181 | unsafe { | 175 | de.set_as_af(de.af_num(), AFType::OutputPushPull); |
| 182 | de.set_as_af(de.af_num(), AFType::OutputPushPull); | 176 | T::regs().cr3().write(|w| { |
| 183 | T::regs().cr3().write(|w| { | 177 | w.set_dem(true); |
| 184 | w.set_dem(true); | 178 | }); |
| 185 | }); | ||
| 186 | } | ||
| 187 | 179 | ||
| 188 | Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) | 180 | Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) |
| 189 | } | 181 | } |
| @@ -205,22 +197,18 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { | |||
| 205 | unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) }; | 197 | unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) }; |
| 206 | 198 | ||
| 207 | let r = T::regs(); | 199 | let r = T::regs(); |
| 208 | unsafe { | 200 | rx.set_as_af(rx.af_num(), AFType::Input); |
| 209 | rx.set_as_af(rx.af_num(), AFType::Input); | 201 | tx.set_as_af(tx.af_num(), AFType::OutputPushPull); |
| 210 | tx.set_as_af(tx.af_num(), AFType::OutputPushPull); | ||
| 211 | } | ||
| 212 | 202 | ||
| 213 | configure(r, &config, T::frequency(), T::KIND, true, true); | 203 | configure(r, &config, T::frequency(), T::KIND, true, true); |
| 214 | 204 | ||
| 215 | unsafe { | 205 | r.cr1().modify(|w| { |
| 216 | r.cr1().modify(|w| { | 206 | #[cfg(lpuart_v2)] |
| 217 | #[cfg(lpuart_v2)] | 207 | w.set_fifoen(true); |
| 218 | w.set_fifoen(true); | ||
| 219 | 208 | ||
| 220 | w.set_rxneie(true); | 209 | w.set_rxneie(true); |
| 221 | w.set_idleie(true); | 210 | w.set_idleie(true); |
| 222 | }); | 211 | }); |
| 223 | } | ||
| 224 | 212 | ||
| 225 | T::Interrupt::unpend(); | 213 | T::Interrupt::unpend(); |
| 226 | unsafe { T::Interrupt::enable() }; | 214 | unsafe { T::Interrupt::enable() }; |
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index da3644a81..47a79c187 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs | |||
| @@ -36,35 +36,31 @@ impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for Interrupt | |||
| 36 | let r = T::regs(); | 36 | let r = T::regs(); |
| 37 | let s = T::state(); | 37 | let s = T::state(); |
| 38 | 38 | ||
| 39 | let (sr, cr1, cr3) = unsafe { (sr(r).read(), r.cr1().read(), r.cr3().read()) }; | 39 | let (sr, cr1, cr3) = (sr(r).read(), r.cr1().read(), r.cr3().read()); |
| 40 | 40 | ||
| 41 | let has_errors = (sr.pe() && cr1.peie()) || ((sr.fe() || sr.ne() || sr.ore()) && cr3.eie()); | 41 | let has_errors = (sr.pe() && cr1.peie()) || ((sr.fe() || sr.ne() || sr.ore()) && cr3.eie()); |
| 42 | if has_errors { | 42 | if has_errors { |
| 43 | // clear all interrupts and DMA Rx Request | 43 | // clear all interrupts and DMA Rx Request |
| 44 | unsafe { | 44 | r.cr1().modify(|w| { |
| 45 | r.cr1().modify(|w| { | 45 | // disable RXNE interrupt |
| 46 | // disable RXNE interrupt | 46 | w.set_rxneie(false); |
| 47 | w.set_rxneie(false); | 47 | // disable parity interrupt |
| 48 | // disable parity interrupt | 48 | w.set_peie(false); |
| 49 | w.set_peie(false); | 49 | // disable idle line interrupt |
| 50 | // disable idle line interrupt | 50 | w.set_idleie(false); |
| 51 | w.set_idleie(false); | 51 | }); |
| 52 | }); | 52 | r.cr3().modify(|w| { |
| 53 | r.cr3().modify(|w| { | 53 | // disable Error Interrupt: (Frame error, Noise error, Overrun error) |
| 54 | // disable Error Interrupt: (Frame error, Noise error, Overrun error) | 54 | w.set_eie(false); |
| 55 | w.set_eie(false); | 55 | // disable DMA Rx Request |
| 56 | // disable DMA Rx Request | 56 | w.set_dmar(false); |
| 57 | w.set_dmar(false); | 57 | }); |
| 58 | }); | ||
| 59 | } | ||
| 60 | } else if cr1.idleie() && sr.idle() { | 58 | } else if cr1.idleie() && sr.idle() { |
| 61 | // IDLE detected: no more data will come | 59 | // IDLE detected: no more data will come |
| 62 | unsafe { | 60 | r.cr1().modify(|w| { |
| 63 | r.cr1().modify(|w| { | 61 | // disable idle line detection |
| 64 | // disable idle line detection | 62 | w.set_idleie(false); |
| 65 | w.set_idleie(false); | 63 | }); |
| 66 | }); | ||
| 67 | } | ||
| 68 | } else if cr1.rxneie() { | 64 | } else if cr1.rxneie() { |
| 69 | // We cannot check the RXNE flag as it is auto-cleared by the DMA controller | 65 | // We cannot check the RXNE flag as it is auto-cleared by the DMA controller |
| 70 | 66 | ||
| @@ -205,12 +201,10 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { | |||
| 205 | T::enable(); | 201 | T::enable(); |
| 206 | T::reset(); | 202 | T::reset(); |
| 207 | 203 | ||
| 208 | unsafe { | 204 | cts.set_as_af(cts.af_num(), AFType::Input); |
| 209 | cts.set_as_af(cts.af_num(), AFType::Input); | 205 | T::regs().cr3().write(|w| { |
| 210 | T::regs().cr3().write(|w| { | 206 | w.set_ctse(true); |
| 211 | w.set_ctse(true); | 207 | }); |
| 212 | }); | ||
| 213 | } | ||
| 214 | Self::new_inner(peri, tx, tx_dma, config) | 208 | Self::new_inner(peri, tx, tx_dma, config) |
| 215 | } | 209 | } |
| 216 | 210 | ||
| @@ -224,9 +218,7 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { | |||
| 224 | 218 | ||
| 225 | let r = T::regs(); | 219 | let r = T::regs(); |
| 226 | 220 | ||
| 227 | unsafe { | 221 | tx.set_as_af(tx.af_num(), AFType::OutputPushPull); |
| 228 | tx.set_as_af(tx.af_num(), AFType::OutputPushPull); | ||
| 229 | } | ||
| 230 | 222 | ||
| 231 | configure(r, &config, T::frequency(), T::KIND, false, true); | 223 | configure(r, &config, T::frequency(), T::KIND, false, true); |
| 232 | 224 | ||
| @@ -245,11 +237,9 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { | |||
| 245 | { | 237 | { |
| 246 | let ch = &mut self.tx_dma; | 238 | let ch = &mut self.tx_dma; |
| 247 | let request = ch.request(); | 239 | let request = ch.request(); |
| 248 | unsafe { | 240 | T::regs().cr3().modify(|reg| { |
| 249 | T::regs().cr3().modify(|reg| { | 241 | reg.set_dmat(true); |
| 250 | reg.set_dmat(true); | 242 | }); |
| 251 | }); | ||
| 252 | } | ||
| 253 | // If we don't assign future to a variable, the data register pointer | 243 | // If we don't assign future to a variable, the data register pointer |
| 254 | // is held across an await and makes the future non-Send. | 244 | // is held across an await and makes the future non-Send. |
| 255 | let transfer = unsafe { Transfer::new_write(ch, request, buffer, tdr(T::regs()), Default::default()) }; | 245 | let transfer = unsafe { Transfer::new_write(ch, request, buffer, tdr(T::regs()), Default::default()) }; |
| @@ -258,21 +248,17 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { | |||
| 258 | } | 248 | } |
| 259 | 249 | ||
| 260 | pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { | 250 | pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
| 261 | unsafe { | 251 | let r = T::regs(); |
| 262 | let r = T::regs(); | 252 | for &b in buffer { |
| 263 | for &b in buffer { | 253 | while !sr(r).read().txe() {} |
| 264 | while !sr(r).read().txe() {} | 254 | unsafe { tdr(r).write_volatile(b) }; |
| 265 | tdr(r).write_volatile(b); | ||
| 266 | } | ||
| 267 | } | 255 | } |
| 268 | Ok(()) | 256 | Ok(()) |
| 269 | } | 257 | } |
| 270 | 258 | ||
| 271 | pub fn blocking_flush(&mut self) -> Result<(), Error> { | 259 | pub fn blocking_flush(&mut self) -> Result<(), Error> { |
| 272 | unsafe { | 260 | let r = T::regs(); |
| 273 | let r = T::regs(); | 261 | while !sr(r).read().tc() {} |
| 274 | while !sr(r).read().tc() {} | ||
| 275 | } | ||
| 276 | Ok(()) | 262 | Ok(()) |
| 277 | } | 263 | } |
| 278 | } | 264 | } |
| @@ -305,12 +291,10 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { | |||
| 305 | T::enable(); | 291 | T::enable(); |
| 306 | T::reset(); | 292 | T::reset(); |
| 307 | 293 | ||
| 308 | unsafe { | 294 | rts.set_as_af(rts.af_num(), AFType::OutputPushPull); |
| 309 | rts.set_as_af(rts.af_num(), AFType::OutputPushPull); | 295 | T::regs().cr3().write(|w| { |
| 310 | T::regs().cr3().write(|w| { | 296 | w.set_rtse(true); |
| 311 | w.set_rtse(true); | 297 | }); |
| 312 | }); | ||
| 313 | } | ||
| 314 | 298 | ||
| 315 | Self::new_inner(peri, rx, rx_dma, config) | 299 | Self::new_inner(peri, rx, rx_dma, config) |
| 316 | } | 300 | } |
| @@ -325,9 +309,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { | |||
| 325 | 309 | ||
| 326 | let r = T::regs(); | 310 | let r = T::regs(); |
| 327 | 311 | ||
| 328 | unsafe { | 312 | rx.set_as_af(rx.af_num(), AFType::Input); |
| 329 | rx.set_as_af(rx.af_num(), AFType::Input); | ||
| 330 | } | ||
| 331 | 313 | ||
| 332 | configure(r, &config, T::frequency(), T::KIND, true, false); | 314 | configure(r, &config, T::frequency(), T::KIND, true, false); |
| 333 | 315 | ||
| @@ -347,7 +329,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { | |||
| 347 | } | 329 | } |
| 348 | 330 | ||
| 349 | #[cfg(any(usart_v1, usart_v2))] | 331 | #[cfg(any(usart_v1, usart_v2))] |
| 350 | unsafe fn check_rx_flags(&mut self) -> Result<bool, Error> { | 332 | fn check_rx_flags(&mut self) -> Result<bool, Error> { |
| 351 | let r = T::regs(); | 333 | let r = T::regs(); |
| 352 | loop { | 334 | loop { |
| 353 | // Handle all buffered error flags. | 335 | // Handle all buffered error flags. |
| @@ -380,7 +362,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { | |||
| 380 | } | 362 | } |
| 381 | 363 | ||
| 382 | #[cfg(any(usart_v3, usart_v4))] | 364 | #[cfg(any(usart_v3, usart_v4))] |
| 383 | unsafe fn check_rx_flags(&mut self) -> Result<bool, Error> { | 365 | fn check_rx_flags(&mut self) -> Result<bool, Error> { |
| 384 | let r = T::regs(); | 366 | let r = T::regs(); |
| 385 | let sr = r.isr().read(); | 367 | let sr = r.isr().read(); |
| 386 | if sr.pe() { | 368 | if sr.pe() { |
| @@ -410,22 +392,18 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { | |||
| 410 | 392 | ||
| 411 | pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> { | 393 | pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> { |
| 412 | let r = T::regs(); | 394 | let r = T::regs(); |
| 413 | unsafe { | 395 | if self.check_rx_flags()? { |
| 414 | if self.check_rx_flags()? { | 396 | Ok(unsafe { rdr(r).read_volatile() }) |
| 415 | Ok(rdr(r).read_volatile()) | 397 | } else { |
| 416 | } else { | 398 | Err(nb::Error::WouldBlock) |
| 417 | Err(nb::Error::WouldBlock) | ||
| 418 | } | ||
| 419 | } | 399 | } |
| 420 | } | 400 | } |
| 421 | 401 | ||
| 422 | pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { | 402 | pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |
| 423 | unsafe { | 403 | let r = T::regs(); |
| 424 | let r = T::regs(); | 404 | for b in buffer { |
| 425 | for b in buffer { | 405 | while !self.check_rx_flags()? {} |
| 426 | while !self.check_rx_flags()? {} | 406 | unsafe { *b = rdr(r).read_volatile() } |
| 427 | *b = rdr(r).read_volatile(); | ||
| 428 | } | ||
| 429 | } | 407 | } |
| 430 | Ok(()) | 408 | Ok(()) |
| 431 | } | 409 | } |
| @@ -451,23 +429,20 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { | |||
| 451 | let on_drop = OnDrop::new(move || { | 429 | let on_drop = OnDrop::new(move || { |
| 452 | // defmt::trace!("Clear all USART interrupts and DMA Read Request"); | 430 | // defmt::trace!("Clear all USART interrupts and DMA Read Request"); |
| 453 | // clear all interrupts and DMA Rx Request | 431 | // clear all interrupts and DMA Rx Request |
| 454 | // SAFETY: only clears Rx related flags | 432 | r.cr1().modify(|w| { |
| 455 | unsafe { | 433 | // disable RXNE interrupt |
| 456 | r.cr1().modify(|w| { | 434 | w.set_rxneie(false); |
| 457 | // disable RXNE interrupt | 435 | // disable parity interrupt |
| 458 | w.set_rxneie(false); | 436 | w.set_peie(false); |
| 459 | // disable parity interrupt | 437 | // disable idle line interrupt |
| 460 | w.set_peie(false); | 438 | w.set_idleie(false); |
| 461 | // disable idle line interrupt | 439 | }); |
| 462 | w.set_idleie(false); | 440 | r.cr3().modify(|w| { |
| 463 | }); | 441 | // disable Error Interrupt: (Frame error, Noise error, Overrun error) |
| 464 | r.cr3().modify(|w| { | 442 | w.set_eie(false); |
| 465 | // disable Error Interrupt: (Frame error, Noise error, Overrun error) | 443 | // disable DMA Rx Request |
| 466 | w.set_eie(false); | 444 | w.set_dmar(false); |
| 467 | // disable DMA Rx Request | 445 | }); |
| 468 | w.set_dmar(false); | ||
| 469 | }); | ||
| 470 | } | ||
| 471 | }); | 446 | }); |
| 472 | 447 | ||
| 473 | let ch = &mut self.rx_dma; | 448 | let ch = &mut self.rx_dma; |
| @@ -480,78 +455,74 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { | |||
| 480 | // future which will complete when DMA Read request completes | 455 | // future which will complete when DMA Read request completes |
| 481 | let transfer = unsafe { Transfer::new_read(ch, request, rdr(T::regs()), buffer, Default::default()) }; | 456 | let transfer = unsafe { Transfer::new_read(ch, request, rdr(T::regs()), buffer, Default::default()) }; |
| 482 | 457 | ||
| 483 | // SAFETY: The only way we might have a problem is using split rx and tx | 458 | // clear ORE flag just before enabling DMA Rx Request: can be mandatory for the second transfer |
| 484 | // here we only modify or read Rx related flags, interrupts and DMA channel | 459 | if !self.detect_previous_overrun { |
| 485 | unsafe { | 460 | let sr = sr(r).read(); |
| 486 | // clear ORE flag just before enabling DMA Rx Request: can be mandatory for the second transfer | 461 | // This read also clears the error and idle interrupt flags on v1. |
| 487 | if !self.detect_previous_overrun { | 462 | unsafe { rdr(r).read_volatile() }; |
| 488 | let sr = sr(r).read(); | 463 | clear_interrupt_flags(r, sr); |
| 489 | // This read also clears the error and idle interrupt flags on v1. | 464 | } |
| 490 | rdr(r).read_volatile(); | ||
| 491 | clear_interrupt_flags(r, sr); | ||
| 492 | } | ||
| 493 | |||
| 494 | r.cr1().modify(|w| { | ||
| 495 | // disable RXNE interrupt | ||
| 496 | w.set_rxneie(false); | ||
| 497 | // enable parity interrupt if not ParityNone | ||
| 498 | w.set_peie(w.pce()); | ||
| 499 | }); | ||
| 500 | 465 | ||
| 501 | r.cr3().modify(|w| { | 466 | r.cr1().modify(|w| { |
| 502 | // enable Error Interrupt: (Frame error, Noise error, Overrun error) | 467 | // disable RXNE interrupt |
| 503 | w.set_eie(true); | 468 | w.set_rxneie(false); |
| 504 | // enable DMA Rx Request | 469 | // enable parity interrupt if not ParityNone |
| 505 | w.set_dmar(true); | 470 | w.set_peie(w.pce()); |
| 506 | }); | 471 | }); |
| 507 | 472 | ||
| 508 | compiler_fence(Ordering::SeqCst); | 473 | r.cr3().modify(|w| { |
| 474 | // enable Error Interrupt: (Frame error, Noise error, Overrun error) | ||
| 475 | w.set_eie(true); | ||
| 476 | // enable DMA Rx Request | ||
| 477 | w.set_dmar(true); | ||
| 478 | }); | ||
| 509 | 479 | ||
| 510 | // In case of errors already pending when reception started, interrupts may have already been raised | 480 | compiler_fence(Ordering::SeqCst); |
| 511 | // and lead to reception abortion (Overrun error for instance). In such a case, all interrupts | ||
| 512 | // have been disabled in interrupt handler and DMA Rx Request has been disabled. | ||
| 513 | 481 | ||
| 514 | let cr3 = r.cr3().read(); | 482 | // In case of errors already pending when reception started, interrupts may have already been raised |
| 483 | // and lead to reception abortion (Overrun error for instance). In such a case, all interrupts | ||
| 484 | // have been disabled in interrupt handler and DMA Rx Request has been disabled. | ||
| 515 | 485 | ||
| 516 | if !cr3.dmar() { | 486 | let cr3 = r.cr3().read(); |
| 517 | // something went wrong | ||
| 518 | // because the only way to get this flag cleared is to have an interrupt | ||
| 519 | 487 | ||
| 520 | // DMA will be stopped when transfer is dropped | 488 | if !cr3.dmar() { |
| 489 | // something went wrong | ||
| 490 | // because the only way to get this flag cleared is to have an interrupt | ||
| 521 | 491 | ||
| 522 | let sr = sr(r).read(); | 492 | // DMA will be stopped when transfer is dropped |
| 523 | // This read also clears the error and idle interrupt flags on v1. | ||
| 524 | rdr(r).read_volatile(); | ||
| 525 | clear_interrupt_flags(r, sr); | ||
| 526 | 493 | ||
| 527 | if sr.pe() { | 494 | let sr = sr(r).read(); |
| 528 | return Err(Error::Parity); | 495 | // This read also clears the error and idle interrupt flags on v1. |
| 529 | } | 496 | unsafe { rdr(r).read_volatile() }; |
| 530 | if sr.fe() { | 497 | clear_interrupt_flags(r, sr); |
| 531 | return Err(Error::Framing); | ||
| 532 | } | ||
| 533 | if sr.ne() { | ||
| 534 | return Err(Error::Noise); | ||
| 535 | } | ||
| 536 | if sr.ore() { | ||
| 537 | return Err(Error::Overrun); | ||
| 538 | } | ||
| 539 | 498 | ||
| 540 | unreachable!(); | 499 | if sr.pe() { |
| 500 | return Err(Error::Parity); | ||
| 541 | } | 501 | } |
| 542 | 502 | if sr.fe() { | |
| 543 | if enable_idle_line_detection { | 503 | return Err(Error::Framing); |
| 544 | // clear idle flag | ||
| 545 | let sr = sr(r).read(); | ||
| 546 | // This read also clears the error and idle interrupt flags on v1. | ||
| 547 | rdr(r).read_volatile(); | ||
| 548 | clear_interrupt_flags(r, sr); | ||
| 549 | |||
| 550 | // enable idle interrupt | ||
| 551 | r.cr1().modify(|w| { | ||
| 552 | w.set_idleie(true); | ||
| 553 | }); | ||
| 554 | } | 504 | } |
| 505 | if sr.ne() { | ||
| 506 | return Err(Error::Noise); | ||
| 507 | } | ||
| 508 | if sr.ore() { | ||
| 509 | return Err(Error::Overrun); | ||
| 510 | } | ||
| 511 | |||
| 512 | unreachable!(); | ||
| 513 | } | ||
| 514 | |||
| 515 | if enable_idle_line_detection { | ||
| 516 | // clear idle flag | ||
| 517 | let sr = sr(r).read(); | ||
| 518 | // This read also clears the error and idle interrupt flags on v1. | ||
| 519 | unsafe { rdr(r).read_volatile() }; | ||
| 520 | clear_interrupt_flags(r, sr); | ||
| 521 | |||
| 522 | // enable idle interrupt | ||
| 523 | r.cr1().modify(|w| { | ||
| 524 | w.set_idleie(true); | ||
| 525 | }); | ||
| 555 | } | 526 | } |
| 556 | 527 | ||
| 557 | compiler_fence(Ordering::SeqCst); | 528 | compiler_fence(Ordering::SeqCst); |
| @@ -562,15 +533,11 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { | |||
| 562 | 533 | ||
| 563 | s.rx_waker.register(cx.waker()); | 534 | s.rx_waker.register(cx.waker()); |
| 564 | 535 | ||
| 565 | // SAFETY: read only and we only use Rx related flags | 536 | let sr = sr(r).read(); |
| 566 | let sr = unsafe { sr(r).read() }; | ||
| 567 | 537 | ||
| 568 | // SAFETY: only clears Rx related flags | 538 | // This read also clears the error and idle interrupt flags on v1. |
| 569 | unsafe { | 539 | unsafe { rdr(r).read_volatile() }; |
| 570 | // This read also clears the error and idle interrupt flags on v1. | 540 | clear_interrupt_flags(r, sr); |
| 571 | rdr(r).read_volatile(); | ||
| 572 | clear_interrupt_flags(r, sr); | ||
| 573 | } | ||
| 574 | 541 | ||
| 575 | compiler_fence(Ordering::SeqCst); | 542 | compiler_fence(Ordering::SeqCst); |
| 576 | 543 | ||
| @@ -677,14 +644,12 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | |||
| 677 | T::enable(); | 644 | T::enable(); |
| 678 | T::reset(); | 645 | T::reset(); |
| 679 | 646 | ||
| 680 | unsafe { | 647 | rts.set_as_af(rts.af_num(), AFType::OutputPushPull); |
| 681 | rts.set_as_af(rts.af_num(), AFType::OutputPushPull); | 648 | cts.set_as_af(cts.af_num(), AFType::Input); |
| 682 | cts.set_as_af(cts.af_num(), AFType::Input); | 649 | T::regs().cr3().write(|w| { |
| 683 | T::regs().cr3().write(|w| { | 650 | w.set_rtse(true); |
| 684 | w.set_rtse(true); | 651 | w.set_ctse(true); |
| 685 | w.set_ctse(true); | 652 | }); |
| 686 | }); | ||
| 687 | } | ||
| 688 | Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config) | 653 | Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config) |
| 689 | } | 654 | } |
| 690 | 655 | ||
| @@ -704,12 +669,10 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | |||
| 704 | T::enable(); | 669 | T::enable(); |
| 705 | T::reset(); | 670 | T::reset(); |
| 706 | 671 | ||
| 707 | unsafe { | 672 | de.set_as_af(de.af_num(), AFType::OutputPushPull); |
| 708 | de.set_as_af(de.af_num(), AFType::OutputPushPull); | 673 | T::regs().cr3().write(|w| { |
| 709 | T::regs().cr3().write(|w| { | 674 | w.set_dem(true); |
| 710 | w.set_dem(true); | 675 | }); |
| 711 | }); | ||
| 712 | } | ||
| 713 | Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config) | 676 | Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config) |
| 714 | } | 677 | } |
| 715 | 678 | ||
| @@ -725,10 +688,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | |||
| 725 | 688 | ||
| 726 | let r = T::regs(); | 689 | let r = T::regs(); |
| 727 | 690 | ||
| 728 | unsafe { | 691 | rx.set_as_af(rx.af_num(), AFType::Input); |
| 729 | rx.set_as_af(rx.af_num(), AFType::Input); | 692 | tx.set_as_af(tx.af_num(), AFType::OutputPushPull); |
| 730 | tx.set_as_af(tx.af_num(), AFType::OutputPushPull); | ||
| 731 | } | ||
| 732 | 693 | ||
| 733 | configure(r, &config, T::frequency(), T::KIND, true, true); | 694 | configure(r, &config, T::frequency(), T::KIND, true, true); |
| 734 | 695 | ||
| @@ -847,11 +808,9 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx: | |||
| 847 | if div * 2 >= brr_min && kind == Kind::Uart && !cfg!(usart_v1) { | 808 | if div * 2 >= brr_min && kind == Kind::Uart && !cfg!(usart_v1) { |
| 848 | over8 = true; | 809 | over8 = true; |
| 849 | let div = div as u32; | 810 | let div = div as u32; |
| 850 | unsafe { | 811 | r.brr().write_value(regs::Brr(((div << 1) & !0xF) | (div & 0x07))); |
| 851 | r.brr().write_value(regs::Brr(((div << 1) & !0xF) | (div & 0x07))); | 812 | #[cfg(usart_v4)] |
| 852 | #[cfg(usart_v4)] | 813 | r.presc().write(|w| w.set_prescaler(_presc_val)); |
| 853 | r.presc().write(|w| w.set_prescaler(_presc_val)); | ||
| 854 | } | ||
| 855 | found = Some(div); | 814 | found = Some(div); |
| 856 | break; | 815 | break; |
| 857 | } | 816 | } |
| @@ -860,11 +819,9 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx: | |||
| 860 | 819 | ||
| 861 | if div < brr_max { | 820 | if div < brr_max { |
| 862 | let div = div as u32; | 821 | let div = div as u32; |
| 863 | unsafe { | 822 | r.brr().write_value(regs::Brr(div)); |
| 864 | r.brr().write_value(regs::Brr(div)); | 823 | #[cfg(usart_v4)] |
| 865 | #[cfg(usart_v4)] | 824 | r.presc().write(|w| w.set_prescaler(_presc_val)); |
| 866 | r.presc().write(|w| w.set_prescaler(_presc_val)); | ||
| 867 | } | ||
| 868 | found = Some(div); | 825 | found = Some(div); |
| 869 | break; | 826 | break; |
| 870 | } | 827 | } |
| @@ -883,44 +840,42 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx: | |||
| 883 | pclk_freq.0 / div | 840 | pclk_freq.0 / div |
| 884 | ); | 841 | ); |
| 885 | 842 | ||
| 886 | unsafe { | 843 | r.cr2().write(|w| { |
| 887 | r.cr2().write(|w| { | 844 | w.set_stop(match config.stop_bits { |
| 888 | w.set_stop(match config.stop_bits { | 845 | StopBits::STOP0P5 => vals::Stop::STOP0P5, |
| 889 | StopBits::STOP0P5 => vals::Stop::STOP0P5, | 846 | StopBits::STOP1 => vals::Stop::STOP1, |
| 890 | StopBits::STOP1 => vals::Stop::STOP1, | 847 | StopBits::STOP1P5 => vals::Stop::STOP1P5, |
| 891 | StopBits::STOP1P5 => vals::Stop::STOP1P5, | 848 | StopBits::STOP2 => vals::Stop::STOP2, |
| 892 | StopBits::STOP2 => vals::Stop::STOP2, | ||
| 893 | }); | ||
| 894 | }); | 849 | }); |
| 895 | r.cr1().write(|w| { | 850 | }); |
| 896 | // enable uart | 851 | r.cr1().write(|w| { |
| 897 | w.set_ue(true); | 852 | // enable uart |
| 898 | // enable transceiver | 853 | w.set_ue(true); |
| 899 | w.set_te(enable_tx); | 854 | // enable transceiver |
| 900 | // enable receiver | 855 | w.set_te(enable_tx); |
| 901 | w.set_re(enable_rx); | 856 | // enable receiver |
| 902 | // configure word size | 857 | w.set_re(enable_rx); |
| 903 | w.set_m0(if config.parity != Parity::ParityNone { | 858 | // configure word size |
| 904 | vals::M0::BIT9 | 859 | w.set_m0(if config.parity != Parity::ParityNone { |
| 905 | } else { | 860 | vals::M0::BIT9 |
| 906 | vals::M0::BIT8 | 861 | } else { |
| 907 | }); | 862 | vals::M0::BIT8 |
| 908 | // configure parity | ||
| 909 | w.set_pce(config.parity != Parity::ParityNone); | ||
| 910 | w.set_ps(match config.parity { | ||
| 911 | Parity::ParityOdd => vals::Ps::ODD, | ||
| 912 | Parity::ParityEven => vals::Ps::EVEN, | ||
| 913 | _ => vals::Ps::EVEN, | ||
| 914 | }); | ||
| 915 | #[cfg(not(usart_v1))] | ||
| 916 | w.set_over8(vals::Over8(over8 as _)); | ||
| 917 | }); | 863 | }); |
| 918 | 864 | // configure parity | |
| 919 | #[cfg(not(usart_v1))] | 865 | w.set_pce(config.parity != Parity::ParityNone); |
| 920 | r.cr3().modify(|w| { | 866 | w.set_ps(match config.parity { |
| 921 | w.set_onebit(config.assume_noise_free); | 867 | Parity::ParityOdd => vals::Ps::ODD, |
| 868 | Parity::ParityEven => vals::Ps::EVEN, | ||
| 869 | _ => vals::Ps::EVEN, | ||
| 922 | }); | 870 | }); |
| 923 | } | 871 | #[cfg(not(usart_v1))] |
| 872 | w.set_over8(vals::Over8(over8 as _)); | ||
| 873 | }); | ||
| 874 | |||
| 875 | #[cfg(not(usart_v1))] | ||
| 876 | r.cr3().modify(|w| { | ||
| 877 | w.set_onebit(config.assume_noise_free); | ||
| 878 | }); | ||
| 924 | } | 879 | } |
| 925 | 880 | ||
| 926 | mod eh02 { | 881 | mod eh02 { |
| @@ -1111,12 +1066,12 @@ use self::sealed::Kind; | |||
| 1111 | 1066 | ||
| 1112 | #[cfg(any(usart_v1, usart_v2))] | 1067 | #[cfg(any(usart_v1, usart_v2))] |
| 1113 | fn tdr(r: crate::pac::usart::Usart) -> *mut u8 { | 1068 | fn tdr(r: crate::pac::usart::Usart) -> *mut u8 { |
| 1114 | r.dr().ptr() as _ | 1069 | r.dr().as_ptr() as _ |
| 1115 | } | 1070 | } |
| 1116 | 1071 | ||
| 1117 | #[cfg(any(usart_v1, usart_v2))] | 1072 | #[cfg(any(usart_v1, usart_v2))] |
| 1118 | fn rdr(r: crate::pac::usart::Usart) -> *mut u8 { | 1073 | fn rdr(r: crate::pac::usart::Usart) -> *mut u8 { |
| 1119 | r.dr().ptr() as _ | 1074 | r.dr().as_ptr() as _ |
| 1120 | } | 1075 | } |
| 1121 | 1076 | ||
| 1122 | #[cfg(any(usart_v1, usart_v2))] | 1077 | #[cfg(any(usart_v1, usart_v2))] |
| @@ -1126,18 +1081,18 @@ fn sr(r: crate::pac::usart::Usart) -> crate::pac::common::Reg<regs::Sr, crate::p | |||
| 1126 | 1081 | ||
| 1127 | #[cfg(any(usart_v1, usart_v2))] | 1082 | #[cfg(any(usart_v1, usart_v2))] |
| 1128 | #[allow(unused)] | 1083 | #[allow(unused)] |
| 1129 | unsafe fn clear_interrupt_flags(_r: Regs, _sr: regs::Sr) { | 1084 | fn clear_interrupt_flags(_r: Regs, _sr: regs::Sr) { |
| 1130 | // On v1 the flags are cleared implicitly by reads and writes to DR. | 1085 | // On v1 the flags are cleared implicitly by reads and writes to DR. |
| 1131 | } | 1086 | } |
| 1132 | 1087 | ||
| 1133 | #[cfg(any(usart_v3, usart_v4))] | 1088 | #[cfg(any(usart_v3, usart_v4))] |
| 1134 | fn tdr(r: Regs) -> *mut u8 { | 1089 | fn tdr(r: Regs) -> *mut u8 { |
| 1135 | r.tdr().ptr() as _ | 1090 | r.tdr().as_ptr() as _ |
| 1136 | } | 1091 | } |
| 1137 | 1092 | ||
| 1138 | #[cfg(any(usart_v3, usart_v4))] | 1093 | #[cfg(any(usart_v3, usart_v4))] |
| 1139 | fn rdr(r: Regs) -> *mut u8 { | 1094 | fn rdr(r: Regs) -> *mut u8 { |
| 1140 | r.rdr().ptr() as _ | 1095 | r.rdr().as_ptr() as _ |
| 1141 | } | 1096 | } |
| 1142 | 1097 | ||
| 1143 | #[cfg(any(usart_v3, usart_v4))] | 1098 | #[cfg(any(usart_v3, usart_v4))] |
| @@ -1147,7 +1102,7 @@ fn sr(r: Regs) -> crate::pac::common::Reg<regs::Isr, crate::pac::common::R> { | |||
| 1147 | 1102 | ||
| 1148 | #[cfg(any(usart_v3, usart_v4))] | 1103 | #[cfg(any(usart_v3, usart_v4))] |
| 1149 | #[allow(unused)] | 1104 | #[allow(unused)] |
| 1150 | unsafe fn clear_interrupt_flags(r: Regs, sr: regs::Isr) { | 1105 | fn clear_interrupt_flags(r: Regs, sr: regs::Isr) { |
| 1151 | r.icr().write(|w| *w = regs::Icr(sr.0)); | 1106 | r.icr().write(|w| *w = regs::Icr(sr.0)); |
| 1152 | } | 1107 | } |
| 1153 | 1108 | ||
| @@ -1214,7 +1169,7 @@ macro_rules! impl_usart { | |||
| 1214 | type Interrupt = crate::interrupt::typelevel::$irq; | 1169 | type Interrupt = crate::interrupt::typelevel::$irq; |
| 1215 | 1170 | ||
| 1216 | fn regs() -> Regs { | 1171 | fn regs() -> Regs { |
| 1217 | Regs(crate::pac::$inst.0) | 1172 | unsafe { Regs::from_ptr(crate::pac::$inst.as_ptr()) } |
| 1218 | } | 1173 | } |
| 1219 | 1174 | ||
| 1220 | fn state() -> &'static crate::usart::sealed::State { | 1175 | fn state() -> &'static crate::usart::sealed::State { |
diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs index 511b71c7f..c74d7e092 100644 --- a/embassy-stm32/src/usart/ringbuffered.rs +++ b/embassy-stm32/src/usart/ringbuffered.rs | |||
| @@ -59,23 +59,20 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxD | |||
| 59 | 59 | ||
| 60 | let r = T::regs(); | 60 | let r = T::regs(); |
| 61 | // clear all interrupts and DMA Rx Request | 61 | // clear all interrupts and DMA Rx Request |
| 62 | // SAFETY: only clears Rx related flags | 62 | r.cr1().modify(|w| { |
| 63 | unsafe { | 63 | // disable RXNE interrupt |
| 64 | r.cr1().modify(|w| { | 64 | w.set_rxneie(false); |
| 65 | // disable RXNE interrupt | 65 | // enable parity interrupt if not ParityNone |
| 66 | w.set_rxneie(false); | 66 | w.set_peie(w.pce()); |
| 67 | // enable parity interrupt if not ParityNone | 67 | // enable idle line interrupt |
| 68 | w.set_peie(w.pce()); | 68 | w.set_idleie(true); |
| 69 | // enable idle line interrupt | 69 | }); |
| 70 | w.set_idleie(true); | 70 | r.cr3().modify(|w| { |
| 71 | }); | 71 | // enable Error Interrupt: (Frame error, Noise error, Overrun error) |
| 72 | r.cr3().modify(|w| { | 72 | w.set_eie(true); |
| 73 | // enable Error Interrupt: (Frame error, Noise error, Overrun error) | 73 | // enable DMA Rx Request |
| 74 | w.set_eie(true); | 74 | w.set_dmar(true); |
| 75 | // enable DMA Rx Request | 75 | }); |
| 76 | w.set_dmar(true); | ||
| 77 | }); | ||
| 78 | } | ||
| 79 | } | 76 | } |
| 80 | 77 | ||
| 81 | /// Stop uart background receive | 78 | /// Stop uart background receive |
| @@ -84,23 +81,20 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxD | |||
| 84 | 81 | ||
| 85 | let r = T::regs(); | 82 | let r = T::regs(); |
| 86 | // clear all interrupts and DMA Rx Request | 83 | // clear all interrupts and DMA Rx Request |
| 87 | // SAFETY: only clears Rx related flags | 84 | r.cr1().modify(|w| { |
| 88 | unsafe { | 85 | // disable RXNE interrupt |
| 89 | r.cr1().modify(|w| { | 86 | w.set_rxneie(false); |
| 90 | // disable RXNE interrupt | 87 | // disable parity interrupt |
| 91 | w.set_rxneie(false); | 88 | w.set_peie(false); |
| 92 | // disable parity interrupt | 89 | // disable idle line interrupt |
| 93 | w.set_peie(false); | 90 | w.set_idleie(false); |
| 94 | // disable idle line interrupt | 91 | }); |
| 95 | w.set_idleie(false); | 92 | r.cr3().modify(|w| { |
| 96 | }); | 93 | // disable Error Interrupt: (Frame error, Noise error, Overrun error) |
| 97 | r.cr3().modify(|w| { | 94 | w.set_eie(false); |
| 98 | // disable Error Interrupt: (Frame error, Noise error, Overrun error) | 95 | // disable DMA Rx Request |
| 99 | w.set_eie(false); | 96 | w.set_dmar(false); |
| 100 | // disable DMA Rx Request | 97 | }); |
| 101 | w.set_dmar(false); | ||
| 102 | }); | ||
| 103 | } | ||
| 104 | 98 | ||
| 105 | compiler_fence(Ordering::SeqCst); | 99 | compiler_fence(Ordering::SeqCst); |
| 106 | } | 100 | } |
| @@ -117,8 +111,7 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxD | |||
| 117 | let r = T::regs(); | 111 | let r = T::regs(); |
| 118 | 112 | ||
| 119 | // Start background receive if it was not already started | 113 | // Start background receive if it was not already started |
| 120 | // SAFETY: read only | 114 | match r.cr3().read().dmar() { |
| 121 | match unsafe { r.cr3().read().dmar() } { | ||
| 122 | false => self.start()?, | 115 | false => self.start()?, |
| 123 | _ => {} | 116 | _ => {} |
| 124 | }; | 117 | }; |
| @@ -213,19 +206,17 @@ fn check_for_errors(s: Sr) -> Result<(), Error> { | |||
| 213 | 206 | ||
| 214 | /// Clear IDLE and return the Sr register | 207 | /// Clear IDLE and return the Sr register |
| 215 | fn clear_idle_flag(r: Regs) -> Sr { | 208 | fn clear_idle_flag(r: Regs) -> Sr { |
| 216 | unsafe { | 209 | // SAFETY: read only and we only use Rx related flags |
| 217 | // SAFETY: read only and we only use Rx related flags | ||
| 218 | 210 | ||
| 219 | let sr = sr(r).read(); | 211 | let sr = sr(r).read(); |
| 220 | 212 | ||
| 221 | // This read also clears the error and idle interrupt flags on v1. | 213 | // This read also clears the error and idle interrupt flags on v1. |
| 222 | rdr(r).read_volatile(); | 214 | unsafe { rdr(r).read_volatile() }; |
| 223 | clear_interrupt_flags(r, sr); | 215 | clear_interrupt_flags(r, sr); |
| 224 | 216 | ||
| 225 | r.cr1().modify(|w| w.set_idleie(true)); | 217 | r.cr1().modify(|w| w.set_idleie(true)); |
| 226 | 218 | ||
| 227 | sr | 219 | sr |
| 228 | } | ||
| 229 | } | 220 | } |
| 230 | 221 | ||
| 231 | #[cfg(all(feature = "unstable-traits", feature = "nightly"))] | 222 | #[cfg(all(feature = "unstable-traits", feature = "nightly"))] |
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs index 7486bd376..2367127e8 100644 --- a/embassy-stm32/src/usb/usb.rs +++ b/embassy-stm32/src/usb/usb.rs | |||
| @@ -28,82 +28,80 @@ pub struct InterruptHandler<T: Instance> { | |||
| 28 | 28 | ||
| 29 | impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { | 29 | impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { |
| 30 | unsafe fn on_interrupt() { | 30 | unsafe fn on_interrupt() { |
| 31 | unsafe { | 31 | let regs = T::regs(); |
| 32 | let regs = T::regs(); | 32 | //let x = regs.istr().read().0; |
| 33 | //let x = regs.istr().read().0; | 33 | //trace!("USB IRQ: {:08x}", x); |
| 34 | //trace!("USB IRQ: {:08x}", x); | ||
| 35 | |||
| 36 | let istr = regs.istr().read(); | ||
| 37 | |||
| 38 | if istr.susp() { | ||
| 39 | //trace!("USB IRQ: susp"); | ||
| 40 | IRQ_SUSPEND.store(true, Ordering::Relaxed); | ||
| 41 | regs.cntr().modify(|w| { | ||
| 42 | w.set_fsusp(true); | ||
| 43 | w.set_lpmode(true); | ||
| 44 | }); | ||
| 45 | |||
| 46 | // Write 0 to clear. | ||
| 47 | let mut clear = regs::Istr(!0); | ||
| 48 | clear.set_susp(false); | ||
| 49 | regs.istr().write_value(clear); | ||
| 50 | |||
| 51 | // Wake main thread. | ||
| 52 | BUS_WAKER.wake(); | ||
| 53 | } | ||
| 54 | 34 | ||
| 55 | if istr.wkup() { | 35 | let istr = regs.istr().read(); |
| 56 | //trace!("USB IRQ: wkup"); | ||
| 57 | IRQ_RESUME.store(true, Ordering::Relaxed); | ||
| 58 | regs.cntr().modify(|w| { | ||
| 59 | w.set_fsusp(false); | ||
| 60 | w.set_lpmode(false); | ||
| 61 | }); | ||
| 62 | |||
| 63 | // Write 0 to clear. | ||
| 64 | let mut clear = regs::Istr(!0); | ||
| 65 | clear.set_wkup(false); | ||
| 66 | regs.istr().write_value(clear); | ||
| 67 | |||
| 68 | // Wake main thread. | ||
| 69 | BUS_WAKER.wake(); | ||
| 70 | } | ||
| 71 | 36 | ||
| 72 | if istr.reset() { | 37 | if istr.susp() { |
| 73 | //trace!("USB IRQ: reset"); | 38 | //trace!("USB IRQ: susp"); |
| 74 | IRQ_RESET.store(true, Ordering::Relaxed); | 39 | IRQ_SUSPEND.store(true, Ordering::Relaxed); |
| 40 | regs.cntr().modify(|w| { | ||
| 41 | w.set_fsusp(true); | ||
| 42 | w.set_lpmode(true); | ||
| 43 | }); | ||
| 75 | 44 | ||
| 76 | // Write 0 to clear. | 45 | // Write 0 to clear. |
| 77 | let mut clear = regs::Istr(!0); | 46 | let mut clear = regs::Istr(!0); |
| 78 | clear.set_reset(false); | 47 | clear.set_susp(false); |
| 79 | regs.istr().write_value(clear); | 48 | regs.istr().write_value(clear); |
| 80 | 49 | ||
| 81 | // Wake main thread. | 50 | // Wake main thread. |
| 82 | BUS_WAKER.wake(); | 51 | BUS_WAKER.wake(); |
| 83 | } | 52 | } |
| 84 | 53 | ||
| 85 | if istr.ctr() { | 54 | if istr.wkup() { |
| 86 | let index = istr.ep_id() as usize; | 55 | //trace!("USB IRQ: wkup"); |
| 87 | let mut epr = regs.epr(index).read(); | 56 | IRQ_RESUME.store(true, Ordering::Relaxed); |
| 88 | if epr.ctr_rx() { | 57 | regs.cntr().modify(|w| { |
| 89 | if index == 0 && epr.setup() { | 58 | w.set_fsusp(false); |
| 90 | EP0_SETUP.store(true, Ordering::Relaxed); | 59 | w.set_lpmode(false); |
| 91 | } | 60 | }); |
| 92 | //trace!("EP {} RX, setup={}", index, epr.setup()); | 61 | |
| 93 | EP_OUT_WAKERS[index].wake(); | 62 | // Write 0 to clear. |
| 94 | } | 63 | let mut clear = regs::Istr(!0); |
| 95 | if epr.ctr_tx() { | 64 | clear.set_wkup(false); |
| 96 | //trace!("EP {} TX", index); | 65 | regs.istr().write_value(clear); |
| 97 | EP_IN_WAKERS[index].wake(); | 66 | |
| 67 | // Wake main thread. | ||
| 68 | BUS_WAKER.wake(); | ||
| 69 | } | ||
| 70 | |||
| 71 | if istr.reset() { | ||
| 72 | //trace!("USB IRQ: reset"); | ||
| 73 | IRQ_RESET.store(true, Ordering::Relaxed); | ||
| 74 | |||
| 75 | // Write 0 to clear. | ||
| 76 | let mut clear = regs::Istr(!0); | ||
| 77 | clear.set_reset(false); | ||
| 78 | regs.istr().write_value(clear); | ||
| 79 | |||
| 80 | // Wake main thread. | ||
| 81 | BUS_WAKER.wake(); | ||
| 82 | } | ||
| 83 | |||
| 84 | if istr.ctr() { | ||
| 85 | let index = istr.ep_id() as usize; | ||
| 86 | let mut epr = regs.epr(index).read(); | ||
| 87 | if epr.ctr_rx() { | ||
| 88 | if index == 0 && epr.setup() { | ||
| 89 | EP0_SETUP.store(true, Ordering::Relaxed); | ||
| 98 | } | 90 | } |
| 99 | epr.set_dtog_rx(false); | 91 | //trace!("EP {} RX, setup={}", index, epr.setup()); |
| 100 | epr.set_dtog_tx(false); | 92 | EP_OUT_WAKERS[index].wake(); |
| 101 | epr.set_stat_rx(Stat(0)); | 93 | } |
| 102 | epr.set_stat_tx(Stat(0)); | 94 | if epr.ctr_tx() { |
| 103 | epr.set_ctr_rx(!epr.ctr_rx()); | 95 | //trace!("EP {} TX", index); |
| 104 | epr.set_ctr_tx(!epr.ctr_tx()); | 96 | EP_IN_WAKERS[index].wake(); |
| 105 | regs.epr(index).write_value(epr); | ||
| 106 | } | 97 | } |
| 98 | epr.set_dtog_rx(false); | ||
| 99 | epr.set_dtog_tx(false); | ||
| 100 | epr.set_stat_rx(Stat(0)); | ||
| 101 | epr.set_stat_tx(Stat(0)); | ||
| 102 | epr.set_ctr_rx(!epr.ctr_rx()); | ||
| 103 | epr.set_ctr_tx(!epr.ctr_tx()); | ||
| 104 | regs.epr(index).write_value(epr); | ||
| 107 | } | 105 | } |
| 108 | } | 106 | } |
| 109 | } | 107 | } |
| @@ -168,20 +166,20 @@ fn calc_out_len(len: u16) -> (u16, u16) { | |||
| 168 | mod btable { | 166 | mod btable { |
| 169 | use super::*; | 167 | use super::*; |
| 170 | 168 | ||
| 171 | pub(super) unsafe fn write_in<T: Instance>(index: usize, addr: u16) { | 169 | pub(super) fn write_in<T: Instance>(index: usize, addr: u16) { |
| 172 | USBRAM.mem(index * 4 + 0).write_value(addr); | 170 | USBRAM.mem(index * 4 + 0).write_value(addr); |
| 173 | } | 171 | } |
| 174 | 172 | ||
| 175 | pub(super) unsafe fn write_in_len<T: Instance>(index: usize, _addr: u16, len: u16) { | 173 | pub(super) fn write_in_len<T: Instance>(index: usize, _addr: u16, len: u16) { |
| 176 | USBRAM.mem(index * 4 + 1).write_value(len); | 174 | USBRAM.mem(index * 4 + 1).write_value(len); |
| 177 | } | 175 | } |
| 178 | 176 | ||
| 179 | pub(super) unsafe fn write_out<T: Instance>(index: usize, addr: u16, max_len_bits: u16) { | 177 | pub(super) fn write_out<T: Instance>(index: usize, addr: u16, max_len_bits: u16) { |
| 180 | USBRAM.mem(index * 4 + 2).write_value(addr); | 178 | USBRAM.mem(index * 4 + 2).write_value(addr); |
| 181 | USBRAM.mem(index * 4 + 3).write_value(max_len_bits); | 179 | USBRAM.mem(index * 4 + 3).write_value(max_len_bits); |
| 182 | } | 180 | } |
| 183 | 181 | ||
| 184 | pub(super) unsafe fn read_out_len<T: Instance>(index: usize) -> u16 { | 182 | pub(super) fn read_out_len<T: Instance>(index: usize) -> u16 { |
| 185 | USBRAM.mem(index * 4 + 3).read() | 183 | USBRAM.mem(index * 4 + 3).read() |
| 186 | } | 184 | } |
| 187 | } | 185 | } |
| @@ -189,19 +187,19 @@ mod btable { | |||
| 189 | mod btable { | 187 | mod btable { |
| 190 | use super::*; | 188 | use super::*; |
| 191 | 189 | ||
| 192 | pub(super) unsafe fn write_in<T: Instance>(_index: usize, _addr: u16) {} | 190 | pub(super) fn write_in<T: Instance>(_index: usize, _addr: u16) {} |
| 193 | 191 | ||
| 194 | pub(super) unsafe fn write_in_len<T: Instance>(index: usize, addr: u16, len: u16) { | 192 | pub(super) fn write_in_len<T: Instance>(index: usize, addr: u16, len: u16) { |
| 195 | USBRAM.mem(index * 2).write_value((addr as u32) | ((len as u32) << 16)); | 193 | USBRAM.mem(index * 2).write_value((addr as u32) | ((len as u32) << 16)); |
| 196 | } | 194 | } |
| 197 | 195 | ||
| 198 | pub(super) unsafe fn write_out<T: Instance>(index: usize, addr: u16, max_len_bits: u16) { | 196 | pub(super) fn write_out<T: Instance>(index: usize, addr: u16, max_len_bits: u16) { |
| 199 | USBRAM | 197 | USBRAM |
| 200 | .mem(index * 2 + 1) | 198 | .mem(index * 2 + 1) |
| 201 | .write_value((addr as u32) | ((max_len_bits as u32) << 16)); | 199 | .write_value((addr as u32) | ((max_len_bits as u32) << 16)); |
| 202 | } | 200 | } |
| 203 | 201 | ||
| 204 | pub(super) unsafe fn read_out_len<T: Instance>(index: usize) -> u16 { | 202 | pub(super) fn read_out_len<T: Instance>(index: usize) -> u16 { |
| 205 | (USBRAM.mem(index * 2 + 1).read() >> 16) as u16 | 203 | (USBRAM.mem(index * 2 + 1).read() >> 16) as u16 |
| 206 | } | 204 | } |
| 207 | } | 205 | } |
| @@ -216,7 +214,7 @@ impl<T: Instance> EndpointBuffer<T> { | |||
| 216 | fn read(&mut self, buf: &mut [u8]) { | 214 | fn read(&mut self, buf: &mut [u8]) { |
| 217 | assert!(buf.len() <= self.len as usize); | 215 | assert!(buf.len() <= self.len as usize); |
| 218 | for i in 0..(buf.len() + USBRAM_ALIGN - 1) / USBRAM_ALIGN { | 216 | for i in 0..(buf.len() + USBRAM_ALIGN - 1) / USBRAM_ALIGN { |
| 219 | let val = unsafe { USBRAM.mem(self.addr as usize / USBRAM_ALIGN + i).read() }; | 217 | let val = USBRAM.mem(self.addr as usize / USBRAM_ALIGN + i).read(); |
| 220 | let n = USBRAM_ALIGN.min(buf.len() - i * USBRAM_ALIGN); | 218 | let n = USBRAM_ALIGN.min(buf.len() - i * USBRAM_ALIGN); |
| 221 | buf[i * USBRAM_ALIGN..][..n].copy_from_slice(&val.to_le_bytes()[..n]); | 219 | buf[i * USBRAM_ALIGN..][..n].copy_from_slice(&val.to_le_bytes()[..n]); |
| 222 | } | 220 | } |
| @@ -233,7 +231,7 @@ impl<T: Instance> EndpointBuffer<T> { | |||
| 233 | let val = u16::from_le_bytes(val); | 231 | let val = u16::from_le_bytes(val); |
| 234 | #[cfg(usbram_32_2048)] | 232 | #[cfg(usbram_32_2048)] |
| 235 | let val = u32::from_le_bytes(val); | 233 | let val = u32::from_le_bytes(val); |
| 236 | unsafe { USBRAM.mem(self.addr as usize / USBRAM_ALIGN + i).write_value(val) }; | 234 | USBRAM.mem(self.addr as usize / USBRAM_ALIGN + i).write_value(val); |
| 237 | } | 235 | } |
| 238 | } | 236 | } |
| 239 | } | 237 | } |
| @@ -266,36 +264,32 @@ impl<'d, T: Instance> Driver<'d, T> { | |||
| 266 | let regs = T::regs(); | 264 | let regs = T::regs(); |
| 267 | 265 | ||
| 268 | #[cfg(stm32l5)] | 266 | #[cfg(stm32l5)] |
| 269 | unsafe { | 267 | { |
| 270 | crate::peripherals::PWR::enable(); | 268 | crate::peripherals::PWR::enable(); |
| 271 | crate::pac::PWR.cr2().modify(|w| w.set_usv(true)); | 269 | crate::pac::PWR.cr2().modify(|w| w.set_usv(true)); |
| 272 | } | 270 | } |
| 273 | 271 | ||
| 274 | #[cfg(pwr_h5)] | 272 | #[cfg(pwr_h5)] |
| 275 | unsafe { | 273 | crate::pac::PWR.usbscr().modify(|w| w.set_usb33sv(true)); |
| 276 | crate::pac::PWR.usbscr().modify(|w| w.set_usb33sv(true)) | ||
| 277 | } | ||
| 278 | 274 | ||
| 279 | unsafe { | 275 | <T as RccPeripheral>::enable(); |
| 280 | <T as RccPeripheral>::enable(); | 276 | <T as RccPeripheral>::reset(); |
| 281 | <T as RccPeripheral>::reset(); | ||
| 282 | 277 | ||
| 283 | regs.cntr().write(|w| { | 278 | regs.cntr().write(|w| { |
| 284 | w.set_pdwn(false); | 279 | w.set_pdwn(false); |
| 285 | w.set_fres(true); | 280 | w.set_fres(true); |
| 286 | }); | 281 | }); |
| 287 | 282 | ||
| 288 | #[cfg(time)] | 283 | #[cfg(time)] |
| 289 | embassy_time::block_for(embassy_time::Duration::from_millis(100)); | 284 | embassy_time::block_for(embassy_time::Duration::from_millis(100)); |
| 290 | #[cfg(not(time))] | 285 | #[cfg(not(time))] |
| 291 | cortex_m::asm::delay(crate::rcc::get_freqs().sys.0 / 10); | 286 | cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.0 / 10); |
| 292 | 287 | ||
| 293 | #[cfg(not(usb_v4))] | 288 | #[cfg(not(usb_v4))] |
| 294 | regs.btable().write(|w| w.set_btable(0)); | 289 | regs.btable().write(|w| w.set_btable(0)); |
| 295 | 290 | ||
| 296 | dp.set_as_af(dp.af_num(), AFType::OutputPushPull); | 291 | dp.set_as_af(dp.af_num(), AFType::OutputPushPull); |
| 297 | dm.set_as_af(dm.af_num(), AFType::OutputPushPull); | 292 | dm.set_as_af(dm.af_num(), AFType::OutputPushPull); |
| 298 | } | ||
| 299 | 293 | ||
| 300 | // Initialize the bus so that it signals that power is available | 294 | // Initialize the bus so that it signals that power is available |
| 301 | BUS_WAKER.wake(); | 295 | BUS_WAKER.wake(); |
| @@ -363,7 +357,7 @@ impl<'d, T: Instance> Driver<'d, T> { | |||
| 363 | let addr = self.alloc_ep_mem(len); | 357 | let addr = self.alloc_ep_mem(len); |
| 364 | 358 | ||
| 365 | trace!(" len_bits = {:04x}", len_bits); | 359 | trace!(" len_bits = {:04x}", len_bits); |
| 366 | unsafe { btable::write_out::<T>(index, addr, len_bits) } | 360 | btable::write_out::<T>(index, addr, len_bits); |
| 367 | 361 | ||
| 368 | EndpointBuffer { | 362 | EndpointBuffer { |
| 369 | addr, | 363 | addr, |
| @@ -379,7 +373,7 @@ impl<'d, T: Instance> Driver<'d, T> { | |||
| 379 | let addr = self.alloc_ep_mem(len); | 373 | let addr = self.alloc_ep_mem(len); |
| 380 | 374 | ||
| 381 | // ep_in_len is written when actually TXing packets. | 375 | // ep_in_len is written when actually TXing packets. |
| 382 | unsafe { btable::write_in::<T>(index, addr) } | 376 | btable::write_in::<T>(index, addr); |
| 383 | 377 | ||
| 384 | EndpointBuffer { | 378 | EndpointBuffer { |
| 385 | addr, | 379 | addr, |
| @@ -440,19 +434,17 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> { | |||
| 440 | 434 | ||
| 441 | let regs = T::regs(); | 435 | let regs = T::regs(); |
| 442 | 436 | ||
| 443 | unsafe { | 437 | regs.cntr().write(|w| { |
| 444 | regs.cntr().write(|w| { | 438 | w.set_pdwn(false); |
| 445 | w.set_pdwn(false); | 439 | w.set_fres(false); |
| 446 | w.set_fres(false); | 440 | w.set_resetm(true); |
| 447 | w.set_resetm(true); | 441 | w.set_suspm(true); |
| 448 | w.set_suspm(true); | 442 | w.set_wkupm(true); |
| 449 | w.set_wkupm(true); | 443 | w.set_ctrm(true); |
| 450 | w.set_ctrm(true); | 444 | }); |
| 451 | }); | ||
| 452 | 445 | ||
| 453 | #[cfg(any(usb_v3, usb_v4))] | 446 | #[cfg(any(usb_v3, usb_v4))] |
| 454 | regs.bcdr().write(|w| w.set_dppu(true)) | 447 | regs.bcdr().write(|w| w.set_dppu(true)); |
| 455 | } | ||
| 456 | 448 | ||
| 457 | trace!("enabled"); | 449 | trace!("enabled"); |
| 458 | 450 | ||
| @@ -485,7 +477,7 @@ pub struct Bus<'d, T: Instance> { | |||
| 485 | 477 | ||
| 486 | impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | 478 | impl<'d, T: Instance> driver::Bus for Bus<'d, T> { |
| 487 | async fn poll(&mut self) -> Event { | 479 | async fn poll(&mut self) -> Event { |
| 488 | poll_fn(move |cx| unsafe { | 480 | poll_fn(move |cx| { |
| 489 | BUS_WAKER.register(cx.waker()); | 481 | BUS_WAKER.register(cx.waker()); |
| 490 | 482 | ||
| 491 | if self.inited { | 483 | if self.inited { |
| @@ -548,7 +540,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||
| 548 | match ep_addr.direction() { | 540 | match ep_addr.direction() { |
| 549 | Direction::In => { | 541 | Direction::In => { |
| 550 | loop { | 542 | loop { |
| 551 | let r = unsafe { reg.read() }; | 543 | let r = reg.read(); |
| 552 | match r.stat_tx() { | 544 | match r.stat_tx() { |
| 553 | Stat::DISABLED => break, // if disabled, stall does nothing. | 545 | Stat::DISABLED => break, // if disabled, stall does nothing. |
| 554 | Stat::STALL => break, // done! | 546 | Stat::STALL => break, // done! |
| @@ -559,7 +551,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||
| 559 | }; | 551 | }; |
| 560 | let mut w = invariant(r); | 552 | let mut w = invariant(r); |
| 561 | w.set_stat_tx(Stat(r.stat_tx().0 ^ want_stat.0)); | 553 | w.set_stat_tx(Stat(r.stat_tx().0 ^ want_stat.0)); |
| 562 | unsafe { reg.write_value(w) }; | 554 | reg.write_value(w); |
| 563 | } | 555 | } |
| 564 | } | 556 | } |
| 565 | } | 557 | } |
| @@ -567,7 +559,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||
| 567 | } | 559 | } |
| 568 | Direction::Out => { | 560 | Direction::Out => { |
| 569 | loop { | 561 | loop { |
| 570 | let r = unsafe { reg.read() }; | 562 | let r = reg.read(); |
| 571 | match r.stat_rx() { | 563 | match r.stat_rx() { |
| 572 | Stat::DISABLED => break, // if disabled, stall does nothing. | 564 | Stat::DISABLED => break, // if disabled, stall does nothing. |
| 573 | Stat::STALL => break, // done! | 565 | Stat::STALL => break, // done! |
| @@ -578,7 +570,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||
| 578 | }; | 570 | }; |
| 579 | let mut w = invariant(r); | 571 | let mut w = invariant(r); |
| 580 | w.set_stat_rx(Stat(r.stat_rx().0 ^ want_stat.0)); | 572 | w.set_stat_rx(Stat(r.stat_rx().0 ^ want_stat.0)); |
| 581 | unsafe { reg.write_value(w) }; | 573 | reg.write_value(w); |
| 582 | } | 574 | } |
| 583 | } | 575 | } |
| 584 | } | 576 | } |
| @@ -589,7 +581,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||
| 589 | 581 | ||
| 590 | fn endpoint_is_stalled(&mut self, ep_addr: EndpointAddress) -> bool { | 582 | fn endpoint_is_stalled(&mut self, ep_addr: EndpointAddress) -> bool { |
| 591 | let regs = T::regs(); | 583 | let regs = T::regs(); |
| 592 | let epr = unsafe { regs.epr(ep_addr.index() as _).read() }; | 584 | let epr = regs.epr(ep_addr.index() as _).read(); |
| 593 | match ep_addr.direction() { | 585 | match ep_addr.direction() { |
| 594 | Direction::In => epr.stat_tx() == Stat::STALL, | 586 | Direction::In => epr.stat_tx() == Stat::STALL, |
| 595 | Direction::Out => epr.stat_rx() == Stat::STALL, | 587 | Direction::Out => epr.stat_rx() == Stat::STALL, |
| @@ -600,7 +592,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||
| 600 | trace!("set_enabled {:x} {}", ep_addr, enabled); | 592 | trace!("set_enabled {:x} {}", ep_addr, enabled); |
| 601 | // This can race, so do a retry loop. | 593 | // This can race, so do a retry loop. |
| 602 | let reg = T::regs().epr(ep_addr.index() as _); | 594 | let reg = T::regs().epr(ep_addr.index() as _); |
| 603 | trace!("EPR before: {:04x}", unsafe { reg.read() }.0); | 595 | trace!("EPR before: {:04x}", reg.read().0); |
| 604 | match ep_addr.direction() { | 596 | match ep_addr.direction() { |
| 605 | Direction::In => { | 597 | Direction::In => { |
| 606 | loop { | 598 | loop { |
| @@ -608,13 +600,13 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||
| 608 | false => Stat::DISABLED, | 600 | false => Stat::DISABLED, |
| 609 | true => Stat::NAK, | 601 | true => Stat::NAK, |
| 610 | }; | 602 | }; |
| 611 | let r = unsafe { reg.read() }; | 603 | let r = reg.read(); |
| 612 | if r.stat_tx() == want_stat { | 604 | if r.stat_tx() == want_stat { |
| 613 | break; | 605 | break; |
| 614 | } | 606 | } |
| 615 | let mut w = invariant(r); | 607 | let mut w = invariant(r); |
| 616 | w.set_stat_tx(Stat(r.stat_tx().0 ^ want_stat.0)); | 608 | w.set_stat_tx(Stat(r.stat_tx().0 ^ want_stat.0)); |
| 617 | unsafe { reg.write_value(w) }; | 609 | reg.write_value(w); |
| 618 | } | 610 | } |
| 619 | EP_IN_WAKERS[ep_addr.index()].wake(); | 611 | EP_IN_WAKERS[ep_addr.index()].wake(); |
| 620 | } | 612 | } |
| @@ -624,18 +616,18 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||
| 624 | false => Stat::DISABLED, | 616 | false => Stat::DISABLED, |
| 625 | true => Stat::VALID, | 617 | true => Stat::VALID, |
| 626 | }; | 618 | }; |
| 627 | let r = unsafe { reg.read() }; | 619 | let r = reg.read(); |
| 628 | if r.stat_rx() == want_stat { | 620 | if r.stat_rx() == want_stat { |
| 629 | break; | 621 | break; |
| 630 | } | 622 | } |
| 631 | let mut w = invariant(r); | 623 | let mut w = invariant(r); |
| 632 | w.set_stat_rx(Stat(r.stat_rx().0 ^ want_stat.0)); | 624 | w.set_stat_rx(Stat(r.stat_rx().0 ^ want_stat.0)); |
| 633 | unsafe { reg.write_value(w) }; | 625 | reg.write_value(w); |
| 634 | } | 626 | } |
| 635 | EP_OUT_WAKERS[ep_addr.index()].wake(); | 627 | EP_OUT_WAKERS[ep_addr.index()].wake(); |
| 636 | } | 628 | } |
| 637 | } | 629 | } |
| 638 | trace!("EPR after: {:04x}", unsafe { reg.read() }.0); | 630 | trace!("EPR after: {:04x}", reg.read().0); |
| 639 | } | 631 | } |
| 640 | 632 | ||
| 641 | async fn enable(&mut self) {} | 633 | async fn enable(&mut self) {} |
| @@ -685,12 +677,12 @@ impl<'d, T: Instance, D> Endpoint<'d, T, D> { | |||
| 685 | fn write_data(&mut self, buf: &[u8]) { | 677 | fn write_data(&mut self, buf: &[u8]) { |
| 686 | let index = self.info.addr.index(); | 678 | let index = self.info.addr.index(); |
| 687 | self.buf.write(buf); | 679 | self.buf.write(buf); |
| 688 | unsafe { btable::write_in_len::<T>(index, self.buf.addr, buf.len() as _) } | 680 | btable::write_in_len::<T>(index, self.buf.addr, buf.len() as _); |
| 689 | } | 681 | } |
| 690 | 682 | ||
| 691 | fn read_data(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> { | 683 | fn read_data(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> { |
| 692 | let index = self.info.addr.index(); | 684 | let index = self.info.addr.index(); |
| 693 | let rx_len = unsafe { btable::read_out_len::<T>(index) as usize } & 0x3FF; | 685 | let rx_len = btable::read_out_len::<T>(index) as usize & 0x3FF; |
| 694 | trace!("READ DONE, rx_len = {}", rx_len); | 686 | trace!("READ DONE, rx_len = {}", rx_len); |
| 695 | if rx_len > buf.len() { | 687 | if rx_len > buf.len() { |
| 696 | return Err(EndpointError::BufferOverflow); | 688 | return Err(EndpointError::BufferOverflow); |
| @@ -711,7 +703,7 @@ impl<'d, T: Instance> driver::Endpoint for Endpoint<'d, T, In> { | |||
| 711 | poll_fn(|cx| { | 703 | poll_fn(|cx| { |
| 712 | EP_OUT_WAKERS[index].register(cx.waker()); | 704 | EP_OUT_WAKERS[index].register(cx.waker()); |
| 713 | let regs = T::regs(); | 705 | let regs = T::regs(); |
| 714 | if unsafe { regs.epr(index).read() }.stat_tx() == Stat::DISABLED { | 706 | if regs.epr(index).read().stat_tx() == Stat::DISABLED { |
| 715 | Poll::Pending | 707 | Poll::Pending |
| 716 | } else { | 708 | } else { |
| 717 | Poll::Ready(()) | 709 | Poll::Ready(()) |
| @@ -733,7 +725,7 @@ impl<'d, T: Instance> driver::Endpoint for Endpoint<'d, T, Out> { | |||
| 733 | poll_fn(|cx| { | 725 | poll_fn(|cx| { |
| 734 | EP_OUT_WAKERS[index].register(cx.waker()); | 726 | EP_OUT_WAKERS[index].register(cx.waker()); |
| 735 | let regs = T::regs(); | 727 | let regs = T::regs(); |
| 736 | if unsafe { regs.epr(index).read() }.stat_rx() == Stat::DISABLED { | 728 | if regs.epr(index).read().stat_rx() == Stat::DISABLED { |
| 737 | Poll::Pending | 729 | Poll::Pending |
| 738 | } else { | 730 | } else { |
| 739 | Poll::Ready(()) | 731 | Poll::Ready(()) |
| @@ -751,7 +743,7 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> { | |||
| 751 | let stat = poll_fn(|cx| { | 743 | let stat = poll_fn(|cx| { |
| 752 | EP_OUT_WAKERS[index].register(cx.waker()); | 744 | EP_OUT_WAKERS[index].register(cx.waker()); |
| 753 | let regs = T::regs(); | 745 | let regs = T::regs(); |
| 754 | let stat = unsafe { regs.epr(index).read() }.stat_rx(); | 746 | let stat = regs.epr(index).read().stat_rx(); |
| 755 | if matches!(stat, Stat::NAK | Stat::DISABLED) { | 747 | if matches!(stat, Stat::NAK | Stat::DISABLED) { |
| 756 | Poll::Ready(stat) | 748 | Poll::Ready(stat) |
| 757 | } else { | 749 | } else { |
| @@ -767,16 +759,14 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> { | |||
| 767 | let rx_len = self.read_data(buf)?; | 759 | let rx_len = self.read_data(buf)?; |
| 768 | 760 | ||
| 769 | let regs = T::regs(); | 761 | let regs = T::regs(); |
| 770 | unsafe { | 762 | regs.epr(index).write(|w| { |
| 771 | regs.epr(index).write(|w| { | 763 | w.set_ep_type(convert_type(self.info.ep_type)); |
| 772 | w.set_ep_type(convert_type(self.info.ep_type)); | 764 | w.set_ea(self.info.addr.index() as _); |
| 773 | w.set_ea(self.info.addr.index() as _); | 765 | w.set_stat_rx(Stat(Stat::NAK.0 ^ Stat::VALID.0)); |
| 774 | w.set_stat_rx(Stat(Stat::NAK.0 ^ Stat::VALID.0)); | 766 | w.set_stat_tx(Stat(0)); |
| 775 | w.set_stat_tx(Stat(0)); | 767 | w.set_ctr_rx(true); // don't clear |
| 776 | w.set_ctr_rx(true); // don't clear | 768 | w.set_ctr_tx(true); // don't clear |
| 777 | w.set_ctr_tx(true); // don't clear | 769 | }); |
| 778 | }) | ||
| 779 | }; | ||
| 780 | trace!("READ OK, rx_len = {}", rx_len); | 770 | trace!("READ OK, rx_len = {}", rx_len); |
| 781 | 771 | ||
| 782 | Ok(rx_len) | 772 | Ok(rx_len) |
| @@ -795,7 +785,7 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> { | |||
| 795 | let stat = poll_fn(|cx| { | 785 | let stat = poll_fn(|cx| { |
| 796 | EP_IN_WAKERS[index].register(cx.waker()); | 786 | EP_IN_WAKERS[index].register(cx.waker()); |
| 797 | let regs = T::regs(); | 787 | let regs = T::regs(); |
| 798 | let stat = unsafe { regs.epr(index).read() }.stat_tx(); | 788 | let stat = regs.epr(index).read().stat_tx(); |
| 799 | if matches!(stat, Stat::NAK | Stat::DISABLED) { | 789 | if matches!(stat, Stat::NAK | Stat::DISABLED) { |
| 800 | Poll::Ready(stat) | 790 | Poll::Ready(stat) |
| 801 | } else { | 791 | } else { |
| @@ -811,16 +801,14 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> { | |||
| 811 | self.write_data(buf); | 801 | self.write_data(buf); |
| 812 | 802 | ||
| 813 | let regs = T::regs(); | 803 | let regs = T::regs(); |
| 814 | unsafe { | 804 | regs.epr(index).write(|w| { |
| 815 | regs.epr(index).write(|w| { | 805 | w.set_ep_type(convert_type(self.info.ep_type)); |
| 816 | w.set_ep_type(convert_type(self.info.ep_type)); | 806 | w.set_ea(self.info.addr.index() as _); |
| 817 | w.set_ea(self.info.addr.index() as _); | 807 | w.set_stat_tx(Stat(Stat::NAK.0 ^ Stat::VALID.0)); |
| 818 | w.set_stat_tx(Stat(Stat::NAK.0 ^ Stat::VALID.0)); | 808 | w.set_stat_rx(Stat(0)); |
| 819 | w.set_stat_rx(Stat(0)); | 809 | w.set_ctr_rx(true); // don't clear |
| 820 | w.set_ctr_rx(true); // don't clear | 810 | w.set_ctr_tx(true); // don't clear |
| 821 | w.set_ctr_tx(true); // don't clear | 811 | }); |
| 822 | }) | ||
| 823 | }; | ||
| 824 | 812 | ||
| 825 | trace!("WRITE OK"); | 813 | trace!("WRITE OK"); |
| 826 | 814 | ||
| @@ -889,22 +877,20 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { | |||
| 889 | } | 877 | } |
| 890 | // Note: if this is the first AND last transfer, the above effectively | 878 | // Note: if this is the first AND last transfer, the above effectively |
| 891 | // changes stat_tx like NAK -> NAK, so noop. | 879 | // changes stat_tx like NAK -> NAK, so noop. |
| 892 | unsafe { | 880 | regs.epr(0).write(|w| { |
| 893 | regs.epr(0).write(|w| { | 881 | w.set_ep_type(EpType::CONTROL); |
| 894 | w.set_ep_type(EpType::CONTROL); | 882 | w.set_stat_rx(Stat(stat_rx)); |
| 895 | w.set_stat_rx(Stat(stat_rx)); | 883 | w.set_stat_tx(Stat(stat_tx)); |
| 896 | w.set_stat_tx(Stat(stat_tx)); | 884 | w.set_ctr_rx(true); // don't clear |
| 897 | w.set_ctr_rx(true); // don't clear | 885 | w.set_ctr_tx(true); // don't clear |
| 898 | w.set_ctr_tx(true); // don't clear | 886 | }); |
| 899 | }) | ||
| 900 | } | ||
| 901 | } | 887 | } |
| 902 | 888 | ||
| 903 | trace!("data_out WAITING, buf.len() = {}", buf.len()); | 889 | trace!("data_out WAITING, buf.len() = {}", buf.len()); |
| 904 | poll_fn(|cx| { | 890 | poll_fn(|cx| { |
| 905 | EP_OUT_WAKERS[0].register(cx.waker()); | 891 | EP_OUT_WAKERS[0].register(cx.waker()); |
| 906 | let regs = T::regs(); | 892 | let regs = T::regs(); |
| 907 | if unsafe { regs.epr(0).read() }.stat_rx() == Stat::NAK { | 893 | if regs.epr(0).read().stat_rx() == Stat::NAK { |
| 908 | Poll::Ready(()) | 894 | Poll::Ready(()) |
| 909 | } else { | 895 | } else { |
| 910 | Poll::Pending | 896 | Poll::Pending |
| @@ -919,19 +905,17 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { | |||
| 919 | 905 | ||
| 920 | let rx_len = self.ep_out.read_data(buf)?; | 906 | let rx_len = self.ep_out.read_data(buf)?; |
| 921 | 907 | ||
| 922 | unsafe { | 908 | regs.epr(0).write(|w| { |
| 923 | regs.epr(0).write(|w| { | 909 | w.set_ep_type(EpType::CONTROL); |
| 924 | w.set_ep_type(EpType::CONTROL); | 910 | w.set_stat_rx(Stat(match last { |
| 925 | w.set_stat_rx(Stat(match last { | 911 | // If last, set STAT_RX=STALL. |
| 926 | // If last, set STAT_RX=STALL. | 912 | true => Stat::NAK.0 ^ Stat::STALL.0, |
| 927 | true => Stat::NAK.0 ^ Stat::STALL.0, | 913 | // Otherwise, set STAT_RX=VALID, to allow the host to send the next packet. |
| 928 | // Otherwise, set STAT_RX=VALID, to allow the host to send the next packet. | 914 | false => Stat::NAK.0 ^ Stat::VALID.0, |
| 929 | false => Stat::NAK.0 ^ Stat::VALID.0, | 915 | })); |
| 930 | })); | 916 | w.set_ctr_rx(true); // don't clear |
| 931 | w.set_ctr_rx(true); // don't clear | 917 | w.set_ctr_tx(true); // don't clear |
| 932 | w.set_ctr_tx(true); // don't clear | 918 | }); |
| 933 | }) | ||
| 934 | }; | ||
| 935 | 919 | ||
| 936 | Ok(rx_len) | 920 | Ok(rx_len) |
| 937 | } | 921 | } |
| @@ -960,15 +944,13 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { | |||
| 960 | } | 944 | } |
| 961 | // Note: if this is the first AND last transfer, the above effectively | 945 | // Note: if this is the first AND last transfer, the above effectively |
| 962 | // does a change of NAK -> VALID. | 946 | // does a change of NAK -> VALID. |
| 963 | unsafe { | 947 | regs.epr(0).write(|w| { |
| 964 | regs.epr(0).write(|w| { | 948 | w.set_ep_type(EpType::CONTROL); |
| 965 | w.set_ep_type(EpType::CONTROL); | 949 | w.set_stat_rx(Stat(stat_rx)); |
| 966 | w.set_stat_rx(Stat(stat_rx)); | 950 | w.set_ep_kind(last); // set OUT_STATUS if last. |
| 967 | w.set_ep_kind(last); // set OUT_STATUS if last. | 951 | w.set_ctr_rx(true); // don't clear |
| 968 | w.set_ctr_rx(true); // don't clear | 952 | w.set_ctr_tx(true); // don't clear |
| 969 | w.set_ctr_tx(true); // don't clear | 953 | }); |
| 970 | }) | ||
| 971 | } | ||
| 972 | } | 954 | } |
| 973 | 955 | ||
| 974 | trace!("WRITE WAITING"); | 956 | trace!("WRITE WAITING"); |
| @@ -976,7 +958,7 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { | |||
| 976 | EP_IN_WAKERS[0].register(cx.waker()); | 958 | EP_IN_WAKERS[0].register(cx.waker()); |
| 977 | EP_OUT_WAKERS[0].register(cx.waker()); | 959 | EP_OUT_WAKERS[0].register(cx.waker()); |
| 978 | let regs = T::regs(); | 960 | let regs = T::regs(); |
| 979 | if unsafe { regs.epr(0).read() }.stat_tx() == Stat::NAK { | 961 | if regs.epr(0).read().stat_tx() == Stat::NAK { |
| 980 | Poll::Ready(()) | 962 | Poll::Ready(()) |
| 981 | } else { | 963 | } else { |
| 982 | Poll::Pending | 964 | Poll::Pending |
| @@ -992,15 +974,13 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { | |||
| 992 | self.ep_in.write_data(data); | 974 | self.ep_in.write_data(data); |
| 993 | 975 | ||
| 994 | let regs = T::regs(); | 976 | let regs = T::regs(); |
| 995 | unsafe { | 977 | regs.epr(0).write(|w| { |
| 996 | regs.epr(0).write(|w| { | 978 | w.set_ep_type(EpType::CONTROL); |
| 997 | w.set_ep_type(EpType::CONTROL); | 979 | w.set_stat_tx(Stat(Stat::NAK.0 ^ Stat::VALID.0)); |
| 998 | w.set_stat_tx(Stat(Stat::NAK.0 ^ Stat::VALID.0)); | 980 | w.set_ep_kind(last); // set OUT_STATUS if last. |
| 999 | w.set_ep_kind(last); // set OUT_STATUS if last. | 981 | w.set_ctr_rx(true); // don't clear |
| 1000 | w.set_ctr_rx(true); // don't clear | 982 | w.set_ctr_tx(true); // don't clear |
| 1001 | w.set_ctr_tx(true); // don't clear | 983 | }); |
| 1002 | }) | ||
| 1003 | }; | ||
| 1004 | 984 | ||
| 1005 | trace!("WRITE OK"); | 985 | trace!("WRITE OK"); |
| 1006 | 986 | ||
| @@ -1014,16 +994,14 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { | |||
| 1014 | self.ep_in.write_data(&[]); | 994 | self.ep_in.write_data(&[]); |
| 1015 | 995 | ||
| 1016 | // Set OUT=stall, IN=accept | 996 | // Set OUT=stall, IN=accept |
| 1017 | unsafe { | 997 | let epr = regs.epr(0).read(); |
| 1018 | let epr = regs.epr(0).read(); | 998 | regs.epr(0).write(|w| { |
| 1019 | regs.epr(0).write(|w| { | 999 | w.set_ep_type(EpType::CONTROL); |
| 1020 | w.set_ep_type(EpType::CONTROL); | 1000 | w.set_stat_rx(Stat(epr.stat_rx().0 ^ Stat::STALL.0)); |
| 1021 | w.set_stat_rx(Stat(epr.stat_rx().0 ^ Stat::STALL.0)); | 1001 | w.set_stat_tx(Stat(epr.stat_tx().0 ^ Stat::VALID.0)); |
| 1022 | w.set_stat_tx(Stat(epr.stat_tx().0 ^ Stat::VALID.0)); | 1002 | w.set_ctr_rx(true); // don't clear |
| 1023 | w.set_ctr_rx(true); // don't clear | 1003 | w.set_ctr_tx(true); // don't clear |
| 1024 | w.set_ctr_tx(true); // don't clear | 1004 | }); |
| 1025 | }); | ||
| 1026 | } | ||
| 1027 | trace!("control: accept WAITING"); | 1005 | trace!("control: accept WAITING"); |
| 1028 | 1006 | ||
| 1029 | // Wait is needed, so that we don't set the address too soon, breaking the status stage. | 1007 | // Wait is needed, so that we don't set the address too soon, breaking the status stage. |
| @@ -1031,7 +1009,7 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { | |||
| 1031 | poll_fn(|cx| { | 1009 | poll_fn(|cx| { |
| 1032 | EP_IN_WAKERS[0].register(cx.waker()); | 1010 | EP_IN_WAKERS[0].register(cx.waker()); |
| 1033 | let regs = T::regs(); | 1011 | let regs = T::regs(); |
| 1034 | if unsafe { regs.epr(0).read() }.stat_tx() == Stat::NAK { | 1012 | if regs.epr(0).read().stat_tx() == Stat::NAK { |
| 1035 | Poll::Ready(()) | 1013 | Poll::Ready(()) |
| 1036 | } else { | 1014 | } else { |
| 1037 | Poll::Pending | 1015 | Poll::Pending |
| @@ -1047,16 +1025,14 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { | |||
| 1047 | trace!("control: reject"); | 1025 | trace!("control: reject"); |
| 1048 | 1026 | ||
| 1049 | // Set IN+OUT to stall | 1027 | // Set IN+OUT to stall |
| 1050 | unsafe { | 1028 | let epr = regs.epr(0).read(); |
| 1051 | let epr = regs.epr(0).read(); | 1029 | regs.epr(0).write(|w| { |
| 1052 | regs.epr(0).write(|w| { | 1030 | w.set_ep_type(EpType::CONTROL); |
| 1053 | w.set_ep_type(EpType::CONTROL); | 1031 | w.set_stat_rx(Stat(epr.stat_rx().0 ^ Stat::STALL.0)); |
| 1054 | w.set_stat_rx(Stat(epr.stat_rx().0 ^ Stat::STALL.0)); | 1032 | w.set_stat_tx(Stat(epr.stat_tx().0 ^ Stat::STALL.0)); |
| 1055 | w.set_stat_tx(Stat(epr.stat_tx().0 ^ Stat::STALL.0)); | 1033 | w.set_ctr_rx(true); // don't clear |
| 1056 | w.set_ctr_rx(true); // don't clear | 1034 | w.set_ctr_tx(true); // don't clear |
| 1057 | w.set_ctr_tx(true); // don't clear | 1035 | }); |
| 1058 | }); | ||
| 1059 | } | ||
| 1060 | } | 1036 | } |
| 1061 | 1037 | ||
| 1062 | async fn accept_set_address(&mut self, addr: u8) { | 1038 | async fn accept_set_address(&mut self, addr: u8) { |
| @@ -1064,11 +1040,9 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { | |||
| 1064 | 1040 | ||
| 1065 | let regs = T::regs(); | 1041 | let regs = T::regs(); |
| 1066 | trace!("setting addr: {}", addr); | 1042 | trace!("setting addr: {}", addr); |
| 1067 | unsafe { | 1043 | regs.daddr().write(|w| { |
| 1068 | regs.daddr().write(|w| { | 1044 | w.set_ef(true); |
| 1069 | w.set_ef(true); | 1045 | w.set_add(addr); |
| 1070 | w.set_add(addr); | 1046 | }); |
| 1071 | }) | ||
| 1072 | } | ||
| 1073 | } | 1047 | } |
| 1074 | } | 1048 | } |
diff --git a/embassy-stm32/src/usb_otg/mod.rs b/embassy-stm32/src/usb_otg/mod.rs index 317264cbb..12e5f0e60 100644 --- a/embassy-stm32/src/usb_otg/mod.rs +++ b/embassy-stm32/src/usb_otg/mod.rs | |||
| @@ -148,7 +148,7 @@ foreach_interrupt!( | |||
| 148 | 148 | ||
| 149 | fn regs() -> crate::pac::otg::Otg { | 149 | fn regs() -> crate::pac::otg::Otg { |
| 150 | // OTG HS registers are a superset of FS registers | 150 | // OTG HS registers are a superset of FS registers |
| 151 | crate::pac::otg::Otg(crate::pac::USB_OTG_HS.0) | 151 | unsafe { crate::pac::otg::Otg::from_ptr(crate::pac::USB_OTG_HS.as_ptr()) } |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | #[cfg(feature = "nightly")] | 154 | #[cfg(feature = "nightly")] |
diff --git a/embassy-stm32/src/usb_otg/usb.rs b/embassy-stm32/src/usb_otg/usb.rs index 16cbf1a95..8af5c7bd5 100644 --- a/embassy-stm32/src/usb_otg/usb.rs +++ b/embassy-stm32/src/usb_otg/usb.rs | |||
| @@ -30,19 +30,16 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 30 | let r = T::regs(); | 30 | let r = T::regs(); |
| 31 | let state = T::state(); | 31 | let state = T::state(); |
| 32 | 32 | ||
| 33 | // SAFETY: atomic read/write | 33 | let ints = r.gintsts().read(); |
| 34 | let ints = unsafe { r.gintsts().read() }; | ||
| 35 | if ints.wkupint() || ints.usbsusp() || ints.usbrst() || ints.enumdne() { | 34 | if ints.wkupint() || ints.usbsusp() || ints.usbrst() || ints.enumdne() { |
| 36 | // Mask interrupts and notify `Bus` to process them | 35 | // Mask interrupts and notify `Bus` to process them |
| 37 | unsafe { r.gintmsk().write(|_| {}) }; | 36 | r.gintmsk().write(|_| {}); |
| 38 | T::state().bus_waker.wake(); | 37 | T::state().bus_waker.wake(); |
| 39 | } | 38 | } |
| 40 | 39 | ||
| 41 | // Handle RX | 40 | // Handle RX |
| 42 | // SAFETY: atomic read with no side effects | 41 | while r.gintsts().read().rxflvl() { |
| 43 | while unsafe { r.gintsts().read().rxflvl() } { | 42 | let status = r.grxstsp().read(); |
| 44 | // SAFETY: atomic "pop" register | ||
| 45 | let status = unsafe { r.grxstsp().read() }; | ||
| 46 | let ep_num = status.epnum() as usize; | 43 | let ep_num = status.epnum() as usize; |
| 47 | let len = status.bcnt() as usize; | 44 | let len = status.bcnt() as usize; |
| 48 | 45 | ||
| @@ -57,21 +54,15 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 57 | if state.ep0_setup_ready.load(Ordering::Relaxed) == false { | 54 | if state.ep0_setup_ready.load(Ordering::Relaxed) == false { |
| 58 | // SAFETY: exclusive access ensured by atomic bool | 55 | // SAFETY: exclusive access ensured by atomic bool |
| 59 | let data = unsafe { &mut *state.ep0_setup_data.get() }; | 56 | let data = unsafe { &mut *state.ep0_setup_data.get() }; |
| 60 | // SAFETY: FIFO reads are exclusive to this IRQ | 57 | data[0..4].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes()); |
| 61 | unsafe { | 58 | data[4..8].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes()); |
| 62 | data[0..4].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes()); | ||
| 63 | data[4..8].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes()); | ||
| 64 | } | ||
| 65 | state.ep0_setup_ready.store(true, Ordering::Release); | 59 | state.ep0_setup_ready.store(true, Ordering::Release); |
| 66 | state.ep_out_wakers[0].wake(); | 60 | state.ep_out_wakers[0].wake(); |
| 67 | } else { | 61 | } else { |
| 68 | error!("received SETUP before previous finished processing"); | 62 | error!("received SETUP before previous finished processing"); |
| 69 | // discard FIFO | 63 | // discard FIFO |
| 70 | // SAFETY: FIFO reads are exclusive to IRQ | 64 | r.fifo(0).read(); |
| 71 | unsafe { | 65 | r.fifo(0).read(); |
| 72 | r.fifo(0).read(); | ||
| 73 | r.fifo(0).read(); | ||
| 74 | } | ||
| 75 | } | 66 | } |
| 76 | } | 67 | } |
| 77 | vals::Pktstsd::OUT_DATA_RX => { | 68 | vals::Pktstsd::OUT_DATA_RX => { |
| @@ -84,8 +75,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 84 | 75 | ||
| 85 | for chunk in buf.chunks_mut(4) { | 76 | for chunk in buf.chunks_mut(4) { |
| 86 | // RX FIFO is shared so always read from fifo(0) | 77 | // RX FIFO is shared so always read from fifo(0) |
| 87 | // SAFETY: FIFO reads are exclusive to IRQ | 78 | let data = r.fifo(0).read().0; |
| 88 | let data = unsafe { r.fifo(0).read().0 }; | ||
| 89 | chunk.copy_from_slice(&data.to_ne_bytes()[0..chunk.len()]); | 79 | chunk.copy_from_slice(&data.to_ne_bytes()[0..chunk.len()]); |
| 90 | } | 80 | } |
| 91 | 81 | ||
| @@ -97,8 +87,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 97 | // discard FIFO data | 87 | // discard FIFO data |
| 98 | let len_words = (len + 3) / 4; | 88 | let len_words = (len + 3) / 4; |
| 99 | for _ in 0..len_words { | 89 | for _ in 0..len_words { |
| 100 | // SAFETY: FIFO reads are exclusive to IRQ | 90 | r.fifo(0).read().data(); |
| 101 | unsafe { r.fifo(0).read().data() }; | ||
| 102 | } | 91 | } |
| 103 | } | 92 | } |
| 104 | } | 93 | } |
| @@ -114,24 +103,20 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 114 | 103 | ||
| 115 | // IN endpoint interrupt | 104 | // IN endpoint interrupt |
| 116 | if ints.iepint() { | 105 | if ints.iepint() { |
| 117 | // SAFETY: atomic read with no side effects | 106 | let mut ep_mask = r.daint().read().iepint(); |
| 118 | let mut ep_mask = unsafe { r.daint().read().iepint() }; | ||
| 119 | let mut ep_num = 0; | 107 | let mut ep_num = 0; |
| 120 | 108 | ||
| 121 | // Iterate over endpoints while there are non-zero bits in the mask | 109 | // Iterate over endpoints while there are non-zero bits in the mask |
| 122 | while ep_mask != 0 { | 110 | while ep_mask != 0 { |
| 123 | if ep_mask & 1 != 0 { | 111 | if ep_mask & 1 != 0 { |
| 124 | // SAFETY: atomic read with no side effects | 112 | let ep_ints = r.diepint(ep_num).read(); |
| 125 | let ep_ints = unsafe { r.diepint(ep_num).read() }; | ||
| 126 | 113 | ||
| 127 | // clear all | 114 | // clear all |
| 128 | // SAFETY: DIEPINT is exclusive to IRQ | 115 | r.diepint(ep_num).write_value(ep_ints); |
| 129 | unsafe { r.diepint(ep_num).write_value(ep_ints) }; | ||
| 130 | 116 | ||
| 131 | // TXFE is cleared in DIEPEMPMSK | 117 | // TXFE is cleared in DIEPEMPMSK |
| 132 | if ep_ints.txfe() { | 118 | if ep_ints.txfe() { |
| 133 | // SAFETY: DIEPEMPMSK is shared with `Endpoint` so critical section is needed for RMW | 119 | critical_section::with(|_| { |
| 134 | critical_section::with(|_| unsafe { | ||
| 135 | r.diepempmsk().modify(|w| { | 120 | r.diepempmsk().modify(|w| { |
| 136 | w.set_ineptxfem(w.ineptxfem() & !(1 << ep_num)); | 121 | w.set_ineptxfem(w.ineptxfem() & !(1 << ep_num)); |
| 137 | }); | 122 | }); |
| @@ -172,8 +157,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 172 | macro_rules! config_ulpi_pins { | 157 | macro_rules! config_ulpi_pins { |
| 173 | ($($pin:ident),*) => { | 158 | ($($pin:ident),*) => { |
| 174 | into_ref!($($pin),*); | 159 | into_ref!($($pin),*); |
| 175 | // NOTE(unsafe) Exclusive access to the registers | 160 | critical_section::with(|_| { |
| 176 | critical_section::with(|_| unsafe { | ||
| 177 | $( | 161 | $( |
| 178 | $pin.set_as_af($pin.af_num(), AFType::OutputPushPull); | 162 | $pin.set_as_af($pin.af_num(), AFType::OutputPushPull); |
| 179 | #[cfg(gpio_v2)] | 163 | #[cfg(gpio_v2)] |
| @@ -298,10 +282,8 @@ impl<'d, T: Instance> Driver<'d, T> { | |||
| 298 | ) -> Self { | 282 | ) -> Self { |
| 299 | into_ref!(dp, dm); | 283 | into_ref!(dp, dm); |
| 300 | 284 | ||
| 301 | unsafe { | 285 | dp.set_as_af(dp.af_num(), AFType::OutputPushPull); |
| 302 | dp.set_as_af(dp.af_num(), AFType::OutputPushPull); | 286 | dm.set_as_af(dm.af_num(), AFType::OutputPushPull); |
| 303 | dm.set_as_af(dm.af_num(), AFType::OutputPushPull); | ||
| 304 | } | ||
| 305 | 287 | ||
| 306 | Self { | 288 | Self { |
| 307 | phantom: PhantomData, | 289 | phantom: PhantomData, |
| @@ -508,18 +490,15 @@ pub struct Bus<'d, T: Instance> { | |||
| 508 | 490 | ||
| 509 | impl<'d, T: Instance> Bus<'d, T> { | 491 | impl<'d, T: Instance> Bus<'d, T> { |
| 510 | fn restore_irqs() { | 492 | fn restore_irqs() { |
| 511 | // SAFETY: atomic write | 493 | T::regs().gintmsk().write(|w| { |
| 512 | unsafe { | 494 | w.set_usbrst(true); |
| 513 | T::regs().gintmsk().write(|w| { | 495 | w.set_enumdnem(true); |
| 514 | w.set_usbrst(true); | 496 | w.set_usbsuspm(true); |
| 515 | w.set_enumdnem(true); | 497 | w.set_wuim(true); |
| 516 | w.set_usbsuspm(true); | 498 | w.set_iepint(true); |
| 517 | w.set_wuim(true); | 499 | w.set_oepint(true); |
| 518 | w.set_iepint(true); | 500 | w.set_rxflvlm(true); |
| 519 | w.set_oepint(true); | 501 | }); |
| 520 | w.set_rxflvlm(true); | ||
| 521 | }); | ||
| 522 | } | ||
| 523 | } | 502 | } |
| 524 | } | 503 | } |
| 525 | 504 | ||
| @@ -533,8 +512,7 @@ impl<'d, T: Instance> Bus<'d, T> { | |||
| 533 | let rx_fifo_size_words = RX_FIFO_EXTRA_SIZE_WORDS + ep_fifo_size(&self.ep_out); | 512 | let rx_fifo_size_words = RX_FIFO_EXTRA_SIZE_WORDS + ep_fifo_size(&self.ep_out); |
| 534 | trace!("configuring rx fifo size={}", rx_fifo_size_words); | 513 | trace!("configuring rx fifo size={}", rx_fifo_size_words); |
| 535 | 514 | ||
| 536 | // SAFETY: register is exclusive to `Bus` with `&mut self` | 515 | r.grxfsiz().modify(|w| w.set_rxfd(rx_fifo_size_words)); |
| 537 | unsafe { r.grxfsiz().modify(|w| w.set_rxfd(rx_fifo_size_words)) }; | ||
| 538 | 516 | ||
| 539 | // Configure TX (USB in direction) fifo size for each endpoint | 517 | // Configure TX (USB in direction) fifo size for each endpoint |
| 540 | let mut fifo_top = rx_fifo_size_words; | 518 | let mut fifo_top = rx_fifo_size_words; |
| @@ -549,13 +527,10 @@ impl<'d, T: Instance> Bus<'d, T> { | |||
| 549 | 527 | ||
| 550 | let dieptxf = if i == 0 { r.dieptxf0() } else { r.dieptxf(i - 1) }; | 528 | let dieptxf = if i == 0 { r.dieptxf0() } else { r.dieptxf(i - 1) }; |
| 551 | 529 | ||
| 552 | // SAFETY: register is exclusive to `Bus` with `&mut self` | 530 | dieptxf.write(|w| { |
| 553 | unsafe { | 531 | w.set_fd(ep.fifo_size_words); |
| 554 | dieptxf.write(|w| { | 532 | w.set_sa(fifo_top); |
| 555 | w.set_fd(ep.fifo_size_words); | 533 | }); |
| 556 | w.set_sa(fifo_top); | ||
| 557 | }); | ||
| 558 | } | ||
| 559 | 534 | ||
| 560 | fifo_top += ep.fifo_size_words; | 535 | fifo_top += ep.fifo_size_words; |
| 561 | } | 536 | } |
| @@ -575,8 +550,7 @@ impl<'d, T: Instance> Bus<'d, T> { | |||
| 575 | // Configure IN endpoints | 550 | // Configure IN endpoints |
| 576 | for (index, ep) in self.ep_in.iter().enumerate() { | 551 | for (index, ep) in self.ep_in.iter().enumerate() { |
| 577 | if let Some(ep) = ep { | 552 | if let Some(ep) = ep { |
| 578 | // SAFETY: DIEPCTL is shared with `Endpoint` so critical section is needed for RMW | 553 | critical_section::with(|_| { |
| 579 | critical_section::with(|_| unsafe { | ||
| 580 | r.diepctl(index).write(|w| { | 554 | r.diepctl(index).write(|w| { |
| 581 | if index == 0 { | 555 | if index == 0 { |
| 582 | w.set_mpsiz(ep0_mpsiz(ep.max_packet_size)); | 556 | w.set_mpsiz(ep0_mpsiz(ep.max_packet_size)); |
| @@ -593,8 +567,7 @@ impl<'d, T: Instance> Bus<'d, T> { | |||
| 593 | // Configure OUT endpoints | 567 | // Configure OUT endpoints |
| 594 | for (index, ep) in self.ep_out.iter().enumerate() { | 568 | for (index, ep) in self.ep_out.iter().enumerate() { |
| 595 | if let Some(ep) = ep { | 569 | if let Some(ep) = ep { |
| 596 | // SAFETY: DOEPCTL/DOEPTSIZ is shared with `Endpoint` so critical section is needed for RMW | 570 | critical_section::with(|_| { |
| 597 | critical_section::with(|_| unsafe { | ||
| 598 | r.doepctl(index).write(|w| { | 571 | r.doepctl(index).write(|w| { |
| 599 | if index == 0 { | 572 | if index == 0 { |
| 600 | w.set_mpsiz(ep0_mpsiz(ep.max_packet_size)); | 573 | w.set_mpsiz(ep0_mpsiz(ep.max_packet_size)); |
| @@ -618,14 +591,11 @@ impl<'d, T: Instance> Bus<'d, T> { | |||
| 618 | } | 591 | } |
| 619 | 592 | ||
| 620 | // Enable IRQs for allocated endpoints | 593 | // Enable IRQs for allocated endpoints |
| 621 | // SAFETY: register is exclusive to `Bus` with `&mut self` | 594 | r.daintmsk().modify(|w| { |
| 622 | unsafe { | 595 | w.set_iepm(ep_irq_mask(&self.ep_in)); |
| 623 | r.daintmsk().modify(|w| { | 596 | // OUT interrupts not used, handled in RXFLVL |
| 624 | w.set_iepm(ep_irq_mask(&self.ep_in)); | 597 | // w.set_oepm(ep_irq_mask(&self.ep_out)); |
| 625 | // OUT interrupts not used, handled in RXFLVL | 598 | }); |
| 626 | // w.set_oepm(ep_irq_mask(&self.ep_out)); | ||
| 627 | }); | ||
| 628 | } | ||
| 629 | } | 599 | } |
| 630 | 600 | ||
| 631 | fn disable(&mut self) { | 601 | fn disable(&mut self) { |
| @@ -634,10 +604,8 @@ impl<'d, T: Instance> Bus<'d, T> { | |||
| 634 | <T as RccPeripheral>::disable(); | 604 | <T as RccPeripheral>::disable(); |
| 635 | 605 | ||
| 636 | #[cfg(stm32l4)] | 606 | #[cfg(stm32l4)] |
| 637 | unsafe { | 607 | crate::pac::PWR.cr2().modify(|w| w.set_usv(false)); |
| 638 | crate::pac::PWR.cr2().modify(|w| w.set_usv(false)); | 608 | // Cannot disable PWR, because other peripherals might be using it |
| 639 | // Cannot disable PWR, because other peripherals might be using it | ||
| 640 | } | ||
| 641 | } | 609 | } |
| 642 | } | 610 | } |
| 643 | 611 | ||
| @@ -653,7 +621,7 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { | |||
| 653 | 621 | ||
| 654 | T::state().bus_waker.register(cx.waker()); | 622 | T::state().bus_waker.register(cx.waker()); |
| 655 | 623 | ||
| 656 | let ints = unsafe { r.gintsts().read() }; | 624 | let ints = r.gintsts().read(); |
| 657 | if ints.usbrst() { | 625 | if ints.usbrst() { |
| 658 | trace!("reset"); | 626 | trace!("reset"); |
| 659 | 627 | ||
| @@ -661,34 +629,27 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { | |||
| 661 | self.configure_endpoints(); | 629 | self.configure_endpoints(); |
| 662 | 630 | ||
| 663 | // Reset address | 631 | // Reset address |
| 664 | // SAFETY: DCFG is shared with `ControlPipe` so critical section is needed for RMW | 632 | critical_section::with(|_| { |
| 665 | critical_section::with(|_| unsafe { | ||
| 666 | r.dcfg().modify(|w| { | 633 | r.dcfg().modify(|w| { |
| 667 | w.set_dad(0); | 634 | w.set_dad(0); |
| 668 | }); | 635 | }); |
| 669 | }); | 636 | }); |
| 670 | 637 | ||
| 671 | // SAFETY: atomic clear on rc_w1 register | 638 | r.gintsts().write(|w| w.set_usbrst(true)); // clear |
| 672 | unsafe { r.gintsts().write(|w| w.set_usbrst(true)) }; // clear | ||
| 673 | Self::restore_irqs(); | 639 | Self::restore_irqs(); |
| 674 | } | 640 | } |
| 675 | 641 | ||
| 676 | if ints.enumdne() { | 642 | if ints.enumdne() { |
| 677 | trace!("enumdne"); | 643 | trace!("enumdne"); |
| 678 | 644 | ||
| 679 | // SAFETY: atomic read with no side effects | 645 | let speed = r.dsts().read().enumspd(); |
| 680 | let speed = unsafe { r.dsts().read().enumspd() }; | ||
| 681 | trace!(" speed={}", speed.0); | 646 | trace!(" speed={}", speed.0); |
| 682 | 647 | ||
| 683 | // SAFETY: register is only accessed by `Bus` under `&mut self` | 648 | r.gusbcfg().modify(|w| { |
| 684 | unsafe { | 649 | w.set_trdt(calculate_trdt(speed, T::frequency())); |
| 685 | r.gusbcfg().modify(|w| { | 650 | }); |
| 686 | w.set_trdt(calculate_trdt(speed, T::frequency())); | ||
| 687 | }) | ||
| 688 | }; | ||
| 689 | 651 | ||
| 690 | // SAFETY: atomic clear on rc_w1 register | 652 | r.gintsts().write(|w| w.set_enumdne(true)); // clear |
| 691 | unsafe { r.gintsts().write(|w| w.set_enumdne(true)) }; // clear | ||
| 692 | Self::restore_irqs(); | 653 | Self::restore_irqs(); |
| 693 | 654 | ||
| 694 | return Poll::Ready(Event::Reset); | 655 | return Poll::Ready(Event::Reset); |
| @@ -696,16 +657,14 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { | |||
| 696 | 657 | ||
| 697 | if ints.usbsusp() { | 658 | if ints.usbsusp() { |
| 698 | trace!("suspend"); | 659 | trace!("suspend"); |
| 699 | // SAFETY: atomic clear on rc_w1 register | 660 | r.gintsts().write(|w| w.set_usbsusp(true)); // clear |
| 700 | unsafe { r.gintsts().write(|w| w.set_usbsusp(true)) }; // clear | ||
| 701 | Self::restore_irqs(); | 661 | Self::restore_irqs(); |
| 702 | return Poll::Ready(Event::Suspend); | 662 | return Poll::Ready(Event::Suspend); |
| 703 | } | 663 | } |
| 704 | 664 | ||
| 705 | if ints.wkupint() { | 665 | if ints.wkupint() { |
| 706 | trace!("resume"); | 666 | trace!("resume"); |
| 707 | // SAFETY: atomic clear on rc_w1 register | 667 | r.gintsts().write(|w| w.set_wkupint(true)); // clear |
| 708 | unsafe { r.gintsts().write(|w| w.set_wkupint(true)) }; // clear | ||
| 709 | Self::restore_irqs(); | 668 | Self::restore_irqs(); |
| 710 | return Poll::Ready(Event::Resume); | 669 | return Poll::Ready(Event::Resume); |
| 711 | } | 670 | } |
| @@ -727,8 +686,7 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { | |||
| 727 | let regs = T::regs(); | 686 | let regs = T::regs(); |
| 728 | match ep_addr.direction() { | 687 | match ep_addr.direction() { |
| 729 | Direction::Out => { | 688 | Direction::Out => { |
| 730 | // SAFETY: DOEPCTL is shared with `Endpoint` so critical section is needed for RMW | 689 | critical_section::with(|_| { |
| 731 | critical_section::with(|_| unsafe { | ||
| 732 | regs.doepctl(ep_addr.index()).modify(|w| { | 690 | regs.doepctl(ep_addr.index()).modify(|w| { |
| 733 | w.set_stall(stalled); | 691 | w.set_stall(stalled); |
| 734 | }); | 692 | }); |
| @@ -737,8 +695,7 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { | |||
| 737 | T::state().ep_out_wakers[ep_addr.index()].wake(); | 695 | T::state().ep_out_wakers[ep_addr.index()].wake(); |
| 738 | } | 696 | } |
| 739 | Direction::In => { | 697 | Direction::In => { |
| 740 | // SAFETY: DIEPCTL is shared with `Endpoint` so critical section is needed for RMW | 698 | critical_section::with(|_| { |
| 741 | critical_section::with(|_| unsafe { | ||
| 742 | regs.diepctl(ep_addr.index()).modify(|w| { | 699 | regs.diepctl(ep_addr.index()).modify(|w| { |
| 743 | w.set_stall(stalled); | 700 | w.set_stall(stalled); |
| 744 | }); | 701 | }); |
| @@ -758,10 +715,9 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { | |||
| 758 | 715 | ||
| 759 | let regs = T::regs(); | 716 | let regs = T::regs(); |
| 760 | 717 | ||
| 761 | // SAFETY: atomic read with no side effects | ||
| 762 | match ep_addr.direction() { | 718 | match ep_addr.direction() { |
| 763 | Direction::Out => unsafe { regs.doepctl(ep_addr.index()).read().stall() }, | 719 | Direction::Out => regs.doepctl(ep_addr.index()).read().stall(), |
| 764 | Direction::In => unsafe { regs.diepctl(ep_addr.index()).read().stall() }, | 720 | Direction::In => regs.diepctl(ep_addr.index()).read().stall(), |
| 765 | } | 721 | } |
| 766 | } | 722 | } |
| 767 | 723 | ||
| @@ -777,8 +733,7 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { | |||
| 777 | let r = T::regs(); | 733 | let r = T::regs(); |
| 778 | match ep_addr.direction() { | 734 | match ep_addr.direction() { |
| 779 | Direction::Out => { | 735 | Direction::Out => { |
| 780 | // SAFETY: DOEPCTL is shared with `Endpoint` so critical section is needed for RMW | 736 | critical_section::with(|_| { |
| 781 | critical_section::with(|_| unsafe { | ||
| 782 | // cancel transfer if active | 737 | // cancel transfer if active |
| 783 | if !enabled && r.doepctl(ep_addr.index()).read().epena() { | 738 | if !enabled && r.doepctl(ep_addr.index()).read().epena() { |
| 784 | r.doepctl(ep_addr.index()).modify(|w| { | 739 | r.doepctl(ep_addr.index()).modify(|w| { |
| @@ -796,8 +751,7 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { | |||
| 796 | T::state().ep_out_wakers[ep_addr.index()].wake(); | 751 | T::state().ep_out_wakers[ep_addr.index()].wake(); |
| 797 | } | 752 | } |
| 798 | Direction::In => { | 753 | Direction::In => { |
| 799 | // SAFETY: DIEPCTL is shared with `Endpoint` so critical section is needed for RMW | 754 | critical_section::with(|_| { |
| 800 | critical_section::with(|_| unsafe { | ||
| 801 | // cancel transfer if active | 755 | // cancel transfer if active |
| 802 | if !enabled && r.diepctl(ep_addr.index()).read().epena() { | 756 | if !enabled && r.diepctl(ep_addr.index()).read().epena() { |
| 803 | r.diepctl(ep_addr.index()).modify(|w| { | 757 | r.diepctl(ep_addr.index()).modify(|w| { |
| @@ -820,195 +774,192 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { | |||
| 820 | async fn enable(&mut self) { | 774 | async fn enable(&mut self) { |
| 821 | trace!("enable"); | 775 | trace!("enable"); |
| 822 | 776 | ||
| 823 | // SAFETY: registers are only accessed by `Bus` under `&mut self` | 777 | #[cfg(stm32l4)] |
| 824 | unsafe { | 778 | { |
| 825 | #[cfg(stm32l4)] | 779 | crate::peripherals::PWR::enable(); |
| 826 | { | 780 | critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true))); |
| 827 | crate::peripherals::PWR::enable(); | 781 | } |
| 828 | critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true))); | ||
| 829 | } | ||
| 830 | 782 | ||
| 831 | #[cfg(stm32f7)] | 783 | #[cfg(stm32f7)] |
| 832 | { | 784 | { |
| 833 | // Enable ULPI clock if external PHY is used | 785 | // Enable ULPI clock if external PHY is used |
| 834 | let ulpien = !self.phy_type.internal(); | 786 | let ulpien = !self.phy_type.internal(); |
| 835 | critical_section::with(|_| { | 787 | critical_section::with(|_| { |
| 836 | crate::pac::RCC.ahb1enr().modify(|w| { | 788 | crate::pac::RCC.ahb1enr().modify(|w| { |
| 837 | if T::HIGH_SPEED { | 789 | if T::HIGH_SPEED { |
| 838 | w.set_usb_otg_hsulpien(ulpien); | 790 | w.set_usb_otg_hsulpien(ulpien); |
| 839 | } else { | 791 | } else { |
| 840 | w.set_usb_otg_hsen(ulpien); | 792 | w.set_usb_otg_hsen(ulpien); |
| 841 | } | 793 | } |
| 842 | }); | 794 | }); |
| 843 | 795 | ||
| 844 | // Low power mode | 796 | // Low power mode |
| 845 | crate::pac::RCC.ahb1lpenr().modify(|w| { | 797 | crate::pac::RCC.ahb1lpenr().modify(|w| { |
| 846 | if T::HIGH_SPEED { | 798 | if T::HIGH_SPEED { |
| 847 | w.set_usb_otg_hsulpilpen(ulpien); | 799 | w.set_usb_otg_hsulpilpen(ulpien); |
| 848 | } else { | 800 | } else { |
| 849 | w.set_usb_otg_hslpen(ulpien); | 801 | w.set_usb_otg_hslpen(ulpien); |
| 850 | } | 802 | } |
| 851 | }); | ||
| 852 | }); | 803 | }); |
| 853 | } | 804 | }); |
| 805 | } | ||
| 854 | 806 | ||
| 855 | #[cfg(stm32h7)] | 807 | #[cfg(stm32h7)] |
| 856 | { | 808 | { |
| 857 | // If true, VDD33USB is generated by internal regulator from VDD50USB | 809 | // If true, VDD33USB is generated by internal regulator from VDD50USB |
| 858 | // If false, VDD33USB and VDD50USB must be suplied directly with 3.3V (default on nucleo) | 810 | // If false, VDD33USB and VDD50USB must be suplied directly with 3.3V (default on nucleo) |
| 859 | // TODO: unhardcode | 811 | // TODO: unhardcode |
| 860 | let internal_regulator = false; | 812 | let internal_regulator = false; |
| 813 | |||
| 814 | // Enable USB power | ||
| 815 | critical_section::with(|_| { | ||
| 816 | crate::pac::PWR.cr3().modify(|w| { | ||
| 817 | w.set_usb33den(true); | ||
| 818 | w.set_usbregen(internal_regulator); | ||
| 819 | }) | ||
| 820 | }); | ||
| 861 | 821 | ||
| 862 | // Enable USB power | 822 | // Wait for USB power to stabilize |
| 863 | critical_section::with(|_| { | 823 | while !crate::pac::PWR.cr3().read().usb33rdy() {} |
| 864 | crate::pac::PWR.cr3().modify(|w| { | ||
| 865 | w.set_usb33den(true); | ||
| 866 | w.set_usbregen(internal_regulator); | ||
| 867 | }) | ||
| 868 | }); | ||
| 869 | 824 | ||
| 870 | // Wait for USB power to stabilize | 825 | // Use internal 48MHz HSI clock. Should be enabled in RCC by default. |
| 871 | while !crate::pac::PWR.cr3().read().usb33rdy() {} | 826 | critical_section::with(|_| { |
| 827 | crate::pac::RCC | ||
| 828 | .d2ccip2r() | ||
| 829 | .modify(|w| w.set_usbsel(crate::pac::rcc::vals::Usbsel::HSI48)) | ||
| 830 | }); | ||
| 872 | 831 | ||
| 873 | // Use internal 48MHz HSI clock. Should be enabled in RCC by default. | 832 | // Enable ULPI clock if external PHY is used |
| 874 | critical_section::with(|_| { | 833 | let ulpien = !self.phy_type.internal(); |
| 875 | crate::pac::RCC | 834 | critical_section::with(|_| { |
| 876 | .d2ccip2r() | 835 | crate::pac::RCC.ahb1enr().modify(|w| { |
| 877 | .modify(|w| w.set_usbsel(crate::pac::rcc::vals::Usbsel::HSI48)) | 836 | if T::HIGH_SPEED { |
| 837 | w.set_usb_otg_hs_ulpien(ulpien); | ||
| 838 | } else { | ||
| 839 | w.set_usb_otg_fs_ulpien(ulpien); | ||
| 840 | } | ||
| 878 | }); | 841 | }); |
| 879 | 842 | crate::pac::RCC.ahb1lpenr().modify(|w| { | |
| 880 | // Enable ULPI clock if external PHY is used | 843 | if T::HIGH_SPEED { |
| 881 | let ulpien = !self.phy_type.internal(); | 844 | w.set_usb_otg_hs_ulpilpen(ulpien); |
| 882 | critical_section::with(|_| { | 845 | } else { |
| 883 | crate::pac::RCC.ahb1enr().modify(|w| { | 846 | w.set_usb_otg_fs_ulpilpen(ulpien); |
| 884 | if T::HIGH_SPEED { | 847 | } |
| 885 | w.set_usb_otg_hs_ulpien(ulpien); | ||
| 886 | } else { | ||
| 887 | w.set_usb_otg_fs_ulpien(ulpien); | ||
| 888 | } | ||
| 889 | }); | ||
| 890 | crate::pac::RCC.ahb1lpenr().modify(|w| { | ||
| 891 | if T::HIGH_SPEED { | ||
| 892 | w.set_usb_otg_hs_ulpilpen(ulpien); | ||
| 893 | } else { | ||
| 894 | w.set_usb_otg_fs_ulpilpen(ulpien); | ||
| 895 | } | ||
| 896 | }); | ||
| 897 | }); | 848 | }); |
| 898 | } | 849 | }); |
| 850 | } | ||
| 899 | 851 | ||
| 900 | #[cfg(stm32u5)] | 852 | #[cfg(stm32u5)] |
| 901 | { | 853 | { |
| 902 | // Enable USB power | 854 | // Enable USB power |
| 903 | critical_section::with(|_| { | 855 | critical_section::with(|_| { |
| 904 | crate::pac::RCC.ahb3enr().modify(|w| { | 856 | crate::pac::RCC.ahb3enr().modify(|w| { |
| 905 | w.set_pwren(true); | 857 | w.set_pwren(true); |
| 906 | }); | 858 | }); |
| 907 | cortex_m::asm::delay(2); | 859 | cortex_m::asm::delay(2); |
| 908 | 860 | ||
| 909 | crate::pac::PWR.svmcr().modify(|w| { | 861 | crate::pac::PWR.svmcr().modify(|w| { |
| 910 | w.set_usv(true); | 862 | w.set_usv(true); |
| 911 | w.set_uvmen(true); | 863 | w.set_uvmen(true); |
| 912 | }); | ||
| 913 | }); | 864 | }); |
| 865 | }); | ||
| 914 | 866 | ||
| 915 | // Wait for USB power to stabilize | 867 | // Wait for USB power to stabilize |
| 916 | while !crate::pac::PWR.svmsr().read().vddusbrdy() {} | 868 | while !crate::pac::PWR.svmsr().read().vddusbrdy() {} |
| 917 | 869 | ||
| 918 | // Select HSI48 as USB clock source. | 870 | // Select HSI48 as USB clock source. |
| 919 | critical_section::with(|_| { | 871 | critical_section::with(|_| { |
| 920 | crate::pac::RCC.ccipr1().modify(|w| { | 872 | crate::pac::RCC.ccipr1().modify(|w| { |
| 921 | w.set_iclksel(crate::pac::rcc::vals::Iclksel::HSI48); | 873 | w.set_iclksel(crate::pac::rcc::vals::Iclksel::HSI48); |
| 922 | }) | 874 | }) |
| 923 | }); | 875 | }); |
| 924 | } | 876 | } |
| 925 | 877 | ||
| 926 | <T as RccPeripheral>::enable(); | 878 | <T as RccPeripheral>::enable(); |
| 927 | <T as RccPeripheral>::reset(); | 879 | <T as RccPeripheral>::reset(); |
| 928 | 880 | ||
| 929 | T::Interrupt::unpend(); | 881 | T::Interrupt::unpend(); |
| 930 | T::Interrupt::enable(); | 882 | unsafe { T::Interrupt::enable() }; |
| 931 | 883 | ||
| 932 | let r = T::regs(); | 884 | let r = T::regs(); |
| 933 | let core_id = r.cid().read().0; | 885 | let core_id = r.cid().read().0; |
| 934 | info!("Core id {:08x}", core_id); | 886 | info!("Core id {:08x}", core_id); |
| 935 | 887 | ||
| 936 | // Wait for AHB ready. | 888 | // Wait for AHB ready. |
| 937 | while !r.grstctl().read().ahbidl() {} | 889 | while !r.grstctl().read().ahbidl() {} |
| 938 | 890 | ||
| 939 | // Configure as device. | 891 | // Configure as device. |
| 940 | r.gusbcfg().write(|w| { | 892 | r.gusbcfg().write(|w| { |
| 941 | // Force device mode | 893 | // Force device mode |
| 942 | w.set_fdmod(true); | 894 | w.set_fdmod(true); |
| 943 | // Enable internal full-speed PHY | 895 | // Enable internal full-speed PHY |
| 944 | w.set_physel(self.phy_type.internal() && !self.phy_type.high_speed()); | 896 | w.set_physel(self.phy_type.internal() && !self.phy_type.high_speed()); |
| 945 | }); | 897 | }); |
| 946 | 898 | ||
| 947 | // Configuring Vbus sense and SOF output | 899 | // Configuring Vbus sense and SOF output |
| 948 | match core_id { | 900 | match core_id { |
| 949 | 0x0000_1200 | 0x0000_1100 => { | 901 | 0x0000_1200 | 0x0000_1100 => { |
| 950 | assert!(self.phy_type != PhyType::InternalHighSpeed); | 902 | assert!(self.phy_type != PhyType::InternalHighSpeed); |
| 951 | 903 | ||
| 952 | r.gccfg_v1().modify(|w| { | 904 | r.gccfg_v1().modify(|w| { |
| 953 | // Enable internal full-speed PHY, logic is inverted | 905 | // Enable internal full-speed PHY, logic is inverted |
| 954 | w.set_pwrdwn(self.phy_type.internal()); | 906 | w.set_pwrdwn(self.phy_type.internal()); |
| 955 | }); | 907 | }); |
| 956 | 908 | ||
| 957 | // F429-like chips have the GCCFG.NOVBUSSENS bit | 909 | // F429-like chips have the GCCFG.NOVBUSSENS bit |
| 958 | r.gccfg_v1().modify(|w| { | 910 | r.gccfg_v1().modify(|w| { |
| 959 | w.set_novbussens(true); | 911 | w.set_novbussens(true); |
| 960 | w.set_vbusasen(false); | 912 | w.set_vbusasen(false); |
| 961 | w.set_vbusbsen(false); | 913 | w.set_vbusbsen(false); |
| 962 | w.set_sofouten(false); | 914 | w.set_sofouten(false); |
| 963 | }); | 915 | }); |
| 964 | } | 916 | } |
| 965 | 0x0000_2000 | 0x0000_2100 | 0x0000_2300 | 0x0000_3000 | 0x0000_3100 => { | 917 | 0x0000_2000 | 0x0000_2100 | 0x0000_2300 | 0x0000_3000 | 0x0000_3100 => { |
| 966 | // F446-like chips have the GCCFG.VBDEN bit with the opposite meaning | 918 | // F446-like chips have the GCCFG.VBDEN bit with the opposite meaning |
| 967 | r.gccfg_v2().modify(|w| { | 919 | r.gccfg_v2().modify(|w| { |
| 968 | // Enable internal full-speed PHY, logic is inverted | 920 | // Enable internal full-speed PHY, logic is inverted |
| 969 | w.set_pwrdwn(self.phy_type.internal() && !self.phy_type.high_speed()); | 921 | w.set_pwrdwn(self.phy_type.internal() && !self.phy_type.high_speed()); |
| 970 | w.set_phyhsen(self.phy_type.internal() && self.phy_type.high_speed()); | 922 | w.set_phyhsen(self.phy_type.internal() && self.phy_type.high_speed()); |
| 971 | }); | 923 | }); |
| 972 | 924 | ||
| 973 | r.gccfg_v2().modify(|w| { | 925 | r.gccfg_v2().modify(|w| { |
| 974 | w.set_vbden(false); | 926 | w.set_vbden(false); |
| 975 | }); | 927 | }); |
| 976 | 928 | ||
| 977 | // Force B-peripheral session | 929 | // Force B-peripheral session |
| 978 | r.gotgctl().modify(|w| { | 930 | r.gotgctl().modify(|w| { |
| 979 | w.set_bvaloen(true); | 931 | w.set_bvaloen(true); |
| 980 | w.set_bvaloval(true); | 932 | w.set_bvaloval(true); |
| 981 | }); | 933 | }); |
| 982 | } | ||
| 983 | _ => unimplemented!("Unknown USB core id {:X}", core_id), | ||
| 984 | } | 934 | } |
| 935 | _ => unimplemented!("Unknown USB core id {:X}", core_id), | ||
| 936 | } | ||
| 985 | 937 | ||
| 986 | // Soft disconnect. | 938 | // Soft disconnect. |
| 987 | r.dctl().write(|w| w.set_sdis(true)); | 939 | r.dctl().write(|w| w.set_sdis(true)); |
| 988 | 940 | ||
| 989 | // Set speed. | 941 | // Set speed. |
| 990 | r.dcfg().write(|w| { | 942 | r.dcfg().write(|w| { |
| 991 | w.set_pfivl(vals::Pfivl::FRAME_INTERVAL_80); | 943 | w.set_pfivl(vals::Pfivl::FRAME_INTERVAL_80); |
| 992 | w.set_dspd(self.phy_type.to_dspd()); | 944 | w.set_dspd(self.phy_type.to_dspd()); |
| 993 | }); | 945 | }); |
| 994 | 946 | ||
| 995 | // Unmask transfer complete EP interrupt | 947 | // Unmask transfer complete EP interrupt |
| 996 | r.diepmsk().write(|w| { | 948 | r.diepmsk().write(|w| { |
| 997 | w.set_xfrcm(true); | 949 | w.set_xfrcm(true); |
| 998 | }); | 950 | }); |
| 999 | 951 | ||
| 1000 | // Unmask and clear core interrupts | 952 | // Unmask and clear core interrupts |
| 1001 | Bus::<T>::restore_irqs(); | 953 | Bus::<T>::restore_irqs(); |
| 1002 | r.gintsts().write_value(regs::Gintsts(0xFFFF_FFFF)); | 954 | r.gintsts().write_value(regs::Gintsts(0xFFFF_FFFF)); |
| 1003 | 955 | ||
| 1004 | // Unmask global interrupt | 956 | // Unmask global interrupt |
| 1005 | r.gahbcfg().write(|w| { | 957 | r.gahbcfg().write(|w| { |
| 1006 | w.set_gint(true); // unmask global interrupt | 958 | w.set_gint(true); // unmask global interrupt |
| 1007 | }); | 959 | }); |
| 1008 | 960 | ||
| 1009 | // Connect | 961 | // Connect |
| 1010 | r.dctl().write(|w| w.set_sdis(false)); | 962 | r.dctl().write(|w| w.set_sdis(false)); |
| 1011 | } | ||
| 1012 | 963 | ||
| 1013 | self.enabled = true; | 964 | self.enabled = true; |
| 1014 | } | 965 | } |
| @@ -1066,8 +1017,7 @@ impl<'d, T: Instance> embassy_usb_driver::Endpoint for Endpoint<'d, T, In> { | |||
| 1066 | 1017 | ||
| 1067 | T::state().ep_in_wakers[ep_index].register(cx.waker()); | 1018 | T::state().ep_in_wakers[ep_index].register(cx.waker()); |
| 1068 | 1019 | ||
| 1069 | // SAFETY: atomic read without side effects | 1020 | if T::regs().diepctl(ep_index).read().usbaep() { |
| 1070 | if unsafe { T::regs().diepctl(ep_index).read().usbaep() } { | ||
| 1071 | Poll::Ready(()) | 1021 | Poll::Ready(()) |
| 1072 | } else { | 1022 | } else { |
| 1073 | Poll::Pending | 1023 | Poll::Pending |
| @@ -1088,8 +1038,7 @@ impl<'d, T: Instance> embassy_usb_driver::Endpoint for Endpoint<'d, T, Out> { | |||
| 1088 | 1038 | ||
| 1089 | T::state().ep_out_wakers[ep_index].register(cx.waker()); | 1039 | T::state().ep_out_wakers[ep_index].register(cx.waker()); |
| 1090 | 1040 | ||
| 1091 | // SAFETY: atomic read without side effects | 1041 | if T::regs().doepctl(ep_index).read().usbaep() { |
| 1092 | if unsafe { T::regs().doepctl(ep_index).read().usbaep() } { | ||
| 1093 | Poll::Ready(()) | 1042 | Poll::Ready(()) |
| 1094 | } else { | 1043 | } else { |
| 1095 | Poll::Pending | 1044 | Poll::Pending |
| @@ -1124,8 +1073,7 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointOut for Endpoint<'d, T, Out> { | |||
| 1124 | // Release buffer | 1073 | // Release buffer |
| 1125 | state.ep_out_size[index].store(EP_OUT_BUFFER_EMPTY, Ordering::Release); | 1074 | state.ep_out_size[index].store(EP_OUT_BUFFER_EMPTY, Ordering::Release); |
| 1126 | 1075 | ||
| 1127 | // SAFETY: DOEPCTL/DOEPTSIZ is shared with `Bus` so a critical section is needed for RMW | 1076 | critical_section::with(|_| { |
| 1128 | critical_section::with(|_| unsafe { | ||
| 1129 | // Receive 1 packet | 1077 | // Receive 1 packet |
| 1130 | T::regs().doeptsiz(index).modify(|w| { | 1078 | T::regs().doeptsiz(index).modify(|w| { |
| 1131 | w.set_xfrsiz(self.info.max_packet_size as _); | 1079 | w.set_xfrsiz(self.info.max_packet_size as _); |
| @@ -1163,8 +1111,7 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> { | |||
| 1163 | poll_fn(|cx| { | 1111 | poll_fn(|cx| { |
| 1164 | state.ep_in_wakers[index].register(cx.waker()); | 1112 | state.ep_in_wakers[index].register(cx.waker()); |
| 1165 | 1113 | ||
| 1166 | // SAFETY: atomic read with no side effects | 1114 | let diepctl = r.diepctl(index).read(); |
| 1167 | let diepctl = unsafe { r.diepctl(index).read() }; | ||
| 1168 | if !diepctl.usbaep() { | 1115 | if !diepctl.usbaep() { |
| 1169 | Poll::Ready(Err(EndpointError::Disabled)) | 1116 | Poll::Ready(Err(EndpointError::Disabled)) |
| 1170 | } else if !diepctl.epena() { | 1117 | } else if !diepctl.epena() { |
| @@ -1181,12 +1128,10 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> { | |||
| 1181 | 1128 | ||
| 1182 | let size_words = (buf.len() + 3) / 4; | 1129 | let size_words = (buf.len() + 3) / 4; |
| 1183 | 1130 | ||
| 1184 | // SAFETY: atomic read with no side effects | 1131 | let fifo_space = r.dtxfsts(index).read().ineptfsav() as usize; |
| 1185 | let fifo_space = unsafe { r.dtxfsts(index).read().ineptfsav() as usize }; | ||
| 1186 | if size_words > fifo_space { | 1132 | if size_words > fifo_space { |
| 1187 | // Not enough space in fifo, enable tx fifo empty interrupt | 1133 | // Not enough space in fifo, enable tx fifo empty interrupt |
| 1188 | // SAFETY: DIEPEMPMSK is shared with IRQ so critical section is needed for RMW | 1134 | critical_section::with(|_| { |
| 1189 | critical_section::with(|_| unsafe { | ||
| 1190 | r.diepempmsk().modify(|w| { | 1135 | r.diepempmsk().modify(|w| { |
| 1191 | w.set_ineptxfem(w.ineptxfem() | (1 << index)); | 1136 | w.set_ineptxfem(w.ineptxfem() | (1 << index)); |
| 1192 | }); | 1137 | }); |
| @@ -1202,18 +1147,14 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> { | |||
| 1202 | .await | 1147 | .await |
| 1203 | } | 1148 | } |
| 1204 | 1149 | ||
| 1205 | // SAFETY: DIEPTSIZ is exclusive to this endpoint under `&mut self` | 1150 | // Setup transfer size |
| 1206 | unsafe { | 1151 | r.dieptsiz(index).write(|w| { |
| 1207 | // Setup transfer size | 1152 | w.set_mcnt(1); |
| 1208 | r.dieptsiz(index).write(|w| { | 1153 | w.set_pktcnt(1); |
| 1209 | w.set_mcnt(1); | 1154 | w.set_xfrsiz(buf.len() as _); |
| 1210 | w.set_pktcnt(1); | 1155 | }); |
| 1211 | w.set_xfrsiz(buf.len() as _); | ||
| 1212 | }); | ||
| 1213 | } | ||
| 1214 | 1156 | ||
| 1215 | // SAFETY: DIEPCTL is shared with `Bus` so a critical section is needed for RMW | 1157 | critical_section::with(|_| { |
| 1216 | critical_section::with(|_| unsafe { | ||
| 1217 | // Enable endpoint | 1158 | // Enable endpoint |
| 1218 | r.diepctl(index).modify(|w| { | 1159 | r.diepctl(index).modify(|w| { |
| 1219 | w.set_cnak(true); | 1160 | w.set_cnak(true); |
| @@ -1225,8 +1166,7 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> { | |||
| 1225 | for chunk in buf.chunks(4) { | 1166 | for chunk in buf.chunks(4) { |
| 1226 | let mut tmp = [0u8; 4]; | 1167 | let mut tmp = [0u8; 4]; |
| 1227 | tmp[0..chunk.len()].copy_from_slice(chunk); | 1168 | tmp[0..chunk.len()].copy_from_slice(chunk); |
| 1228 | // SAFETY: FIFO is exclusive to this endpoint under `&mut self` | 1169 | r.fifo(index).write_value(regs::Fifo(u32::from_ne_bytes(tmp))); |
| 1229 | unsafe { r.fifo(index).write_value(regs::Fifo(u32::from_ne_bytes(tmp))) }; | ||
| 1230 | } | 1170 | } |
| 1231 | 1171 | ||
| 1232 | trace!("write done ep={:?}", self.info.addr); | 1172 | trace!("write done ep={:?}", self.info.addr); |
| @@ -1258,17 +1198,15 @@ impl<'d, T: Instance> embassy_usb_driver::ControlPipe for ControlPipe<'d, T> { | |||
| 1258 | state.ep0_setup_ready.store(false, Ordering::Release); | 1198 | state.ep0_setup_ready.store(false, Ordering::Release); |
| 1259 | 1199 | ||
| 1260 | // EP0 should not be controlled by `Bus` so this RMW does not need a critical section | 1200 | // EP0 should not be controlled by `Bus` so this RMW does not need a critical section |
| 1261 | unsafe { | 1201 | // Receive 1 SETUP packet |
| 1262 | // Receive 1 SETUP packet | 1202 | T::regs().doeptsiz(self.ep_out.info.addr.index()).modify(|w| { |
| 1263 | T::regs().doeptsiz(self.ep_out.info.addr.index()).modify(|w| { | 1203 | w.set_rxdpid_stupcnt(1); |
| 1264 | w.set_rxdpid_stupcnt(1); | 1204 | }); |
| 1265 | }); | ||
| 1266 | 1205 | ||
| 1267 | // Clear NAK to indicate we are ready to receive more data | 1206 | // Clear NAK to indicate we are ready to receive more data |
| 1268 | T::regs().doepctl(self.ep_out.info.addr.index()).modify(|w| { | 1207 | T::regs().doepctl(self.ep_out.info.addr.index()).modify(|w| { |
| 1269 | w.set_cnak(true); | 1208 | w.set_cnak(true); |
| 1270 | }); | 1209 | }); |
| 1271 | } | ||
| 1272 | 1210 | ||
| 1273 | trace!("SETUP received: {:?}", data); | 1211 | trace!("SETUP received: {:?}", data); |
| 1274 | Poll::Ready(data) | 1212 | Poll::Ready(data) |
| @@ -1313,20 +1251,18 @@ impl<'d, T: Instance> embassy_usb_driver::ControlPipe for ControlPipe<'d, T> { | |||
| 1313 | trace!("control: reject"); | 1251 | trace!("control: reject"); |
| 1314 | 1252 | ||
| 1315 | // EP0 should not be controlled by `Bus` so this RMW does not need a critical section | 1253 | // EP0 should not be controlled by `Bus` so this RMW does not need a critical section |
| 1316 | unsafe { | 1254 | let regs = T::regs(); |
| 1317 | let regs = T::regs(); | 1255 | regs.diepctl(self.ep_in.info.addr.index()).modify(|w| { |
| 1318 | regs.diepctl(self.ep_in.info.addr.index()).modify(|w| { | 1256 | w.set_stall(true); |
| 1319 | w.set_stall(true); | 1257 | }); |
| 1320 | }); | 1258 | regs.doepctl(self.ep_out.info.addr.index()).modify(|w| { |
| 1321 | regs.doepctl(self.ep_out.info.addr.index()).modify(|w| { | 1259 | w.set_stall(true); |
| 1322 | w.set_stall(true); | 1260 | }); |
| 1323 | }); | ||
| 1324 | } | ||
| 1325 | } | 1261 | } |
| 1326 | 1262 | ||
| 1327 | async fn accept_set_address(&mut self, addr: u8) { | 1263 | async fn accept_set_address(&mut self, addr: u8) { |
| 1328 | trace!("setting addr: {}", addr); | 1264 | trace!("setting addr: {}", addr); |
| 1329 | critical_section::with(|_| unsafe { | 1265 | critical_section::with(|_| { |
| 1330 | T::regs().dcfg().modify(|w| { | 1266 | T::regs().dcfg().modify(|w| { |
| 1331 | w.set_dad(addr); | 1267 | w.set_dad(addr); |
| 1332 | }); | 1268 | }); |
diff --git a/embassy-stm32/src/wdg/mod.rs b/embassy-stm32/src/wdg/mod.rs index 18ebf97d8..5907a4e54 100644 --- a/embassy-stm32/src/wdg/mod.rs +++ b/embassy-stm32/src/wdg/mod.rs | |||
| @@ -48,11 +48,9 @@ impl<'d, T: Instance> IndependentWatchdog<'d, T> { | |||
| 48 | let rl = reload_value(psc, timeout_us); | 48 | let rl = reload_value(psc, timeout_us); |
| 49 | 49 | ||
| 50 | let wdg = T::regs(); | 50 | let wdg = T::regs(); |
| 51 | unsafe { | 51 | wdg.kr().write(|w| w.set_key(Key::ENABLE)); |
| 52 | wdg.kr().write(|w| w.set_key(Key::ENABLE)); | 52 | wdg.pr().write(|w| w.set_pr(Pr(pr))); |
| 53 | wdg.pr().write(|w| w.set_pr(Pr(pr))); | 53 | wdg.rlr().write(|w| w.set_rl(rl)); |
| 54 | wdg.rlr().write(|w| w.set_rl(rl)); | ||
| 55 | } | ||
| 56 | 54 | ||
| 57 | trace!( | 55 | trace!( |
| 58 | "Watchdog configured with {}us timeout, desired was {}us (PR={}, RL={})", | 56 | "Watchdog configured with {}us timeout, desired was {}us (PR={}, RL={})", |
| @@ -67,11 +65,11 @@ impl<'d, T: Instance> IndependentWatchdog<'d, T> { | |||
| 67 | } | 65 | } |
| 68 | } | 66 | } |
| 69 | 67 | ||
| 70 | pub unsafe fn unleash(&mut self) { | 68 | pub fn unleash(&mut self) { |
| 71 | T::regs().kr().write(|w| w.set_key(Key::START)); | 69 | T::regs().kr().write(|w| w.set_key(Key::START)); |
| 72 | } | 70 | } |
| 73 | 71 | ||
| 74 | pub unsafe fn pet(&mut self) { | 72 | pub fn pet(&mut self) { |
| 75 | T::regs().kr().write(|w| w.set_key(Key::RESET)); | 73 | T::regs().kr().write(|w| w.set_key(Key::RESET)); |
| 76 | } | 74 | } |
| 77 | } | 75 | } |
diff --git a/examples/stm32f0/src/bin/wdg.rs b/examples/stm32f0/src/bin/wdg.rs index 80e76f901..a44b17528 100644 --- a/examples/stm32f0/src/bin/wdg.rs +++ b/examples/stm32f0/src/bin/wdg.rs | |||
| @@ -16,10 +16,10 @@ async fn main(_spawner: Spawner) { | |||
| 16 | let mut wdg = IndependentWatchdog::new(p.IWDG, 20_000_00); | 16 | let mut wdg = IndependentWatchdog::new(p.IWDG, 20_000_00); |
| 17 | 17 | ||
| 18 | info!("Watchdog start"); | 18 | info!("Watchdog start"); |
| 19 | unsafe { wdg.unleash() }; | 19 | wdg.unleash(); |
| 20 | 20 | ||
| 21 | loop { | 21 | loop { |
| 22 | Timer::after(Duration::from_secs(1)).await; | 22 | Timer::after(Duration::from_secs(1)).await; |
| 23 | unsafe { wdg.pet() }; | 23 | wdg.pet(); |
| 24 | } | 24 | } |
| 25 | } | 25 | } |
diff --git a/examples/stm32f4/src/bin/wdt.rs b/examples/stm32f4/src/bin/wdt.rs index b2c587fa1..e5d122af7 100644 --- a/examples/stm32f4/src/bin/wdt.rs +++ b/examples/stm32f4/src/bin/wdt.rs | |||
| @@ -17,9 +17,7 @@ async fn main(_spawner: Spawner) { | |||
| 17 | let mut led = Output::new(p.PB7, Level::High, Speed::Low); | 17 | let mut led = Output::new(p.PB7, Level::High, Speed::Low); |
| 18 | 18 | ||
| 19 | let mut wdt = IndependentWatchdog::new(p.IWDG, 1_000_000); | 19 | let mut wdt = IndependentWatchdog::new(p.IWDG, 1_000_000); |
| 20 | unsafe { | 20 | wdt.unleash(); |
| 21 | wdt.unleash(); | ||
| 22 | } | ||
| 23 | 21 | ||
| 24 | let mut i = 0; | 22 | let mut i = 0; |
| 25 | 23 | ||
| @@ -36,9 +34,7 @@ async fn main(_spawner: Spawner) { | |||
| 36 | // MCU should restart in 1 second after the last pet. | 34 | // MCU should restart in 1 second after the last pet. |
| 37 | if i < 5 { | 35 | if i < 5 { |
| 38 | info!("Petting watchdog"); | 36 | info!("Petting watchdog"); |
| 39 | unsafe { | 37 | wdt.pet(); |
| 40 | wdt.pet(); | ||
| 41 | } | ||
| 42 | } | 38 | } |
| 43 | 39 | ||
| 44 | i += 1; | 40 | i += 1; |
diff --git a/examples/stm32g4/src/bin/usb_serial.rs b/examples/stm32g4/src/bin/usb_serial.rs index ecbe3a6e6..c111a9787 100644 --- a/examples/stm32g4/src/bin/usb_serial.rs +++ b/examples/stm32g4/src/bin/usb_serial.rs | |||
| @@ -38,9 +38,7 @@ async fn main(_spawner: Spawner) { | |||
| 38 | let p = embassy_stm32::init(config); | 38 | let p = embassy_stm32::init(config); |
| 39 | info!("Hello World!"); | 39 | info!("Hello World!"); |
| 40 | 40 | ||
| 41 | unsafe { | 41 | pac::RCC.ccipr().write(|w| w.set_clk48sel(0b10)); |
| 42 | pac::RCC.ccipr().write(|w| w.set_clk48sel(0b10)); | ||
| 43 | } | ||
| 44 | 42 | ||
| 45 | let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11); | 43 | let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11); |
| 46 | 44 | ||
diff --git a/examples/stm32h5/src/bin/usb_serial.rs b/examples/stm32h5/src/bin/usb_serial.rs index 3912327e2..336eed644 100644 --- a/examples/stm32h5/src/bin/usb_serial.rs +++ b/examples/stm32h5/src/bin/usb_serial.rs | |||
| @@ -45,11 +45,9 @@ async fn main(_spawner: Spawner) { | |||
| 45 | 45 | ||
| 46 | info!("Hello World!"); | 46 | info!("Hello World!"); |
| 47 | 47 | ||
| 48 | unsafe { | 48 | pac::RCC.ccipr4().write(|w| { |
| 49 | pac::RCC.ccipr4().write(|w| { | 49 | w.set_usbsel(pac::rcc::vals::Usbsel::HSI48); |
| 50 | w.set_usbsel(pac::rcc::vals::Usbsel::HSI48); | 50 | }); |
| 51 | }); | ||
| 52 | } | ||
| 53 | 51 | ||
| 54 | // Create the driver, from the HAL. | 52 | // Create the driver, from the HAL. |
| 55 | let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11); | 53 | let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11); |
diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs index 1972f8ff2..d360df085 100644 --- a/examples/stm32h7/src/bin/low_level_timer_api.rs +++ b/examples/stm32h7/src/bin/low_level_timer_api.rs | |||
| @@ -62,49 +62,39 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> { | |||
| 62 | T::enable(); | 62 | T::enable(); |
| 63 | <T as embassy_stm32::rcc::low_level::RccPeripheral>::reset(); | 63 | <T as embassy_stm32::rcc::low_level::RccPeripheral>::reset(); |
| 64 | 64 | ||
| 65 | unsafe { | 65 | ch1.set_speed(Speed::VeryHigh); |
| 66 | ch1.set_speed(Speed::VeryHigh); | 66 | ch1.set_as_af(ch1.af_num(), AFType::OutputPushPull); |
| 67 | ch1.set_as_af(ch1.af_num(), AFType::OutputPushPull); | 67 | ch2.set_speed(Speed::VeryHigh); |
| 68 | ch2.set_speed(Speed::VeryHigh); | 68 | ch2.set_as_af(ch1.af_num(), AFType::OutputPushPull); |
| 69 | ch2.set_as_af(ch1.af_num(), AFType::OutputPushPull); | 69 | ch3.set_speed(Speed::VeryHigh); |
| 70 | ch3.set_speed(Speed::VeryHigh); | 70 | ch3.set_as_af(ch1.af_num(), AFType::OutputPushPull); |
| 71 | ch3.set_as_af(ch1.af_num(), AFType::OutputPushPull); | 71 | ch4.set_speed(Speed::VeryHigh); |
| 72 | ch4.set_speed(Speed::VeryHigh); | 72 | ch4.set_as_af(ch1.af_num(), AFType::OutputPushPull); |
| 73 | ch4.set_as_af(ch1.af_num(), AFType::OutputPushPull); | ||
| 74 | } | ||
| 75 | 73 | ||
| 76 | let mut this = Self { inner: tim }; | 74 | let mut this = Self { inner: tim }; |
| 77 | 75 | ||
| 78 | this.set_freq(freq); | 76 | this.set_freq(freq); |
| 79 | this.inner.start(); | 77 | this.inner.start(); |
| 80 | 78 | ||
| 81 | unsafe { | 79 | let r = T::regs_gp32(); |
| 82 | T::regs_gp32() | 80 | r.ccmr_output(0) |
| 83 | .ccmr_output(0) | 81 | .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into())); |
| 84 | .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into())); | 82 | r.ccmr_output(0) |
| 85 | T::regs_gp32() | 83 | .modify(|w| w.set_ocm(1, OutputCompareMode::PwmMode1.into())); |
| 86 | .ccmr_output(0) | 84 | r.ccmr_output(1) |
| 87 | .modify(|w| w.set_ocm(1, OutputCompareMode::PwmMode1.into())); | 85 | .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into())); |
| 88 | T::regs_gp32() | 86 | r.ccmr_output(1) |
| 89 | .ccmr_output(1) | 87 | .modify(|w| w.set_ocm(1, OutputCompareMode::PwmMode1.into())); |
| 90 | .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into())); | 88 | |
| 91 | T::regs_gp32() | ||
| 92 | .ccmr_output(1) | ||
| 93 | .modify(|w| w.set_ocm(1, OutputCompareMode::PwmMode1.into())); | ||
| 94 | } | ||
| 95 | this | 89 | this |
| 96 | } | 90 | } |
| 97 | 91 | ||
| 98 | pub fn enable(&mut self, channel: Channel) { | 92 | pub fn enable(&mut self, channel: Channel) { |
| 99 | unsafe { | 93 | T::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), true)); |
| 100 | T::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), true)); | ||
| 101 | } | ||
| 102 | } | 94 | } |
| 103 | 95 | ||
| 104 | pub fn disable(&mut self, channel: Channel) { | 96 | pub fn disable(&mut self, channel: Channel) { |
| 105 | unsafe { | 97 | T::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), false)); |
| 106 | T::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), false)); | ||
| 107 | } | ||
| 108 | } | 98 | } |
| 109 | 99 | ||
| 110 | pub fn set_freq(&mut self, freq: Hertz) { | 100 | pub fn set_freq(&mut self, freq: Hertz) { |
| @@ -112,11 +102,11 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> { | |||
| 112 | } | 102 | } |
| 113 | 103 | ||
| 114 | pub fn get_max_duty(&self) -> u32 { | 104 | pub fn get_max_duty(&self) -> u32 { |
| 115 | unsafe { T::regs_gp32().arr().read().arr() } | 105 | T::regs_gp32().arr().read().arr() |
| 116 | } | 106 | } |
| 117 | 107 | ||
| 118 | pub fn set_duty(&mut self, channel: Channel, duty: u32) { | 108 | pub fn set_duty(&mut self, channel: Channel, duty: u32) { |
| 119 | defmt::assert!(duty < self.get_max_duty()); | 109 | defmt::assert!(duty < self.get_max_duty()); |
| 120 | unsafe { T::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(duty)) } | 110 | T::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(duty)) |
| 121 | } | 111 | } |
| 122 | } | 112 | } |
diff --git a/examples/stm32h7/src/bin/wdg.rs b/examples/stm32h7/src/bin/wdg.rs index 2b0301aad..9181dfd67 100644 --- a/examples/stm32h7/src/bin/wdg.rs +++ b/examples/stm32h7/src/bin/wdg.rs | |||
| @@ -15,10 +15,10 @@ async fn main(_spawner: Spawner) { | |||
| 15 | 15 | ||
| 16 | let mut wdg = IndependentWatchdog::new(p.IWDG1, 20_000_000); | 16 | let mut wdg = IndependentWatchdog::new(p.IWDG1, 20_000_000); |
| 17 | 17 | ||
| 18 | unsafe { wdg.unleash() }; | 18 | wdg.unleash(); |
| 19 | 19 | ||
| 20 | loop { | 20 | loop { |
| 21 | Timer::after(Duration::from_secs(1)).await; | 21 | Timer::after(Duration::from_secs(1)).await; |
| 22 | unsafe { wdg.pet() }; | 22 | wdg.pet(); |
| 23 | } | 23 | } |
| 24 | } | 24 | } |
diff --git a/examples/stm32l4/src/bin/adc.rs b/examples/stm32l4/src/bin/adc.rs index 281346e5f..1771e5202 100644 --- a/examples/stm32l4/src/bin/adc.rs +++ b/examples/stm32l4/src/bin/adc.rs | |||
| @@ -12,12 +12,10 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 12 | fn main() -> ! { | 12 | fn main() -> ! { |
| 13 | info!("Hello World!"); | 13 | info!("Hello World!"); |
| 14 | 14 | ||
| 15 | unsafe { | 15 | pac::RCC.ccipr().modify(|w| { |
| 16 | pac::RCC.ccipr().modify(|w| { | 16 | w.set_adcsel(0b11); |
| 17 | w.set_adcsel(0b11); | 17 | }); |
| 18 | }); | 18 | pac::RCC.ahb2enr().modify(|w| w.set_adcen(true)); |
| 19 | pac::RCC.ahb2enr().modify(|w| w.set_adcen(true)); | ||
| 20 | } | ||
| 21 | 19 | ||
| 22 | let p = embassy_stm32::init(Default::default()); | 20 | let p = embassy_stm32::init(Default::default()); |
| 23 | 21 | ||
diff --git a/examples/stm32l4/src/bin/dac.rs b/examples/stm32l4/src/bin/dac.rs index d6e744aa6..a36ed5d90 100644 --- a/examples/stm32l4/src/bin/dac.rs +++ b/examples/stm32l4/src/bin/dac.rs | |||
| @@ -11,11 +11,9 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 11 | fn main() -> ! { | 11 | fn main() -> ! { |
| 12 | info!("Hello World!"); | 12 | info!("Hello World!"); |
| 13 | 13 | ||
| 14 | unsafe { | 14 | pac::RCC.apb1enr1().modify(|w| { |
| 15 | pac::RCC.apb1enr1().modify(|w| { | 15 | w.set_dac1en(true); |
| 16 | w.set_dac1en(true); | 16 | }); |
| 17 | }); | ||
| 18 | } | ||
| 19 | 17 | ||
| 20 | let p = embassy_stm32::init(Default::default()); | 18 | let p = embassy_stm32::init(Default::default()); |
| 21 | 19 | ||
diff --git a/examples/stm32wl/src/bin/lora_lorawan.rs b/examples/stm32wl/src/bin/lora_lorawan.rs index e179c5ca1..805d21418 100644 --- a/examples/stm32wl/src/bin/lora_lorawan.rs +++ b/examples/stm32wl/src/bin/lora_lorawan.rs | |||
| @@ -35,7 +35,7 @@ async fn main(_spawner: Spawner) { | |||
| 35 | config.rcc.enable_lsi = true; // enable RNG | 35 | config.rcc.enable_lsi = true; // enable RNG |
| 36 | let p = embassy_stm32::init(config); | 36 | let p = embassy_stm32::init(config); |
| 37 | 37 | ||
| 38 | unsafe { pac::RCC.ccipr().modify(|w| w.set_rngsel(0b01)) } | 38 | pac::RCC.ccipr().modify(|w| w.set_rngsel(0b01)); |
| 39 | 39 | ||
| 40 | let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2); | 40 | let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2); |
| 41 | 41 | ||
diff --git a/examples/stm32wl/src/bin/random.rs b/examples/stm32wl/src/bin/random.rs index 182c607f9..d8562fca5 100644 --- a/examples/stm32wl/src/bin/random.rs +++ b/examples/stm32wl/src/bin/random.rs | |||
| @@ -15,11 +15,9 @@ async fn main(_spawner: Spawner) { | |||
| 15 | config.rcc.enable_lsi = true; //Needed for RNG to work | 15 | config.rcc.enable_lsi = true; //Needed for RNG to work |
| 16 | 16 | ||
| 17 | let p = embassy_stm32::init(config); | 17 | let p = embassy_stm32::init(config); |
| 18 | unsafe { | 18 | pac::RCC.ccipr().modify(|w| { |
| 19 | pac::RCC.ccipr().modify(|w| { | 19 | w.set_rngsel(0b01); |
| 20 | w.set_rngsel(0b01); | 20 | }); |
| 21 | }); | ||
| 22 | } | ||
| 23 | 21 | ||
| 24 | info!("Hello World!"); | 22 | info!("Hello World!"); |
| 25 | 23 | ||
diff --git a/tests/stm32/src/bin/rtc.rs b/tests/stm32/src/bin/rtc.rs index 32d35c42c..582df5753 100644 --- a/tests/stm32/src/bin/rtc.rs +++ b/tests/stm32/src/bin/rtc.rs | |||
| @@ -24,10 +24,8 @@ async fn main(_spawner: Spawner) { | |||
| 24 | 24 | ||
| 25 | info!("Starting LSI"); | 25 | info!("Starting LSI"); |
| 26 | 26 | ||
| 27 | unsafe { | 27 | pac::RCC.csr().modify(|w| w.set_lsion(true)); |
| 28 | pac::RCC.csr().modify(|w| w.set_lsion(true)); | 28 | while !pac::RCC.csr().read().lsirdy() {} |
| 29 | while !pac::RCC.csr().read().lsirdy() {} | ||
| 30 | } | ||
| 31 | 29 | ||
| 32 | info!("Started LSI"); | 30 | info!("Started LSI"); |
| 33 | 31 | ||
