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 743d0c34..aecba075 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() -> ! { let led = Output::new(p.PB14, Level::Low, Speed::Low); let mut button = Input::new(p.PC13, Pull::Up); - cortex_m::interrupt::free(|cs| unsafe { + cortex_m::interrupt::free(|cs| { enable_interrupt(&mut button); LED.borrow(cs).borrow_mut().replace(led); BUTTON.borrow(cs).borrow_mut().replace(button); - NVIC::unmask(pac::Interrupt::EXTI15_10); + unsafe { NVIC::unmask(pac::Interrupt::EXTI15_10) }; }); loop { @@ -64,25 +64,21 @@ const PORT: u8 = 2; const PIN: usize = 13; fn check_interrupt(_pin: &mut Input<'static, P>) -> bool { let exti = pac::EXTI; - unsafe { - let pin = PIN; - let lines = exti.pr(0).read(); - lines.line(pin) - } + let pin = PIN; + let lines = exti.pr(0).read(); + lines.line(pin) } fn clear_interrupt(_pin: &mut Input<'static, P>) { let exti = pac::EXTI; - unsafe { - let pin = PIN; - let mut lines = exti.pr(0).read(); - lines.set_line(pin, true); - exti.pr(0).write_value(lines); - } + let pin = PIN; + let mut lines = exti.pr(0).read(); + lines.set_line(pin, true); + exti.pr(0).write_value(lines); } fn enable_interrupt(_pin: &mut Input<'static, P>) { - cortex_m::interrupt::free(|_| unsafe { + cortex_m::interrupt::free(|_| { let rcc = pac::RCC; rcc.apb2enr().modify(|w| w.set_syscfgen(true)); diff --git a/embassy-lora/src/iv.rs b/embassy-lora/src/iv.rs index 2e0b68d1..136973fe 100644 --- a/embassy-lora/src/iv.rs +++ b/embassy-lora/src/iv.rs @@ -68,29 +68,23 @@ where } async fn set_nss_low(&mut self) -> Result<(), RadioError> { let pwr = pac::PWR; - unsafe { - pwr.subghzspicr().modify(|w| w.set_nss(pac::pwr::vals::Nss::LOW)); - } + pwr.subghzspicr().modify(|w| w.set_nss(pac::pwr::vals::Nss::LOW)); Ok(()) } async fn set_nss_high(&mut self) -> Result<(), RadioError> { let pwr = pac::PWR; - unsafe { - pwr.subghzspicr().modify(|w| w.set_nss(pac::pwr::vals::Nss::HIGH)); - } + pwr.subghzspicr().modify(|w| w.set_nss(pac::pwr::vals::Nss::HIGH)); Ok(()) } async fn reset(&mut self, _delay: &mut impl DelayUs) -> Result<(), RadioError> { let rcc = pac::RCC; - unsafe { - rcc.csr().modify(|w| w.set_rfrst(true)); - rcc.csr().modify(|w| w.set_rfrst(false)); - } + rcc.csr().modify(|w| w.set_rfrst(true)); + rcc.csr().modify(|w| w.set_rfrst(false)); Ok(()) } async fn wait_on_busy(&mut self) -> Result<(), RadioError> { let pwr = pac::PWR; - while unsafe { pwr.sr2().read().rfbusys() == pac::pwr::vals::Rfbusys::BUSY } {} + while pwr.sr2().read().rfbusys() == pac::pwr::vals::Rfbusys::BUSY {} Ok(()) } diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index f876c714..3d9ee826 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -57,7 +57,7 @@ sdio-host = "0.5.0" embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } critical-section = "1.1" atomic-polyfill = "1.0.1" -stm32-metapac = "9" +stm32-metapac = "10" vcell = "0.1.3" bxcan = "0.7.0" nb = "1.0.0" @@ -74,7 +74,7 @@ critical-section = { version = "1.1", features = ["std"] } [build-dependencies] proc-macro2 = "1.0.36" quote = "1.0.15" -stm32-metapac = { version = "9", default-features = false, features = ["metadata"]} +stm32-metapac = { version = "10", default-features = false, features = ["metadata"]} [features] default = ["rt"] diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 9e597f18..f71074bc 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -322,7 +322,7 @@ fn main() { let rst_reg = format_ident!("{}", rst.register.to_ascii_lowercase()); let set_rst_field = format_ident!("set_{}", rst.field.to_ascii_lowercase()); quote! { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(true)); crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(false)); }); @@ -353,13 +353,13 @@ fn main() { }) } fn enable() { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); #after_enable }) } fn disable() { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); }) } diff --git a/embassy-stm32/src/adc/f1.rs b/embassy-stm32/src/adc/f1.rs index d30ec001..2322204d 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> { into_ref!(adc); T::enable(); T::reset(); - unsafe { - T::regs().cr2().modify(|reg| reg.set_adon(true)); - } + T::regs().cr2().modify(|reg| reg.set_adon(true)); // 11.4: Before starting a calibration, the ADC must have been in power-on state (ADON bit = ‘1’) // for at least two ADC clock cycles delay.delay_us((1_000_000 * 2) / Self::freq().0 + 1); - unsafe { - // Reset calibration - T::regs().cr2().modify(|reg| reg.set_rstcal(true)); - while T::regs().cr2().read().rstcal() { - // spin - } + // Reset calibration + T::regs().cr2().modify(|reg| reg.set_rstcal(true)); + while T::regs().cr2().read().rstcal() { + // spin + } - // Calibrate - T::regs().cr2().modify(|reg| reg.set_cal(true)); - while T::regs().cr2().read().cal() { - // spin - } + // Calibrate + T::regs().cr2().modify(|reg| reg.set_cal(true)); + while T::regs().cr2().read().cal() { + // spin } // One cycle after calibration @@ -81,20 +77,16 @@ impl<'d, T: Instance> Adc<'d, T> { } pub fn enable_vref(&self, _delay: &mut impl DelayUs) -> Vref { - unsafe { - T::regs().cr2().modify(|reg| { - reg.set_tsvrefe(true); - }) - } + T::regs().cr2().modify(|reg| { + reg.set_tsvrefe(true); + }); Vref {} } pub fn enable_temperature(&self) -> Temperature { - unsafe { - T::regs().cr2().modify(|reg| { - reg.set_tsvrefe(true); - }) - } + T::regs().cr2().modify(|reg| { + reg.set_tsvrefe(true); + }); Temperature {} } @@ -104,41 +96,37 @@ impl<'d, T: Instance> Adc<'d, T> { /// Perform a single conversion. fn convert(&mut self) -> u16 { - unsafe { - T::regs().cr2().modify(|reg| { - reg.set_adon(true); - reg.set_swstart(true); - }); - while T::regs().cr2().read().swstart() {} - while !T::regs().sr().read().eoc() {} + T::regs().cr2().modify(|reg| { + reg.set_adon(true); + reg.set_swstart(true); + }); + while T::regs().cr2().read().swstart() {} + while !T::regs().sr().read().eoc() {} - T::regs().dr().read().0 as u16 - } + T::regs().dr().read().0 as u16 } pub fn read(&mut self, pin: &mut impl AdcPin) -> u16 { - unsafe { - Self::set_channel_sample_time(pin.channel(), self.sample_time); - T::regs().cr1().modify(|reg| { - reg.set_scan(false); - reg.set_discen(false); - }); - T::regs().sqr1().modify(|reg| reg.set_l(0)); + Self::set_channel_sample_time(pin.channel(), self.sample_time); + T::regs().cr1().modify(|reg| { + reg.set_scan(false); + reg.set_discen(false); + }); + T::regs().sqr1().modify(|reg| reg.set_l(0)); - T::regs().cr2().modify(|reg| { - reg.set_cont(false); - reg.set_exttrig(true); - reg.set_swstart(false); - reg.set_extsel(crate::pac::adc::vals::Extsel::SWSTART); - }); - } + T::regs().cr2().modify(|reg| { + reg.set_cont(false); + reg.set_exttrig(true); + reg.set_swstart(false); + reg.set_extsel(crate::pac::adc::vals::Extsel::SWSTART); + }); // Configure the channel to sample - unsafe { T::regs().sqr3().write(|reg| reg.set_sq(0, pin.channel())) } + T::regs().sqr3().write(|reg| reg.set_sq(0, pin.channel())); self.convert() } - unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { + fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { let sample_time = sample_time.into(); if ch <= 9 { 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 82a8c3ef..d9af0c55 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> { // // 6.3.20 Vbat monitoring characteristics // ts_vbat ≥ 4μs - unsafe { - T::regs().ccr().modify(|reg| reg.set_vbaten(true)); - } + T::regs().ccr().modify(|reg| reg.set_vbaten(true)); Vbat } pub fn enable_vref(&self, delay: &mut impl DelayUs) -> Vref { // Table 28. Embedded internal reference voltage // tstart = 10μs - unsafe { - T::regs().ccr().modify(|reg| reg.set_vrefen(true)); - } + T::regs().ccr().modify(|reg| reg.set_vrefen(true)); delay.delay_us(10); Vref } @@ -79,27 +75,23 @@ impl<'d, T: Instance> Adc<'d, T> { // 6.3.19 Temperature sensor characteristics // tstart ≤ 10μs // ts_temp ≥ 4μs - unsafe { - T::regs().ccr().modify(|reg| reg.set_tsen(true)); - } + T::regs().ccr().modify(|reg| reg.set_tsen(true)); delay.delay_us(10); Temperature } fn calibrate(&self) { - unsafe { - // A.7.1 ADC calibration code example - if T::regs().cr().read().aden() { - T::regs().cr().modify(|reg| reg.set_addis(true)); - } - while T::regs().cr().read().aden() { - // spin - } - T::regs().cfgr1().modify(|reg| reg.set_dmaen(false)); - T::regs().cr().modify(|reg| reg.set_adcal(true)); - while T::regs().cr().read().adcal() { - // spin - } + // A.7.1 ADC calibration code example + if T::regs().cr().read().aden() { + T::regs().cr().modify(|reg| reg.set_addis(true)); + } + while T::regs().cr().read().aden() { + // spin + } + T::regs().cfgr1().modify(|reg| reg.set_dmaen(false)); + T::regs().cr().modify(|reg| reg.set_adcal(true)); + while T::regs().cr().read().adcal() { + // spin } } @@ -108,9 +100,7 @@ impl<'d, T: Instance> Adc<'d, T> { } pub fn set_resolution(&mut self, resolution: Resolution) { - unsafe { - T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into())); - } + T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into())); } pub fn read

(&mut self, pin: &mut P) -> u16 @@ -118,18 +108,16 @@ impl<'d, T: Instance> Adc<'d, T> { P: AdcPin + crate::gpio::sealed::Pin, { let channel = pin.channel(); - unsafe { - pin.set_as_analog(); - self.read_channel(channel) - } + pin.set_as_analog(); + self.read_channel(channel) } pub fn read_internal(&mut self, channel: &mut impl InternalChannel) -> u16 { let channel = channel.channel(); - unsafe { self.read_channel(channel) } + self.read_channel(channel) } - unsafe fn read_channel(&mut self, channel: u8) -> u16 { + fn read_channel(&mut self, channel: u8) -> u16 { // A.7.2 ADC enable sequence code example if T::regs().isr().read().adrdy() { 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 11a51f99..091c1d44 100644 --- a/embassy-stm32/src/adc/v2.rs +++ b/embassy-stm32/src/adc/v2.rs @@ -100,13 +100,10 @@ where T::reset(); let presc = Prescaler::from_pclk2(T::frequency()); - unsafe { - T::common_regs().ccr().modify(|w| w.set_adcpre(presc.adcpre())); - - T::regs().cr2().modify(|reg| { - reg.set_adon(crate::pac::adc::vals::Adon::ENABLED); - }); - } + T::common_regs().ccr().modify(|w| w.set_adcpre(presc.adcpre())); + T::regs().cr2().modify(|reg| { + reg.set_adon(crate::pac::adc::vals::Adon::ENABLED); + }); delay.delay_us(ADC_POWERUP_TIME_US); @@ -121,19 +118,15 @@ where } pub fn set_resolution(&mut self, resolution: Resolution) { - unsafe { - T::regs().cr1().modify(|reg| reg.set_res(resolution.into())); - } + T::regs().cr1().modify(|reg| reg.set_res(resolution.into())); } /// Enables internal voltage reference and returns [VrefInt], which can be used in /// [Adc::read_internal()] to perform conversion. pub fn enable_vrefint(&self) -> VrefInt { - unsafe { - T::common_regs().ccr().modify(|reg| { - reg.set_tsvrefe(crate::pac::adccommon::vals::Tsvrefe::ENABLED); - }); - } + T::common_regs().ccr().modify(|reg| { + reg.set_tsvrefe(crate::pac::adccommon::vals::Tsvrefe::ENABLED); + }); VrefInt {} } @@ -144,11 +137,9 @@ where /// On STM32F42 and STM32F43 this can not be used together with [Vbat]. If both are enabled, /// temperature sensor will return vbat value. pub fn enable_temperature(&self) -> Temperature { - unsafe { - T::common_regs().ccr().modify(|reg| { - reg.set_tsvrefe(crate::pac::adccommon::vals::Tsvrefe::ENABLED); - }); - } + T::common_regs().ccr().modify(|reg| { + reg.set_tsvrefe(crate::pac::adccommon::vals::Tsvrefe::ENABLED); + }); Temperature {} } @@ -156,37 +147,33 @@ where /// Enables vbat input and returns [Vbat], which can be used in /// [Adc::read_internal()] to perform conversion. pub fn enable_vbat(&self) -> Vbat { - unsafe { - T::common_regs().ccr().modify(|reg| { - reg.set_vbate(crate::pac::adccommon::vals::Vbate::ENABLED); - }); - } + T::common_regs().ccr().modify(|reg| { + reg.set_vbate(crate::pac::adccommon::vals::Vbate::ENABLED); + }); Vbat {} } /// Perform a single conversion. fn convert(&mut self) -> u16 { - unsafe { - // clear end of conversion flag - T::regs().sr().modify(|reg| { - reg.set_eoc(crate::pac::adc::vals::Eoc::NOTCOMPLETE); - }); + // clear end of conversion flag + T::regs().sr().modify(|reg| { + reg.set_eoc(crate::pac::adc::vals::Eoc::NOTCOMPLETE); + }); - // Start conversion - T::regs().cr2().modify(|reg| { - reg.set_swstart(true); - }); + // Start conversion + T::regs().cr2().modify(|reg| { + reg.set_swstart(true); + }); - while T::regs().sr().read().strt() == crate::pac::adc::vals::Strt::NOTSTARTED { - // spin //wait for actual start - } - while T::regs().sr().read().eoc() == crate::pac::adc::vals::Eoc::NOTCOMPLETE { - // spin //wait for finish - } - - T::regs().dr().read().0 as u16 + while T::regs().sr().read().strt() == crate::pac::adc::vals::Strt::NOTSTARTED { + // spin //wait for actual start } + while T::regs().sr().read().eoc() == crate::pac::adc::vals::Eoc::NOTCOMPLETE { + // spin //wait for finish + } + + T::regs().dr().read().0 as u16 } pub fn read

(&mut self, pin: &mut P) -> u16 @@ -194,18 +181,16 @@ where P: AdcPin, P: crate::gpio::sealed::Pin, { - unsafe { - pin.set_as_analog(); + pin.set_as_analog(); - self.read_channel(pin.channel()) - } + self.read_channel(pin.channel()) } pub fn read_internal(&mut self, channel: &mut impl InternalChannel) -> u16 { - unsafe { self.read_channel(channel.channel()) } + self.read_channel(channel.channel()) } - unsafe fn read_channel(&mut self, channel: u8) -> u16 { + fn read_channel(&mut self, channel: u8) -> u16 { // Configure ADC // Select channel @@ -219,7 +204,7 @@ where val } - unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { + fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { let sample_time = sample_time.into(); if ch <= 9 { 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 90aa7d3b..94cdc86c 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; /// Sadly we cannot use `RccPeripheral::enable` since devices are quite inconsistent ADC clock /// configuration. fn enable() { - critical_section::with(|_| unsafe { + critical_section::with(|_| { #[cfg(stm32h7)] crate::pac::RCC.apb2enr().modify(|w| w.set_adcen(true)); #[cfg(stm32g0)] @@ -62,29 +62,25 @@ impl<'d, T: Instance> Adc<'d, T> { pub fn new(adc: impl Peripheral

+ 'd, delay: &mut impl DelayUs) -> Self { into_ref!(adc); enable(); - unsafe { - T::regs().cr().modify(|reg| { - #[cfg(not(adc_g0))] - reg.set_deeppwd(false); - reg.set_advregen(true); - }); + T::regs().cr().modify(|reg| { + #[cfg(not(adc_g0))] + reg.set_deeppwd(false); + reg.set_advregen(true); + }); - #[cfg(adc_g0)] - T::regs().cfgr1().modify(|reg| { - reg.set_chselrmod(false); - }); - } + #[cfg(adc_g0)] + T::regs().cfgr1().modify(|reg| { + reg.set_chselrmod(false); + }); delay.delay_us(20); - unsafe { - T::regs().cr().modify(|reg| { - reg.set_adcal(true); - }); + T::regs().cr().modify(|reg| { + reg.set_adcal(true); + }); - while T::regs().cr().read().adcal() { - // spin - } + while T::regs().cr().read().adcal() { + // spin } delay.delay_us(1); @@ -96,11 +92,9 @@ impl<'d, T: Instance> Adc<'d, T> { } pub fn enable_vrefint(&self, delay: &mut impl DelayUs) -> VrefInt { - unsafe { - T::common_regs().ccr().modify(|reg| { - reg.set_vrefen(true); - }); - } + T::common_regs().ccr().modify(|reg| { + reg.set_vrefen(true); + }); // "Table 24. Embedded internal voltage reference" states that it takes a maximum of 12 us // to stabilize the internal voltage reference, we wait a little more. @@ -112,21 +106,17 @@ impl<'d, T: Instance> Adc<'d, T> { } pub fn enable_temperature(&self) -> Temperature { - unsafe { - T::common_regs().ccr().modify(|reg| { - reg.set_ch17sel(true); - }); - } + T::common_regs().ccr().modify(|reg| { + reg.set_ch17sel(true); + }); Temperature {} } pub fn enable_vbat(&self) -> Vbat { - unsafe { - T::common_regs().ccr().modify(|reg| { - reg.set_ch18sel(true); - }); - } + T::common_regs().ccr().modify(|reg| { + reg.set_ch18sel(true); + }); Vbat {} } @@ -136,12 +126,10 @@ impl<'d, T: Instance> Adc<'d, T> { } pub fn set_resolution(&mut self, resolution: Resolution) { - unsafe { - #[cfg(not(stm32g0))] - T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); - #[cfg(stm32g0)] - T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into())); - } + #[cfg(not(stm32g0))] + T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); + #[cfg(stm32g0)] + T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into())); } /* @@ -155,77 +143,73 @@ impl<'d, T: Instance> Adc<'d, T> { /// Perform a single conversion. fn convert(&mut self) -> u16 { - unsafe { - T::regs().isr().modify(|reg| { - reg.set_eos(true); - reg.set_eoc(true); - }); + T::regs().isr().modify(|reg| { + reg.set_eos(true); + reg.set_eoc(true); + }); - // Start conversion - T::regs().cr().modify(|reg| { - reg.set_adstart(true); - }); + // Start conversion + T::regs().cr().modify(|reg| { + reg.set_adstart(true); + }); - while !T::regs().isr().read().eos() { - // spin - } - - T::regs().dr().read().0 as u16 + while !T::regs().isr().read().eos() { + // spin } + + T::regs().dr().read().0 as u16 } pub fn read(&mut self, pin: &mut impl AdcPin) -> u16 { - unsafe { - // Make sure bits are off - while T::regs().cr().read().addis() { - // spin - } - - // Enable ADC - T::regs().isr().modify(|reg| { - reg.set_adrdy(true); - }); - T::regs().cr().modify(|reg| { - reg.set_aden(true); - }); - - while !T::regs().isr().read().adrdy() { - // spin - } - - // Configure channel - Self::set_channel_sample_time(pin.channel(), self.sample_time); - - // Select channel - #[cfg(not(stm32g0))] - T::regs().sqr1().write(|reg| reg.set_sq(0, pin.channel())); - #[cfg(stm32g0)] - T::regs().chselr().write(|reg| reg.set_chsel(1 << pin.channel())); - - // Some models are affected by an erratum: - // If we perform conversions slower than 1 kHz, the first read ADC value can be - // corrupted, so we discard it and measure again. - // - // STM32L471xx: Section 2.7.3 - // STM32G4: Section 2.7.3 - #[cfg(any(rcc_l4, rcc_g4))] - let _ = self.convert(); - - let val = self.convert(); - - T::regs().cr().modify(|reg| reg.set_addis(true)); - - val + // Make sure bits are off + while T::regs().cr().read().addis() { + // spin } + + // Enable ADC + T::regs().isr().modify(|reg| { + reg.set_adrdy(true); + }); + T::regs().cr().modify(|reg| { + reg.set_aden(true); + }); + + while !T::regs().isr().read().adrdy() { + // spin + } + + // Configure channel + Self::set_channel_sample_time(pin.channel(), self.sample_time); + + // Select channel + #[cfg(not(stm32g0))] + T::regs().sqr1().write(|reg| reg.set_sq(0, pin.channel())); + #[cfg(stm32g0)] + T::regs().chselr().write(|reg| reg.set_chsel(1 << pin.channel())); + + // Some models are affected by an erratum: + // If we perform conversions slower than 1 kHz, the first read ADC value can be + // corrupted, so we discard it and measure again. + // + // STM32L471xx: Section 2.7.3 + // STM32G4: Section 2.7.3 + #[cfg(any(rcc_l4, rcc_g4))] + let _ = self.convert(); + + let val = self.convert(); + + T::regs().cr().modify(|reg| reg.set_addis(true)); + + val } #[cfg(stm32g0)] - unsafe fn set_channel_sample_time(_ch: u8, sample_time: SampleTime) { + fn set_channel_sample_time(_ch: u8, sample_time: SampleTime) { T::regs().smpr().modify(|reg| reg.set_smp1(sample_time.into())); } #[cfg(not(stm32g0))] - unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { + fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { let sample_time = sample_time.into(); if ch <= 9 { 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 4707b7c9..c51c6840 100644 --- a/embassy-stm32/src/adc/v4.rs +++ b/embassy-stm32/src/adc/v4.rs @@ -46,8 +46,8 @@ foreach_peripheral!( (adc, ADC1) => { impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC1 { fn frequency() -> crate::time::Hertz { - critical_section::with(|_| unsafe { - match crate::rcc::get_freqs().adc { + critical_section::with(|_| { + match unsafe { crate::rcc::get_freqs() }.adc { Some(ck) => ck, None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.") } @@ -55,7 +55,7 @@ foreach_peripheral!( } fn enable() { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(true)) }); ADC12_ENABLE_COUNTER.fetch_add(1, Ordering::SeqCst); @@ -63,7 +63,7 @@ foreach_peripheral!( fn disable() { if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(false)); }) } @@ -72,7 +72,7 @@ foreach_peripheral!( fn reset() { if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(true)); crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(false)); }); @@ -85,8 +85,8 @@ foreach_peripheral!( (adc, ADC2) => { impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC2 { fn frequency() -> crate::time::Hertz { - critical_section::with(|_| unsafe { - match crate::rcc::get_freqs().adc { + critical_section::with(|_| { + match unsafe { crate::rcc::get_freqs() }.adc { Some(ck) => ck, None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.") } @@ -94,7 +94,7 @@ foreach_peripheral!( } fn enable() { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(true)) }); ADC12_ENABLE_COUNTER.fetch_add(1, Ordering::SeqCst); @@ -102,7 +102,7 @@ foreach_peripheral!( fn disable() { if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(false)); }) } @@ -111,7 +111,7 @@ foreach_peripheral!( fn reset() { if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(true)); crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(false)); }); @@ -124,8 +124,8 @@ foreach_peripheral!( (adc, ADC3) => { impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC3 { fn frequency() -> crate::time::Hertz { - critical_section::with(|_| unsafe { - match crate::rcc::get_freqs().adc { + critical_section::with(|_| { + match unsafe { crate::rcc::get_freqs() }.adc { Some(ck) => ck, None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.") } @@ -133,22 +133,22 @@ foreach_peripheral!( } fn enable() { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.ahb4enr().modify(|w| w.set_adc3en(true)) }); } fn disable() { - critical_section::with(|_| unsafe { - crate::pac::RCC.ahb4enr().modify(|w| w.set_adc3en(false)); - }) + critical_section::with(|_| { + crate::pac::RCC.ahb4enr().modify(|w| w.set_adc3en(false)); + }) } fn reset() { - critical_section::with(|_| unsafe { - crate::pac::RCC.ahb4rstr().modify(|w| w.set_adc3rst(true)); - crate::pac::RCC.ahb4rstr().modify(|w| w.set_adc3rst(false)); - }); + critical_section::with(|_| { + crate::pac::RCC.ahb4rstr().modify(|w| w.set_adc3rst(true)); + crate::pac::RCC.ahb4rstr().modify(|w| w.set_adc3rst(false)); + }); } } @@ -232,9 +232,7 @@ impl<'d, T: Instance> Adc<'d, T> { let prescaler = Prescaler::from_ker_ck(T::frequency()); - unsafe { - T::common_regs().ccr().modify(|w| w.set_presc(prescaler.presc())); - } + T::common_regs().ccr().modify(|w| w.set_presc(prescaler.presc())); let frequency = Hertz(T::frequency().0 / prescaler.divisor()); info!("ADC frequency set to {} Hz", frequency.0); @@ -251,9 +249,7 @@ impl<'d, T: Instance> Adc<'d, T> { } else { Boost::LT50 }; - unsafe { - T::regs().cr().modify(|w| w.set_boost(boost)); - } + T::regs().cr().modify(|w| w.set_boost(boost)); let mut s = Self { adc, @@ -272,84 +268,68 @@ impl<'d, T: Instance> Adc<'d, T> { } fn power_up(&mut self, delay: &mut impl DelayUs) { - unsafe { - T::regs().cr().modify(|reg| { - reg.set_deeppwd(false); - reg.set_advregen(true); - }); - } + T::regs().cr().modify(|reg| { + reg.set_deeppwd(false); + reg.set_advregen(true); + }); delay.delay_us(10); } fn configure_differential_inputs(&mut self) { - unsafe { - T::regs().difsel().modify(|w| { - for n in 0..20 { - w.set_difsel(n, Difsel::SINGLEENDED); - } - }) - }; + T::regs().difsel().modify(|w| { + for n in 0..20 { + w.set_difsel(n, Difsel::SINGLEENDED); + } + }); } fn calibrate(&mut self) { - unsafe { - T::regs().cr().modify(|w| { - w.set_adcaldif(Adcaldif::SINGLEENDED); - w.set_adcallin(true); - }); + T::regs().cr().modify(|w| { + w.set_adcaldif(Adcaldif::SINGLEENDED); + w.set_adcallin(true); + }); - T::regs().cr().modify(|w| w.set_adcal(true)); + T::regs().cr().modify(|w| w.set_adcal(true)); - while T::regs().cr().read().adcal() {} - } + while T::regs().cr().read().adcal() {} } fn enable(&mut self) { - unsafe { - T::regs().isr().write(|w| w.set_adrdy(true)); - T::regs().cr().modify(|w| w.set_aden(true)); - while !T::regs().isr().read().adrdy() {} - T::regs().isr().write(|w| w.set_adrdy(true)); - } + T::regs().isr().write(|w| w.set_adrdy(true)); + T::regs().cr().modify(|w| w.set_aden(true)); + while !T::regs().isr().read().adrdy() {} + T::regs().isr().write(|w| w.set_adrdy(true)); } fn configure(&mut self) { // single conversion mode, software trigger - unsafe { - T::regs().cfgr().modify(|w| { - w.set_cont(false); - w.set_exten(Exten::DISABLED); - }) - } + T::regs().cfgr().modify(|w| { + w.set_cont(false); + w.set_exten(Exten::DISABLED); + }); } pub fn enable_vrefint(&self) -> VrefInt { - unsafe { - T::common_regs().ccr().modify(|reg| { - reg.set_vrefen(true); - }); - } + T::common_regs().ccr().modify(|reg| { + reg.set_vrefen(true); + }); VrefInt {} } pub fn enable_temperature(&self) -> Temperature { - unsafe { - T::common_regs().ccr().modify(|reg| { - reg.set_vsenseen(true); - }); - } + T::common_regs().ccr().modify(|reg| { + reg.set_vsenseen(true); + }); Temperature {} } pub fn enable_vbat(&self) -> Vbat { - unsafe { - T::common_regs().ccr().modify(|reg| { - reg.set_vbaten(true); - }); - } + T::common_regs().ccr().modify(|reg| { + reg.set_vbaten(true); + }); Vbat {} } @@ -359,30 +339,26 @@ impl<'d, T: Instance> Adc<'d, T> { } pub fn set_resolution(&mut self, resolution: Resolution) { - unsafe { - T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); - } + T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); } /// Perform a single conversion. fn convert(&mut self) -> u16 { - unsafe { - T::regs().isr().modify(|reg| { - reg.set_eos(true); - reg.set_eoc(true); - }); + T::regs().isr().modify(|reg| { + reg.set_eos(true); + reg.set_eoc(true); + }); - // Start conversion - T::regs().cr().modify(|reg| { - reg.set_adstart(true); - }); + // Start conversion + T::regs().cr().modify(|reg| { + reg.set_adstart(true); + }); - while !T::regs().isr().read().eos() { - // spin - } - - T::regs().dr().read().0 as u16 + while !T::regs().isr().read().eos() { + // spin } + + T::regs().dr().read().0 as u16 } pub fn read

(&mut self, pin: &mut P) -> u16 @@ -390,18 +366,16 @@ impl<'d, T: Instance> Adc<'d, T> { P: AdcPin, P: crate::gpio::sealed::Pin, { - unsafe { - pin.set_as_analog(); + pin.set_as_analog(); - self.read_channel(pin.channel()) - } + self.read_channel(pin.channel()) } pub fn read_internal(&mut self, channel: &mut impl InternalChannel) -> u16 { - unsafe { self.read_channel(channel.channel()) } + self.read_channel(channel.channel()) } - unsafe fn read_channel(&mut self, channel: u8) -> u16 { + fn read_channel(&mut self, channel: u8) -> u16 { // Configure channel Self::set_channel_sample_time(channel, self.sample_time); @@ -417,7 +391,7 @@ impl<'d, T: Instance> Adc<'d, T> { self.convert() } - unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { + fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { let sample_time = sample_time.into(); if ch <= 9 { 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 bd92b35a..85f6e99a 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> { ) -> Self { into_ref!(peri, rx, tx); - unsafe { - rx.set_as_af(rx.af_num(), AFType::Input); - tx.set_as_af(tx.af_num(), AFType::OutputPushPull); - } + rx.set_as_af(rx.af_num(), AFType::Input); + tx.set_as_af(tx.af_num(), AFType::OutputPushPull); T::enable(); T::reset(); @@ -42,10 +40,8 @@ impl<'d, T: Instance> Can<'d, T> { ) -> Self { into_ref!(peri, rx, tx); - unsafe { - rx.set_as_af(rx.af_num(), AFType::Input); - tx.set_as_af(tx.af_num(), AFType::OutputPushPull); - } + rx.set_as_af(rx.af_num(), AFType::Input); + tx.set_as_af(tx.af_num(), AFType::OutputPushPull); T::enable(); T::reset(); @@ -60,7 +56,7 @@ impl<'d, T: Instance> Drop for Can<'d, T> { fn drop(&mut self) { // Cannot call `free()` because it moves the instance. // Manually reset the peripheral. - unsafe { T::regs().mcr().write(|w| w.set_reset(true)) } + T::regs().mcr().write(|w| w.set_reset(true)); T::disable(); } } @@ -98,7 +94,7 @@ unsafe impl<'d, T: Instance> bxcan::Instance for BxcanInstance<'d, T> { foreach_peripheral!( (can, $inst:ident) => { impl sealed::Instance for peripherals::$inst { - const REGISTERS: *mut bxcan::RegisterBlock = crate::pac::$inst.0 as *mut _; + const REGISTERS: *mut bxcan::RegisterBlock = crate::pac::$inst.as_ptr() as *mut _; fn regs() -> &'static crate::pac::can::Can { &crate::pac::$inst diff --git a/embassy-stm32/src/crc/v1.rs b/embassy-stm32/src/crc/v1.rs index 393089ee..3946a2d4 100644 --- a/embassy-stm32/src/crc/v1.rs +++ b/embassy-stm32/src/crc/v1.rs @@ -27,26 +27,24 @@ impl<'d> Crc<'d> { /// Resets the CRC unit to default value (0xFFFF_FFFF) pub fn reset(&mut self) { - unsafe { PAC_CRC.cr().write(|w| w.set_reset(true)) }; + PAC_CRC.cr().write(|w| w.set_reset(true)); } /// Feeds a word to the peripheral and returns the current CRC value pub fn feed_word(&mut self, word: u32) -> u32 { // write a single byte to the device, and return the result - unsafe { - PAC_CRC.dr().write_value(word); - } + PAC_CRC.dr().write_value(word); self.read() } /// Feed a slice of words to the peripheral and return the result. pub fn feed_words(&mut self, words: &[u32]) -> u32 { for word in words { - unsafe { PAC_CRC.dr().write_value(*word) } + PAC_CRC.dr().write_value(*word); } self.read() } pub fn read(&self) -> u32 { - unsafe { PAC_CRC.dr().read() } + PAC_CRC.dr().read() } } diff --git a/embassy-stm32/src/crc/v2v3.rs b/embassy-stm32/src/crc/v2v3.rs index 8acb3a77..f337055a 100644 --- a/embassy-stm32/src/crc/v2v3.rs +++ b/embassy-stm32/src/crc/v2v3.rs @@ -85,95 +85,79 @@ impl<'d> Crc<'d> { } pub fn reset(&mut self) { - unsafe { - PAC_CRC.cr().modify(|w| w.set_reset(true)); - } + PAC_CRC.cr().modify(|w| w.set_reset(true)); } /// Reconfigures the CRC peripheral. Doesn't reset. fn reconfigure(&mut self) { - unsafe { - // Init CRC value - PAC_CRC.init().write_value(self._config.crc_init_value); - #[cfg(crc_v3)] - PAC_CRC.pol().write_value(self._config.crc_poly); + // Init CRC value + PAC_CRC.init().write_value(self._config.crc_init_value); + #[cfg(crc_v3)] + PAC_CRC.pol().write_value(self._config.crc_poly); - // configure CR components - // (reverse I/O, polysize, poly) - PAC_CRC.cr().write(|w| { - // configure reverse output - w.set_rev_out(match self._config.reverse_out { - true => vals::RevOut::REVERSED, - false => vals::RevOut::NORMAL, - }); - // configure reverse input - w.set_rev_in(match self._config.reverse_in { - InputReverseConfig::None => vals::RevIn::NORMAL, - InputReverseConfig::Byte => vals::RevIn::BYTE, - InputReverseConfig::Halfword => vals::RevIn::HALFWORD, - InputReverseConfig::Word => vals::RevIn::WORD, - }); - // configure the polynomial. - #[cfg(crc_v3)] - w.set_polysize(match self._config.poly_size { - PolySize::Width7 => vals::Polysize::POLYSIZE7, - PolySize::Width8 => vals::Polysize::POLYSIZE8, - PolySize::Width16 => vals::Polysize::POLYSIZE16, - PolySize::Width32 => vals::Polysize::POLYSIZE32, - }); - }) - } + // configure CR components + // (reverse I/O, polysize, poly) + PAC_CRC.cr().write(|w| { + // configure reverse output + w.set_rev_out(match self._config.reverse_out { + true => vals::RevOut::REVERSED, + false => vals::RevOut::NORMAL, + }); + // configure reverse input + w.set_rev_in(match self._config.reverse_in { + InputReverseConfig::None => vals::RevIn::NORMAL, + InputReverseConfig::Byte => vals::RevIn::BYTE, + InputReverseConfig::Halfword => vals::RevIn::HALFWORD, + InputReverseConfig::Word => vals::RevIn::WORD, + }); + // configure the polynomial. + #[cfg(crc_v3)] + w.set_polysize(match self._config.poly_size { + PolySize::Width7 => vals::Polysize::POLYSIZE7, + PolySize::Width8 => vals::Polysize::POLYSIZE8, + PolySize::Width16 => vals::Polysize::POLYSIZE16, + PolySize::Width32 => vals::Polysize::POLYSIZE32, + }); + }); self.reset(); } /// Feeds a byte into the CRC peripheral. Returns the computed checksum. pub fn feed_byte(&mut self, byte: u8) -> u32 { - unsafe { - PAC_CRC.dr8().write_value(byte); - PAC_CRC.dr().read() - } + PAC_CRC.dr8().write_value(byte); + PAC_CRC.dr().read() } /// Feeds an slice of bytes into the CRC peripheral. Returns the computed checksum. pub fn feed_bytes(&mut self, bytes: &[u8]) -> u32 { for byte in bytes { - unsafe { - PAC_CRC.dr8().write_value(*byte); - } + PAC_CRC.dr8().write_value(*byte); } - unsafe { PAC_CRC.dr().read() } + PAC_CRC.dr().read() } /// Feeds a halfword into the CRC peripheral. Returns the computed checksum. pub fn feed_halfword(&mut self, halfword: u16) -> u32 { - unsafe { - PAC_CRC.dr16().write_value(halfword); - PAC_CRC.dr().read() - } + PAC_CRC.dr16().write_value(halfword); + PAC_CRC.dr().read() } /// Feeds an slice of halfwords into the CRC peripheral. Returns the computed checksum. pub fn feed_halfwords(&mut self, halfwords: &[u16]) -> u32 { for halfword in halfwords { - unsafe { - PAC_CRC.dr16().write_value(*halfword); - } + PAC_CRC.dr16().write_value(*halfword); } - unsafe { PAC_CRC.dr().read() } + PAC_CRC.dr().read() } /// Feeds a words into the CRC peripheral. Returns the computed checksum. pub fn feed_word(&mut self, word: u32) -> u32 { - unsafe { - PAC_CRC.dr().write_value(word as u32); - PAC_CRC.dr().read() - } + PAC_CRC.dr().write_value(word as u32); + PAC_CRC.dr().read() } /// Feeds an slice of words into the CRC peripheral. Returns the computed checksum. pub fn feed_words(&mut self, words: &[u32]) -> u32 { for word in words { - unsafe { - PAC_CRC.dr().write_value(*word as u32); - } + PAC_CRC.dr().write_value(*word as u32); } - unsafe { PAC_CRC.dr().read() } + PAC_CRC.dr().read() } } diff --git a/embassy-stm32/src/dac.rs b/embassy-stm32/src/dac.rs index 60e856c7..63111887 100644 --- a/embassy-stm32/src/dac.rs +++ b/embassy-stm32/src/dac.rs @@ -121,13 +121,11 @@ impl<'d, T: Instance> Dac<'d, T> { T::enable(); T::reset(); - unsafe { - T::regs().cr().modify(|reg| { - for ch in 0..channels { - reg.set_en(ch as usize, true); - } - }); - } + T::regs().cr().modify(|reg| { + for ch in 0..channels { + reg.set_en(ch as usize, true); + } + }); Self { channels, _peri: peri } } @@ -143,11 +141,9 @@ impl<'d, T: Instance> Dac<'d, T> { fn set_channel_enable(&mut self, ch: Channel, on: bool) -> Result<(), Error> { self.check_channel_exists(ch)?; - unsafe { - T::regs().cr().modify(|reg| { - reg.set_en(ch.index(), on); - }) - } + T::regs().cr().modify(|reg| { + reg.set_en(ch.index(), on); + }); Ok(()) } @@ -162,56 +158,42 @@ impl<'d, T: Instance> Dac<'d, T> { pub fn select_trigger_ch1(&mut self, trigger: Ch1Trigger) -> Result<(), Error> { self.check_channel_exists(Channel::Ch1)?; unwrap!(self.disable_channel(Channel::Ch1)); - unsafe { - T::regs().cr().modify(|reg| { - reg.set_tsel1(trigger.tsel()); - }) - } + T::regs().cr().modify(|reg| { + reg.set_tsel1(trigger.tsel()); + }); Ok(()) } pub fn select_trigger_ch2(&mut self, trigger: Ch2Trigger) -> Result<(), Error> { self.check_channel_exists(Channel::Ch2)?; unwrap!(self.disable_channel(Channel::Ch2)); - unsafe { - T::regs().cr().modify(|reg| { - reg.set_tsel2(trigger.tsel()); - }) - } + T::regs().cr().modify(|reg| { + reg.set_tsel2(trigger.tsel()); + }); Ok(()) } pub fn trigger(&mut self, ch: Channel) -> Result<(), Error> { self.check_channel_exists(ch)?; - unsafe { - T::regs().swtrigr().write(|reg| { - reg.set_swtrig(ch.index(), true); - }); - } + T::regs().swtrigr().write(|reg| { + reg.set_swtrig(ch.index(), true); + }); Ok(()) } pub fn trigger_all(&mut self) { - unsafe { - T::regs().swtrigr().write(|reg| { - reg.set_swtrig(Channel::Ch1.index(), true); - reg.set_swtrig(Channel::Ch2.index(), true); - }) - } + T::regs().swtrigr().write(|reg| { + reg.set_swtrig(Channel::Ch1.index(), true); + reg.set_swtrig(Channel::Ch2.index(), true); + }); } pub fn set(&mut self, ch: Channel, value: Value) -> Result<(), Error> { self.check_channel_exists(ch)?; match value { - Value::Bit8(v) => unsafe { - T::regs().dhr8r(ch.index()).write(|reg| reg.set_dhr(v)); - }, - Value::Bit12(v, Alignment::Left) => unsafe { - T::regs().dhr12l(ch.index()).write(|reg| reg.set_dhr(v)); - }, - Value::Bit12(v, Alignment::Right) => unsafe { - T::regs().dhr12r(ch.index()).write(|reg| reg.set_dhr(v)); - }, + Value::Bit8(v) => T::regs().dhr8r(ch.index()).write(|reg| reg.set_dhr(v)), + Value::Bit12(v, Alignment::Left) => T::regs().dhr12l(ch.index()).write(|reg| reg.set_dhr(v)), + Value::Bit12(v, Alignment::Right) => T::regs().dhr12r(ch.index()).write(|reg| reg.set_dhr(v)), } Ok(()) } @@ -239,20 +221,20 @@ foreach_peripheral!( } fn reset() { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(true)); crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(false)); }) } fn enable() { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true)); }) } fn disable() { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(false)); }) } diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs index 41305d27..78b026cb 100644 --- a/embassy-stm32/src/dcmi.rs +++ b/embassy-stm32/src/dcmi.rs @@ -96,8 +96,7 @@ impl Default for Config { macro_rules! config_pins { ($($pin:ident),*) => { into_ref!($($pin),*); - // NOTE(unsafe) Exclusive access to the registers - critical_section::with(|_| unsafe { + critical_section::with(|_| { $( $pin.set_as_af($pin.af_num(), AFType::Input); $pin.set_speed(Speed::VeryHigh); @@ -334,17 +333,15 @@ where T::reset(); T::enable(); - unsafe { - peri.regs().cr().modify(|r| { - r.set_cm(true); // disable continuous mode (snapshot mode) - r.set_ess(use_embedded_synchronization); - r.set_pckpol(config.pixclk_polarity == PixelClockPolarity::RisingEdge); - r.set_vspol(config.vsync_level == VSyncDataInvalidLevel::High); - r.set_hspol(config.hsync_level == HSyncDataInvalidLevel::High); - r.set_fcrc(0x00); // capture every frame - r.set_edm(edm); // extended data mode - }); - } + peri.regs().cr().modify(|r| { + r.set_cm(true); // disable continuous mode (snapshot mode) + r.set_ess(use_embedded_synchronization); + r.set_pckpol(config.pixclk_polarity == PixelClockPolarity::RisingEdge); + r.set_vspol(config.vsync_level == VSyncDataInvalidLevel::High); + r.set_hspol(config.hsync_level == HSyncDataInvalidLevel::High); + r.set_fcrc(0x00); // capture every frame + r.set_edm(edm); // extended data mode + }); T::Interrupt::unpend(); unsafe { T::Interrupt::enable() }; @@ -352,7 +349,7 @@ where Self { inner: peri, dma } } - unsafe fn toggle(enable: bool) { + fn toggle(enable: bool) { crate::pac::DCMI.cr().modify(|r| { r.set_enable(enable); r.set_capture(enable); @@ -360,23 +357,19 @@ where } fn enable_irqs() { - unsafe { - crate::pac::DCMI.ier().modify(|r| { - r.set_err_ie(true); - r.set_ovr_ie(true); - r.set_frame_ie(true); - }); - } + crate::pac::DCMI.ier().modify(|r| { + r.set_err_ie(true); + r.set_ovr_ie(true); + r.set_frame_ie(true); + }); } fn clear_interrupt_flags() { - unsafe { - crate::pac::DCMI.icr().write(|r| { - r.set_ovr_isc(true); - r.set_err_isc(true); - r.set_frame_isc(true); - }) - } + crate::pac::DCMI.icr().write(|r| { + r.set_ovr_isc(true); + r.set_err_isc(true); + r.set_frame_isc(true); + }) } /// This method starts the capture and finishes when both the dma transfer and DCMI finish the frame transfer. @@ -392,41 +385,30 @@ where return self.capture_giant(buffer).await; } } + async fn capture_small(&mut self, buffer: &mut [u32]) -> Result<(), Error> { let r = self.inner.regs(); - let src = r.dr().ptr() as *mut u32; + let src = r.dr().as_ptr() as *mut u32; let request = self.dma.request(); let dma_read = unsafe { Transfer::new_read(&mut self.dma, request, src, buffer, Default::default()) }; Self::clear_interrupt_flags(); Self::enable_irqs(); - unsafe { Self::toggle(true) }; + Self::toggle(true); let result = poll_fn(|cx| { STATE.waker.register(cx.waker()); - let ris = unsafe { crate::pac::DCMI.ris().read() }; + let ris = crate::pac::DCMI.ris().read(); if ris.err_ris() { - unsafe { - crate::pac::DCMI.icr().write(|r| { - r.set_err_isc(true); - }) - }; + crate::pac::DCMI.icr().write(|r| r.set_err_isc(true)); Poll::Ready(Err(Error::PeripheralError)) } else if ris.ovr_ris() { - unsafe { - crate::pac::DCMI.icr().write(|r| { - r.set_ovr_isc(true); - }) - }; + crate::pac::DCMI.icr().write(|r| r.set_ovr_isc(true)); Poll::Ready(Err(Error::Overrun)) } else if ris.frame_ris() { - unsafe { - crate::pac::DCMI.icr().write(|r| { - r.set_frame_isc(true); - }) - }; + crate::pac::DCMI.icr().write(|r| r.set_frame_isc(true)); Poll::Ready(Ok(())) } else { Poll::Pending @@ -435,7 +417,7 @@ where let (_, result) = embassy_futures::join::join(dma_read, result).await; - unsafe { Self::toggle(false) }; + Self::toggle(false); result } @@ -468,7 +450,7 @@ where let request = channel.request(); let r = self.inner.regs(); - let src = r.dr().ptr() as *mut u32; + let src = r.dr().as_ptr() as *mut u32; let mut transfer = unsafe { crate::dma::DoubleBuffered::new_read( @@ -526,38 +508,26 @@ where let result = poll_fn(|cx| { STATE.waker.register(cx.waker()); - let ris = unsafe { crate::pac::DCMI.ris().read() }; + let ris = crate::pac::DCMI.ris().read(); if ris.err_ris() { - unsafe { - crate::pac::DCMI.icr().write(|r| { - r.set_err_isc(true); - }) - }; + crate::pac::DCMI.icr().write(|r| r.set_err_isc(true)); Poll::Ready(Err(Error::PeripheralError)) } else if ris.ovr_ris() { - unsafe { - crate::pac::DCMI.icr().write(|r| { - r.set_ovr_isc(true); - }) - }; + crate::pac::DCMI.icr().write(|r| r.set_ovr_isc(true)); Poll::Ready(Err(Error::Overrun)) } else if ris.frame_ris() { - unsafe { - crate::pac::DCMI.icr().write(|r| { - r.set_frame_isc(true); - }) - }; + crate::pac::DCMI.icr().write(|r| r.set_frame_isc(true)); Poll::Ready(Ok(())) } else { Poll::Pending } }); - unsafe { Self::toggle(true) }; + Self::toggle(true); let (_, result) = embassy_futures::join::join(dma_result, result).await; - unsafe { Self::toggle(false) }; + Self::toggle(false); result } diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs index c0a503e2..5fcb30f6 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 let cr = dma.ch(channel_num).cr(); if isr.teif(channel_num) { - panic!("DMA: error on BDMA@{:08x} channel {}", dma.0 as u32, channel_num); + panic!("DMA: error on BDMA@{:08x} channel {}", dma.as_ptr() as u32, channel_num); } if isr.htif(channel_num) && cr.read().htie() { @@ -291,29 +291,25 @@ impl<'a, C: Channel> Transfer<'a, C> { } fn clear_irqs(&mut self) { - unsafe { - self.channel.regs().ifcr().write(|w| { - w.set_tcif(self.channel.num(), true); - w.set_teif(self.channel.num(), true); - }) - } + self.channel.regs().ifcr().write(|w| { + w.set_tcif(self.channel.num(), true); + w.set_teif(self.channel.num(), true); + }); } pub fn request_stop(&mut self) { let ch = self.channel.regs().ch(self.channel.num()); // Disable the channel. Keep the IEs enabled so the irqs still fire. - unsafe { - ch.cr().write(|w| { - w.set_teie(true); - w.set_tcie(true); - }) - } + ch.cr().write(|w| { + w.set_teie(true); + w.set_tcie(true); + }); } pub fn is_running(&mut self) -> bool { let ch = self.channel.regs().ch(self.channel.num()); - let en = unsafe { ch.cr().read() }.en(); + let en = ch.cr().read().en(); let tcif = STATE.complete_count[self.channel.index()].load(Ordering::Acquire) != 0; en && !tcif } @@ -322,7 +318,7 @@ impl<'a, C: Channel> Transfer<'a, C> { /// Note: this will be zero for transfers that completed without cancellation. pub fn get_remaining_transfers(&self) -> u16 { let ch = self.channel.regs().ch(self.channel.num()); - unsafe { ch.ndtr().read() }.ndt() + ch.ndtr().read().ndt() } pub fn blocking_wait(mut self) { @@ -366,7 +362,7 @@ struct DmaCtrlImpl<'a, C: Channel>(PeripheralRef<'a, C>); impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> { fn get_remaining_transfers(&self) -> usize { let ch = self.0.regs().ch(self.0.num()); - unsafe { ch.ndtr().read() }.ndt() as usize + ch.ndtr().read().ndt() as usize } fn get_complete_count(&self) -> usize { @@ -442,7 +438,7 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> { pub fn start(&mut self) { let ch = self.channel.regs().ch(self.channel.num()); - unsafe { ch.cr().write_value(self.cr) } + ch.cr().write_value(self.cr) } pub fn clear(&mut self) { @@ -469,31 +465,27 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> { fn clear_irqs(&mut self) { let dma = self.channel.regs(); - unsafe { - dma.ifcr().write(|w| { - w.set_htif(self.channel.num(), true); - w.set_tcif(self.channel.num(), true); - w.set_teif(self.channel.num(), true); - }) - } + dma.ifcr().write(|w| { + w.set_htif(self.channel.num(), true); + w.set_tcif(self.channel.num(), true); + w.set_teif(self.channel.num(), true); + }); } pub fn request_stop(&mut self) { let ch = self.channel.regs().ch(self.channel.num()); // Disable the channel. Keep the IEs enabled so the irqs still fire. - unsafe { - ch.cr().write(|w| { - w.set_teie(true); - w.set_htie(true); - w.set_tcie(true); - }) - } + ch.cr().write(|w| { + w.set_teie(true); + w.set_htie(true); + w.set_tcie(true); + }); } pub fn is_running(&mut self) -> bool { let ch = self.channel.regs().ch(self.channel.num()); - unsafe { ch.cr().read() }.en() + ch.cr().read().en() } } diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs index 874cb013..8abe541d 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: let isr = dma.isr(channel_num / 4).read(); if isr.teif(channel_num % 4) { - panic!("DMA: error on DMA@{:08x} channel {}", dma.0 as u32, channel_num); + panic!("DMA: error on DMA@{:08x} channel {}", dma.as_ptr() as u32, channel_num); } if isr.htif(channel_num % 4) && cr.read().htie() { @@ -387,36 +387,32 @@ impl<'a, C: Channel> Transfer<'a, C> { let isrn = self.channel.num() / 4; let isrbit = self.channel.num() % 4; - unsafe { - self.channel.regs().ifcr(isrn).write(|w| { - w.set_tcif(isrbit, true); - w.set_teif(isrbit, true); - }) - } + self.channel.regs().ifcr(isrn).write(|w| { + w.set_tcif(isrbit, true); + w.set_teif(isrbit, true); + }); } pub fn request_stop(&mut self) { let ch = self.channel.regs().st(self.channel.num()); // Disable the channel. Keep the IEs enabled so the irqs still fire. - unsafe { - ch.cr().write(|w| { - w.set_teie(true); - w.set_tcie(true); - }) - } + ch.cr().write(|w| { + w.set_teie(true); + w.set_tcie(true); + }); } pub fn is_running(&mut self) -> bool { let ch = self.channel.regs().st(self.channel.num()); - unsafe { ch.cr().read() }.en() + ch.cr().read().en() } /// Gets the total remaining transfers for the channel /// Note: this will be zero for transfers that completed without cancellation. pub fn get_remaining_transfers(&self) -> u16 { let ch = self.channel.regs().st(self.channel.num()); - unsafe { ch.ndtr().read() }.ndt() + ch.ndtr().read().ndt() } pub fn blocking_wait(mut self) { @@ -537,13 +533,11 @@ impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> { let isrn = channel_number / 4; let isrbit = channel_number % 4; - unsafe { - dma.ifcr(isrn).write(|w| { - w.set_htif(isrbit, true); - w.set_tcif(isrbit, true); - w.set_teif(isrbit, true); - }) - } + dma.ifcr(isrn).write(|w| { + w.set_htif(isrbit, true); + w.set_tcif(isrbit, true); + w.set_teif(isrbit, true); + }); } pub unsafe fn set_buffer0(&mut self, buffer: *mut W) { @@ -558,7 +552,7 @@ impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> { pub fn is_buffer0_accessible(&mut self) -> bool { let ch = self.channel.regs().st(self.channel.num()); - unsafe { ch.cr().read() }.ct() == vals::Ct::MEMORY1 + ch.cr().read().ct() == vals::Ct::MEMORY1 } pub fn set_waker(&mut self, waker: &Waker) { @@ -569,24 +563,22 @@ impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> { let ch = self.channel.regs().st(self.channel.num()); // Disable the channel. Keep the IEs enabled so the irqs still fire. - unsafe { - ch.cr().write(|w| { - w.set_teie(true); - w.set_tcie(true); - }) - } + ch.cr().write(|w| { + w.set_teie(true); + w.set_tcie(true); + }); } pub fn is_running(&mut self) -> bool { let ch = self.channel.regs().st(self.channel.num()); - unsafe { ch.cr().read() }.en() + ch.cr().read().en() } /// Gets the total remaining transfers for the channel /// Note: this will be zero for transfers that completed without cancellation. pub fn get_remaining_transfers(&self) -> u16 { let ch = self.channel.regs().st(self.channel.num()); - unsafe { ch.ndtr().read() }.ndt() + ch.ndtr().read().ndt() } } @@ -607,7 +599,7 @@ struct DmaCtrlImpl<'a, C: Channel>(PeripheralRef<'a, C>); impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> { fn get_remaining_transfers(&self) -> usize { let ch = self.0.regs().st(self.0.num()); - unsafe { ch.ndtr().read() }.ndt() as usize + ch.ndtr().read().ndt() as usize } fn get_complete_count(&self) -> usize { @@ -698,7 +690,7 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> { pub fn start(&mut self) { let ch = self.channel.regs().st(self.channel.num()); - unsafe { ch.cr().write_value(self.cr) } + ch.cr().write_value(self.cr); } pub fn clear(&mut self) { @@ -729,31 +721,27 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> { let isrn = channel_number / 4; let isrbit = channel_number % 4; - unsafe { - dma.ifcr(isrn).write(|w| { - w.set_htif(isrbit, true); - w.set_tcif(isrbit, true); - w.set_teif(isrbit, true); - }) - } + dma.ifcr(isrn).write(|w| { + w.set_htif(isrbit, true); + w.set_tcif(isrbit, true); + w.set_teif(isrbit, true); + }); } pub fn request_stop(&mut self) { let ch = self.channel.regs().st(self.channel.num()); // Disable the channel. Keep the IEs enabled so the irqs still fire. - unsafe { - ch.cr().write(|w| { - w.set_teie(true); - w.set_htie(true); - w.set_tcie(true); - }) - } + ch.cr().write(|w| { + w.set_teie(true); + w.set_htie(true); + w.set_tcie(true); + }); } pub fn is_running(&mut self) -> bool { let ch = self.channel.regs().st(self.channel.num()); - unsafe { ch.cr().read() }.en() + ch.cr().read().en() } } diff --git a/embassy-stm32/src/dma/dmamux.rs b/embassy-stm32/src/dma/dmamux.rs index a8c4c582..36fc0340 100644 --- a/embassy-stm32/src/dma/dmamux.rs +++ b/embassy-stm32/src/dma/dmamux.rs @@ -2,7 +2,7 @@ use crate::{pac, peripherals}; -pub(crate) unsafe fn configure_dmamux(channel: &mut M, request: u8) { +pub(crate) fn configure_dmamux(channel: &mut M, request: u8) { let ch_mux_regs = channel.mux_regs().ccr(channel.mux_num()); ch_mux_regs.write(|reg| { reg.set_nbreq(0); diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs index 3f0d5e8f..c600df92 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 if sr.dtef() { panic!( "DMA: data transfer error on DMA@{:08x} channel {}", - dma.0 as u32, channel_num + dma.as_ptr() as u32, + channel_num ); } if sr.usef() { panic!( "DMA: user settings error on DMA@{:08x} channel {}", - dma.0 as u32, channel_num + dma.as_ptr() as u32, + channel_num ); } @@ -298,26 +300,24 @@ impl<'a, C: Channel> Transfer<'a, C> { let ch = self.channel.regs().ch(self.channel.num()); // Disable the channel. Keep the IEs enabled so the irqs still fire. - unsafe { - ch.cr().write(|w| { - w.set_tcie(true); - w.set_useie(true); - w.set_dteie(true); - w.set_suspie(true); - }) - } + ch.cr().write(|w| { + w.set_tcie(true); + w.set_useie(true); + w.set_dteie(true); + w.set_suspie(true); + }) } pub fn is_running(&mut self) -> bool { let ch = self.channel.regs().ch(self.channel.num()); - !unsafe { ch.sr().read() }.tcf() + !ch.sr().read().tcf() } /// Gets the total remaining transfers for the channel /// Note: this will be zero for transfers that completed without cancellation. pub fn get_remaining_transfers(&self) -> u16 { let ch = self.channel.regs().ch(self.channel.num()); - unsafe { ch.br1().read() }.bndt() + ch.br1().read().bndt() } 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 540cdd02..b53c2d0f 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 for InterruptHandl WAKER.wake(); // TODO: Check and clear more flags - unsafe { - let dma = ETH.ethernet_dma(); + let dma = ETH.ethernet_dma(); - dma.dmasr().modify(|w| { - w.set_ts(true); - w.set_rs(true); - w.set_nis(true); - }); - // Delay two peripheral's clock - dma.dmasr().read(); - dma.dmasr().read(); - } + dma.dmasr().modify(|w| { + w.set_ts(true); + w.set_rs(true); + w.set_nis(true); + }); + // Delay two peripheral's clock + dma.dmasr().read(); + dma.dmasr().read(); } } @@ -59,7 +57,6 @@ pub struct Ethernet<'d, T: Instance, P: PHY> { #[cfg(eth_v1a)] macro_rules! config_in_pins { ($($pin:ident),*) => { - // NOTE(unsafe) Exclusive access to the registers critical_section::with(|_| { $( // TODO properly create a set_as_input function @@ -72,7 +69,6 @@ macro_rules! config_in_pins { #[cfg(eth_v1a)] macro_rules! config_af_pins { ($($pin:ident),*) => { - // NOTE(unsafe) Exclusive access to the registers critical_section::with(|_| { $( // We are lucky here, this configures to max speed (50MHz) @@ -85,7 +81,6 @@ macro_rules! config_af_pins { #[cfg(any(eth_v1b, eth_v1c))] macro_rules! config_pins { ($($pin:ident),*) => { - // NOTE(unsafe) Exclusive access to the registers critical_section::with(|_| { $( $pin.set_as_af($pin.af_num(), AFType::OutputPushPull); @@ -116,222 +111,208 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { ) -> Self { into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); - unsafe { - // Enable the necessary Clocks - // NOTE(unsafe) We have exclusive access to the registers - #[cfg(eth_v1a)] - critical_section::with(|_| { - RCC.apb2enr().modify(|w| w.set_afioen(true)); + // Enable the necessary Clocks + #[cfg(eth_v1a)] + critical_section::with(|_| { + RCC.apb2enr().modify(|w| w.set_afioen(true)); - // Select RMII (Reduced Media Independent Interface) - // Must be done prior to enabling peripheral clock - AFIO.mapr().modify(|w| w.set_mii_rmii_sel(true)); + // Select RMII (Reduced Media Independent Interface) + // Must be done prior to enabling peripheral clock + AFIO.mapr().modify(|w| w.set_mii_rmii_sel(true)); - RCC.ahbenr().modify(|w| { - w.set_ethen(true); - w.set_ethtxen(true); - w.set_ethrxen(true); - }); + RCC.ahbenr().modify(|w| { + w.set_ethen(true); + w.set_ethtxen(true); + w.set_ethrxen(true); + }); + }); + + #[cfg(any(eth_v1b, eth_v1c))] + critical_section::with(|_| { + RCC.apb2enr().modify(|w| w.set_syscfgen(true)); + RCC.ahb1enr().modify(|w| { + w.set_ethen(true); + w.set_ethtxen(true); + w.set_ethrxen(true); }); - #[cfg(any(eth_v1b, eth_v1c))] - critical_section::with(|_| { - RCC.apb2enr().modify(|w| w.set_syscfgen(true)); - RCC.ahb1enr().modify(|w| { - w.set_ethen(true); - w.set_ethtxen(true); - w.set_ethrxen(true); - }); + // RMII (Reduced Media Independent Interface) + SYSCFG.pmc().modify(|w| w.set_mii_rmii_sel(true)); + }); - // RMII (Reduced Media Independent Interface) - SYSCFG.pmc().modify(|w| w.set_mii_rmii_sel(true)); - }); - - #[cfg(eth_v1a)] - { - config_in_pins!(ref_clk, rx_d0, rx_d1); - config_af_pins!(mdio, mdc, tx_d0, tx_d1, tx_en); - } - - #[cfg(any(eth_v1b, eth_v1c))] - config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); - - // NOTE(unsafe) We have exclusive access to the registers - let dma = ETH.ethernet_dma(); - let mac = ETH.ethernet_mac(); - - // Reset and wait - dma.dmabmr().modify(|w| w.set_sr(true)); - while dma.dmabmr().read().sr() {} - - mac.maccr().modify(|w| { - w.set_ifg(Ifg::IFG96); // inter frame gap 96 bit times - w.set_apcs(Apcs::STRIP); // automatic padding and crc stripping - w.set_fes(Fes::FES100); // fast ethernet speed - w.set_dm(Dm::FULLDUPLEX); // full duplex - // TODO: Carrier sense ? ECRSFD - }); - - // Note: Writing to LR triggers synchronisation of both LR and HR into the MAC core, - // so the LR write must happen after the HR write. - mac.maca0hr() - .modify(|w| w.set_maca0h(u16::from(mac_addr[4]) | (u16::from(mac_addr[5]) << 8))); - mac.maca0lr().write(|w| { - w.set_maca0l( - u32::from(mac_addr[0]) - | (u32::from(mac_addr[1]) << 8) - | (u32::from(mac_addr[2]) << 16) - | (u32::from(mac_addr[3]) << 24), - ) - }); - - // pause time - mac.macfcr().modify(|w| w.set_pt(0x100)); - - // Transfer and Forward, Receive and Forward - dma.dmaomr().modify(|w| { - w.set_tsf(Tsf::STOREFORWARD); - w.set_rsf(Rsf::STOREFORWARD); - }); - - dma.dmabmr().modify(|w| { - w.set_pbl(Pbl::PBL32) // programmable burst length - 32 ? - }); - - // TODO MTU size setting not found for v1 ethernet, check if correct - - // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called - let hclk = crate::rcc::get_freqs().ahb1; - let hclk_mhz = hclk.0 / 1_000_000; - - // Set the MDC clock frequency in the range 1MHz - 2.5MHz - let clock_range = match hclk_mhz { - 0..=24 => panic!("Invalid HCLK frequency - should be at least 25 MHz."), - 25..=34 => Cr::CR_20_35, // Divide by 16 - 35..=59 => Cr::CR_35_60, // Divide by 26 - 60..=99 => Cr::CR_60_100, // Divide by 42 - 100..=149 => Cr::CR_100_150, // Divide by 62 - 150..=216 => Cr::CR_150_168, // Divide by 102 - _ => { - panic!("HCLK results in MDC clock > 2.5MHz even for the highest CSR clock divider") - } - }; - - let pins = [ - ref_clk.map_into(), - mdio.map_into(), - mdc.map_into(), - crs.map_into(), - rx_d0.map_into(), - rx_d1.map_into(), - tx_d0.map_into(), - tx_d1.map_into(), - tx_en.map_into(), - ]; - - let mut this = Self { - _peri: peri, - pins, - _phy: phy, - clock_range, - phy_addr, - mac_addr, - tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), - rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), - }; - - fence(Ordering::SeqCst); - - let mac = ETH.ethernet_mac(); - let dma = ETH.ethernet_dma(); - - mac.maccr().modify(|w| { - w.set_re(true); - w.set_te(true); - }); - dma.dmaomr().modify(|w| { - w.set_ftf(Ftf::FLUSH); // flush transmit fifo (queue) - w.set_st(St::STARTED); // start transmitting channel - w.set_sr(DmaomrSr::STARTED); // start receiving channel - }); - - this.rx.demand_poll(); - - // Enable interrupts - dma.dmaier().modify(|w| { - w.set_nise(true); - w.set_rie(true); - w.set_tie(true); - }); - - P::phy_reset(&mut this); - P::phy_init(&mut this); - - interrupt::ETH.unpend(); - interrupt::ETH.enable(); - - this + #[cfg(eth_v1a)] + { + config_in_pins!(ref_clk, rx_d0, rx_d1); + config_af_pins!(mdio, mdc, tx_d0, tx_d1, tx_en); } + + #[cfg(any(eth_v1b, eth_v1c))] + config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); + + let dma = ETH.ethernet_dma(); + let mac = ETH.ethernet_mac(); + + // Reset and wait + dma.dmabmr().modify(|w| w.set_sr(true)); + while dma.dmabmr().read().sr() {} + + mac.maccr().modify(|w| { + w.set_ifg(Ifg::IFG96); // inter frame gap 96 bit times + w.set_apcs(Apcs::STRIP); // automatic padding and crc stripping + w.set_fes(Fes::FES100); // fast ethernet speed + w.set_dm(Dm::FULLDUPLEX); // full duplex + // TODO: Carrier sense ? ECRSFD + }); + + // Note: Writing to LR triggers synchronisation of both LR and HR into the MAC core, + // so the LR write must happen after the HR write. + mac.maca0hr() + .modify(|w| w.set_maca0h(u16::from(mac_addr[4]) | (u16::from(mac_addr[5]) << 8))); + mac.maca0lr().write(|w| { + w.set_maca0l( + u32::from(mac_addr[0]) + | (u32::from(mac_addr[1]) << 8) + | (u32::from(mac_addr[2]) << 16) + | (u32::from(mac_addr[3]) << 24), + ) + }); + + // pause time + mac.macfcr().modify(|w| w.set_pt(0x100)); + + // Transfer and Forward, Receive and Forward + dma.dmaomr().modify(|w| { + w.set_tsf(Tsf::STOREFORWARD); + w.set_rsf(Rsf::STOREFORWARD); + }); + + dma.dmabmr().modify(|w| { + w.set_pbl(Pbl::PBL32) // programmable burst length - 32 ? + }); + + // TODO MTU size setting not found for v1 ethernet, check if correct + + // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called + let hclk = unsafe { crate::rcc::get_freqs() }.ahb1; + let hclk_mhz = hclk.0 / 1_000_000; + + // Set the MDC clock frequency in the range 1MHz - 2.5MHz + let clock_range = match hclk_mhz { + 0..=24 => panic!("Invalid HCLK frequency - should be at least 25 MHz."), + 25..=34 => Cr::CR_20_35, // Divide by 16 + 35..=59 => Cr::CR_35_60, // Divide by 26 + 60..=99 => Cr::CR_60_100, // Divide by 42 + 100..=149 => Cr::CR_100_150, // Divide by 62 + 150..=216 => Cr::CR_150_168, // Divide by 102 + _ => { + panic!("HCLK results in MDC clock > 2.5MHz even for the highest CSR clock divider") + } + }; + + let pins = [ + ref_clk.map_into(), + mdio.map_into(), + mdc.map_into(), + crs.map_into(), + rx_d0.map_into(), + rx_d1.map_into(), + tx_d0.map_into(), + tx_d1.map_into(), + tx_en.map_into(), + ]; + + let mut this = Self { + _peri: peri, + pins, + _phy: phy, + clock_range, + phy_addr, + mac_addr, + tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), + rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), + }; + + fence(Ordering::SeqCst); + + let mac = ETH.ethernet_mac(); + let dma = ETH.ethernet_dma(); + + mac.maccr().modify(|w| { + w.set_re(true); + w.set_te(true); + }); + dma.dmaomr().modify(|w| { + w.set_ftf(Ftf::FLUSH); // flush transmit fifo (queue) + w.set_st(St::STARTED); // start transmitting channel + w.set_sr(DmaomrSr::STARTED); // start receiving channel + }); + + this.rx.demand_poll(); + + // Enable interrupts + dma.dmaier().modify(|w| { + w.set_nise(true); + w.set_rie(true); + w.set_tie(true); + }); + + P::phy_reset(&mut this); + P::phy_init(&mut this); + + interrupt::ETH.unpend(); + unsafe { interrupt::ETH.enable() }; + + this } } unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> { fn smi_read(&mut self, reg: u8) -> u16 { - // NOTE(unsafe) These registers aren't used in the interrupt and we have `&mut self` - unsafe { - let mac = ETH.ethernet_mac(); + let mac = ETH.ethernet_mac(); - mac.macmiiar().modify(|w| { - w.set_pa(self.phy_addr); - w.set_mr(reg); - w.set_mw(Mw::READ); // read operation - w.set_cr(self.clock_range); - w.set_mb(MbProgress::BUSY); // indicate that operation is in progress - }); - while mac.macmiiar().read().mb() == MbProgress::BUSY {} - mac.macmiidr().read().md() - } + mac.macmiiar().modify(|w| { + w.set_pa(self.phy_addr); + w.set_mr(reg); + w.set_mw(Mw::READ); // read operation + w.set_cr(self.clock_range); + w.set_mb(MbProgress::BUSY); // indicate that operation is in progress + }); + while mac.macmiiar().read().mb() == MbProgress::BUSY {} + mac.macmiidr().read().md() } fn smi_write(&mut self, reg: u8, val: u16) { - // NOTE(unsafe) These registers aren't used in the interrupt and we have `&mut self` - unsafe { - let mac = ETH.ethernet_mac(); + let mac = ETH.ethernet_mac(); - mac.macmiidr().write(|w| w.set_md(val)); - mac.macmiiar().modify(|w| { - w.set_pa(self.phy_addr); - w.set_mr(reg); - w.set_mw(Mw::WRITE); // write - w.set_cr(self.clock_range); - w.set_mb(MbProgress::BUSY); - }); - while mac.macmiiar().read().mb() == MbProgress::BUSY {} - } + mac.macmiidr().write(|w| w.set_md(val)); + mac.macmiiar().modify(|w| { + w.set_pa(self.phy_addr); + w.set_mr(reg); + w.set_mw(Mw::WRITE); // write + w.set_cr(self.clock_range); + w.set_mb(MbProgress::BUSY); + }); + while mac.macmiiar().read().mb() == MbProgress::BUSY {} } } impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { fn drop(&mut self) { - // NOTE(unsafe) We have `&mut self` and the interrupt doesn't use this registers - unsafe { - let dma = ETH.ethernet_dma(); - let mac = ETH.ethernet_mac(); + let dma = ETH.ethernet_dma(); + let mac = ETH.ethernet_mac(); - // Disable the TX DMA and wait for any previous transmissions to be completed - dma.dmaomr().modify(|w| w.set_st(St::STOPPED)); + // Disable the TX DMA and wait for any previous transmissions to be completed + dma.dmaomr().modify(|w| w.set_st(St::STOPPED)); - // Disable MAC transmitter and receiver - mac.maccr().modify(|w| { - w.set_re(false); - w.set_te(false); - }); + // Disable MAC transmitter and receiver + mac.maccr().modify(|w| { + w.set_re(false); + w.set_te(false); + }); - dma.dmaomr().modify(|w| w.set_sr(DmaomrSr::STOPPED)); - } + dma.dmaomr().modify(|w| w.set_sr(DmaomrSr::STOPPED)); - // NOTE(unsafe) Exclusive access to the regs - critical_section::with(|_| unsafe { + critical_section::with(|_| { for pin in self.pins.iter_mut() { pin.set_as_disconnected(); } diff --git a/embassy-stm32/src/eth/v1/rx_desc.rs b/embassy-stm32/src/eth/v1/rx_desc.rs index 8b8566d9..01a073bb 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> { } // Register rx descriptor start - // NOTE (unsafe) Used for atomic writes - unsafe { - ETH.ethernet_dma() - .dmardlar() - .write(|w| w.0 = descriptors.as_ptr() as u32); - }; + ETH.ethernet_dma() + .dmardlar() + .write(|w| w.0 = descriptors.as_ptr() as u32); // We already have fences in `set_owned`, which is called in `setup` Self { @@ -162,12 +159,12 @@ impl<'a> RDesRing<'a> { } pub(crate) fn demand_poll(&self) { - unsafe { ETH.ethernet_dma().dmarpdr().write(|w| w.set_rpd(Rpd::POLL)) }; + ETH.ethernet_dma().dmarpdr().write(|w| w.set_rpd(Rpd::POLL)); } /// Get current `RunningState` fn running_state(&self) -> RunningState { - match unsafe { ETH.ethernet_dma().dmasr().read().rps() } { + match ETH.ethernet_dma().dmasr().read().rps() { // Reset or Stop Receive Command issued Rps::STOPPED => RunningState::Stopped, // 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 0e63c544..1317d20f 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> { } // Register txdescriptor start - // NOTE (unsafe) Used for atomic writes - unsafe { - ETH.ethernet_dma() - .dmatdlar() - .write(|w| w.0 = descriptors.as_ptr() as u32); - } + ETH.ethernet_dma() + .dmatdlar() + .write(|w| w.0 = descriptors.as_ptr() as u32); Self { descriptors, @@ -169,6 +166,6 @@ impl<'a> TDesRing<'a> { self.index = 0 } // Request the DMA engine to poll the latest tx descriptor - unsafe { ETH.ethernet_dma().dmatpdr().modify(|w| w.0 = 1) } + ETH.ethernet_dma().dmatpdr().modify(|w| w.0 = 1) } } diff --git a/embassy-stm32/src/eth/v2/descriptors.rs b/embassy-stm32/src/eth/v2/descriptors.rs index 2426596f..e9799adf 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> { // Initialize the pointers in the DMA engine. (There will be a memory barrier later // before the DMA engine is enabled.) - // NOTE (unsafe) Used for atomic writes - unsafe { - let dma = ETH.ethernet_dma(); - - dma.dmactx_dlar().write(|w| w.0 = descriptors.as_mut_ptr() as u32); - dma.dmactx_rlr().write(|w| w.set_tdrl((descriptors.len() as u16) - 1)); - dma.dmactx_dtpr().write(|w| w.0 = 0); - } + let dma = ETH.ethernet_dma(); + dma.dmactx_dlar().write(|w| w.0 = descriptors.as_mut_ptr() as u32); + dma.dmactx_rlr().write(|w| w.set_tdrl((descriptors.len() as u16) - 1)); + dma.dmactx_dtpr().write(|w| w.0 = 0); Self { descriptors, @@ -129,8 +125,7 @@ impl<'a> TDesRing<'a> { } // signal DMA it can try again. - // NOTE(unsafe) Atomic write - unsafe { ETH.ethernet_dma().dmactx_dtpr().write(|w| w.0 = 0) } + ETH.ethernet_dma().dmactx_dtpr().write(|w| w.0 = 0) } } @@ -199,13 +194,10 @@ impl<'a> RDesRing<'a> { desc.set_ready(buffers[i].0.as_mut_ptr()); } - unsafe { - let dma = ETH.ethernet_dma(); - - dma.dmacrx_dlar().write(|w| w.0 = descriptors.as_mut_ptr() as u32); - dma.dmacrx_rlr().write(|w| w.set_rdrl((descriptors.len() as u16) - 1)); - dma.dmacrx_dtpr().write(|w| w.0 = 0); - } + let dma = ETH.ethernet_dma(); + dma.dmacrx_dlar().write(|w| w.0 = descriptors.as_mut_ptr() as u32); + dma.dmacrx_rlr().write(|w| w.set_rdrl((descriptors.len() as u16) - 1)); + dma.dmacrx_dtpr().write(|w| w.0 = 0); Self { descriptors, @@ -254,8 +246,7 @@ impl<'a> RDesRing<'a> { fence(Ordering::Release); // signal DMA it can try again. - // NOTE(unsafe) Atomic write - unsafe { ETH.ethernet_dma().dmacrx_dtpr().write(|w| w.0 = 0) } + ETH.ethernet_dma().dmacrx_dtpr().write(|w| w.0 = 0); // Increment index. self.index += 1; diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs index 3e45eafd..600e1d3b 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 for InterruptHandl WAKER.wake(); // TODO: Check and clear more flags - unsafe { - let dma = ETH.ethernet_dma(); + let dma = ETH.ethernet_dma(); - dma.dmacsr().modify(|w| { - w.set_ti(true); - w.set_ri(true); - w.set_nis(true); - }); - // Delay two peripheral's clock - dma.dmacsr().read(); - dma.dmacsr().read(); - } + dma.dmacsr().modify(|w| { + w.set_ti(true); + w.set_ri(true); + w.set_nis(true); + }); + // Delay two peripheral's clock + dma.dmacsr().read(); + dma.dmacsr().read(); } } @@ -50,7 +48,6 @@ pub struct Ethernet<'d, T: Instance, P: PHY> { macro_rules! config_pins { ($($pin:ident),*) => { - // NOTE(unsafe) Exclusive access to the registers critical_section::with(|_| { $( $pin.set_as_af($pin.af_num(), AFType::OutputPushPull); @@ -80,239 +77,225 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { ) -> Self { into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); - unsafe { - // Enable the necessary Clocks - // NOTE(unsafe) We have exclusive access to the registers - #[cfg(not(rcc_h5))] - critical_section::with(|_| { - crate::pac::RCC.apb4enr().modify(|w| w.set_syscfgen(true)); - crate::pac::RCC.ahb1enr().modify(|w| { - w.set_eth1macen(true); - w.set_eth1txen(true); - w.set_eth1rxen(true); - }); - - // RMII - crate::pac::SYSCFG.pmcr().modify(|w| w.set_epis(0b100)); + // Enable the necessary Clocks + #[cfg(not(rcc_h5))] + critical_section::with(|_| { + crate::pac::RCC.apb4enr().modify(|w| w.set_syscfgen(true)); + crate::pac::RCC.ahb1enr().modify(|w| { + w.set_eth1macen(true); + w.set_eth1txen(true); + w.set_eth1rxen(true); }); - #[cfg(rcc_h5)] - critical_section::with(|_| { - crate::pac::RCC.apb3enr().modify(|w| w.set_sbsen(true)); + // RMII + crate::pac::SYSCFG.pmcr().modify(|w| w.set_epis(0b100)); + }); - crate::pac::RCC.ahb1enr().modify(|w| { - w.set_ethen(true); - w.set_ethtxen(true); - w.set_ethrxen(true); - }); + #[cfg(rcc_h5)] + critical_section::with(|_| { + crate::pac::RCC.apb3enr().modify(|w| w.set_sbsen(true)); - // RMII - crate::pac::SBS - .pmcr() - .modify(|w| w.set_eth_sel_phy(crate::pac::sbs::vals::EthSelPhy::B_0X4)); + crate::pac::RCC.ahb1enr().modify(|w| { + w.set_ethen(true); + w.set_ethtxen(true); + w.set_ethrxen(true); }); - config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); + // RMII + crate::pac::SBS + .pmcr() + .modify(|w| w.set_eth_sel_phy(crate::pac::sbs::vals::EthSelPhy::B_0X4)); + }); - // NOTE(unsafe) We have exclusive access to the registers - let dma = ETH.ethernet_dma(); - let mac = ETH.ethernet_mac(); - let mtl = ETH.ethernet_mtl(); + config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); - // Reset and wait - dma.dmamr().modify(|w| w.set_swr(true)); - while dma.dmamr().read().swr() {} + let dma = ETH.ethernet_dma(); + let mac = ETH.ethernet_mac(); + let mtl = ETH.ethernet_mtl(); - mac.maccr().modify(|w| { - w.set_ipg(0b000); // 96 bit times - w.set_acs(true); - w.set_fes(true); - w.set_dm(true); - // TODO: Carrier sense ? ECRSFD - }); + // Reset and wait + dma.dmamr().modify(|w| w.set_swr(true)); + while dma.dmamr().read().swr() {} - // Note: Writing to LR triggers synchronisation of both LR and HR into the MAC core, - // so the LR write must happen after the HR write. - mac.maca0hr() - .modify(|w| w.set_addrhi(u16::from(mac_addr[4]) | (u16::from(mac_addr[5]) << 8))); - mac.maca0lr().write(|w| { - w.set_addrlo( - u32::from(mac_addr[0]) - | (u32::from(mac_addr[1]) << 8) - | (u32::from(mac_addr[2]) << 16) - | (u32::from(mac_addr[3]) << 24), - ) - }); + mac.maccr().modify(|w| { + w.set_ipg(0b000); // 96 bit times + w.set_acs(true); + w.set_fes(true); + w.set_dm(true); + // TODO: Carrier sense ? ECRSFD + }); - mac.macqtx_fcr().modify(|w| w.set_pt(0x100)); + // Note: Writing to LR triggers synchronisation of both LR and HR into the MAC core, + // so the LR write must happen after the HR write. + mac.maca0hr() + .modify(|w| w.set_addrhi(u16::from(mac_addr[4]) | (u16::from(mac_addr[5]) << 8))); + mac.maca0lr().write(|w| { + w.set_addrlo( + u32::from(mac_addr[0]) + | (u32::from(mac_addr[1]) << 8) + | (u32::from(mac_addr[2]) << 16) + | (u32::from(mac_addr[3]) << 24), + ) + }); - // disable all MMC RX interrupts - mac.mmc_rx_interrupt_mask().write(|w| { - w.set_rxcrcerpim(true); - w.set_rxalgnerpim(true); - w.set_rxucgpim(true); - w.set_rxlpiuscim(true); - w.set_rxlpitrcim(true) - }); + mac.macqtx_fcr().modify(|w| w.set_pt(0x100)); - // disable all MMC TX interrupts - mac.mmc_tx_interrupt_mask().write(|w| { - w.set_txscolgpim(true); - w.set_txmcolgpim(true); - w.set_txgpktim(true); - w.set_txlpiuscim(true); - w.set_txlpitrcim(true); - }); + // disable all MMC RX interrupts + mac.mmc_rx_interrupt_mask().write(|w| { + w.set_rxcrcerpim(true); + w.set_rxalgnerpim(true); + w.set_rxucgpim(true); + w.set_rxlpiuscim(true); + w.set_rxlpitrcim(true) + }); - mtl.mtlrx_qomr().modify(|w| w.set_rsf(true)); - mtl.mtltx_qomr().modify(|w| w.set_tsf(true)); + // disable all MMC TX interrupts + mac.mmc_tx_interrupt_mask().write(|w| { + w.set_txscolgpim(true); + w.set_txmcolgpim(true); + w.set_txgpktim(true); + w.set_txlpiuscim(true); + w.set_txlpitrcim(true); + }); - dma.dmactx_cr().modify(|w| w.set_txpbl(1)); // 32 ? - dma.dmacrx_cr().modify(|w| { - w.set_rxpbl(1); // 32 ? - w.set_rbsz(MTU as u16); - }); + mtl.mtlrx_qomr().modify(|w| w.set_rsf(true)); + mtl.mtltx_qomr().modify(|w| w.set_tsf(true)); - // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called - let hclk = crate::rcc::get_freqs().ahb1; - let hclk_mhz = hclk.0 / 1_000_000; + dma.dmactx_cr().modify(|w| w.set_txpbl(1)); // 32 ? + dma.dmacrx_cr().modify(|w| { + w.set_rxpbl(1); // 32 ? + w.set_rbsz(MTU as u16); + }); - // Set the MDC clock frequency in the range 1MHz - 2.5MHz - let clock_range = match hclk_mhz { - 0..=34 => 2, // Divide by 16 - 35..=59 => 3, // Divide by 26 - 60..=99 => 0, // Divide by 42 - 100..=149 => 1, // Divide by 62 - 150..=249 => 4, // Divide by 102 - 250..=310 => 5, // Divide by 124 - _ => { - panic!("HCLK results in MDC clock > 2.5MHz even for the highest CSR clock divider") - } - }; + // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called + let hclk = unsafe { crate::rcc::get_freqs() }.ahb1; + let hclk_mhz = hclk.0 / 1_000_000; - let pins = [ - ref_clk.map_into(), - mdio.map_into(), - mdc.map_into(), - crs.map_into(), - rx_d0.map_into(), - rx_d1.map_into(), - tx_d0.map_into(), - tx_d1.map_into(), - tx_en.map_into(), - ]; + // Set the MDC clock frequency in the range 1MHz - 2.5MHz + let clock_range = match hclk_mhz { + 0..=34 => 2, // Divide by 16 + 35..=59 => 3, // Divide by 26 + 60..=99 => 0, // Divide by 42 + 100..=149 => 1, // Divide by 62 + 150..=249 => 4, // Divide by 102 + 250..=310 => 5, // Divide by 124 + _ => { + panic!("HCLK results in MDC clock > 2.5MHz even for the highest CSR clock divider") + } + }; - let mut this = Self { - _peri: peri, - tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), - rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), - pins, - _phy: phy, - clock_range, - phy_addr, - mac_addr, - }; + let pins = [ + ref_clk.map_into(), + mdio.map_into(), + mdc.map_into(), + crs.map_into(), + rx_d0.map_into(), + rx_d1.map_into(), + tx_d0.map_into(), + tx_d1.map_into(), + tx_en.map_into(), + ]; - fence(Ordering::SeqCst); + let mut this = Self { + _peri: peri, + tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), + rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), + pins, + _phy: phy, + clock_range, + phy_addr, + mac_addr, + }; - let mac = ETH.ethernet_mac(); - let mtl = ETH.ethernet_mtl(); - let dma = ETH.ethernet_dma(); + fence(Ordering::SeqCst); - mac.maccr().modify(|w| { - w.set_re(true); - w.set_te(true); - }); - mtl.mtltx_qomr().modify(|w| w.set_ftq(true)); + let mac = ETH.ethernet_mac(); + let mtl = ETH.ethernet_mtl(); + let dma = ETH.ethernet_dma(); - dma.dmactx_cr().modify(|w| w.set_st(true)); - dma.dmacrx_cr().modify(|w| w.set_sr(true)); + mac.maccr().modify(|w| { + w.set_re(true); + w.set_te(true); + }); + mtl.mtltx_qomr().modify(|w| w.set_ftq(true)); - // Enable interrupts - dma.dmacier().modify(|w| { - w.set_nie(true); - w.set_rie(true); - w.set_tie(true); - }); + dma.dmactx_cr().modify(|w| w.set_st(true)); + dma.dmacrx_cr().modify(|w| w.set_sr(true)); - P::phy_reset(&mut this); - P::phy_init(&mut this); + // Enable interrupts + dma.dmacier().modify(|w| { + w.set_nie(true); + w.set_rie(true); + w.set_tie(true); + }); - interrupt::ETH.unpend(); - interrupt::ETH.enable(); + P::phy_reset(&mut this); + P::phy_init(&mut this); - this - } + interrupt::ETH.unpend(); + unsafe { interrupt::ETH.enable() }; + + this } } unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> { fn smi_read(&mut self, reg: u8) -> u16 { - // NOTE(unsafe) These registers aren't used in the interrupt and we have `&mut self` - unsafe { - let mac = ETH.ethernet_mac(); + let mac = ETH.ethernet_mac(); - mac.macmdioar().modify(|w| { - w.set_pa(self.phy_addr); - w.set_rda(reg); - w.set_goc(0b11); // read - w.set_cr(self.clock_range); - w.set_mb(true); - }); - while mac.macmdioar().read().mb() {} - mac.macmdiodr().read().md() - } + mac.macmdioar().modify(|w| { + w.set_pa(self.phy_addr); + w.set_rda(reg); + w.set_goc(0b11); // read + w.set_cr(self.clock_range); + w.set_mb(true); + }); + while mac.macmdioar().read().mb() {} + mac.macmdiodr().read().md() } fn smi_write(&mut self, reg: u8, val: u16) { - // NOTE(unsafe) These registers aren't used in the interrupt and we have `&mut self` - unsafe { - let mac = ETH.ethernet_mac(); + let mac = ETH.ethernet_mac(); - mac.macmdiodr().write(|w| w.set_md(val)); - mac.macmdioar().modify(|w| { - w.set_pa(self.phy_addr); - w.set_rda(reg); - w.set_goc(0b01); // write - w.set_cr(self.clock_range); - w.set_mb(true); - }); - while mac.macmdioar().read().mb() {} - } + mac.macmdiodr().write(|w| w.set_md(val)); + mac.macmdioar().modify(|w| { + w.set_pa(self.phy_addr); + w.set_rda(reg); + w.set_goc(0b01); // write + w.set_cr(self.clock_range); + w.set_mb(true); + }); + while mac.macmdioar().read().mb() {} } } impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { fn drop(&mut self) { - // NOTE(unsafe) We have `&mut self` and the interrupt doesn't use this registers - unsafe { - let dma = ETH.ethernet_dma(); - let mac = ETH.ethernet_mac(); - let mtl = ETH.ethernet_mtl(); + let dma = ETH.ethernet_dma(); + let mac = ETH.ethernet_mac(); + let mtl = ETH.ethernet_mtl(); - // Disable the TX DMA and wait for any previous transmissions to be completed - dma.dmactx_cr().modify(|w| w.set_st(false)); - while { - let txqueue = mtl.mtltx_qdr().read(); - txqueue.trcsts() == 0b01 || txqueue.txqsts() - } {} + // Disable the TX DMA and wait for any previous transmissions to be completed + dma.dmactx_cr().modify(|w| w.set_st(false)); + while { + let txqueue = mtl.mtltx_qdr().read(); + txqueue.trcsts() == 0b01 || txqueue.txqsts() + } {} - // Disable MAC transmitter and receiver - mac.maccr().modify(|w| { - w.set_re(false); - w.set_te(false); - }); + // Disable MAC transmitter and receiver + mac.maccr().modify(|w| { + w.set_re(false); + w.set_te(false); + }); - // Wait for previous receiver transfers to be completed and then disable the RX DMA - while { - let rxqueue = mtl.mtlrx_qdr().read(); - rxqueue.rxqsts() != 0b00 || rxqueue.prxq() != 0 - } {} - dma.dmacrx_cr().modify(|w| w.set_sr(false)); - } + // Wait for previous receiver transfers to be completed and then disable the RX DMA + while { + let rxqueue = mtl.mtlrx_qdr().read(); + rxqueue.rxqsts() != 0b00 || rxqueue.prxq() != 0 + } {} + dma.dmacrx_cr().modify(|w| w.set_sr(false)); - // NOTE(unsafe) Exclusive access to the regs - critical_section::with(|_| unsafe { + critical_section::with(|_| { for pin in self.pins.iter_mut() { pin.set_as_disconnected(); } diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs index 0631ae47..3ff92c9e 100644 --- a/embassy-stm32/src/exti.rs +++ b/embassy-stm32/src/exti.rs @@ -206,7 +206,7 @@ struct ExtiInputFuture<'a> { impl<'a> ExtiInputFuture<'a> { fn new(pin: u8, port: u8, rising: bool, falling: bool) -> Self { - critical_section::with(|_| unsafe { + critical_section::with(|_| { let pin = pin as usize; exticr_regs().exticr(pin / 4).modify(|w| w.set_exti(pin % 4, port)); EXTI.rtsr(0).modify(|w| w.set_line(pin, rising)); @@ -233,7 +233,7 @@ impl<'a> ExtiInputFuture<'a> { impl<'a> Drop for ExtiInputFuture<'a> { fn drop(&mut self) { - critical_section::with(|_| unsafe { + critical_section::with(|_| { let pin = self.pin as _; cpu_regs().imr(0).modify(|w| w.set_line(pin, false)); }); @@ -246,7 +246,7 @@ impl<'a> Future for ExtiInputFuture<'a> { fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { EXTI_WAKERS[self.pin as usize].register(cx.waker()); - let imr = unsafe { cpu_regs().imr(0).read() }; + let imr = cpu_regs().imr(0).read(); if !imr.line(self.pin as _) { Poll::Ready(()) } else { diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 5e1fc696..242d9927 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -192,7 +192,7 @@ impl FlashSector { #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] pub(crate) fn is_default_layout() -> bool { - unsafe { !pac::FLASH.optcr().read().db1m() } + !pac::FLASH.optcr().read().db1m() } #[cfg(not(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479)))] @@ -336,7 +336,7 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E ret } -pub(crate) unsafe fn clear_all_err() { +pub(crate) fn clear_all_err() { pac::FLASH.sr().write(|w| { w.set_pgserr(true); w.set_pgperr(true); @@ -345,7 +345,7 @@ pub(crate) unsafe fn clear_all_err() { }); } -pub(crate) async unsafe fn wait_ready() -> Result<(), Error> { +pub(crate) async fn wait_ready() -> Result<(), Error> { use core::task::Poll; use futures::future::poll_fn; @@ -391,10 +391,10 @@ fn save_data_cache_state() { let dual_bank = get_flash_regions().last().unwrap().bank == FlashBank::Bank2; if dual_bank { // Disable data cache during write/erase if there are two banks, see errata 2.2.12 - let dcen = unsafe { pac::FLASH.acr().read().dcen() }; + let dcen = pac::FLASH.acr().read().dcen(); DATA_CACHE_WAS_ENABLED.store(dcen, Ordering::Relaxed); if dcen { - unsafe { pac::FLASH.acr().modify(|w| w.set_dcen(false)) }; + pac::FLASH.acr().modify(|w| w.set_dcen(false)); } } } @@ -405,12 +405,10 @@ fn restore_data_cache_state() { // Restore data cache if it was enabled let dcen = DATA_CACHE_WAS_ENABLED.load(Ordering::Relaxed); if dcen { - unsafe { - // Reset data cache before we enable it again - pac::FLASH.acr().modify(|w| w.set_dcrst(true)); - pac::FLASH.acr().modify(|w| w.set_dcrst(false)); - pac::FLASH.acr().modify(|w| w.set_dcen(true)) - }; + // Reset data cache before we enable it again + pac::FLASH.acr().modify(|w| w.set_dcrst(true)); + pac::FLASH.acr().modify(|w| w.set_dcrst(false)); + pac::FLASH.acr().modify(|w| w.set_dcen(true)) } } } @@ -445,7 +443,7 @@ pub(crate) fn assert_not_corrupted_read(end_address: u32) { feature = "stm32f439vi", feature = "stm32f439zi", ))] - if second_bank_read && unsafe { pac::DBGMCU.idcode().read().rev_id() < REVISION_3 && !pa12_is_output_pull_low() } { + if second_bank_read && pac::DBGMCU.idcode().read().rev_id() < REVISION_3 && !pa12_is_output_pull_low() { panic!("Read corruption for stm32f42xxI and stm32f43xxI when PA12 is in use for chips below revision 3, see errata 2.2.11"); } @@ -479,11 +477,9 @@ fn pa12_is_output_pull_low() -> bool { use pac::gpio::vals; use pac::GPIOA; const PIN: usize = 12; - unsafe { - GPIOA.moder().read().moder(PIN) == vals::Moder::OUTPUT - && GPIOA.pupdr().read().pupdr(PIN) == vals::Pupdr::PULLDOWN - && GPIOA.odr().read().odr(PIN) == vals::Odr::LOW - } + GPIOA.moder().read().moder(PIN) == vals::Moder::OUTPUT + && GPIOA.pupdr().read().pupdr(PIN) == vals::Pupdr::PULLDOWN + && GPIOA.odr().read().odr(PIN) == vals::Odr::LOW } #[cfg(test)] diff --git a/embassy-stm32/src/fmc.rs b/embassy-stm32/src/fmc.rs index b9129cb5..a4f3b968 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> where T: Instance, { - const REGISTERS: *const () = T::REGS.0 as *const _; + const REGISTERS: *const () = T::REGS.as_ptr() as *const _; fn enable(&mut self) { ::enable(); @@ -28,9 +28,7 @@ where // fsmc v1, v2 and v3 does not have the fmcen bit // This is a "not" because it is expected that all future versions have this bit #[cfg(not(any(fmc_v1x3, fmc_v2x1, fsmc_v1x0, fsmc_v1x3, fsmc_v2x3, fsmc_v3x1)))] - unsafe { - T::REGS.bcr1().modify(|r| r.set_fmcen(true)) - }; + T::REGS.bcr1().modify(|r| r.set_fmcen(true)); } fn source_clock_hz(&self) -> u32 { @@ -67,7 +65,7 @@ macro_rules! fmc_sdram_constructor { chip: CHIP ) -> stm32_fmc::Sdram, CHIP> { - critical_section::with(|_| unsafe { + critical_section::with(|_| { config_pins!( $($addr_pin_name),*, $($ba_pin_name),*, diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs index 7a066a4c..af3a8eac 100644 --- a/embassy-stm32/src/gpio.rs +++ b/embassy-stm32/src/gpio.rs @@ -46,7 +46,7 @@ impl<'d, T: Pin> Flex<'d, T> { /// Put the pin into input mode. #[inline] pub fn set_as_input(&mut self, pull: Pull) { - critical_section::with(|_| unsafe { + critical_section::with(|_| { let r = self.pin.block(); let n = self.pin.pin() as usize; #[cfg(gpio_v1)] @@ -84,7 +84,7 @@ impl<'d, T: Pin> Flex<'d, T> { /// at a specific level, call `set_high`/`set_low` on the pin first. #[inline] pub fn set_as_output(&mut self, speed: Speed) { - critical_section::with(|_| unsafe { + critical_section::with(|_| { let r = self.pin.block(); let n = self.pin.pin() as usize; #[cfg(gpio_v1)] @@ -116,7 +116,7 @@ impl<'d, T: Pin> Flex<'d, T> { /// at a specific level, call `set_high`/`set_low` on the pin first. #[inline] pub fn set_as_input_output(&mut self, speed: Speed, pull: Pull) { - critical_section::with(|_| unsafe { + critical_section::with(|_| { let r = self.pin.block(); let n = self.pin.pin() as usize; #[cfg(gpio_v1)] @@ -147,7 +147,7 @@ impl<'d, T: Pin> Flex<'d, T> { #[inline] pub fn is_low(&self) -> bool { - let state = unsafe { self.pin.block().idr().read().idr(self.pin.pin() as _) }; + let state = self.pin.block().idr().read().idr(self.pin.pin() as _); state == vals::Idr::LOW } @@ -164,7 +164,7 @@ impl<'d, T: Pin> Flex<'d, T> { /// Is the output pin set as low? #[inline] pub fn is_set_low(&self) -> bool { - let state = unsafe { self.pin.block().odr().read().odr(self.pin.pin() as _) }; + let state = self.pin.block().odr().read().odr(self.pin.pin() as _); state == vals::Odr::LOW } @@ -207,7 +207,7 @@ impl<'d, T: Pin> Flex<'d, T> { impl<'d, T: Pin> Drop for Flex<'d, T> { #[inline] fn drop(&mut self) { - critical_section::with(|_| unsafe { + critical_section::with(|_| { let r = self.pin.block(); let n = self.pin.pin() as usize; #[cfg(gpio_v1)] @@ -534,29 +534,25 @@ pub(crate) mod sealed { /// Set the output as high. #[inline] fn set_high(&self) { - unsafe { - let n = self._pin() as _; - self.block().bsrr().write(|w| w.set_bs(n, true)); - } + let n = self._pin() as _; + self.block().bsrr().write(|w| w.set_bs(n, true)); } /// Set the output as low. #[inline] fn set_low(&self) { - unsafe { - let n = self._pin() as _; - self.block().bsrr().write(|w| w.set_br(n, true)); - } + let n = self._pin() as _; + self.block().bsrr().write(|w| w.set_br(n, true)); } #[inline] - unsafe fn set_as_af(&self, af_num: u8, af_type: AFType) { + fn set_as_af(&self, af_num: u8, af_type: AFType) { self.set_as_af_pull(af_num, af_type, Pull::None); } #[cfg(gpio_v1)] #[inline] - unsafe fn set_as_af_pull(&self, _af_num: u8, af_type: AFType, pull: Pull) { + fn set_as_af_pull(&self, _af_num: u8, af_type: AFType, pull: Pull) { // F1 uses the AFIO register for remapping. // For now, this is not implemented, so af_num is ignored // _af_num should be zero here, since it is not set by stm32-data @@ -599,7 +595,7 @@ pub(crate) mod sealed { #[cfg(gpio_v2)] #[inline] - unsafe fn set_as_af_pull(&self, af_num: u8, af_type: AFType, pull: Pull) { + fn set_as_af_pull(&self, af_num: u8, af_type: AFType, pull: Pull) { let pin = self._pin() as usize; let block = self.block(); block.afr(pin / 8).modify(|w| w.set_afr(pin % 8, af_num)); @@ -614,7 +610,7 @@ pub(crate) mod sealed { } #[inline] - unsafe fn set_as_analog(&self) { + fn set_as_analog(&self) { let pin = self._pin() as usize; let block = self.block(); #[cfg(gpio_v1)] @@ -635,12 +631,12 @@ pub(crate) mod sealed { /// This is currently the same as set_as_analog but is semantically different really. /// Drivers should set_as_disconnected pins when dropped. #[inline] - unsafe fn set_as_disconnected(&self) { + fn set_as_disconnected(&self) { self.set_as_analog(); } #[inline] - unsafe fn set_speed(&self, speed: Speed) { + fn set_speed(&self, speed: Speed) { let pin = self._pin() as usize; #[cfg(gpio_v1)] diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index e0403888..aa485cd8 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> { T::enable(); T::reset(); - unsafe { - scl.set_as_af_pull( - scl.af_num(), - AFType::OutputOpenDrain, - match config.scl_pullup { - true => Pull::Up, - false => Pull::None, - }, - ); - sda.set_as_af_pull( - sda.af_num(), - AFType::OutputOpenDrain, - match config.sda_pullup { - true => Pull::Up, - false => Pull::None, - }, - ); - } + scl.set_as_af_pull( + scl.af_num(), + AFType::OutputOpenDrain, + match config.scl_pullup { + true => Pull::Up, + false => Pull::None, + }, + ); + sda.set_as_af_pull( + sda.af_num(), + AFType::OutputOpenDrain, + match config.sda_pullup { + true => Pull::Up, + false => Pull::None, + }, + ); - unsafe { - T::regs().cr1().modify(|reg| { - reg.set_pe(false); - //reg.set_anfoff(false); - }); - } + T::regs().cr1().modify(|reg| { + reg.set_pe(false); + //reg.set_anfoff(false); + }); let timings = Timings::new(T::frequency(), freq.into()); - unsafe { - T::regs().cr2().modify(|reg| { - reg.set_freq(timings.freq); - }); - T::regs().ccr().modify(|reg| { - reg.set_f_s(timings.mode.f_s()); - reg.set_duty(timings.duty.duty()); - reg.set_ccr(timings.ccr); - }); - T::regs().trise().modify(|reg| { - reg.set_trise(timings.trise); - }); - } + T::regs().cr2().modify(|reg| { + reg.set_freq(timings.freq); + }); + T::regs().ccr().modify(|reg| { + reg.set_f_s(timings.mode.f_s()); + reg.set_duty(timings.duty.duty()); + reg.set_ccr(timings.ccr); + }); + T::regs().trise().modify(|reg| { + reg.set_trise(timings.trise); + }); - unsafe { - T::regs().cr1().modify(|reg| { - reg.set_pe(true); - }); - } + T::regs().cr1().modify(|reg| { + reg.set_pe(true); + }); Self { phantom: PhantomData, @@ -123,7 +115,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { } } - unsafe fn check_and_clear_error_flags(&self) -> Result { + fn check_and_clear_error_flags(&self) -> Result { // Note that flags should only be cleared once they have been registered. If flags are // cleared otherwise, there may be an inherent race condition and flags may be missed. let sr1 = T::regs().sr1().read(); @@ -162,7 +154,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { Ok(sr1) } - unsafe fn write_bytes( + fn write_bytes( &mut self, addr: u8, bytes: &[u8], @@ -211,7 +203,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { Ok(()) } - unsafe fn send_byte(&self, byte: u8, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { + fn send_byte(&self, byte: u8, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { // Wait until we're ready for sending while { // 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> { Ok(()) } - unsafe fn recv_byte(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result { + fn recv_byte(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result { while { // Check for any potential error conditions. self.check_and_clear_error_flags()?; @@ -256,56 +248,52 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { ) -> Result<(), Error> { if let Some((last, buffer)) = buffer.split_last_mut() { // Send a START condition and set ACK bit - unsafe { - T::regs().cr1().modify(|reg| { - reg.set_start(true); - reg.set_ack(true); - }); - } + T::regs().cr1().modify(|reg| { + reg.set_start(true); + reg.set_ack(true); + }); // Wait until START condition was generated - while unsafe { !self.check_and_clear_error_flags()?.start() } { + while !self.check_and_clear_error_flags()?.start() { check_timeout()?; } // Also wait until signalled we're master and everything is waiting for us while { - let sr2 = unsafe { T::regs().sr2().read() }; + let sr2 = T::regs().sr2().read(); !sr2.msl() && !sr2.busy() } { check_timeout()?; } // Set up current address, we're trying to talk to - unsafe { T::regs().dr().write(|reg| reg.set_dr((addr << 1) + 1)) } + T::regs().dr().write(|reg| reg.set_dr((addr << 1) + 1)); // Wait until address was sent // Wait for the address to be acknowledged - while unsafe { !self.check_and_clear_error_flags()?.addr() } { + while !self.check_and_clear_error_flags()?.addr() { check_timeout()?; } // Clear condition by reading SR2 - let _ = unsafe { T::regs().sr2().read() }; + let _ = T::regs().sr2().read(); // Receive bytes into buffer for c in buffer { - *c = unsafe { self.recv_byte(&check_timeout)? }; + *c = self.recv_byte(&check_timeout)?; } // Prepare to send NACK then STOP after next byte - unsafe { - T::regs().cr1().modify(|reg| { - reg.set_ack(false); - reg.set_stop(true); - }) - } + T::regs().cr1().modify(|reg| { + reg.set_ack(false); + reg.set_stop(true); + }); // Receive last byte - *last = unsafe { self.recv_byte(&check_timeout)? }; + *last = self.recv_byte(&check_timeout)?; // Wait for the STOP to be sent. - while unsafe { T::regs().cr1().read().stop() } { + while T::regs().cr1().read().stop() { check_timeout()?; } @@ -326,15 +314,13 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { write: &[u8], check_timeout: impl Fn() -> Result<(), Error>, ) -> Result<(), Error> { - unsafe { - self.write_bytes(addr, write, &check_timeout)?; - // Send a STOP condition - T::regs().cr1().modify(|reg| reg.set_stop(true)); - // Wait for STOP condition to transmit. - while T::regs().cr1().read().stop() { - check_timeout()?; - } - }; + self.write_bytes(addr, write, &check_timeout)?; + // Send a STOP condition + T::regs().cr1().modify(|reg| reg.set_stop(true)); + // Wait for STOP condition to transmit. + while T::regs().cr1().read().stop() { + check_timeout()?; + } // Fallthrough is success Ok(()) @@ -351,7 +337,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { read: &mut [u8], check_timeout: impl Fn() -> Result<(), Error>, ) -> Result<(), Error> { - unsafe { self.write_bytes(addr, write, &check_timeout)? }; + self.write_bytes(addr, write, &check_timeout)?; self.blocking_read_timeout(addr, read, &check_timeout)?; Ok(()) @@ -478,8 +464,6 @@ impl Timings { assert!(freq >= 2 && freq <= 50); // Configure bus frequency into I2C peripheral - //self.i2c.cr2.write(|w| unsafe { w.freq().bits(freq as u8) }); - let trise = if speed <= 100_000 { freq + 1 } else { @@ -539,18 +523,16 @@ impl<'d, T: Instance> SetConfig for I2c<'d, T> { type Config = Hertz; fn set_config(&mut self, config: &Self::Config) { let timings = Timings::new(T::frequency(), *config); - unsafe { - T::regs().cr2().modify(|reg| { - reg.set_freq(timings.freq); - }); - T::regs().ccr().modify(|reg| { - reg.set_f_s(timings.mode.f_s()); - reg.set_duty(timings.duty.duty()); - reg.set_ccr(timings.ccr); - }); - T::regs().trise().modify(|reg| { - reg.set_trise(timings.trise); - }); - } + T::regs().cr2().modify(|reg| { + reg.set_freq(timings.freq); + }); + T::regs().ccr().modify(|reg| { + reg.set_f_s(timings.mode.f_s()); + reg.set_duty(timings.duty.duty()); + reg.set_ccr(timings.ccr); + }); + T::regs().trise().modify(|reg| { + reg.set_trise(timings.trise); + }); } } diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 1aaf2b46..1f036d55 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> { T::enable(); T::reset(); - unsafe { - scl.set_as_af_pull( - scl.af_num(), - AFType::OutputOpenDrain, - match config.scl_pullup { - true => Pull::Up, - false => Pull::None, - }, - ); - sda.set_as_af_pull( - sda.af_num(), - AFType::OutputOpenDrain, - match config.sda_pullup { - true => Pull::Up, - false => Pull::None, - }, - ); - } + scl.set_as_af_pull( + scl.af_num(), + AFType::OutputOpenDrain, + match config.scl_pullup { + true => Pull::Up, + false => Pull::None, + }, + ); + sda.set_as_af_pull( + sda.af_num(), + AFType::OutputOpenDrain, + match config.sda_pullup { + true => Pull::Up, + false => Pull::None, + }, + ); - unsafe { - T::regs().cr1().modify(|reg| { - reg.set_pe(false); - reg.set_anfoff(false); - }); - } + T::regs().cr1().modify(|reg| { + reg.set_pe(false); + reg.set_anfoff(false); + }); let timings = Timings::new(T::frequency(), freq.into()); - unsafe { - T::regs().timingr().write(|reg| { - reg.set_presc(timings.prescale); - reg.set_scll(timings.scll); - reg.set_sclh(timings.sclh); - reg.set_sdadel(timings.sdadel); - reg.set_scldel(timings.scldel); - }); - } + T::regs().timingr().write(|reg| { + reg.set_presc(timings.prescale); + reg.set_scll(timings.scll); + reg.set_sclh(timings.sclh); + reg.set_sdadel(timings.sdadel); + reg.set_scldel(timings.scldel); + }); - unsafe { - T::regs().cr1().modify(|reg| { - reg.set_pe(true); - }); - } + T::regs().cr1().modify(|reg| { + reg.set_pe(true); + }); T::Interrupt::unpend(); unsafe { T::Interrupt::enable() }; @@ -144,12 +136,10 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { } fn master_stop(&mut self) { - unsafe { - T::regs().cr2().write(|w| w.set_stop(true)); - } + T::regs().cr2().write(|w| w.set_stop(true)); } - unsafe fn master_read( + fn master_read( address: u8, length: usize, stop: Stop, @@ -191,7 +181,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { Ok(()) } - unsafe fn master_write( + fn master_write( address: u8, length: usize, stop: Stop, @@ -229,7 +219,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { Ok(()) } - unsafe fn master_continue( + fn master_continue( length: usize, reload: bool, check_timeout: impl Fn() -> Result<(), Error>, @@ -259,13 +249,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { //$i2c.txdr.write(|w| w.txdata().bits(0)); //} - unsafe { - if T::regs().isr().read().txis() { - T::regs().txdr().write(|w| w.set_txdata(0)); - } - if !T::regs().isr().read().txe() { - T::regs().isr().modify(|w| w.set_txe(true)) - } + if T::regs().isr().read().txis() { + T::regs().txdr().write(|w| w.set_txdata(0)); + } + if !T::regs().isr().read().txe() { + T::regs().isr().modify(|w| w.set_txe(true)) } // 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> { fn wait_txe(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { loop { - unsafe { - let isr = T::regs().isr().read(); - if isr.txe() { - return Ok(()); - } else if isr.berr() { - T::regs().icr().write(|reg| reg.set_berrcf(true)); - return Err(Error::Bus); - } else if isr.arlo() { - T::regs().icr().write(|reg| reg.set_arlocf(true)); - return Err(Error::Arbitration); - } else if isr.nackf() { - T::regs().icr().write(|reg| reg.set_nackcf(true)); - self.flush_txdr(); - return Err(Error::Nack); - } + let isr = T::regs().isr().read(); + if isr.txe() { + return Ok(()); + } else if isr.berr() { + T::regs().icr().write(|reg| reg.set_berrcf(true)); + return Err(Error::Bus); + } else if isr.arlo() { + T::regs().icr().write(|reg| reg.set_arlocf(true)); + return Err(Error::Arbitration); + } else if isr.nackf() { + T::regs().icr().write(|reg| reg.set_nackcf(true)); + self.flush_txdr(); + return Err(Error::Nack); } check_timeout()?; @@ -299,21 +285,19 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { fn wait_rxne(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { loop { - unsafe { - let isr = T::regs().isr().read(); - if isr.rxne() { - return Ok(()); - } else if isr.berr() { - T::regs().icr().write(|reg| reg.set_berrcf(true)); - return Err(Error::Bus); - } else if isr.arlo() { - T::regs().icr().write(|reg| reg.set_arlocf(true)); - return Err(Error::Arbitration); - } else if isr.nackf() { - T::regs().icr().write(|reg| reg.set_nackcf(true)); - self.flush_txdr(); - return Err(Error::Nack); - } + let isr = T::regs().isr().read(); + if isr.rxne() { + return Ok(()); + } else if isr.berr() { + T::regs().icr().write(|reg| reg.set_berrcf(true)); + return Err(Error::Bus); + } else if isr.arlo() { + T::regs().icr().write(|reg| reg.set_arlocf(true)); + return Err(Error::Arbitration); + } else if isr.nackf() { + T::regs().icr().write(|reg| reg.set_nackcf(true)); + self.flush_txdr(); + return Err(Error::Nack); } check_timeout()?; @@ -322,21 +306,19 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { fn wait_tc(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { loop { - unsafe { - let isr = T::regs().isr().read(); - if isr.tc() { - return Ok(()); - } else if isr.berr() { - T::regs().icr().write(|reg| reg.set_berrcf(true)); - return Err(Error::Bus); - } else if isr.arlo() { - T::regs().icr().write(|reg| reg.set_arlocf(true)); - return Err(Error::Arbitration); - } else if isr.nackf() { - T::regs().icr().write(|reg| reg.set_nackcf(true)); - self.flush_txdr(); - return Err(Error::Nack); - } + let isr = T::regs().isr().read(); + if isr.tc() { + return Ok(()); + } else if isr.berr() { + T::regs().icr().write(|reg| reg.set_berrcf(true)); + return Err(Error::Bus); + } else if isr.arlo() { + T::regs().icr().write(|reg| reg.set_arlocf(true)); + return Err(Error::Arbitration); + } else if isr.nackf() { + T::regs().icr().write(|reg| reg.set_nackcf(true)); + self.flush_txdr(); + return Err(Error::Nack); } check_timeout()?; @@ -358,32 +340,25 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { }; let last_chunk_idx = total_chunks.saturating_sub(1); - unsafe { - Self::master_read( - address, - read.len().min(255), - Stop::Automatic, - last_chunk_idx != 0, - restart, - &check_timeout, - )?; - } + Self::master_read( + address, + read.len().min(255), + Stop::Automatic, + last_chunk_idx != 0, + restart, + &check_timeout, + )?; for (number, chunk) in read.chunks_mut(255).enumerate() { if number != 0 { - // NOTE(unsafe) We have &mut self - unsafe { - Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?; - } + Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?; } for byte in chunk { // Wait until we have received something self.wait_rxne(&check_timeout)?; - unsafe { - *byte = T::regs().rxdr().read().rxdata(); - } + *byte = T::regs().rxdr().read().rxdata(); } } Ok(()) @@ -407,23 +382,17 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { // I2C start // // ST SAD+W - // NOTE(unsafe) We have &mut self - unsafe { - Self::master_write( - address, - write.len().min(255), - Stop::Software, - last_chunk_idx != 0, - &check_timeout, - )?; - } + Self::master_write( + address, + write.len().min(255), + Stop::Software, + last_chunk_idx != 0, + &check_timeout, + )?; for (number, chunk) in write.chunks(255).enumerate() { if number != 0 { - // NOTE(unsafe) We have &mut self - unsafe { - Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?; - } + Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?; } for byte in chunk { @@ -432,9 +401,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { // through) self.wait_txe(&check_timeout)?; - unsafe { - T::regs().txdr().write(|w| w.set_txdata(*byte)); - } + T::regs().txdr().write(|w| w.set_txdata(*byte)); } } // Wait until the write finishes @@ -467,7 +434,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { w.set_tcie(true); } }); - let dst = regs.txdr().ptr() as *mut u8; + let dst = regs.txdr().as_ptr() as *mut u8; let ch = &mut self.tx_dma; let request = ch.request(); @@ -479,37 +446,30 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { let on_drop = OnDrop::new(|| { let regs = T::regs(); - unsafe { - regs.cr1().modify(|w| { - if last_slice { - w.set_txdmaen(false); - } - w.set_tcie(false); - }) - } + regs.cr1().modify(|w| { + if last_slice { + w.set_txdmaen(false); + } + w.set_tcie(false); + }) }); poll_fn(|cx| { state.waker.register(cx.waker()); - let isr = unsafe { T::regs().isr().read() }; + let isr = T::regs().isr().read(); if remaining_len == total_len { - // NOTE(unsafe) self.tx_dma does not fiddle with the i2c registers if first_slice { - unsafe { - Self::master_write( - address, - total_len.min(255), - Stop::Software, - (total_len > 255) || !last_slice, - &check_timeout, - )?; - } + Self::master_write( + address, + total_len.min(255), + Stop::Software, + (total_len > 255) || !last_slice, + &check_timeout, + )?; } else { - unsafe { - Self::master_continue(total_len.min(255), (total_len > 255) || !last_slice, &check_timeout)?; - T::regs().cr1().modify(|w| w.set_tcie(true)); - } + Self::master_continue(total_len.min(255), (total_len > 255) || !last_slice, &check_timeout)?; + T::regs().cr1().modify(|w| w.set_tcie(true)); } } else if !(isr.tcr() || isr.tc()) { // poll_fn was woken without an interrupt present @@ -519,13 +479,10 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { } else { let last_piece = (remaining_len <= 255) && last_slice; - // NOTE(unsafe) self.tx_dma does not fiddle with the i2c registers - unsafe { - if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) { - return Poll::Ready(Err(e)); - } - T::regs().cr1().modify(|w| w.set_tcie(true)); + if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) { + return Poll::Ready(Err(e)); } + T::regs().cr1().modify(|w| w.set_tcie(true)); } remaining_len = remaining_len.saturating_sub(255); @@ -564,7 +521,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { w.set_rxdmaen(true); w.set_tcie(true); }); - let src = regs.rxdr().ptr() as *mut u8; + let src = regs.rxdr().as_ptr() as *mut u8; let ch = &mut self.rx_dma; let request = ch.request(); @@ -576,30 +533,25 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { let on_drop = OnDrop::new(|| { let regs = T::regs(); - unsafe { - regs.cr1().modify(|w| { - w.set_rxdmaen(false); - w.set_tcie(false); - }) - } + regs.cr1().modify(|w| { + w.set_rxdmaen(false); + w.set_tcie(false); + }) }); poll_fn(|cx| { state.waker.register(cx.waker()); - let isr = unsafe { T::regs().isr().read() }; + let isr = T::regs().isr().read(); if remaining_len == total_len { - // NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers - unsafe { - Self::master_read( - address, - total_len.min(255), - Stop::Software, - total_len > 255, - restart, - &check_timeout, - )?; - } + Self::master_read( + address, + total_len.min(255), + Stop::Software, + total_len > 255, + restart, + &check_timeout, + )?; } else if !(isr.tcr() || isr.tc()) { // poll_fn was woken without an interrupt present return Poll::Pending; @@ -608,13 +560,10 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { } else { let last_piece = remaining_len <= 255; - // NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers - unsafe { - if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) { - return Poll::Ready(Err(e)); - } - T::regs().cr1().modify(|w| w.set_tcie(true)); + if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) { + return Poll::Ready(Err(e)); } + T::regs().cr1().modify(|w| w.set_tcie(true)); } remaining_len = remaining_len.saturating_sub(255); @@ -758,16 +707,13 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { let first_length = write[0].len(); let last_slice_index = write.len() - 1; - // NOTE(unsafe) We have &mut self - unsafe { - Self::master_write( - address, - first_length.min(255), - Stop::Software, - (first_length > 255) || (last_slice_index != 0), - &check_timeout, - )?; - } + Self::master_write( + address, + first_length.min(255), + Stop::Software, + (first_length > 255) || (last_slice_index != 0), + &check_timeout, + )?; for (idx, slice) in write.iter().enumerate() { let slice_len = slice.len(); @@ -780,26 +726,20 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { let last_chunk_idx = total_chunks.saturating_sub(1); if idx != 0 { - // NOTE(unsafe) We have &mut self - unsafe { - Self::master_continue( - slice_len.min(255), - (idx != last_slice_index) || (slice_len > 255), - &check_timeout, - )?; - } + Self::master_continue( + slice_len.min(255), + (idx != last_slice_index) || (slice_len > 255), + &check_timeout, + )?; } for (number, chunk) in slice.chunks(255).enumerate() { if number != 0 { - // NOTE(unsafe) We have &mut self - unsafe { - Self::master_continue( - chunk.len(), - (number != last_chunk_idx) || (idx != last_slice_index), - &check_timeout, - )?; - } + Self::master_continue( + chunk.len(), + (number != last_chunk_idx) || (idx != last_slice_index), + &check_timeout, + )?; } for byte in chunk { @@ -810,9 +750,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { // Put byte on the wire //self.i2c.txdr.write(|w| w.txdata().bits(*byte)); - unsafe { - T::regs().txdr().write(|w| w.set_txdata(*byte)); - } + T::regs().txdr().write(|w| w.set_txdata(*byte)); } } } @@ -1061,14 +999,12 @@ impl<'d, T: Instance> SetConfig for I2c<'d, T> { type Config = Hertz; fn set_config(&mut self, config: &Self::Config) { let timings = Timings::new(T::frequency(), *config); - unsafe { - T::regs().timingr().write(|reg| { - reg.set_presc(timings.prescale); - reg.set_scll(timings.scll); - reg.set_sclh(timings.sclh); - reg.set_sdadel(timings.sdadel); - reg.set_scldel(timings.scldel); - }); - } + T::regs().timingr().write(|reg| { + reg.set_presc(timings.prescale); + reg.set_scll(timings.scll); + reg.set_sclh(timings.sclh); + reg.set_sdadel(timings.sdadel); + reg.set_scldel(timings.scldel); + }); } } diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs index 2bb199f6..62dda69b 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> { ) -> Self { into_ref!(sd, ws, ck, mck); - unsafe { - sd.set_as_af(sd.af_num(), AFType::OutputPushPull); - sd.set_speed(crate::gpio::Speed::VeryHigh); + sd.set_as_af(sd.af_num(), AFType::OutputPushPull); + sd.set_speed(crate::gpio::Speed::VeryHigh); - ws.set_as_af(ws.af_num(), AFType::OutputPushPull); - ws.set_speed(crate::gpio::Speed::VeryHigh); + ws.set_as_af(ws.af_num(), AFType::OutputPushPull); + ws.set_speed(crate::gpio::Speed::VeryHigh); - ck.set_as_af(ck.af_num(), AFType::OutputPushPull); - ck.set_speed(crate::gpio::Speed::VeryHigh); + ck.set_as_af(ck.af_num(), AFType::OutputPushPull); + ck.set_speed(crate::gpio::Speed::VeryHigh); - mck.set_as_af(mck.af_num(), AFType::OutputPushPull); - mck.set_speed(crate::gpio::Speed::VeryHigh); - } + mck.set_as_af(mck.af_num(), AFType::OutputPushPull); + mck.set_speed(crate::gpio::Speed::VeryHigh); let spi = Spi::new_internal(peri, txdma, rxdma, freq, SpiConfig::default()); @@ -178,7 +176,7 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> { let (odd, div) = compute_baud_rate(pclk, freq, config.master_clock, config.format); #[cfg(any(spi_v1, spi_f1))] - unsafe { + { use stm32_metapac::spi::vals::{I2scfg, Odd}; // 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> { w.set_i2se(true) }); } - #[cfg(spi_v2)] - unsafe {} - #[cfg(any(spi_v3, spi_v4))] - unsafe {} Self { _peri: spi, @@ -264,12 +258,10 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> { impl<'d, T: Instance, Tx, Rx> Drop for I2S<'d, T, Tx, Rx> { fn drop(&mut self) { - unsafe { - self.sd.as_ref().map(|x| x.set_as_disconnected()); - self.ws.as_ref().map(|x| x.set_as_disconnected()); - self.ck.as_ref().map(|x| x.set_as_disconnected()); - self.mck.as_ref().map(|x| x.set_as_disconnected()); - } + self.sd.as_ref().map(|x| x.set_as_disconnected()); + self.ws.as_ref().map(|x| x.set_as_disconnected()); + self.ck.as_ref().map(|x| x.set_as_disconnected()); + self.mck.as_ref().map(|x| x.set_as_disconnected()); } } diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs index 609c4d2c..3062226c 100644 --- a/embassy-stm32/src/ipcc.rs +++ b/embassy-stm32/src/ipcc.rs @@ -26,7 +26,7 @@ impl interrupt::typelevel::Handler for Receive ]; // Status register gives channel occupied status. For rx, use cpu1. - let sr = unsafe { regs.cpu(1).sr().read() }; + let sr = regs.cpu(1).sr().read(); regs.cpu(0).mr().modify(|w| { for channel in channels { if sr.chf(channel as usize) { @@ -57,7 +57,7 @@ impl interrupt::typelevel::Handler for Transmi ]; // Status register gives channel occupied status. For tx, use cpu0. - let sr = unsafe { regs.cpu(0).sr().read() }; + let sr = regs.cpu(0).sr().read(); regs.cpu(0).mr().modify(|w| { for channel in channels { if !sr.chf(channel as usize) { @@ -98,16 +98,14 @@ impl Ipcc { IPCC::reset(); IPCC::set_cpu2(true); - unsafe { _configure_pwr() }; + _configure_pwr(); let regs = IPCC::regs(); - unsafe { - regs.cpu(0).cr().modify(|w| { - w.set_rxoie(true); - w.set_txfie(true); - }) - } + regs.cpu(0).cr().modify(|w| { + w.set_rxoie(true); + w.set_txfie(true); + }); // enable interrupts crate::interrupt::typelevel::IPCC_C1_RX::unpend(); @@ -129,7 +127,7 @@ impl Ipcc { compiler_fence(Ordering::SeqCst); trace!("ipcc: ch {}: send data", channel as u8); - unsafe { regs.cpu(0).scr().write(|w| w.set_chs(channel as usize, true)) } + regs.cpu(0).scr().write(|w| w.set_chs(channel as usize, true)); } /// Wait for the tx channel to become clear @@ -137,20 +135,20 @@ impl Ipcc { let regs = IPCC::regs(); // This is a race, but is nice for debugging - if unsafe { regs.cpu(0).sr().read() }.chf(channel as usize) { + if regs.cpu(0).sr().read().chf(channel as usize) { trace!("ipcc: ch {}: wait for tx free", channel as u8); } poll_fn(|cx| { IPCC::state().tx_waker_for(channel).register(cx.waker()); // If bit is set to 1 then interrupt is disabled; we want to enable the interrupt - unsafe { regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, false)) } + regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, false)); compiler_fence(Ordering::SeqCst); - if !unsafe { regs.cpu(0).sr().read() }.chf(channel as usize) { + if !regs.cpu(0).sr().read().chf(channel as usize) { // If bit is set to 1 then interrupt is disabled; we want to disable the interrupt - unsafe { regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, true)) } + regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, true)); Poll::Ready(()) } else { @@ -166,20 +164,20 @@ impl Ipcc { loop { // This is a race, but is nice for debugging - if !unsafe { regs.cpu(1).sr().read() }.chf(channel as usize) { + if !regs.cpu(1).sr().read().chf(channel as usize) { trace!("ipcc: ch {}: wait for rx occupied", channel as u8); } poll_fn(|cx| { IPCC::state().rx_waker_for(channel).register(cx.waker()); // If bit is set to 1 then interrupt is disabled; we want to enable the interrupt - unsafe { regs.cpu(0).mr().modify(|w| w.set_chom(channel as usize, false)) } + regs.cpu(0).mr().modify(|w| w.set_chom(channel as usize, false)); compiler_fence(Ordering::SeqCst); - if unsafe { regs.cpu(1).sr().read() }.chf(channel as usize) { + if regs.cpu(1).sr().read().chf(channel as usize) { // If bit is set to 1 then interrupt is disabled; we want to disable the interrupt - unsafe { regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, true)) } + regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, true)); Poll::Ready(()) } else { @@ -199,7 +197,7 @@ impl Ipcc { trace!("ipcc: ch {}: clear rx", channel as u8); compiler_fence(Ordering::SeqCst); // If the channel is clear and the read function returns none, fetch more data - unsafe { regs.cpu(0).scr().write(|w| w.set_chc(channel as usize, true)) } + regs.cpu(0).scr().write(|w| w.set_chc(channel as usize, true)); } } } @@ -210,7 +208,7 @@ impl sealed::Instance for crate::peripherals::IPCC { } fn set_cpu2(enabled: bool) { - unsafe { crate::pac::PWR.cr4().modify(|w| w.set_c2boot(enabled)) } + crate::pac::PWR.cr4().modify(|w| w.set_c2boot(enabled)); } fn state() -> &'static self::sealed::State { @@ -269,7 +267,7 @@ pub(crate) mod sealed { } } -unsafe fn _configure_pwr() { +fn _configure_pwr() { // TODO: move this to RCC let pwr = crate::pac::PWR; diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 6fde61c0..45a7b547 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -146,35 +146,35 @@ impl Default for Config { pub fn init(config: Config) -> Peripherals { let p = Peripherals::take(); - unsafe { - #[cfg(dbgmcu)] - if config.enable_debug_during_sleep { - crate::pac::DBGMCU.cr().modify(|cr| { - #[cfg(any(dbgmcu_f0, dbgmcu_c0, dbgmcu_g0, dbgmcu_u5))] - { - cr.set_dbg_stop(true); - cr.set_dbg_standby(true); - } - #[cfg(any( - dbgmcu_f1, dbgmcu_f2, dbgmcu_f3, dbgmcu_f4, dbgmcu_f7, dbgmcu_g4, dbgmcu_f7, dbgmcu_l0, dbgmcu_l1, - dbgmcu_l4, dbgmcu_wb, dbgmcu_wl - ))] - { - cr.set_dbg_sleep(true); - cr.set_dbg_stop(true); - cr.set_dbg_standby(true); - } - #[cfg(dbgmcu_h7)] - { - cr.set_d1dbgcken(true); - cr.set_d3dbgcken(true); - cr.set_dbgsleep_d1(true); - cr.set_dbgstby_d1(true); - cr.set_dbgstop_d1(true); - } - }); - } + #[cfg(dbgmcu)] + if config.enable_debug_during_sleep { + crate::pac::DBGMCU.cr().modify(|cr| { + #[cfg(any(dbgmcu_f0, dbgmcu_c0, dbgmcu_g0, dbgmcu_u5))] + { + cr.set_dbg_stop(true); + cr.set_dbg_standby(true); + } + #[cfg(any( + dbgmcu_f1, dbgmcu_f2, dbgmcu_f3, dbgmcu_f4, dbgmcu_f7, dbgmcu_g4, dbgmcu_f7, dbgmcu_l0, dbgmcu_l1, + dbgmcu_l4, dbgmcu_wb, dbgmcu_wl + ))] + { + cr.set_dbg_sleep(true); + cr.set_dbg_stop(true); + cr.set_dbg_standby(true); + } + #[cfg(dbgmcu_h7)] + { + cr.set_d1dbgcken(true); + cr.set_d3dbgcken(true); + cr.set_dbgsleep_d1(true); + cr.set_dbgstby_d1(true); + cr.set_dbgstop_d1(true); + } + }); + } + unsafe { gpio::init(); dma::init( #[cfg(bdma)] diff --git a/embassy-stm32/src/pwm/complementary_pwm.rs b/embassy-stm32/src/pwm/complementary_pwm.rs index cfb79947..0e153202 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 { impl<'d, Perip: CaptureCompare16bitInstance> ComplementaryPwmPin<'d, Perip, $channel> { pub fn $new_chx(pin: impl Peripheral

> + 'd) -> Self { into_ref!(pin); - critical_section::with(|_| unsafe { + critical_section::with(|_| { pin.set_low(); pin.set_as_af(pin.af_num(), AFType::OutputPushPull); #[cfg(gpio_v2)] @@ -72,33 +72,27 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { this.inner.set_frequency(freq); this.inner.start(); - unsafe { - this.inner.enable_outputs(true); + this.inner.enable_outputs(true); - this.inner - .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1); - this.inner - .set_output_compare_mode(Channel::Ch2, OutputCompareMode::PwmMode1); - this.inner - .set_output_compare_mode(Channel::Ch3, OutputCompareMode::PwmMode1); - this.inner - .set_output_compare_mode(Channel::Ch4, OutputCompareMode::PwmMode1); - } + this.inner + .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1); + this.inner + .set_output_compare_mode(Channel::Ch2, OutputCompareMode::PwmMode1); + this.inner + .set_output_compare_mode(Channel::Ch3, OutputCompareMode::PwmMode1); + this.inner + .set_output_compare_mode(Channel::Ch4, OutputCompareMode::PwmMode1); this } pub fn enable(&mut self, channel: Channel) { - unsafe { - self.inner.enable_channel(channel, true); - self.inner.enable_complementary_channel(channel, true); - } + self.inner.enable_channel(channel, true); + self.inner.enable_complementary_channel(channel, true); } pub fn disable(&mut self, channel: Channel) { - unsafe { - self.inner.enable_complementary_channel(channel, false); - self.inner.enable_channel(channel, false); - } + self.inner.enable_complementary_channel(channel, false); + self.inner.enable_channel(channel, false); } pub fn set_freq(&mut self, freq: Hertz) { @@ -106,22 +100,20 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { } pub fn get_max_duty(&self) -> u16 { - unsafe { self.inner.get_max_compare_value() } + self.inner.get_max_compare_value() } pub fn set_duty(&mut self, channel: Channel, duty: u16) { assert!(duty < self.get_max_duty()); - unsafe { self.inner.set_compare_value(channel, duty) } + self.inner.set_compare_value(channel, duty) } /// Set the dead time as a proportion of max_duty pub fn set_dead_time(&mut self, value: u16) { let (ckd, value) = compute_dead_time_value(value); - unsafe { - self.inner.set_dead_time_clock_division(ckd); - self.inner.set_dead_time_value(value); - } + self.inner.set_dead_time_clock_division(ckd); + self.inner.set_dead_time_value(value); } } diff --git a/embassy-stm32/src/pwm/mod.rs b/embassy-stm32/src/pwm/mod.rs index 0bef0708..5aba2663 100644 --- a/embassy-stm32/src/pwm/mod.rs +++ b/embassy-stm32/src/pwm/mod.rs @@ -59,33 +59,33 @@ pub(crate) mod sealed { pub trait CaptureCompare16bitInstance: crate::timer::sealed::GeneralPurpose16bitInstance { /// Global output enable. Does not do anything on non-advanced timers. - unsafe fn enable_outputs(&mut self, enable: bool); + fn enable_outputs(&mut self, enable: bool); - unsafe fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); + fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); - unsafe fn enable_channel(&mut self, channel: Channel, enable: bool); + fn enable_channel(&mut self, channel: Channel, enable: bool); - unsafe fn set_compare_value(&mut self, channel: Channel, value: u16); + fn set_compare_value(&mut self, channel: Channel, value: u16); - unsafe fn get_max_compare_value(&self) -> u16; + fn get_max_compare_value(&self) -> u16; } pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance { - unsafe fn set_dead_time_clock_division(&mut self, value: Ckd); + fn set_dead_time_clock_division(&mut self, value: Ckd); - unsafe fn set_dead_time_value(&mut self, value: u8); + fn set_dead_time_value(&mut self, value: u8); - unsafe fn enable_complementary_channel(&mut self, channel: Channel, enable: bool); + fn enable_complementary_channel(&mut self, channel: Channel, enable: bool); } pub trait CaptureCompare32bitInstance: crate::timer::sealed::GeneralPurpose32bitInstance { - unsafe fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); + fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); - unsafe fn enable_channel(&mut self, channel: Channel, enable: bool); + fn enable_channel(&mut self, channel: Channel, enable: bool); - unsafe fn set_compare_value(&mut self, channel: Channel, value: u32); + fn set_compare_value(&mut self, channel: Channel, value: u32); - unsafe fn get_max_compare_value(&self) -> u32; + fn get_max_compare_value(&self) -> u32; } } @@ -108,9 +108,9 @@ pub trait CaptureCompare32bitInstance: macro_rules! impl_compare_capable_16bit { ($inst:ident) => { impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { - unsafe fn enable_outputs(&mut self, _enable: bool) {} + fn enable_outputs(&mut self, _enable: bool) {} - unsafe fn set_output_compare_mode(&mut self, channel: crate::pwm::Channel, mode: OutputCompareMode) { + fn set_output_compare_mode(&mut self, channel: crate::pwm::Channel, mode: OutputCompareMode) { use crate::timer::sealed::GeneralPurpose16bitInstance; let r = Self::regs_gp16(); let raw_channel: usize = channel.raw(); @@ -118,19 +118,19 @@ macro_rules! impl_compare_capable_16bit { .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); } - unsafe fn enable_channel(&mut self, channel: Channel, enable: bool) { + fn enable_channel(&mut self, channel: Channel, enable: bool) { use crate::timer::sealed::GeneralPurpose16bitInstance; Self::regs_gp16() .ccer() .modify(|w| w.set_cce(channel.raw(), enable)); } - unsafe fn set_compare_value(&mut self, channel: Channel, value: u16) { + fn set_compare_value(&mut self, channel: Channel, value: u16) { use crate::timer::sealed::GeneralPurpose16bitInstance; Self::regs_gp16().ccr(channel.raw()).modify(|w| w.set_ccr(value)); } - unsafe fn get_max_compare_value(&self) -> u16 { + fn get_max_compare_value(&self) -> u16 { use crate::timer::sealed::GeneralPurpose16bitInstance; Self::regs_gp16().arr().read().arr() } @@ -150,7 +150,7 @@ foreach_interrupt! { ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => { impl_compare_capable_16bit!($inst); impl crate::pwm::sealed::CaptureCompare32bitInstance for crate::peripherals::$inst { - unsafe fn set_output_compare_mode( + fn set_output_compare_mode( &mut self, channel: crate::pwm::Channel, mode: OutputCompareMode, @@ -160,17 +160,17 @@ foreach_interrupt! { Self::regs_gp32().ccmr_output(raw_channel / 2).modify(|w| w.set_ocm(raw_channel % 2, mode.into())); } - unsafe fn enable_channel(&mut self, channel: Channel, enable: bool) { + fn enable_channel(&mut self, channel: Channel, enable: bool) { use crate::timer::sealed::GeneralPurpose32bitInstance; Self::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), enable)); } - unsafe fn set_compare_value(&mut self, channel: Channel, value: u32) { + fn set_compare_value(&mut self, channel: Channel, value: u32) { use crate::timer::sealed::GeneralPurpose32bitInstance; Self::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(value)); } - unsafe fn get_max_compare_value(&self) -> u32 { + fn get_max_compare_value(&self) -> u32 { use crate::timer::sealed::GeneralPurpose32bitInstance; Self::regs_gp32().arr().read().arr() as u32 } @@ -185,13 +185,13 @@ foreach_interrupt! { ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => { impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { - unsafe fn enable_outputs(&mut self, enable: bool) { + fn enable_outputs(&mut self, enable: bool) { use crate::timer::sealed::AdvancedControlInstance; let r = Self::regs_advanced(); r.bdtr().modify(|w| w.set_moe(enable)); } - unsafe fn set_output_compare_mode( + fn set_output_compare_mode( &mut self, channel: crate::pwm::Channel, mode: OutputCompareMode, @@ -203,21 +203,21 @@ foreach_interrupt! { .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); } - unsafe fn enable_channel(&mut self, channel: Channel, enable: bool) { + fn enable_channel(&mut self, channel: Channel, enable: bool) { use crate::timer::sealed::AdvancedControlInstance; Self::regs_advanced() .ccer() .modify(|w| w.set_cce(channel.raw(), enable)); } - unsafe fn set_compare_value(&mut self, channel: Channel, value: u16) { + fn set_compare_value(&mut self, channel: Channel, value: u16) { use crate::timer::sealed::AdvancedControlInstance; Self::regs_advanced() .ccr(channel.raw()) .modify(|w| w.set_ccr(value)); } - unsafe fn get_max_compare_value(&self) -> u16 { + fn get_max_compare_value(&self) -> u16 { use crate::timer::sealed::AdvancedControlInstance; Self::regs_advanced().arr().read().arr() } @@ -228,17 +228,17 @@ foreach_interrupt! { } impl crate::pwm::sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst { - unsafe fn set_dead_time_clock_division(&mut self, value: Ckd) { + fn set_dead_time_clock_division(&mut self, value: Ckd) { use crate::timer::sealed::AdvancedControlInstance; Self::regs_advanced().cr1().modify(|w| w.set_ckd(value)); } - unsafe fn set_dead_time_value(&mut self, value: u8) { + fn set_dead_time_value(&mut self, value: u8) { use crate::timer::sealed::AdvancedControlInstance; Self::regs_advanced().bdtr().modify(|w| w.set_dtg(value)); } - unsafe fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) { + fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) { use crate::timer::sealed::AdvancedControlInstance; Self::regs_advanced() .ccer() diff --git a/embassy-stm32/src/pwm/simple_pwm.rs b/embassy-stm32/src/pwm/simple_pwm.rs index b045a2d7..995f59c2 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 { impl<'d, Perip: CaptureCompare16bitInstance> PwmPin<'d, Perip, $channel> { pub fn $new_chx(pin: impl Peripheral

> + 'd) -> Self { into_ref!(pin); - critical_section::with(|_| unsafe { + critical_section::with(|_| { pin.set_low(); pin.set_as_af(pin.af_num(), AFType::OutputPushPull); #[cfg(gpio_v2)] @@ -71,31 +71,25 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { this.inner.set_frequency(freq); this.inner.start(); - unsafe { - this.inner.enable_outputs(true); + this.inner.enable_outputs(true); - this.inner - .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1); - this.inner - .set_output_compare_mode(Channel::Ch2, OutputCompareMode::PwmMode1); - this.inner - .set_output_compare_mode(Channel::Ch3, OutputCompareMode::PwmMode1); - this.inner - .set_output_compare_mode(Channel::Ch4, OutputCompareMode::PwmMode1); - } + this.inner + .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1); + this.inner + .set_output_compare_mode(Channel::Ch2, OutputCompareMode::PwmMode1); + this.inner + .set_output_compare_mode(Channel::Ch3, OutputCompareMode::PwmMode1); + this.inner + .set_output_compare_mode(Channel::Ch4, OutputCompareMode::PwmMode1); this } pub fn enable(&mut self, channel: Channel) { - unsafe { - self.inner.enable_channel(channel, true); - } + self.inner.enable_channel(channel, true); } pub fn disable(&mut self, channel: Channel) { - unsafe { - self.inner.enable_channel(channel, false); - } + self.inner.enable_channel(channel, false); } pub fn set_freq(&mut self, freq: Hertz) { @@ -103,11 +97,11 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { } pub fn get_max_duty(&self) -> u16 { - unsafe { self.inner.get_max_compare_value() } + self.inner.get_max_compare_value() } pub fn set_duty(&mut self, channel: Channel, duty: u16) { assert!(duty < self.get_max_duty()); - unsafe { self.inner.set_compare_value(channel, duty) } + self.inner.set_compare_value(channel, duty) } } diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs index c3126b37..e9db934b 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> { ) -> Self { into_ref!(peri, d0, d1, d2, d3, sck, nss); - unsafe { - sck.set_as_af(sck.af_num(), AFType::OutputPushPull); - sck.set_speed(crate::gpio::Speed::VeryHigh); - nss.set_as_af(nss.af_num(), AFType::OutputPushPull); - nss.set_speed(crate::gpio::Speed::VeryHigh); - d0.set_as_af(d0.af_num(), AFType::OutputPushPull); - d0.set_speed(crate::gpio::Speed::VeryHigh); - d1.set_as_af(d1.af_num(), AFType::OutputPushPull); - d1.set_speed(crate::gpio::Speed::VeryHigh); - d2.set_as_af(d2.af_num(), AFType::OutputPushPull); - d2.set_speed(crate::gpio::Speed::VeryHigh); - d3.set_as_af(d3.af_num(), AFType::OutputPushPull); - d3.set_speed(crate::gpio::Speed::VeryHigh); - } + sck.set_as_af(sck.af_num(), AFType::OutputPushPull); + sck.set_speed(crate::gpio::Speed::VeryHigh); + nss.set_as_af(nss.af_num(), AFType::OutputPushPull); + nss.set_speed(crate::gpio::Speed::VeryHigh); + d0.set_as_af(d0.af_num(), AFType::OutputPushPull); + d0.set_speed(crate::gpio::Speed::VeryHigh); + d1.set_as_af(d1.af_num(), AFType::OutputPushPull); + d1.set_speed(crate::gpio::Speed::VeryHigh); + d2.set_as_af(d2.af_num(), AFType::OutputPushPull); + d2.set_speed(crate::gpio::Speed::VeryHigh); + d3.set_as_af(d3.af_num(), AFType::OutputPushPull); + d3.set_speed(crate::gpio::Speed::VeryHigh); Self::new_inner( peri, @@ -138,21 +136,19 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { into_ref!(peri, dma); T::enable(); - unsafe { - T::REGS.cr().write(|w| w.set_fthres(config.fifo_threshold.into())); + T::REGS.cr().write(|w| w.set_fthres(config.fifo_threshold.into())); - while T::REGS.sr().read().busy() {} + while T::REGS.sr().read().busy() {} - T::REGS.cr().write(|w| { - w.set_prescaler(config.prescaler); - w.set_en(true); - }); - T::REGS.dcr().write(|w| { - w.set_fsize(config.memory_size.into()); - w.set_csht(config.cs_high_time.into()); - w.set_ckmode(false); - }); - } + T::REGS.cr().write(|w| { + w.set_prescaler(config.prescaler); + w.set_en(true); + }); + T::REGS.dcr().write(|w| { + w.set_fsize(config.memory_size.into()); + w.set_csht(config.cs_high_time.into()); + w.set_ckmode(false); + }); Self { _peri: peri, @@ -168,148 +164,140 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { } pub fn command(&mut self, transaction: TransferConfig) { - unsafe { - T::REGS.cr().modify(|v| v.set_dmaen(false)); - self.setup_transaction(QspiMode::IndirectWrite, &transaction); + T::REGS.cr().modify(|v| v.set_dmaen(false)); + self.setup_transaction(QspiMode::IndirectWrite, &transaction); - while !T::REGS.sr().read().tcf() {} - T::REGS.fcr().modify(|v| v.set_ctcf(true)); - } + while !T::REGS.sr().read().tcf() {} + T::REGS.fcr().modify(|v| v.set_ctcf(true)); } pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) { - unsafe { - T::REGS.cr().modify(|v| v.set_dmaen(false)); - self.setup_transaction(QspiMode::IndirectWrite, &transaction); + T::REGS.cr().modify(|v| v.set_dmaen(false)); + self.setup_transaction(QspiMode::IndirectWrite, &transaction); - if let Some(len) = transaction.data_len { - let current_ar = T::REGS.ar().read().address(); - T::REGS.ccr().modify(|v| { - v.set_fmode(QspiMode::IndirectRead.into()); - }); - T::REGS.ar().write(|v| { - v.set_address(current_ar); - }); + if let Some(len) = transaction.data_len { + let current_ar = T::REGS.ar().read().address(); + T::REGS.ccr().modify(|v| { + v.set_fmode(QspiMode::IndirectRead.into()); + }); + T::REGS.ar().write(|v| { + v.set_address(current_ar); + }); - for idx in 0..len { - while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {} - buf[idx] = *(T::REGS.dr().ptr() as *mut u8); - } + for idx in 0..len { + while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {} + buf[idx] = unsafe { (T::REGS.dr().as_ptr() as *mut u8).read_volatile() }; } - - while !T::REGS.sr().read().tcf() {} - T::REGS.fcr().modify(|v| v.set_ctcf(true)); } + + while !T::REGS.sr().read().tcf() {} + T::REGS.fcr().modify(|v| v.set_ctcf(true)); } pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) { - unsafe { - T::REGS.cr().modify(|v| v.set_dmaen(false)); - self.setup_transaction(QspiMode::IndirectWrite, &transaction); + T::REGS.cr().modify(|v| v.set_dmaen(false)); + self.setup_transaction(QspiMode::IndirectWrite, &transaction); - if let Some(len) = transaction.data_len { - T::REGS.ccr().modify(|v| { - v.set_fmode(QspiMode::IndirectWrite.into()); - }); + if let Some(len) = transaction.data_len { + T::REGS.ccr().modify(|v| { + v.set_fmode(QspiMode::IndirectWrite.into()); + }); - for idx in 0..len { - while !T::REGS.sr().read().ftf() {} - *(T::REGS.dr().ptr() as *mut u8) = buf[idx]; - } + for idx in 0..len { + while !T::REGS.sr().read().ftf() {} + unsafe { (T::REGS.dr().as_ptr() as *mut u8).write_volatile(buf[idx]) }; } - - while !T::REGS.sr().read().tcf() {} - T::REGS.fcr().modify(|v| v.set_ctcf(true)); } + + while !T::REGS.sr().read().tcf() {} + T::REGS.fcr().modify(|v| v.set_ctcf(true)); } pub fn blocking_read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig) where Dma: QuadDma, { - unsafe { - self.setup_transaction(QspiMode::IndirectWrite, &transaction); + self.setup_transaction(QspiMode::IndirectWrite, &transaction); - T::REGS.ccr().modify(|v| { - v.set_fmode(QspiMode::IndirectRead.into()); - }); - let current_ar = T::REGS.ar().read().address(); - T::REGS.ar().write(|v| { - v.set_address(current_ar); - }); + T::REGS.ccr().modify(|v| { + v.set_fmode(QspiMode::IndirectRead.into()); + }); + let current_ar = T::REGS.ar().read().address(); + T::REGS.ar().write(|v| { + v.set_address(current_ar); + }); - let request = self.dma.request(); - let transfer = Transfer::new_read( + let request = self.dma.request(); + let transfer = unsafe { + Transfer::new_read( &mut self.dma, request, - T::REGS.dr().ptr() as *mut u8, + T::REGS.dr().as_ptr() as *mut u8, buf, Default::default(), - ); + ) + }; - T::REGS.cr().modify(|v| v.set_dmaen(true)); + T::REGS.cr().modify(|v| v.set_dmaen(true)); - transfer.blocking_wait(); - } + transfer.blocking_wait(); } pub fn blocking_write_dma(&mut self, buf: &[u8], transaction: TransferConfig) where Dma: QuadDma, { - unsafe { - self.setup_transaction(QspiMode::IndirectWrite, &transaction); + self.setup_transaction(QspiMode::IndirectWrite, &transaction); - T::REGS.ccr().modify(|v| { - v.set_fmode(QspiMode::IndirectWrite.into()); - }); + T::REGS.ccr().modify(|v| { + v.set_fmode(QspiMode::IndirectWrite.into()); + }); - let request = self.dma.request(); - let transfer = Transfer::new_write( + let request = self.dma.request(); + let transfer = unsafe { + Transfer::new_write( &mut self.dma, request, buf, - T::REGS.dr().ptr() as *mut u8, + T::REGS.dr().as_ptr() as *mut u8, Default::default(), - ); + ) + }; - T::REGS.cr().modify(|v| v.set_dmaen(true)); + T::REGS.cr().modify(|v| v.set_dmaen(true)); - transfer.blocking_wait(); - } + transfer.blocking_wait(); } fn setup_transaction(&mut self, fmode: QspiMode, transaction: &TransferConfig) { - unsafe { - T::REGS.fcr().modify(|v| { - v.set_csmf(true); - v.set_ctcf(true); - v.set_ctef(true); - v.set_ctof(true); + T::REGS.fcr().modify(|v| { + v.set_csmf(true); + v.set_ctcf(true); + v.set_ctef(true); + v.set_ctof(true); + }); + + while T::REGS.sr().read().busy() {} + + if let Some(len) = transaction.data_len { + T::REGS.dlr().write(|v| v.set_dl(len as u32 - 1)); + } + + T::REGS.ccr().write(|v| { + v.set_fmode(fmode.into()); + v.set_imode(transaction.iwidth.into()); + v.set_instruction(transaction.instruction); + v.set_admode(transaction.awidth.into()); + v.set_adsize(self.config.address_size.into()); + v.set_dmode(transaction.dwidth.into()); + v.set_abmode(QspiWidth::NONE.into()); + v.set_dcyc(transaction.dummy.into()); + }); + + if let Some(addr) = transaction.address { + T::REGS.ar().write(|v| { + v.set_address(addr); }); - - while T::REGS.sr().read().busy() {} - - if let Some(len) = transaction.data_len { - T::REGS.dlr().write(|v| v.set_dl(len as u32 - 1)); - } - - T::REGS.ccr().write(|v| { - v.set_fmode(fmode.into()); - v.set_imode(transaction.iwidth.into()); - v.set_instruction(transaction.instruction); - v.set_admode(transaction.awidth.into()); - v.set_adsize(self.config.address_size.into()); - v.set_dmode(transaction.dwidth.into()); - v.set_abmode(QspiWidth::NONE.into()); - v.set_dcyc(transaction.dummy.into()); - }); - - if let Some(addr) = transaction.address { - T::REGS.ar().write(|v| { - v.set_address(addr); - }); - } } } } diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index e0929ca4..bc430afb 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -36,18 +36,18 @@ pub struct Config { } #[cfg(stm32f410)] -unsafe fn setup_i2s_pll(_vco_in: u32, _plli2s: Option) -> Option { +fn setup_i2s_pll(_vco_in: u32, _plli2s: Option) -> Option { None } // Not currently implemented, but will be in the future #[cfg(any(stm32f411, stm32f412, stm32f413, stm32f423, stm32f446))] -unsafe fn setup_i2s_pll(_vco_in: u32, _plli2s: Option) -> Option { +fn setup_i2s_pll(_vco_in: u32, _plli2s: Option) -> Option { None } #[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))] -unsafe fn setup_i2s_pll(vco_in: u32, plli2s: Option) -> Option { +fn setup_i2s_pll(vco_in: u32, plli2s: Option) -> Option { let min_div = 2; let max_div = 7; let target = match plli2s { @@ -82,13 +82,7 @@ unsafe fn setup_i2s_pll(vco_in: u32, plli2s: Option) -> Option { Some(output) } -unsafe fn setup_pll( - pllsrcclk: u32, - use_hse: bool, - pllsysclk: Option, - plli2s: Option, - pll48clk: bool, -) -> PllResults { +fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, plli2s: Option, pll48clk: bool) -> PllResults { use crate::pac::rcc::vals::{Pllp, Pllsrc}; let sysclk = pllsysclk.unwrap_or(pllsrcclk); @@ -320,7 +314,7 @@ impl<'d, T: McoInstance> Mco<'d, T> { } } -unsafe fn flash_setup(sysclk: u32) { +fn flash_setup(sysclk: u32) { use crate::pac::flash::vals::Latency; // Be conservative with voltage ranges diff --git a/embassy-stm32/src/rcc/f7.rs b/embassy-stm32/src/rcc/f7.rs index 2d21326a..71215cac 100644 --- a/embassy-stm32/src/rcc/f7.rs +++ b/embassy-stm32/src/rcc/f7.rs @@ -25,7 +25,7 @@ pub struct Config { pub pll48: bool, } -unsafe fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, pll48clk: bool) -> PllResults { +fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, pll48clk: bool) -> PllResults { use crate::pac::rcc::vals::{Pllp, Pllsrc}; let sysclk = pllsysclk.unwrap_or(pllsrcclk); @@ -97,7 +97,7 @@ unsafe fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, pll48 } } -unsafe fn flash_setup(sysclk: u32) { +fn flash_setup(sysclk: u32) { use crate::pac::flash::vals::Latency; // Be conservative with voltage ranges diff --git a/embassy-stm32/src/rcc/g0.rs b/embassy-stm32/src/rcc/g0.rs index 3e138c7a..17c73c36 100644 --- a/embassy-stm32/src/rcc/g0.rs +++ b/embassy-stm32/src/rcc/g0.rs @@ -245,7 +245,7 @@ impl Default for Config { } impl PllConfig { - pub(crate) unsafe fn init(self) -> u32 { + pub(crate) fn init(self) -> u32 { assert!(self.n >= 8 && self.n <= 86); let (src, input_freq) = match self.source { 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 17fbc605..4025a4e0 100644 --- a/embassy-stm32/src/rcc/h5.rs +++ b/embassy-stm32/src/rcc/h5.rs @@ -462,7 +462,7 @@ struct PllOutput { r: Option, } -unsafe fn init_pll(num: usize, config: Option, input: &PllInput) -> PllOutput { +fn init_pll(num: usize, config: Option, input: &PllInput) -> PllOutput { let Some(config) = config else { // Stop PLL RCC.cr().modify(|w| w.set_pllon(num, false)); @@ -595,12 +595,9 @@ fn flash_setup(clk: Hertz, vos: VoltageScale) { defmt::debug!("flash: latency={} wrhighfreq={}", latency, wrhighfreq); - // NOTE(unsafe) Atomic write - unsafe { - FLASH.acr().write(|w| { - w.set_wrhighfreq(wrhighfreq); - w.set_latency(latency); - }); - while FLASH.acr().read().latency() != latency {} - } + FLASH.acr().write(|w| { + w.set_wrhighfreq(wrhighfreq); + w.set_latency(latency); + }); + while FLASH.acr().read().latency() != latency {} } diff --git a/embassy-stm32/src/rcc/h7.rs b/embassy-stm32/src/rcc/h7.rs index 0185f7ae..daa1cd61 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) { }, }; - // NOTE(unsafe) Atomic write - unsafe { - FLASH.acr().write(|w| { - w.set_wrhighfreq(progr_delay); - w.set_latency(wait_states) - }); - while FLASH.acr().read().latency() != wait_states {} - } + FLASH.acr().write(|w| { + w.set_wrhighfreq(progr_delay); + w.set_latency(wait_states) + }); + while FLASH.acr().read().latency() != wait_states {} } pub enum McoClock { @@ -474,7 +471,6 @@ pub(crate) unsafe fn init(mut config: Config) { // Configure traceclk from PLL if needed traceclk_setup(&mut config, sys_use_pll1_p); - // NOTE(unsafe) We have exclusive access to the RCC let (pll1_p_ck, pll1_q_ck, pll1_r_ck) = pll::pll_setup(srcclk.0, &config.pll1, 0); let (pll2_p_ck, pll2_q_ck, pll2_r_ck) = pll::pll_setup(srcclk.0, &config.pll2, 1); let (pll3_p_ck, pll3_q_ck, pll3_r_ck) = pll::pll_setup(srcclk.0, &config.pll3, 2); @@ -756,7 +752,7 @@ mod pll { /// # Safety /// /// Must have exclusive access to the RCC register block - unsafe fn vco_setup(pll_src: u32, requested_output: u32, plln: usize) -> PllConfigResults { + fn vco_setup(pll_src: u32, requested_output: u32, plln: usize) -> PllConfigResults { use crate::pac::rcc::vals::{Pllrge, Pllvcosel}; let (vco_ck_target, pll_x_p) = vco_output_divider_setup(requested_output, plln); @@ -785,11 +781,7 @@ mod pll { /// # Safety /// /// Must have exclusive access to the RCC register block - pub(super) unsafe fn pll_setup( - pll_src: u32, - config: &PllConfig, - plln: usize, - ) -> (Option, Option, Option) { + pub(super) fn pll_setup(pll_src: u32, config: &PllConfig, plln: usize) -> (Option, Option, Option) { use crate::pac::rcc::vals::Divp; match config.p_ck { diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs index c657bf70..b2faec53 100644 --- a/embassy-stm32/src/rng.rs +++ b/embassy-stm32/src/rng.rs @@ -34,40 +34,34 @@ impl<'d, T: Instance> Rng<'d, T> { pub fn reset(&mut self) { // rng_v2 locks up on seed error, needs reset #[cfg(rng_v2)] - if unsafe { T::regs().sr().read().seis() } { + if T::regs().sr().read().seis() { T::reset(); } - unsafe { - T::regs().cr().modify(|reg| { - reg.set_rngen(true); - reg.set_ie(true); - }); - T::regs().sr().modify(|reg| { - reg.set_seis(false); - reg.set_ceis(false); - }); - } + T::regs().cr().modify(|reg| { + reg.set_rngen(true); + reg.set_ie(true); + }); + T::regs().sr().modify(|reg| { + reg.set_seis(false); + reg.set_ceis(false); + }); // Reference manual says to discard the first. let _ = self.next_u32(); } pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { - unsafe { - T::regs().cr().modify(|reg| { - reg.set_rngen(true); - }) - } + T::regs().cr().modify(|reg| { + reg.set_rngen(true); + }); for chunk in dest.chunks_mut(4) { poll_fn(|cx| { RNG_WAKER.register(cx.waker()); - unsafe { - T::regs().cr().modify(|reg| { - reg.set_ie(true); - }); - } + T::regs().cr().modify(|reg| { + reg.set_ie(true); + }); - let bits = unsafe { T::regs().sr().read() }; + let bits = T::regs().sr().read(); if bits.drdy() { Poll::Ready(Ok(())) @@ -82,7 +76,7 @@ impl<'d, T: Instance> Rng<'d, T> { } }) .await?; - let random_bytes = unsafe { T::regs().dr().read() }.to_be_bytes(); + let random_bytes = T::regs().dr().read().to_be_bytes(); for (dest, src) in chunk.iter_mut().zip(random_bytes.iter()) { *dest = *src } @@ -95,11 +89,11 @@ impl<'d, T: Instance> Rng<'d, T> { impl<'d, T: Instance> RngCore for Rng<'d, T> { fn next_u32(&mut self) -> u32 { loop { - let sr = unsafe { T::regs().sr().read() }; + let sr = T::regs().sr().read(); if sr.seis() | sr.ceis() { self.reset(); } else if sr.drdy() { - return unsafe { T::regs().dr().read() }; + return T::regs().dr().read(); } } } diff --git a/embassy-stm32/src/rtc/datetime.rs b/embassy-stm32/src/rtc/datetime.rs index 0a590c1b..a9c48d88 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) { let yr_offset = (yr - 1970_u16) as u8; let (yt, yu) = byte_to_bcd2(yr_offset); - unsafe { - use crate::pac::rtc::vals::Ampm; + use crate::pac::rtc::vals::Ampm; - rtc.tr().write(|w| { - w.set_ht(ht); - w.set_hu(hu); - w.set_mnt(mnt); - w.set_mnu(mnu); - w.set_st(st); - w.set_su(su); - w.set_pm(Ampm::AM); - }); + rtc.tr().write(|w| { + w.set_ht(ht); + w.set_hu(hu); + w.set_mnt(mnt); + w.set_mnu(mnu); + w.set_st(st); + w.set_su(su); + w.set_pm(Ampm::AM); + }); - rtc.dr().write(|w| { - w.set_dt(dt); - w.set_du(du); - w.set_mt(mt > 0); - w.set_mu(mu); - w.set_yt(yt); - w.set_yu(yu); - w.set_wdu(day_of_week_to_u8(t.day_of_week)); - }); - } + rtc.dr().write(|w| { + w.set_dt(dt); + w.set_du(du); + w.set_mt(mt > 0); + w.set_mu(mu); + w.set_yt(yt); + w.set_yu(yu); + w.set_wdu(day_of_week_to_u8(t.day_of_week)); + }); } pub(super) fn datetime( diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 962927fb..12a2ac79 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -113,7 +113,7 @@ impl Default for RtcCalibrationCyclePeriod { impl<'d, T: Instance> Rtc<'d, T> { pub fn new(_rtc: impl Peripheral

+ 'd, rtc_config: RtcConfig) -> Self { - unsafe { T::enable_peripheral_clk() }; + T::enable_peripheral_clk(); let mut rtc_struct = Self { phantom: PhantomData, @@ -144,34 +144,32 @@ impl<'d, T: Instance> Rtc<'d, T> { /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`]. pub fn now(&self) -> Result { let r = T::regs(); - unsafe { - let tr = r.tr().read(); - let second = bcd2_to_byte((tr.st(), tr.su())); - let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); - let hour = bcd2_to_byte((tr.ht(), tr.hu())); - // Reading either RTC_SSR or RTC_TR locks the values in the higher-order - // calendar shadow registers until RTC_DR is read. - let dr = r.dr().read(); + let tr = r.tr().read(); + let second = bcd2_to_byte((tr.st(), tr.su())); + let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); + let hour = bcd2_to_byte((tr.ht(), tr.hu())); + // Reading either RTC_SSR or RTC_TR locks the values in the higher-order + // calendar shadow registers until RTC_DR is read. + let dr = r.dr().read(); - let weekday = dr.wdu(); - let day = bcd2_to_byte((dr.dt(), dr.du())); - let month = bcd2_to_byte((dr.mt() as u8, dr.mu())); - let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16; + let weekday = dr.wdu(); + let day = bcd2_to_byte((dr.dt(), dr.du())); + let month = bcd2_to_byte((dr.mt() as u8, dr.mu())); + let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16; - self::datetime::datetime(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime) - } + self::datetime::datetime(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime) } /// Check if daylight savings time is active. pub fn get_daylight_savings(&self) -> bool { - let cr = unsafe { T::regs().cr().read() }; + let cr = T::regs().cr().read(); cr.bkp() } /// Enable/disable daylight savings time. pub fn set_daylight_savings(&mut self, daylight_savings: bool) { self.write(true, |rtc| { - unsafe { rtc.cr().modify(|w| w.set_bkp(daylight_savings)) }; + rtc.cr().modify(|w| w.set_bkp(daylight_savings)); }) } @@ -228,7 +226,7 @@ pub(crate) mod sealed { crate::pac::RTC } - unsafe fn enable_peripheral_clk() {} + fn enable_peripheral_clk() {} /// Read content of the backup register. /// diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index adaafe67..e1615b34 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> { /// It this changes the RTC clock source the time will be reset pub(super) fn apply_config(&mut self, rtc_config: RtcConfig) { // Unlock the backup domain - unsafe { - let clock_config = rtc_config.clock_config as u8; + let clock_config = rtc_config.clock_config as u8; - #[cfg(not(rtc_v2wb))] - use stm32_metapac::rcc::vals::Rtcsel; + #[cfg(not(rtc_v2wb))] + use stm32_metapac::rcc::vals::Rtcsel; - #[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1))] - let cr = crate::pac::PWR.cr(); - #[cfg(any(rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] - let cr = crate::pac::PWR.cr1(); + #[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1))] + let cr = crate::pac::PWR.cr(); + #[cfg(any(rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] + let cr = crate::pac::PWR.cr1(); - // TODO: Missing from PAC for l0 and f0? - #[cfg(not(any(rtc_v2f0, rtc_v2l0)))] - { - cr.modify(|w| w.set_dbp(true)); - while !cr.read().dbp() {} - } - - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - let reg = crate::pac::RCC.bdcr().read(); - #[cfg(any(rtc_v2l0, rtc_v2l1))] - let reg = crate::pac::RCC.csr().read(); - - #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb))] - assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); - - #[cfg(rtc_v2wb)] - let rtcsel = reg.rtcsel(); - #[cfg(not(rtc_v2wb))] - let rtcsel = reg.rtcsel().0; - - if !reg.rtcen() || rtcsel != clock_config { - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); - - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - let cr = crate::pac::RCC.bdcr(); - #[cfg(any(rtc_v2l0, rtc_v2l1))] - let cr = crate::pac::RCC.csr(); - - cr.modify(|w| { - // Reset - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - w.set_bdrst(false); - - // Select RTC source - #[cfg(not(rtc_v2wb))] - w.set_rtcsel(Rtcsel(clock_config)); - #[cfg(rtc_v2wb)] - w.set_rtcsel(clock_config); - w.set_rtcen(true); - - // Restore bcdr - #[cfg(any(rtc_v2l4, rtc_v2wb))] - w.set_lscosel(reg.lscosel()); - #[cfg(any(rtc_v2l4, rtc_v2wb))] - w.set_lscoen(reg.lscoen()); - - w.set_lseon(reg.lseon()); - - #[cfg(any(rtc_v2f0, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] - w.set_lsedrv(reg.lsedrv()); - w.set_lsebyp(reg.lsebyp()); - }); - } + // TODO: Missing from PAC for l0 and f0? + #[cfg(not(any(rtc_v2f0, rtc_v2l0)))] + { + cr.modify(|w| w.set_dbp(true)); + while !cr.read().dbp() {} } - self.write(true, |rtc| unsafe { + #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] + let reg = crate::pac::RCC.bdcr().read(); + #[cfg(any(rtc_v2l0, rtc_v2l1))] + let reg = crate::pac::RCC.csr().read(); + + #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb))] + assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); + + #[cfg(rtc_v2wb)] + let rtcsel = reg.rtcsel(); + #[cfg(not(rtc_v2wb))] + let rtcsel = reg.rtcsel().0; + + if !reg.rtcen() || rtcsel != clock_config { + #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] + crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); + + #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] + let cr = crate::pac::RCC.bdcr(); + #[cfg(any(rtc_v2l0, rtc_v2l1))] + let cr = crate::pac::RCC.csr(); + + cr.modify(|w| { + // Reset + #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] + w.set_bdrst(false); + + // Select RTC source + #[cfg(not(rtc_v2wb))] + w.set_rtcsel(Rtcsel(clock_config)); + #[cfg(rtc_v2wb)] + w.set_rtcsel(clock_config); + w.set_rtcen(true); + + // Restore bcdr + #[cfg(any(rtc_v2l4, rtc_v2wb))] + w.set_lscosel(reg.lscosel()); + #[cfg(any(rtc_v2l4, rtc_v2wb))] + w.set_lscoen(reg.lscoen()); + + w.set_lseon(reg.lseon()); + + #[cfg(any(rtc_v2f0, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] + w.set_lsedrv(reg.lsedrv()); + w.set_lsebyp(reg.lsebyp()); + }); + } + + self.write(true, |rtc| { rtc.cr().modify(|w| { #[cfg(rtc_v2f2)] w.set_fmt(false); @@ -117,47 +115,45 @@ impl<'d, T: Instance> super::Rtc<'d, T> { clock_drift = clock_drift / RTC_CALR_RESOLUTION_PPM; self.write(false, |rtc| { - unsafe { - rtc.calr().write(|w| { - match period { - super::RtcCalibrationCyclePeriod::Seconds8 => { - w.set_calw8(stm32_metapac::rtc::vals::Calw8::EIGHT_SECOND); - } - super::RtcCalibrationCyclePeriod::Seconds16 => { - w.set_calw16(stm32_metapac::rtc::vals::Calw16::SIXTEEN_SECOND); - } - super::RtcCalibrationCyclePeriod::Seconds32 => { - // Set neither `calw8` nor `calw16` to use 32 seconds - } + rtc.calr().write(|w| { + match period { + super::RtcCalibrationCyclePeriod::Seconds8 => { + w.set_calw8(stm32_metapac::rtc::vals::Calw8::EIGHT_SECOND); } - - // Extra pulses during calibration cycle period: CALP * 512 - CALM - // - // CALP sets whether pulses are added or omitted. - // - // CALM contains how many pulses (out of 512) are masked in a - // given calibration cycle period. - if clock_drift > 0.0 { - // Maximum (about 512.2) rounds to 512. - clock_drift += 0.5; - - // When the offset is positive (0 to 512), the opposite of - // the offset (512 - offset) is masked, i.e. for the - // maximum offset (512), 0 pulses are masked. - w.set_calp(stm32_metapac::rtc::vals::Calp::INCREASEFREQ); - w.set_calm(512 - clock_drift as u16); - } else { - // Minimum (about -510.7) rounds to -511. - clock_drift -= 0.5; - - // When the offset is negative or zero (-511 to 0), - // the absolute offset is masked, i.e. for the minimum - // offset (-511), 511 pulses are masked. - w.set_calp(stm32_metapac::rtc::vals::Calp::NOCHANGE); - w.set_calm((clock_drift * -1.0) as u16); + super::RtcCalibrationCyclePeriod::Seconds16 => { + w.set_calw16(stm32_metapac::rtc::vals::Calw16::SIXTEEN_SECOND); } - }); - } + super::RtcCalibrationCyclePeriod::Seconds32 => { + // Set neither `calw8` nor `calw16` to use 32 seconds + } + } + + // Extra pulses during calibration cycle period: CALP * 512 - CALM + // + // CALP sets whether pulses are added or omitted. + // + // CALM contains how many pulses (out of 512) are masked in a + // given calibration cycle period. + if clock_drift > 0.0 { + // Maximum (about 512.2) rounds to 512. + clock_drift += 0.5; + + // When the offset is positive (0 to 512), the opposite of + // the offset (512 - offset) is masked, i.e. for the + // maximum offset (512), 0 pulses are masked. + w.set_calp(stm32_metapac::rtc::vals::Calp::INCREASEFREQ); + w.set_calm(512 - clock_drift as u16); + } else { + // Minimum (about -510.7) rounds to -511. + clock_drift -= 0.5; + + // When the offset is negative or zero (-511 to 0), + // the absolute offset is masked, i.e. for the minimum + // offset (-511), 511 pulses are masked. + w.set_calp(stm32_metapac::rtc::vals::Calp::NOCHANGE); + w.set_calm((clock_drift * -1.0) as u16); + } + }); }) } @@ -168,31 +164,27 @@ impl<'d, T: Instance> super::Rtc<'d, T> { let r = T::regs(); // Disable write protection. // This is safe, as we're only writin the correct and expected values. - unsafe { - r.wpr().write(|w| w.set_key(0xca)); - r.wpr().write(|w| w.set_key(0x53)); + r.wpr().write(|w| w.set_key(0xca)); + r.wpr().write(|w| w.set_key(0x53)); - // true if initf bit indicates RTC peripheral is in init mode - if init_mode && !r.isr().read().initf() { - // to update calendar date/time, time format, and prescaler configuration, RTC must be in init mode - r.isr().modify(|w| w.set_init(Init::INITMODE)); - // wait till init state entered - // ~2 RTCCLK cycles - while !r.isr().read().initf() {} - } + // true if initf bit indicates RTC peripheral is in init mode + if init_mode && !r.isr().read().initf() { + // to update calendar date/time, time format, and prescaler configuration, RTC must be in init mode + r.isr().modify(|w| w.set_init(Init::INITMODE)); + // wait till init state entered + // ~2 RTCCLK cycles + while !r.isr().read().initf() {} } let result = f(&r); - unsafe { - if init_mode { - r.isr().modify(|w| w.set_init(Init::FREERUNNINGMODE)); // Exits init mode - } - - // Re-enable write protection. - // This is safe, as the field accepts the full range of 8-bit values. - r.wpr().write(|w| w.set_key(0xff)); + if init_mode { + r.isr().modify(|w| w.set_init(Init::FREERUNNINGMODE)); // Exits init mode } + + // Re-enable write protection. + // This is safe, as the field accepts the full range of 8-bit values. + r.wpr().write(|w| w.set_key(0xff)); result } } @@ -200,7 +192,7 @@ impl<'d, T: Instance> super::Rtc<'d, T> { impl sealed::Instance for crate::peripherals::RTC { const BACKUP_REGISTER_COUNT: usize = 20; - unsafe fn enable_peripheral_clk() { + fn enable_peripheral_clk() { #[cfg(any(rtc_v2l4, rtc_v2wb))] { // enable peripheral clock for communication @@ -213,7 +205,7 @@ impl sealed::Instance for crate::peripherals::RTC { fn read_backup_register(rtc: &Rtc, register: usize) -> Option { if register < Self::BACKUP_REGISTER_COUNT { - Some(unsafe { rtc.bkpr(register).read().bkp() }) + Some(rtc.bkpr(register).read().bkp()) } else { None } @@ -221,7 +213,7 @@ impl sealed::Instance for crate::peripherals::RTC { fn write_backup_register(rtc: &Rtc, register: usize, value: u32) { if register < Self::BACKUP_REGISTER_COUNT { - unsafe { rtc.bkpr(register).write(|w| w.set_bkp(value)) } + rtc.bkpr(register).write(|w| w.set_bkp(value)); } } } diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index 24f6496a..7c91046a 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> { /// It this changes the RTC clock source the time will be reset pub(super) fn apply_config(&mut self, rtc_config: RtcConfig) { // Unlock the backup domain - unsafe { - #[cfg(not(any(rtc_v3u5, rcc_wl5, rcc_wle)))] - { - crate::pac::PWR.cr1().modify(|w| w.set_dbp(true)); - while !crate::pac::PWR.cr1().read().dbp() {} - } - #[cfg(any(rcc_wl5, rcc_wle))] - { - use crate::pac::pwr::vals::Dbp; + #[cfg(not(any(rtc_v3u5, rcc_wl5, rcc_wle)))] + { + crate::pac::PWR.cr1().modify(|w| w.set_dbp(true)); + while !crate::pac::PWR.cr1().read().dbp() {} + } + #[cfg(any(rcc_wl5, rcc_wle))] + { + use crate::pac::pwr::vals::Dbp; - crate::pac::PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED)); - while crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED {} - } + crate::pac::PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED)); + while crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED {} + } - let reg = crate::pac::RCC.bdcr().read(); - assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); + let reg = crate::pac::RCC.bdcr().read(); + assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); - let config_rtcsel = rtc_config.clock_config as u8; - #[cfg(not(any(rcc_wl5, rcc_wle)))] - let config_rtcsel = crate::pac::rcc::vals::Rtcsel(config_rtcsel); + let config_rtcsel = rtc_config.clock_config as u8; + #[cfg(not(any(rcc_wl5, rcc_wle)))] + let config_rtcsel = crate::pac::rcc::vals::Rtcsel(config_rtcsel); - if !reg.rtcen() || reg.rtcsel() != config_rtcsel { - crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); + if !reg.rtcen() || reg.rtcsel() != config_rtcsel { + crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); - crate::pac::RCC.bdcr().modify(|w| { - // Reset - w.set_bdrst(false); + crate::pac::RCC.bdcr().modify(|w| { + // Reset + w.set_bdrst(false); - // Select RTC source - w.set_rtcsel(config_rtcsel); + // Select RTC source + w.set_rtcsel(config_rtcsel); - w.set_rtcen(true); + w.set_rtcen(true); - // Restore bcdr - w.set_lscosel(reg.lscosel()); - w.set_lscoen(reg.lscoen()); + // Restore bcdr + w.set_lscosel(reg.lscosel()); + w.set_lscoen(reg.lscoen()); - w.set_lseon(reg.lseon()); - w.set_lsedrv(reg.lsedrv()); - w.set_lsebyp(reg.lsebyp()); - }); - } + w.set_lseon(reg.lseon()); + w.set_lsedrv(reg.lsedrv()); + w.set_lsebyp(reg.lsebyp()); + }); } self.write(true, |rtc| { - unsafe { - rtc.cr().modify(|w| { - w.set_fmt(Fmt::TWENTYFOURHOUR); - w.set_osel(Osel::DISABLED); - w.set_pol(Pol::HIGH); - }); + rtc.cr().modify(|w| { + w.set_fmt(Fmt::TWENTYFOURHOUR); + w.set_osel(Osel::DISABLED); + w.set_pol(Pol::HIGH); + }); - rtc.prer().modify(|w| { - w.set_prediv_s(rtc_config.sync_prescaler); - w.set_prediv_a(rtc_config.async_prescaler); - }); + rtc.prer().modify(|w| { + w.set_prediv_s(rtc_config.sync_prescaler); + w.set_prediv_a(rtc_config.async_prescaler); + }); - // TODO: configuration for output pins - rtc.cr().modify(|w| { - w.set_out2en(false); - w.set_tampalrm_type(TampalrmType::PUSHPULL); - w.set_tampalrm_pu(TampalrmPu::NOPULLUP); - }); - } + // TODO: configuration for output pins + rtc.cr().modify(|w| { + w.set_out2en(false); + w.set_tampalrm_type(TampalrmType::PUSHPULL); + w.set_tampalrm_pu(TampalrmPu::NOPULLUP); + }); }); self.rtc_config = rtc_config; @@ -99,47 +95,45 @@ impl<'d, T: Instance> super::Rtc<'d, T> { clock_drift = clock_drift / Self::RTC_CALR_RESOLUTION_PPM; self.write(false, |rtc| { - unsafe { - rtc.calr().write(|w| { - match period { - RtcCalibrationCyclePeriod::Seconds8 => { - w.set_calw8(Calw8::EIGHTSECONDS); - } - RtcCalibrationCyclePeriod::Seconds16 => { - w.set_calw16(Calw16::SIXTEENSECONDS); - } - RtcCalibrationCyclePeriod::Seconds32 => { - // Set neither `calw8` nor `calw16` to use 32 seconds - } + rtc.calr().write(|w| { + match period { + RtcCalibrationCyclePeriod::Seconds8 => { + w.set_calw8(Calw8::EIGHTSECONDS); } - - // Extra pulses during calibration cycle period: CALP * 512 - CALM - // - // CALP sets whether pulses are added or omitted. - // - // CALM contains how many pulses (out of 512) are masked in a - // given calibration cycle period. - if clock_drift > 0.0 { - // Maximum (about 512.2) rounds to 512. - clock_drift += 0.5; - - // When the offset is positive (0 to 512), the opposite of - // the offset (512 - offset) is masked, i.e. for the - // maximum offset (512), 0 pulses are masked. - w.set_calp(Calp::INCREASEFREQ); - w.set_calm(512 - clock_drift as u16); - } else { - // Minimum (about -510.7) rounds to -511. - clock_drift -= 0.5; - - // When the offset is negative or zero (-511 to 0), - // the absolute offset is masked, i.e. for the minimum - // offset (-511), 511 pulses are masked. - w.set_calp(Calp::NOCHANGE); - w.set_calm((clock_drift * -1.0) as u16); + RtcCalibrationCyclePeriod::Seconds16 => { + w.set_calw16(Calw16::SIXTEENSECONDS); } - }); - } + RtcCalibrationCyclePeriod::Seconds32 => { + // Set neither `calw8` nor `calw16` to use 32 seconds + } + } + + // Extra pulses during calibration cycle period: CALP * 512 - CALM + // + // CALP sets whether pulses are added or omitted. + // + // CALM contains how many pulses (out of 512) are masked in a + // given calibration cycle period. + if clock_drift > 0.0 { + // Maximum (about 512.2) rounds to 512. + clock_drift += 0.5; + + // When the offset is positive (0 to 512), the opposite of + // the offset (512 - offset) is masked, i.e. for the + // maximum offset (512), 0 pulses are masked. + w.set_calp(Calp::INCREASEFREQ); + w.set_calm(512 - clock_drift as u16); + } else { + // Minimum (about -510.7) rounds to -511. + clock_drift -= 0.5; + + // When the offset is negative or zero (-511 to 0), + // the absolute offset is masked, i.e. for the minimum + // offset (-511), 511 pulses are masked. + w.set_calp(Calp::NOCHANGE); + w.set_calm((clock_drift * -1.0) as u16); + } + }); }) } @@ -150,29 +144,26 @@ impl<'d, T: Instance> super::Rtc<'d, T> { let r = T::regs(); // Disable write protection. // This is safe, as we're only writin the correct and expected values. - unsafe { - r.wpr().write(|w| w.set_key(Key::DEACTIVATE1)); - r.wpr().write(|w| w.set_key(Key::DEACTIVATE2)); + r.wpr().write(|w| w.set_key(Key::DEACTIVATE1)); + r.wpr().write(|w| w.set_key(Key::DEACTIVATE2)); - if init_mode && !r.icsr().read().initf() { - r.icsr().modify(|w| w.set_init(Init::INITMODE)); - // wait till init state entered - // ~2 RTCCLK cycles - while !r.icsr().read().initf() {} - } + if init_mode && !r.icsr().read().initf() { + r.icsr().modify(|w| w.set_init(Init::INITMODE)); + // wait till init state entered + // ~2 RTCCLK cycles + while !r.icsr().read().initf() {} } let result = f(&r); - unsafe { - if init_mode { - r.icsr().modify(|w| w.set_init(Init::FREERUNNINGMODE)); // Exits init mode - } - - // Re-enable write protection. - // This is safe, as the field accepts the full range of 8-bit values. - r.wpr().write(|w| w.set_key(Key::ACTIVATE)); + if init_mode { + r.icsr().modify(|w| w.set_init(Init::FREERUNNINGMODE)); // Exits init mode } + + // Re-enable write protection. + // This is safe, as the field accepts the full range of 8-bit values. + r.wpr().write(|w| w.set_key(Key::ACTIVATE)); + result } } @@ -192,7 +183,7 @@ impl sealed::Instance for crate::peripherals::RTC { fn write_backup_register(_rtc: &Rtc, register: usize, _value: u32) { if register < Self::BACKUP_REGISTER_COUNT { // RTC3 backup registers come from the TAMP peripe=heral, not RTC. Not() even in the L412 PAC - //unsafe { self.rtc.bkpr()[register].write(|w| w.bits(value)) } + //self.rtc.bkpr()[register].write(|w| w.bits(value)) } } } diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index 28eb49ab..80a336a4 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs @@ -28,17 +28,14 @@ pub struct InterruptHandler { impl InterruptHandler { fn data_interrupts(enable: bool) { let regs = T::regs(); - // NOTE(unsafe) Atomic write - unsafe { - regs.maskr().write(|w| { - w.set_dcrcfailie(enable); - w.set_dtimeoutie(enable); - w.set_dataendie(enable); + regs.maskr().write(|w| { + w.set_dcrcfailie(enable); + w.set_dtimeoutie(enable); + w.set_dataendie(enable); - #[cfg(sdmmc_v2)] - w.set_dabortie(enable); - }); - } + #[cfg(sdmmc_v2)] + w.set_dabortie(enable); + }); } } @@ -285,7 +282,7 @@ impl<'d, T: Instance, Dma: SdmmcDma> Sdmmc<'d, T, Dma> { ) -> Self { into_ref!(clk, cmd, d0); - critical_section::with(|_| unsafe { + critical_section::with(|_| { clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None); cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up); d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up); @@ -322,7 +319,7 @@ impl<'d, T: Instance, Dma: SdmmcDma> Sdmmc<'d, T, Dma> { ) -> Self { into_ref!(clk, cmd, d0, d1, d2, d3); - critical_section::with(|_| unsafe { + critical_section::with(|_| { clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None); cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up); d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up); @@ -364,7 +361,7 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { ) -> Self { into_ref!(clk, cmd, d0); - critical_section::with(|_| unsafe { + critical_section::with(|_| { clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None); cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up); d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up); @@ -400,7 +397,7 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { ) -> Self { into_ref!(clk, cmd, d0, d1, d2, d3); - critical_section::with(|_| unsafe { + critical_section::with(|_| { clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None); cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up); d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up); @@ -451,26 +448,24 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { unsafe { T::Interrupt::enable() }; let regs = T::regs(); - unsafe { - regs.clkcr().write(|w| { - w.set_pwrsav(false); - w.set_negedge(false); + regs.clkcr().write(|w| { + w.set_pwrsav(false); + w.set_negedge(false); - // Hardware flow control is broken on SDIOv1 and causes clock glitches, which result in CRC errors. - // See chip erratas for more details. - #[cfg(sdmmc_v1)] - w.set_hwfc_en(false); - #[cfg(sdmmc_v2)] - w.set_hwfc_en(true); + // Hardware flow control is broken on SDIOv1 and causes clock glitches, which result in CRC errors. + // See chip erratas for more details. + #[cfg(sdmmc_v1)] + w.set_hwfc_en(false); + #[cfg(sdmmc_v2)] + w.set_hwfc_en(true); - #[cfg(sdmmc_v1)] - w.set_clken(true); - }); + #[cfg(sdmmc_v1)] + w.set_clken(true); + }); - // Power off, writen 00: Clock to the card is stopped; - // D[7:0], CMD, and CK are driven high. - regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::Off as u8)); - } + // Power off, writen 00: Clock to the card is stopped; + // D[7:0], CMD, and CK are driven high. + regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::Off as u8)); Self { _peri: sdmmc, @@ -495,14 +490,11 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { fn data_active() -> bool { let regs = T::regs(); - // NOTE(unsafe) Atomic read with no side-effects - unsafe { - let status = regs.star().read(); - #[cfg(sdmmc_v1)] - return status.rxact() || status.txact(); - #[cfg(sdmmc_v2)] - return status.dpsmact(); - } + let status = regs.star().read(); + #[cfg(sdmmc_v1)] + return status.rxact() || status.txact(); + #[cfg(sdmmc_v2)] + return status.dpsmact(); } /// Coammand transfer is in progress @@ -510,14 +502,11 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { fn cmd_active() -> bool { let regs = T::regs(); - // NOTE(unsafe) Atomic read with no side-effects - unsafe { - let status = regs.star().read(); - #[cfg(sdmmc_v1)] - return status.cmdact(); - #[cfg(sdmmc_v2)] - return status.cpsmact(); - } + let status = regs.star().read(); + #[cfg(sdmmc_v1)] + return status.cmdact(); + #[cfg(sdmmc_v2)] + return status.cpsmact(); } /// Wait idle on CMDACT, RXACT and TXACT (v1) or DOSNACT and CPSMACT (v2) @@ -542,44 +531,41 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { Self::wait_idle(); Self::clear_interrupt_flags(); - // NOTE(unsafe) We have exclusive access to the regisers - unsafe { - regs.dtimer() - .write(|w| w.set_datatime(self.config.data_transfer_timeout)); - regs.dlenr().write(|w| w.set_datalength(length_bytes)); + regs.dtimer() + .write(|w| w.set_datatime(self.config.data_transfer_timeout)); + regs.dlenr().write(|w| w.set_datalength(length_bytes)); + #[cfg(sdmmc_v1)] + let transfer = unsafe { + let request = self.dma.request(); + Transfer::new_read( + &mut self.dma, + request, + regs.fifor().as_ptr() as *mut u32, + buffer, + DMA_TRANSFER_OPTIONS, + ) + }; + #[cfg(sdmmc_v2)] + let transfer = { + regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_mut_ptr() as u32)); + regs.idmactrlr().modify(|w| w.set_idmaen(true)); + Transfer { + _dummy: core::marker::PhantomData, + } + }; + + regs.dctrl().modify(|w| { + w.set_dblocksize(block_size); + w.set_dtdir(true); #[cfg(sdmmc_v1)] - let transfer = { - let request = self.dma.request(); - Transfer::new_read( - &mut self.dma, - request, - regs.fifor().ptr() as *mut u32, - buffer, - DMA_TRANSFER_OPTIONS, - ) - }; - #[cfg(sdmmc_v2)] - let transfer = { - regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_mut_ptr() as u32)); - regs.idmactrlr().modify(|w| w.set_idmaen(true)); - Transfer { - _dummy: core::marker::PhantomData, - } - }; + { + w.set_dmaen(true); + w.set_dten(true); + } + }); - regs.dctrl().modify(|w| { - w.set_dblocksize(block_size); - w.set_dtdir(true); - #[cfg(sdmmc_v1)] - { - w.set_dmaen(true); - w.set_dten(true); - } - }); - - transfer - } + transfer } /// # Safety @@ -598,59 +584,54 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { Self::wait_idle(); Self::clear_interrupt_flags(); - // NOTE(unsafe) We have exclusive access to the regisers - unsafe { - regs.dtimer() - .write(|w| w.set_datatime(self.config.data_transfer_timeout)); - regs.dlenr().write(|w| w.set_datalength(length_bytes)); + regs.dtimer() + .write(|w| w.set_datatime(self.config.data_transfer_timeout)); + regs.dlenr().write(|w| w.set_datalength(length_bytes)); + #[cfg(sdmmc_v1)] + let transfer = unsafe { + let request = self.dma.request(); + Transfer::new_write( + &mut self.dma, + request, + buffer, + regs.fifor().as_ptr() as *mut u32, + DMA_TRANSFER_OPTIONS, + ) + }; + #[cfg(sdmmc_v2)] + let transfer = { + regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_ptr() as u32)); + regs.idmactrlr().modify(|w| w.set_idmaen(true)); + Transfer { + _dummy: core::marker::PhantomData, + } + }; + + regs.dctrl().modify(|w| { + w.set_dblocksize(block_size); + w.set_dtdir(false); #[cfg(sdmmc_v1)] - let transfer = { - let request = self.dma.request(); - Transfer::new_write( - &mut self.dma, - request, - buffer, - regs.fifor().ptr() as *mut u32, - DMA_TRANSFER_OPTIONS, - ) - }; - #[cfg(sdmmc_v2)] - let transfer = { - regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_ptr() as u32)); - regs.idmactrlr().modify(|w| w.set_idmaen(true)); - Transfer { - _dummy: core::marker::PhantomData, - } - }; + { + w.set_dmaen(true); + w.set_dten(true); + } + }); - regs.dctrl().modify(|w| { - w.set_dblocksize(block_size); - w.set_dtdir(false); - #[cfg(sdmmc_v1)] - { - w.set_dmaen(true); - w.set_dten(true); - } - }); - - transfer - } + transfer } /// Stops the DMA datapath fn stop_datapath() { let regs = T::regs(); - unsafe { - #[cfg(sdmmc_v1)] - regs.dctrl().modify(|w| { - w.set_dmaen(false); - w.set_dten(false); - }); - #[cfg(sdmmc_v2)] - regs.idmactrlr().modify(|w| w.set_idmaen(false)); - } + #[cfg(sdmmc_v1)] + regs.dctrl().modify(|w| { + w.set_dmaen(false); + w.set_dten(false); + }); + #[cfg(sdmmc_v2)] + regs.idmactrlr().modify(|w| w.set_idmaen(false)); } /// Sets the CLKDIV field in CLKCR. Updates clock field in self @@ -673,16 +654,13 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { assert!(ker_ck.0 > 3 * sdmmc_bus_bandwidth / 32); self.clock = new_clock; - // NOTE(unsafe) We have exclusive access to the regblock - unsafe { - // CPSMACT and DPSMACT must be 0 to set CLKDIV - Self::wait_idle(); - regs.clkcr().modify(|w| { - w.set_clkdiv(clkdiv); - #[cfg(sdmmc_v1)] - w.set_bypass(_bypass); - }); - } + // CPSMACT and DPSMACT must be 0 to set CLKDIV + Self::wait_idle(); + regs.clkcr().modify(|w| { + w.set_clkdiv(clkdiv); + #[cfg(sdmmc_v1)] + w.set_bypass(_bypass); + }); Ok(()) } @@ -710,7 +688,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { // Arm `OnDrop` after the buffer, so it will be dropped first let regs = T::regs(); - let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); + let on_drop = OnDrop::new(|| Self::on_drop()); let transfer = self.prepare_datapath_read(&mut status, 64, 6); InterruptHandler::::data_interrupts(true); @@ -718,7 +696,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { let res = poll_fn(|cx| { T::state().register(cx.waker()); - let status = unsafe { regs.star().read() }; + let status = regs.star().read(); if status.dcrcfail() { return Poll::Ready(Err(Error::Crc)); @@ -769,8 +747,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { Self::cmd(Cmd::card_status(rca << 16), false)?; // CMD13 - // NOTE(unsafe) Atomic read with no side-effects - let r1 = unsafe { regs.respr(0).read().cardstatus() }; + let r1 = regs.respr(0).read().cardstatus(); Ok(r1.into()) } @@ -786,7 +763,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { // Arm `OnDrop` after the buffer, so it will be dropped first let regs = T::regs(); - let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); + let on_drop = OnDrop::new(|| Self::on_drop()); let transfer = self.prepare_datapath_read(&mut status, 64, 6); InterruptHandler::::data_interrupts(true); @@ -794,7 +771,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { let res = poll_fn(|cx| { T::state().register(cx.waker()); - let status = unsafe { regs.star().read() }; + let status = regs.star().read(); if status.dcrcfail() { return Poll::Ready(Err(Error::Crc)); @@ -840,35 +817,32 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { #[inline(always)] fn clear_interrupt_flags() { let regs = T::regs(); - // NOTE(unsafe) Atomic write - unsafe { - regs.icr().write(|w| { - w.set_ccrcfailc(true); - w.set_dcrcfailc(true); - w.set_ctimeoutc(true); - w.set_dtimeoutc(true); - w.set_txunderrc(true); - w.set_rxoverrc(true); - w.set_cmdrendc(true); - w.set_cmdsentc(true); - w.set_dataendc(true); - w.set_dbckendc(true); - w.set_sdioitc(true); + regs.icr().write(|w| { + w.set_ccrcfailc(true); + w.set_dcrcfailc(true); + w.set_ctimeoutc(true); + w.set_dtimeoutc(true); + w.set_txunderrc(true); + w.set_rxoverrc(true); + w.set_cmdrendc(true); + w.set_cmdsentc(true); + w.set_dataendc(true); + w.set_dbckendc(true); + w.set_sdioitc(true); - #[cfg(sdmmc_v2)] - { - w.set_dholdc(true); - w.set_dabortc(true); - w.set_busyd0endc(true); - w.set_ackfailc(true); - w.set_acktimeoutc(true); - w.set_vswendc(true); - w.set_ckstopc(true); - w.set_idmatec(true); - w.set_idmabtcc(true); - } - }); - } + #[cfg(sdmmc_v2)] + { + w.set_dholdc(true); + w.set_dabortc(true); + w.set_busyd0endc(true); + w.set_ackfailc(true); + w.set_acktimeoutc(true); + w.set_vswendc(true); + w.set_ckstopc(true); + w.set_idmatec(true); + w.set_idmabtcc(true); + } + }); } async fn get_scr(&mut self, card: &mut Card) -> Result<(), Error> { @@ -880,7 +854,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { // Arm `OnDrop` after the buffer, so it will be dropped first let regs = T::regs(); - let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); + let on_drop = OnDrop::new(|| Self::on_drop()); let transfer = self.prepare_datapath_read(&mut scr[..], 8, 3); InterruptHandler::::data_interrupts(true); @@ -888,7 +862,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { let res = poll_fn(|cx| { T::state().register(cx.waker()); - let status = unsafe { regs.star().read() }; + let status = regs.star().read(); if status.dcrcfail() { return Poll::Ready(Err(Error::Crc)); @@ -921,59 +895,53 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { let regs = T::regs(); Self::clear_interrupt_flags(); - // NOTE(safety) Atomic operations - unsafe { - // CP state machine must be idle - while Self::cmd_active() {} + // CP state machine must be idle + while Self::cmd_active() {} - // Command arg - regs.argr().write(|w| w.set_cmdarg(cmd.arg)); + // Command arg + regs.argr().write(|w| w.set_cmdarg(cmd.arg)); - // Command index and start CP State Machine - regs.cmdr().write(|w| { - w.set_waitint(false); - w.set_waitresp(cmd.resp as u8); - w.set_cmdindex(cmd.cmd); - w.set_cpsmen(true); + // Command index and start CP State Machine + regs.cmdr().write(|w| { + w.set_waitint(false); + w.set_waitresp(cmd.resp as u8); + w.set_cmdindex(cmd.cmd); + w.set_cpsmen(true); - #[cfg(sdmmc_v2)] - { - // Special mode in CP State Machine - // CMD12: Stop Transmission - let cpsm_stop_transmission = cmd.cmd == 12; - w.set_cmdstop(cpsm_stop_transmission); - w.set_cmdtrans(data); - } - }); - - let mut status; - if cmd.resp == Response::None { - // Wait for CMDSENT or a timeout - while { - status = regs.star().read(); - !(status.ctimeout() || status.cmdsent()) - } {} - } else { - // Wait for CMDREND or CCRCFAIL or a timeout - while { - status = regs.star().read(); - !(status.ctimeout() || status.cmdrend() || status.ccrcfail()) - } {} + #[cfg(sdmmc_v2)] + { + // Special mode in CP State Machine + // CMD12: Stop Transmission + let cpsm_stop_transmission = cmd.cmd == 12; + w.set_cmdstop(cpsm_stop_transmission); + w.set_cmdtrans(data); } + }); - if status.ctimeout() { - return Err(Error::Timeout); - } else if status.ccrcfail() { - return Err(Error::Crc); - } - Ok(()) + let mut status; + if cmd.resp == Response::None { + // Wait for CMDSENT or a timeout + while { + status = regs.star().read(); + !(status.ctimeout() || status.cmdsent()) + } {} + } else { + // Wait for CMDREND or CCRCFAIL or a timeout + while { + status = regs.star().read(); + !(status.ctimeout() || status.cmdrend() || status.ccrcfail()) + } {} } + + if status.ctimeout() { + return Err(Error::Timeout); + } else if status.ccrcfail() { + return Err(Error::Crc); + } + Ok(()) } - /// # Safety - /// - /// Ensure that `regs` has exclusive access to the regblocks - unsafe fn on_drop() { + fn on_drop() { let regs = T::regs(); if Self::data_active() { Self::clear_interrupt_flags(); @@ -1017,141 +985,138 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { false => BusWidth::One, }; - // NOTE(unsafe) We have exclusive access to the peripheral - unsafe { - // While the SD/SDIO card or eMMC is in identification mode, - // the SDMMC_CK frequency must be no more than 400 kHz. - let (_bypass, clkdiv, init_clock) = unwrap!(clk_div(ker_ck, SD_INIT_FREQ.0)); - self.clock = init_clock; + // While the SD/SDIO card or eMMC is in identification mode, + // the SDMMC_CK frequency must be no more than 400 kHz. + let (_bypass, clkdiv, init_clock) = unwrap!(clk_div(ker_ck, SD_INIT_FREQ.0)); + self.clock = init_clock; - // CPSMACT and DPSMACT must be 0 to set WIDBUS - Self::wait_idle(); + // CPSMACT and DPSMACT must be 0 to set WIDBUS + Self::wait_idle(); - regs.clkcr().modify(|w| { - w.set_widbus(0); - w.set_clkdiv(clkdiv); - #[cfg(sdmmc_v1)] - w.set_bypass(_bypass); - }); + regs.clkcr().modify(|w| { + w.set_widbus(0); + w.set_clkdiv(clkdiv); + #[cfg(sdmmc_v1)] + w.set_bypass(_bypass); + }); - regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8)); - Self::cmd(Cmd::idle(), false)?; + regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8)); + Self::cmd(Cmd::idle(), false)?; - // Check if cards supports CMD8 (with pattern) - Self::cmd(Cmd::hs_send_ext_csd(0x1AA), false)?; - let r1 = regs.respr(0).read().cardstatus(); + // Check if cards supports CMD8 (with pattern) + Self::cmd(Cmd::hs_send_ext_csd(0x1AA), false)?; + let r1 = regs.respr(0).read().cardstatus(); - let mut card = if r1 == 0x1AA { - // Card echoed back the pattern. Must be at least v2 - Card::default() - } else { - return Err(Error::UnsupportedCardVersion); - }; + let mut card = if r1 == 0x1AA { + // Card echoed back the pattern. Must be at least v2 + Card::default() + } else { + return Err(Error::UnsupportedCardVersion); + }; - let ocr = loop { - // Signal that next command is a app command - Self::cmd(Cmd::app_cmd(0), false)?; // CMD55 + let ocr = loop { + // Signal that next command is a app command + Self::cmd(Cmd::app_cmd(0), false)?; // CMD55 - let arg = CmdAppOper::VOLTAGE_WINDOW_SD as u32 - | CmdAppOper::HIGH_CAPACITY as u32 - | CmdAppOper::SD_SWITCH_1_8V_CAPACITY as u32; + let arg = CmdAppOper::VOLTAGE_WINDOW_SD as u32 + | CmdAppOper::HIGH_CAPACITY as u32 + | CmdAppOper::SD_SWITCH_1_8V_CAPACITY as u32; - // Initialize card - match Self::cmd(Cmd::app_op_cmd(arg), false) { - // ACMD41 - Ok(_) => (), - Err(Error::Crc) => (), - Err(err) => return Err(err), - } - let ocr: OCR = regs.respr(0).read().cardstatus().into(); - if !ocr.is_busy() { - // Power up done - break ocr; - } - }; - - if ocr.high_capacity() { - // Card is SDHC or SDXC or SDUC - card.card_type = CardCapacity::SDHC; - } else { - card.card_type = CardCapacity::SDSC; + // Initialize card + match Self::cmd(Cmd::app_op_cmd(arg), false) { + // ACMD41 + Ok(_) => (), + Err(Error::Crc) => (), + Err(err) => return Err(err), } - card.ocr = ocr; - - Self::cmd(Cmd::all_send_cid(), false)?; // CMD2 - let cid0 = regs.respr(0).read().cardstatus() as u128; - let cid1 = regs.respr(1).read().cardstatus() as u128; - let cid2 = regs.respr(2).read().cardstatus() as u128; - let cid3 = regs.respr(3).read().cardstatus() as u128; - let cid = (cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3); - card.cid = cid.into(); - - Self::cmd(Cmd::send_rel_addr(), false)?; - card.rca = regs.respr(0).read().cardstatus() >> 16; - - Self::cmd(Cmd::send_csd(card.rca << 16), false)?; - let csd0 = regs.respr(0).read().cardstatus() as u128; - let csd1 = regs.respr(1).read().cardstatus() as u128; - let csd2 = regs.respr(2).read().cardstatus() as u128; - let csd3 = regs.respr(3).read().cardstatus() as u128; - let csd = (csd0 << 96) | (csd1 << 64) | (csd2 << 32) | (csd3); - card.csd = csd.into(); - - self.select_card(Some(&card))?; - - self.get_scr(&mut card).await?; - - // Set bus width - let (width, acmd_arg) = match bus_width { - BusWidth::Eight => unimplemented!(), - BusWidth::Four if card.scr.bus_width_four() => (BusWidth::Four, 2), - _ => (BusWidth::One, 0), - }; - Self::cmd(Cmd::app_cmd(card.rca << 16), false)?; - Self::cmd(Cmd::cmd6(acmd_arg), false)?; - - // CPSMACT and DPSMACT must be 0 to set WIDBUS - Self::wait_idle(); - - regs.clkcr().modify(|w| { - w.set_widbus(match width { - BusWidth::One => 0, - BusWidth::Four => 1, - BusWidth::Eight => 2, - _ => panic!("Invalid Bus Width"), - }) - }); - - // Set Clock - if freq.0 <= 25_000_000 { - // Final clock frequency - self.clkcr_set_clkdiv(freq.0, width)?; - } else { - // Switch to max clock for SDR12 - self.clkcr_set_clkdiv(25_000_000, width)?; + let ocr: OCR = regs.respr(0).read().cardstatus().into(); + if !ocr.is_busy() { + // Power up done + break ocr; } + }; - self.card = Some(card); - - // Read status - self.read_sd_status().await?; - - if freq.0 > 25_000_000 { - // Switch to SDR25 - self.signalling = self.switch_signalling_mode(Signalling::SDR25).await?; - - if self.signalling == Signalling::SDR25 { - // Set final clock frequency - self.clkcr_set_clkdiv(freq.0, width)?; - - if self.read_status(&card)?.state() != CurrentState::Transfer { - return Err(Error::SignalingSwitchFailed); - } - } - } - // Read status after signalling change - self.read_sd_status().await?; + if ocr.high_capacity() { + // Card is SDHC or SDXC or SDUC + card.card_type = CardCapacity::SDHC; + } else { + card.card_type = CardCapacity::SDSC; } + card.ocr = ocr; + + Self::cmd(Cmd::all_send_cid(), false)?; // CMD2 + let cid0 = regs.respr(0).read().cardstatus() as u128; + let cid1 = regs.respr(1).read().cardstatus() as u128; + let cid2 = regs.respr(2).read().cardstatus() as u128; + let cid3 = regs.respr(3).read().cardstatus() as u128; + let cid = (cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3); + card.cid = cid.into(); + + Self::cmd(Cmd::send_rel_addr(), false)?; + card.rca = regs.respr(0).read().cardstatus() >> 16; + + Self::cmd(Cmd::send_csd(card.rca << 16), false)?; + let csd0 = regs.respr(0).read().cardstatus() as u128; + let csd1 = regs.respr(1).read().cardstatus() as u128; + let csd2 = regs.respr(2).read().cardstatus() as u128; + let csd3 = regs.respr(3).read().cardstatus() as u128; + let csd = (csd0 << 96) | (csd1 << 64) | (csd2 << 32) | (csd3); + card.csd = csd.into(); + + self.select_card(Some(&card))?; + + self.get_scr(&mut card).await?; + + // Set bus width + let (width, acmd_arg) = match bus_width { + BusWidth::Eight => unimplemented!(), + BusWidth::Four if card.scr.bus_width_four() => (BusWidth::Four, 2), + _ => (BusWidth::One, 0), + }; + Self::cmd(Cmd::app_cmd(card.rca << 16), false)?; + Self::cmd(Cmd::cmd6(acmd_arg), false)?; + + // CPSMACT and DPSMACT must be 0 to set WIDBUS + Self::wait_idle(); + + regs.clkcr().modify(|w| { + w.set_widbus(match width { + BusWidth::One => 0, + BusWidth::Four => 1, + BusWidth::Eight => 2, + _ => panic!("Invalid Bus Width"), + }) + }); + + // Set Clock + if freq.0 <= 25_000_000 { + // Final clock frequency + self.clkcr_set_clkdiv(freq.0, width)?; + } else { + // Switch to max clock for SDR12 + self.clkcr_set_clkdiv(25_000_000, width)?; + } + + self.card = Some(card); + + // Read status + self.read_sd_status().await?; + + if freq.0 > 25_000_000 { + // Switch to SDR25 + self.signalling = self.switch_signalling_mode(Signalling::SDR25).await?; + + if self.signalling == Signalling::SDR25 { + // Set final clock frequency + self.clkcr_set_clkdiv(freq.0, width)?; + + if self.read_status(&card)?.state() != CurrentState::Transfer { + return Err(Error::SignalingSwitchFailed); + } + } + } + // Read status after signalling change + self.read_sd_status().await?; Ok(()) } @@ -1172,7 +1137,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { Self::cmd(Cmd::set_block_length(512), false)?; // CMD16 let regs = T::regs(); - let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); + let on_drop = OnDrop::new(|| Self::on_drop()); let transfer = self.prepare_datapath_read(buffer, 512, 9); InterruptHandler::::data_interrupts(true); @@ -1180,7 +1145,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { let res = poll_fn(|cx| { T::state().register(cx.waker()); - let status = unsafe { regs.star().read() }; + let status = regs.star().read(); if status.dcrcfail() { return Poll::Ready(Err(Error::Crc)); @@ -1217,7 +1182,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { Self::cmd(Cmd::set_block_length(512), false)?; // CMD16 let regs = T::regs(); - let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); + let on_drop = OnDrop::new(|| Self::on_drop()); // sdmmc_v1 uses different cmd/dma order than v2, but only for writes #[cfg(sdmmc_v1)] @@ -1231,7 +1196,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { let res = poll_fn(|cx| { T::state().register(cx.waker()); - let status = unsafe { regs.star().read() }; + let status = regs.star().read(); if status.dcrcfail() { return Poll::Ready(Err(Error::Crc)); @@ -1289,9 +1254,9 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { impl<'d, T: Instance, Dma: SdmmcDma + 'd> Drop for Sdmmc<'d, T, Dma> { fn drop(&mut self) { T::Interrupt::disable(); - unsafe { Self::on_drop() }; + Self::on_drop(); - critical_section::with(|_| unsafe { + critical_section::with(|_| { self.clk.set_as_disconnected(); self.cmd.set_as_disconnected(); self.d0.set_as_disconnected(); diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 580971e4..1cddac99 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> { Polarity::IdleHigh => Pull::Up, }; - unsafe { - sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, sck_pull_mode); - sck.set_speed(crate::gpio::Speed::VeryHigh); - mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); - mosi.set_speed(crate::gpio::Speed::VeryHigh); - miso.set_as_af(miso.af_num(), AFType::Input); - miso.set_speed(crate::gpio::Speed::VeryHigh); - } + sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, sck_pull_mode); + sck.set_speed(crate::gpio::Speed::VeryHigh); + mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); + mosi.set_speed(crate::gpio::Speed::VeryHigh); + miso.set_as_af(miso.af_num(), AFType::Input); + miso.set_speed(crate::gpio::Speed::VeryHigh); Self::new_inner( peri, @@ -129,12 +127,10 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { config: Config, ) -> Self { into_ref!(sck, miso); - unsafe { - sck.set_as_af(sck.af_num(), AFType::OutputPushPull); - sck.set_speed(crate::gpio::Speed::VeryHigh); - miso.set_as_af(miso.af_num(), AFType::Input); - miso.set_speed(crate::gpio::Speed::VeryHigh); - } + sck.set_as_af(sck.af_num(), AFType::OutputPushPull); + sck.set_speed(crate::gpio::Speed::VeryHigh); + miso.set_as_af(miso.af_num(), AFType::Input); + miso.set_speed(crate::gpio::Speed::VeryHigh); Self::new_inner( peri, @@ -158,12 +154,10 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { config: Config, ) -> Self { into_ref!(sck, mosi); - unsafe { - sck.set_as_af(sck.af_num(), AFType::OutputPushPull); - sck.set_speed(crate::gpio::Speed::VeryHigh); - mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); - mosi.set_speed(crate::gpio::Speed::VeryHigh); - } + sck.set_as_af(sck.af_num(), AFType::OutputPushPull); + sck.set_speed(crate::gpio::Speed::VeryHigh); + mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); + mosi.set_speed(crate::gpio::Speed::VeryHigh); Self::new_inner( peri, @@ -186,10 +180,8 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { config: Config, ) -> Self { into_ref!(mosi); - unsafe { - mosi.set_as_af_pull(mosi.af_num(), AFType::OutputPushPull, Pull::Down); - mosi.set_speed(crate::gpio::Speed::Medium); - } + mosi.set_as_af_pull(mosi.af_num(), AFType::OutputPushPull, Pull::Down); + mosi.set_speed(crate::gpio::Speed::Medium); Self::new_inner(peri, None, Some(mosi.map_into()), None, txdma, rxdma, freq, config) } @@ -247,7 +239,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { T::reset(); #[cfg(any(spi_v1, spi_f1))] - unsafe { + { T::REGS.cr2().modify(|w| { w.set_ssoe(false); }); @@ -270,7 +262,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { }); } #[cfg(spi_v2)] - unsafe { + { T::REGS.cr2().modify(|w| { let (ds, frxth) = ::CONFIG; w.set_frxth(frxth); @@ -292,7 +284,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { }); } #[cfg(any(spi_v3, spi_v4, spi_v5))] - unsafe { + { T::REGS.ifcr().write(|w| w.0 = 0xffff_ffff); T::REGS.cfg2().modify(|w| { //w.set_ssoe(true); @@ -343,29 +335,25 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { let lsbfirst = config.raw_byte_order(); #[cfg(any(spi_v1, spi_f1, spi_v2))] - unsafe { - T::REGS.cr1().modify(|w| { - w.set_cpha(cpha); - w.set_cpol(cpol); - w.set_lsbfirst(lsbfirst); - }); - } + T::REGS.cr1().modify(|w| { + w.set_cpha(cpha); + w.set_cpol(cpol); + w.set_lsbfirst(lsbfirst); + }); #[cfg(any(spi_v3, spi_v4, spi_v5))] - unsafe { - T::REGS.cfg2().modify(|w| { - w.set_cpha(cpha); - w.set_cpol(cpol); - w.set_lsbfirst(lsbfirst); - }); - } + T::REGS.cfg2().modify(|w| { + w.set_cpha(cpha); + w.set_cpol(cpol); + w.set_lsbfirst(lsbfirst); + }); } pub fn get_current_config(&self) -> Config { #[cfg(any(spi_v1, spi_f1, spi_v2))] - let cfg = unsafe { T::REGS.cr1().read() }; + let cfg = T::REGS.cr1().read(); #[cfg(any(spi_v3, spi_v4, spi_v5))] - let cfg = unsafe { T::REGS.cfg2().read() }; + let cfg = T::REGS.cfg2().read(); let polarity = if cfg.cpol() == vals::Cpol::IDLELOW { Polarity::IdleLow } else { @@ -395,7 +383,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { } #[cfg(any(spi_v1, spi_f1))] - unsafe { + { T::REGS.cr1().modify(|reg| { reg.set_spe(false); reg.set_dff(word_size) @@ -405,7 +393,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { }); } #[cfg(spi_v2)] - unsafe { + { T::REGS.cr1().modify(|w| { w.set_spe(false); }); @@ -418,7 +406,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { }); } #[cfg(any(spi_v3, spi_v4, spi_v5))] - unsafe { + { T::REGS.cr1().modify(|w| { w.set_csusp(true); }); @@ -447,26 +435,22 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { } self.set_word_size(W::CONFIG); - unsafe { - T::REGS.cr1().modify(|w| { - w.set_spe(false); - }); - } + T::REGS.cr1().modify(|w| { + w.set_spe(false); + }); let tx_request = self.txdma.request(); let tx_dst = T::REGS.tx_ptr(); let tx_f = unsafe { Transfer::new_write(&mut self.txdma, tx_request, data, tx_dst, Default::default()) }; - unsafe { - set_txdmaen(T::REGS, true); - T::REGS.cr1().modify(|w| { - w.set_spe(true); - }); - #[cfg(any(spi_v3, spi_v4, spi_v5))] - T::REGS.cr1().modify(|w| { - w.set_cstart(true); - }); - } + set_txdmaen(T::REGS, true); + T::REGS.cr1().modify(|w| { + w.set_spe(true); + }); + #[cfg(any(spi_v3, spi_v4, spi_v5))] + T::REGS.cr1().modify(|w| { + w.set_cstart(true); + }); tx_f.await; @@ -485,11 +469,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { } self.set_word_size(W::CONFIG); - unsafe { - T::REGS.cr1().modify(|w| { - w.set_spe(false); - }); - } + T::REGS.cr1().modify(|w| { + w.set_spe(false); + }); // SPIv3 clears rxfifo on SPE=0 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] @@ -517,16 +499,14 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { ) }; - unsafe { - set_txdmaen(T::REGS, true); - T::REGS.cr1().modify(|w| { - w.set_spe(true); - }); - #[cfg(any(spi_v3, spi_v4, spi_v5))] - T::REGS.cr1().modify(|w| { - w.set_cstart(true); - }); - } + set_txdmaen(T::REGS, true); + T::REGS.cr1().modify(|w| { + w.set_spe(true); + }); + #[cfg(any(spi_v3, spi_v4, spi_v5))] + T::REGS.cr1().modify(|w| { + w.set_cstart(true); + }); join(tx_f, rx_f).await; @@ -548,11 +528,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { } self.set_word_size(W::CONFIG); - unsafe { - T::REGS.cr1().modify(|w| { - w.set_spe(false); - }); - } + T::REGS.cr1().modify(|w| { + w.set_spe(false); + }); // SPIv3 clears rxfifo on SPE=0 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] @@ -568,16 +546,14 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { let tx_dst = T::REGS.tx_ptr(); let tx_f = unsafe { Transfer::new_write_raw(&mut self.txdma, tx_request, write, tx_dst, Default::default()) }; - unsafe { - set_txdmaen(T::REGS, true); - T::REGS.cr1().modify(|w| { - w.set_spe(true); - }); - #[cfg(any(spi_v3, spi_v4, spi_v5))] - T::REGS.cr1().modify(|w| { - w.set_cstart(true); - }); - } + set_txdmaen(T::REGS, true); + T::REGS.cr1().modify(|w| { + w.set_spe(true); + }); + #[cfg(any(spi_v3, spi_v4, spi_v5))] + T::REGS.cr1().modify(|w| { + w.set_cstart(true); + }); join(tx_f, rx_f).await; @@ -603,7 +579,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { } pub fn blocking_write(&mut self, words: &[W]) -> Result<(), Error> { - unsafe { T::REGS.cr1().modify(|w| w.set_spe(true)) } + T::REGS.cr1().modify(|w| w.set_spe(true)); flush_rx_fifo(T::REGS); self.set_word_size(W::CONFIG); for word in words.iter() { @@ -613,7 +589,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { } pub fn blocking_read(&mut self, words: &mut [W]) -> Result<(), Error> { - unsafe { T::REGS.cr1().modify(|w| w.set_spe(true)) } + T::REGS.cr1().modify(|w| w.set_spe(true)); flush_rx_fifo(T::REGS); self.set_word_size(W::CONFIG); for word in words.iter_mut() { @@ -623,7 +599,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { } pub fn blocking_transfer_in_place(&mut self, words: &mut [W]) -> Result<(), Error> { - unsafe { T::REGS.cr1().modify(|w| w.set_spe(true)) } + T::REGS.cr1().modify(|w| w.set_spe(true)); flush_rx_fifo(T::REGS); self.set_word_size(W::CONFIG); for word in words.iter_mut() { @@ -633,7 +609,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { } pub fn blocking_transfer(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> { - unsafe { T::REGS.cr1().modify(|w| w.set_spe(true)) } + T::REGS.cr1().modify(|w| w.set_spe(true)); flush_rx_fifo(T::REGS); self.set_word_size(W::CONFIG); let len = read.len().max(write.len()); @@ -650,11 +626,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> { fn drop(&mut self) { - unsafe { - self.sck.as_ref().map(|x| x.set_as_disconnected()); - self.mosi.as_ref().map(|x| x.set_as_disconnected()); - self.miso.as_ref().map(|x| x.set_as_disconnected()); - } + self.sck.as_ref().map(|x| x.set_as_disconnected()); + self.mosi.as_ref().map(|x| x.set_as_disconnected()); + self.miso.as_ref().map(|x| x.set_as_disconnected()); } } @@ -690,7 +664,7 @@ impl RegsExt for Regs { let dr = self.dr(); #[cfg(any(spi_v3, spi_v4, spi_v5))] let dr = self.txdr(); - dr.ptr() as *mut W + dr.as_ptr() as *mut W } fn rx_ptr(&self) -> *mut W { @@ -698,7 +672,7 @@ impl RegsExt for Regs { let dr = self.dr(); #[cfg(any(spi_v3, spi_v4, spi_v5))] let dr = self.rxdr(); - dr.ptr() as *mut W + dr.as_ptr() as *mut W } } @@ -731,7 +705,7 @@ fn check_error_flags(sr: regs::Sr) -> Result<(), Error> { fn spin_until_tx_ready(regs: Regs) -> Result<(), Error> { loop { - let sr = unsafe { regs.sr().read() }; + let sr = regs.sr().read(); check_error_flags(sr)?; @@ -748,7 +722,7 @@ fn spin_until_tx_ready(regs: Regs) -> Result<(), Error> { fn spin_until_rx_ready(regs: Regs) -> Result<(), Error> { loop { - let sr = unsafe { regs.sr().read() }; + let sr = regs.sr().read(); check_error_flags(sr)?; @@ -764,72 +738,64 @@ fn spin_until_rx_ready(regs: Regs) -> Result<(), Error> { } fn flush_rx_fifo(regs: Regs) { - unsafe { - #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] - while regs.sr().read().rxne() { - let _ = regs.dr().read(); - } - #[cfg(any(spi_v3, spi_v4, spi_v5))] - while regs.sr().read().rxp() { - let _ = regs.rxdr().read(); - } + #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] + while regs.sr().read().rxne() { + let _ = regs.dr().read(); + } + #[cfg(any(spi_v3, spi_v4, spi_v5))] + while regs.sr().read().rxp() { + let _ = regs.rxdr().read(); } } fn set_txdmaen(regs: Regs, val: bool) { - unsafe { - #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] - regs.cr2().modify(|reg| { - reg.set_txdmaen(val); - }); - #[cfg(any(spi_v3, spi_v4, spi_v5))] - regs.cfg1().modify(|reg| { - reg.set_txdmaen(val); - }); - } + #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] + regs.cr2().modify(|reg| { + reg.set_txdmaen(val); + }); + #[cfg(any(spi_v3, spi_v4, spi_v5))] + regs.cfg1().modify(|reg| { + reg.set_txdmaen(val); + }); } fn set_rxdmaen(regs: Regs, val: bool) { - unsafe { - #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] - regs.cr2().modify(|reg| { - reg.set_rxdmaen(val); - }); - #[cfg(any(spi_v3, spi_v4, spi_v5))] - regs.cfg1().modify(|reg| { - reg.set_rxdmaen(val); - }); - } + #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] + regs.cr2().modify(|reg| { + reg.set_rxdmaen(val); + }); + #[cfg(any(spi_v3, spi_v4, spi_v5))] + regs.cfg1().modify(|reg| { + reg.set_rxdmaen(val); + }); } fn finish_dma(regs: Regs) { - unsafe { - #[cfg(spi_v2)] - while regs.sr().read().ftlvl() > 0 {} + #[cfg(spi_v2)] + while regs.sr().read().ftlvl() > 0 {} - #[cfg(any(spi_v3, spi_v4, spi_v5))] - while !regs.sr().read().txc() {} - #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] - while regs.sr().read().bsy() {} + #[cfg(any(spi_v3, spi_v4, spi_v5))] + while !regs.sr().read().txc() {} + #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] + while regs.sr().read().bsy() {} - // Disable the spi peripheral - regs.cr1().modify(|w| { - w.set_spe(false); - }); + // Disable the spi peripheral + regs.cr1().modify(|w| { + w.set_spe(false); + }); - // The peripheral automatically disables the DMA stream on completion without error, - // but it does not clear the RXDMAEN/TXDMAEN flag in CR2. - #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] - regs.cr2().modify(|reg| { - reg.set_txdmaen(false); - reg.set_rxdmaen(false); - }); - #[cfg(any(spi_v3, spi_v4, spi_v5))] - regs.cfg1().modify(|reg| { - reg.set_txdmaen(false); - reg.set_rxdmaen(false); - }); - } + // The peripheral automatically disables the DMA stream on completion without error, + // but it does not clear the RXDMAEN/TXDMAEN flag in CR2. + #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] + regs.cr2().modify(|reg| { + reg.set_txdmaen(false); + reg.set_rxdmaen(false); + }); + #[cfg(any(spi_v3, spi_v4, spi_v5))] + regs.cfg1().modify(|reg| { + reg.set_txdmaen(false); + reg.set_rxdmaen(false); + }); } fn transfer_word(regs: Regs, tx_word: W) -> Result { diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs index e82501a4..2622442f 100644 --- a/embassy-stm32/src/time_driver.rs +++ b/embassy-stm32/src/time_driver.rs @@ -155,8 +155,7 @@ impl RtcDriver { let timer_freq = T::frequency(); - // NOTE(unsafe) Critical section to use the unsafe methods - critical_section::with(|_| unsafe { + critical_section::with(|_| { r.cr1().modify(|w| w.set_cen(false)); r.cnt().write(|w| w.set_cnt(0)); @@ -184,7 +183,7 @@ impl RtcDriver { }); ::Interrupt::unpend(); - ::Interrupt::enable(); + unsafe { ::Interrupt::enable() }; r.cr1().modify(|w| w.set_cen(true)); }) @@ -193,9 +192,8 @@ impl RtcDriver { fn on_interrupt(&self) { let r = T::regs_gp16(); - // NOTE(unsafe) Use critical section to access the methods // XXX: reduce the size of this critical section ? - critical_section::with(|cs| unsafe { + critical_section::with(|cs| { let sr = r.sr().read(); let dier = r.dier().read(); @@ -228,7 +226,7 @@ impl RtcDriver { let period = self.period.fetch_add(1, Ordering::Relaxed) + 1; let t = (period as u64) << 15; - critical_section::with(move |cs| unsafe { + critical_section::with(move |cs| { r.dier().modify(move |w| { for n in 0..ALARM_COUNT { let alarm = &self.alarms.borrow(cs)[n]; @@ -269,8 +267,7 @@ impl Driver for RtcDriver { let period = self.period.load(Ordering::Relaxed); compiler_fence(Ordering::Acquire); - // NOTE(unsafe) Atomic read with no side-effects - let counter = unsafe { r.cnt().read().cnt() }; + let counter = r.cnt().read().cnt(); calc_now(period, counter) } @@ -310,7 +307,7 @@ impl Driver for RtcDriver { if timestamp <= t { // If alarm timestamp has passed the alarm will not fire. // Disarm the alarm and return `false` to indicate that. - unsafe { r.dier().modify(|w| w.set_ccie(n + 1, false)) }; + r.dier().modify(|w| w.set_ccie(n + 1, false)); alarm.timestamp.set(u64::MAX); @@ -321,12 +318,11 @@ impl Driver for RtcDriver { // Write the CCR value regardless of whether we're going to enable it now or not. // This way, when we enable it later, the right value is already set. - unsafe { r.ccr(n + 1).write(|w| w.set_ccr(safe_timestamp as u16)) }; + r.ccr(n + 1).write(|w| w.set_ccr(safe_timestamp as u16)); // Enable it if it'll happen soon. Otherwise, `next_period` will enable it. let diff = timestamp - t; - // NOTE(unsafe) We're in a critical section - unsafe { r.dier().modify(|w| w.set_ccie(n + 1, diff < 0xc000)) }; + r.dier().modify(|w| w.set_ccie(n + 1, diff < 0xc000)); true }) diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 14db9702..09b7a377 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 { type Interrupt = crate::interrupt::typelevel::$irq; fn regs() -> crate::pac::timer::TimBasic { - crate::pac::timer::TimBasic(crate::pac::$inst.0) + unsafe { crate::pac::timer::TimBasic::from_ptr(crate::pac::$inst.as_ptr()) } } fn start(&mut self) { - unsafe { - Self::regs().cr1().modify(|r| r.set_cen(true)); - } + Self::regs().cr1().modify(|r| r.set_cen(true)); } fn stop(&mut self) { - unsafe { - Self::regs().cr1().modify(|r| r.set_cen(false)); - } + Self::regs().cr1().modify(|r| r.set_cen(false)); } fn reset(&mut self) { - unsafe { - Self::regs().cnt().write(|r| r.set_cnt(0)); - } + Self::regs().cnt().write(|r| r.set_cnt(0)); } fn set_frequency(&mut self, frequency: Hertz) { @@ -90,35 +84,29 @@ macro_rules! impl_basic_16bit_timer { let arr: u16 = unwrap!((pclk_ticks_per_timer_period / (u32::from(psc) + 1)).try_into()); let regs = Self::regs(); - unsafe { - regs.psc().write(|r| r.set_psc(psc)); - regs.arr().write(|r| r.set_arr(arr)); + regs.psc().write(|r| r.set_psc(psc)); + regs.arr().write(|r| r.set_arr(arr)); - regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); - regs.egr().write(|r| r.set_ug(true)); - regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); - } + regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); + regs.egr().write(|r| r.set_ug(true)); + regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); } fn clear_update_interrupt(&mut self) -> bool { let regs = Self::regs(); - unsafe { - let sr = regs.sr().read(); - if sr.uif() { - regs.sr().modify(|r| { - r.set_uif(false); - }); - true - } else { - false - } + let sr = regs.sr().read(); + if sr.uif() { + regs.sr().modify(|r| { + r.set_uif(false); + }); + true + } else { + false } } fn enable_update_interrupt(&mut self, enable: bool) { - unsafe { - Self::regs().dier().write(|r| r.set_uie(enable)); - } + Self::regs().dier().write(|r| r.set_uie(enable)); } } }; @@ -141,14 +129,12 @@ macro_rules! impl_32bit_timer { let arr: u32 = unwrap!(((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into())); let regs = Self::regs_gp32(); - unsafe { - regs.psc().write(|r| r.set_psc(psc)); - regs.arr().write(|r| r.set_arr(arr)); + regs.psc().write(|r| r.set_psc(psc)); + regs.arr().write(|r| r.set_arr(arr)); - regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); - regs.egr().write(|r| r.set_ug(true)); - regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); - } + regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); + regs.egr().write(|r| r.set_ug(true)); + regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); } } }; @@ -185,7 +171,7 @@ foreach_interrupt! { impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { fn regs_gp16() -> crate::pac::timer::TimGp16 { - crate::pac::timer::TimGp16(crate::pac::$inst.0) + unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } } } @@ -206,7 +192,7 @@ foreach_interrupt! { impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { fn regs_gp16() -> crate::pac::timer::TimGp16 { - crate::pac::timer::TimGp16(crate::pac::$inst.0) + unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } } } diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index 086196a2..433ad299 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -19,68 +19,64 @@ impl interrupt::typelevel::Handler for Interrupt let state = T::buffered_state(); // RX - unsafe { - let sr = sr(r).read(); - // On v1 & v2, reading DR clears the rxne, error and idle interrupt - // flags. Keep this close to the SR read to reduce the chance of a - // flag being set in-between. - let dr = if sr.rxne() || cfg!(any(usart_v1, usart_v2)) && (sr.ore() || sr.idle()) { - Some(rdr(r).read_volatile()) + let sr_val = sr(r).read(); + // On v1 & v2, reading DR clears the rxne, error and idle interrupt + // flags. Keep this close to the SR read to reduce the chance of a + // flag being set in-between. + let dr = if sr_val.rxne() || cfg!(any(usart_v1, usart_v2)) && (sr_val.ore() || sr_val.idle()) { + Some(rdr(r).read_volatile()) + } else { + None + }; + clear_interrupt_flags(r, sr_val); + + if sr_val.pe() { + warn!("Parity error"); + } + if sr_val.fe() { + warn!("Framing error"); + } + if sr_val.ne() { + warn!("Noise error"); + } + if sr_val.ore() { + warn!("Overrun error"); + } + if sr_val.rxne() { + let mut rx_writer = state.rx_buf.writer(); + let buf = rx_writer.push_slice(); + if !buf.is_empty() { + buf[0] = dr.unwrap(); + rx_writer.push_done(1); } else { - None - }; - clear_interrupt_flags(r, sr); - - if sr.pe() { - warn!("Parity error"); - } - if sr.fe() { - warn!("Framing error"); - } - if sr.ne() { - warn!("Noise error"); - } - if sr.ore() { - warn!("Overrun error"); - } - if sr.rxne() { - let mut rx_writer = state.rx_buf.writer(); - let buf = rx_writer.push_slice(); - if !buf.is_empty() { - buf[0] = dr.unwrap(); - rx_writer.push_done(1); - } else { - // FIXME: Should we disable any further RX interrupts when the buffer becomes full. - } - - if state.rx_buf.is_full() { - state.rx_waker.wake(); - } + // FIXME: Should we disable any further RX interrupts when the buffer becomes full. } - if sr.idle() { + if state.rx_buf.is_full() { state.rx_waker.wake(); } } + if sr_val.idle() { + state.rx_waker.wake(); + } + // TX - unsafe { - if sr(r).read().txe() { - let mut tx_reader = state.tx_buf.reader(); - let buf = tx_reader.pop_slice(); - if !buf.is_empty() { - r.cr1().modify(|w| { - w.set_txeie(true); - }); - tdr(r).write_volatile(buf[0].into()); - tx_reader.pop_done(1); - state.tx_waker.wake(); - } else { - // Disable interrupt until we have something to transmit again - r.cr1().modify(|w| { - w.set_txeie(false); - }); - } + if sr(r).read().txe() { + let mut tx_reader = state.tx_buf.reader(); + let buf = tx_reader.pop_slice(); + if !buf.is_empty() { + r.cr1().modify(|w| { + w.set_txeie(true); + }); + tdr(r).write_volatile(buf[0].into()); + tx_reader.pop_done(1); + state.tx_waker.wake(); + } else { + // Disable interrupt until we have something to transmit again + r.cr1().modify(|w| { + w.set_txeie(false); + }); } } } @@ -150,14 +146,12 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { T::enable(); T::reset(); - unsafe { - rts.set_as_af(rts.af_num(), AFType::OutputPushPull); - cts.set_as_af(cts.af_num(), AFType::Input); - T::regs().cr3().write(|w| { - w.set_rtse(true); - w.set_ctse(true); - }); - } + rts.set_as_af(rts.af_num(), AFType::OutputPushPull); + cts.set_as_af(cts.af_num(), AFType::Input); + T::regs().cr3().write(|w| { + w.set_rtse(true); + w.set_ctse(true); + }); Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) } @@ -178,12 +172,10 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { T::enable(); T::reset(); - unsafe { - de.set_as_af(de.af_num(), AFType::OutputPushPull); - T::regs().cr3().write(|w| { - w.set_dem(true); - }); - } + de.set_as_af(de.af_num(), AFType::OutputPushPull); + T::regs().cr3().write(|w| { + w.set_dem(true); + }); Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) } @@ -205,22 +197,18 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) }; let r = T::regs(); - unsafe { - rx.set_as_af(rx.af_num(), AFType::Input); - tx.set_as_af(tx.af_num(), AFType::OutputPushPull); - } + rx.set_as_af(rx.af_num(), AFType::Input); + tx.set_as_af(tx.af_num(), AFType::OutputPushPull); configure(r, &config, T::frequency(), T::KIND, true, true); - unsafe { - r.cr1().modify(|w| { - #[cfg(lpuart_v2)] - w.set_fifoen(true); + r.cr1().modify(|w| { + #[cfg(lpuart_v2)] + w.set_fifoen(true); - w.set_rxneie(true); - w.set_idleie(true); - }); - } + w.set_rxneie(true); + w.set_idleie(true); + }); T::Interrupt::unpend(); unsafe { T::Interrupt::enable() }; diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index da3644a8..47a79c18 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -36,35 +36,31 @@ impl interrupt::typelevel::Handler for Interrupt let r = T::regs(); let s = T::state(); - let (sr, cr1, cr3) = unsafe { (sr(r).read(), r.cr1().read(), r.cr3().read()) }; + let (sr, cr1, cr3) = (sr(r).read(), r.cr1().read(), r.cr3().read()); let has_errors = (sr.pe() && cr1.peie()) || ((sr.fe() || sr.ne() || sr.ore()) && cr3.eie()); if has_errors { // clear all interrupts and DMA Rx Request - unsafe { - r.cr1().modify(|w| { - // disable RXNE interrupt - w.set_rxneie(false); - // disable parity interrupt - w.set_peie(false); - // disable idle line interrupt - w.set_idleie(false); - }); - r.cr3().modify(|w| { - // disable Error Interrupt: (Frame error, Noise error, Overrun error) - w.set_eie(false); - // disable DMA Rx Request - w.set_dmar(false); - }); - } + r.cr1().modify(|w| { + // disable RXNE interrupt + w.set_rxneie(false); + // disable parity interrupt + w.set_peie(false); + // disable idle line interrupt + w.set_idleie(false); + }); + r.cr3().modify(|w| { + // disable Error Interrupt: (Frame error, Noise error, Overrun error) + w.set_eie(false); + // disable DMA Rx Request + w.set_dmar(false); + }); } else if cr1.idleie() && sr.idle() { // IDLE detected: no more data will come - unsafe { - r.cr1().modify(|w| { - // disable idle line detection - w.set_idleie(false); - }); - } + r.cr1().modify(|w| { + // disable idle line detection + w.set_idleie(false); + }); } else if cr1.rxneie() { // We cannot check the RXNE flag as it is auto-cleared by the DMA controller @@ -205,12 +201,10 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { T::enable(); T::reset(); - unsafe { - cts.set_as_af(cts.af_num(), AFType::Input); - T::regs().cr3().write(|w| { - w.set_ctse(true); - }); - } + cts.set_as_af(cts.af_num(), AFType::Input); + T::regs().cr3().write(|w| { + w.set_ctse(true); + }); Self::new_inner(peri, tx, tx_dma, config) } @@ -224,9 +218,7 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { let r = T::regs(); - unsafe { - tx.set_as_af(tx.af_num(), AFType::OutputPushPull); - } + tx.set_as_af(tx.af_num(), AFType::OutputPushPull); configure(r, &config, T::frequency(), T::KIND, false, true); @@ -245,11 +237,9 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { { let ch = &mut self.tx_dma; let request = ch.request(); - unsafe { - T::regs().cr3().modify(|reg| { - reg.set_dmat(true); - }); - } + T::regs().cr3().modify(|reg| { + reg.set_dmat(true); + }); // If we don't assign future to a variable, the data register pointer // is held across an await and makes the future non-Send. 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> { } pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { - unsafe { - let r = T::regs(); - for &b in buffer { - while !sr(r).read().txe() {} - tdr(r).write_volatile(b); - } + let r = T::regs(); + for &b in buffer { + while !sr(r).read().txe() {} + unsafe { tdr(r).write_volatile(b) }; } Ok(()) } pub fn blocking_flush(&mut self) -> Result<(), Error> { - unsafe { - let r = T::regs(); - while !sr(r).read().tc() {} - } + let r = T::regs(); + while !sr(r).read().tc() {} Ok(()) } } @@ -305,12 +291,10 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { T::enable(); T::reset(); - unsafe { - rts.set_as_af(rts.af_num(), AFType::OutputPushPull); - T::regs().cr3().write(|w| { - w.set_rtse(true); - }); - } + rts.set_as_af(rts.af_num(), AFType::OutputPushPull); + T::regs().cr3().write(|w| { + w.set_rtse(true); + }); Self::new_inner(peri, rx, rx_dma, config) } @@ -325,9 +309,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { let r = T::regs(); - unsafe { - rx.set_as_af(rx.af_num(), AFType::Input); - } + rx.set_as_af(rx.af_num(), AFType::Input); configure(r, &config, T::frequency(), T::KIND, true, false); @@ -347,7 +329,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { } #[cfg(any(usart_v1, usart_v2))] - unsafe fn check_rx_flags(&mut self) -> Result { + fn check_rx_flags(&mut self) -> Result { let r = T::regs(); loop { // Handle all buffered error flags. @@ -380,7 +362,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { } #[cfg(any(usart_v3, usart_v4))] - unsafe fn check_rx_flags(&mut self) -> Result { + fn check_rx_flags(&mut self) -> Result { let r = T::regs(); let sr = r.isr().read(); if sr.pe() { @@ -410,22 +392,18 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { pub fn nb_read(&mut self) -> Result> { let r = T::regs(); - unsafe { - if self.check_rx_flags()? { - Ok(rdr(r).read_volatile()) - } else { - Err(nb::Error::WouldBlock) - } + if self.check_rx_flags()? { + Ok(unsafe { rdr(r).read_volatile() }) + } else { + Err(nb::Error::WouldBlock) } } pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { - unsafe { - let r = T::regs(); - for b in buffer { - while !self.check_rx_flags()? {} - *b = rdr(r).read_volatile(); - } + let r = T::regs(); + for b in buffer { + while !self.check_rx_flags()? {} + unsafe { *b = rdr(r).read_volatile() } } Ok(()) } @@ -451,23 +429,20 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { let on_drop = OnDrop::new(move || { // defmt::trace!("Clear all USART interrupts and DMA Read Request"); // clear all interrupts and DMA Rx Request - // SAFETY: only clears Rx related flags - unsafe { - r.cr1().modify(|w| { - // disable RXNE interrupt - w.set_rxneie(false); - // disable parity interrupt - w.set_peie(false); - // disable idle line interrupt - w.set_idleie(false); - }); - r.cr3().modify(|w| { - // disable Error Interrupt: (Frame error, Noise error, Overrun error) - w.set_eie(false); - // disable DMA Rx Request - w.set_dmar(false); - }); - } + r.cr1().modify(|w| { + // disable RXNE interrupt + w.set_rxneie(false); + // disable parity interrupt + w.set_peie(false); + // disable idle line interrupt + w.set_idleie(false); + }); + r.cr3().modify(|w| { + // disable Error Interrupt: (Frame error, Noise error, Overrun error) + w.set_eie(false); + // disable DMA Rx Request + w.set_dmar(false); + }); }); let ch = &mut self.rx_dma; @@ -480,78 +455,74 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { // future which will complete when DMA Read request completes let transfer = unsafe { Transfer::new_read(ch, request, rdr(T::regs()), buffer, Default::default()) }; - // SAFETY: The only way we might have a problem is using split rx and tx - // here we only modify or read Rx related flags, interrupts and DMA channel - unsafe { - // clear ORE flag just before enabling DMA Rx Request: can be mandatory for the second transfer - if !self.detect_previous_overrun { - let sr = sr(r).read(); - // This read also clears the error and idle interrupt flags on v1. - rdr(r).read_volatile(); - clear_interrupt_flags(r, sr); + // clear ORE flag just before enabling DMA Rx Request: can be mandatory for the second transfer + if !self.detect_previous_overrun { + let sr = sr(r).read(); + // This read also clears the error and idle interrupt flags on v1. + unsafe { rdr(r).read_volatile() }; + clear_interrupt_flags(r, sr); + } + + r.cr1().modify(|w| { + // disable RXNE interrupt + w.set_rxneie(false); + // enable parity interrupt if not ParityNone + w.set_peie(w.pce()); + }); + + r.cr3().modify(|w| { + // enable Error Interrupt: (Frame error, Noise error, Overrun error) + w.set_eie(true); + // enable DMA Rx Request + w.set_dmar(true); + }); + + compiler_fence(Ordering::SeqCst); + + // In case of errors already pending when reception started, interrupts may have already been raised + // and lead to reception abortion (Overrun error for instance). In such a case, all interrupts + // have been disabled in interrupt handler and DMA Rx Request has been disabled. + + let cr3 = r.cr3().read(); + + if !cr3.dmar() { + // something went wrong + // because the only way to get this flag cleared is to have an interrupt + + // DMA will be stopped when transfer is dropped + + let sr = sr(r).read(); + // This read also clears the error and idle interrupt flags on v1. + unsafe { rdr(r).read_volatile() }; + clear_interrupt_flags(r, sr); + + if sr.pe() { + return Err(Error::Parity); + } + if sr.fe() { + return Err(Error::Framing); + } + if sr.ne() { + return Err(Error::Noise); + } + if sr.ore() { + return Err(Error::Overrun); } + unreachable!(); + } + + if enable_idle_line_detection { + // clear idle flag + let sr = sr(r).read(); + // This read also clears the error and idle interrupt flags on v1. + unsafe { rdr(r).read_volatile() }; + clear_interrupt_flags(r, sr); + + // enable idle interrupt r.cr1().modify(|w| { - // disable RXNE interrupt - w.set_rxneie(false); - // enable parity interrupt if not ParityNone - w.set_peie(w.pce()); + w.set_idleie(true); }); - - r.cr3().modify(|w| { - // enable Error Interrupt: (Frame error, Noise error, Overrun error) - w.set_eie(true); - // enable DMA Rx Request - w.set_dmar(true); - }); - - compiler_fence(Ordering::SeqCst); - - // In case of errors already pending when reception started, interrupts may have already been raised - // and lead to reception abortion (Overrun error for instance). In such a case, all interrupts - // have been disabled in interrupt handler and DMA Rx Request has been disabled. - - let cr3 = r.cr3().read(); - - if !cr3.dmar() { - // something went wrong - // because the only way to get this flag cleared is to have an interrupt - - // DMA will be stopped when transfer is dropped - - let sr = sr(r).read(); - // This read also clears the error and idle interrupt flags on v1. - rdr(r).read_volatile(); - clear_interrupt_flags(r, sr); - - if sr.pe() { - return Err(Error::Parity); - } - if sr.fe() { - return Err(Error::Framing); - } - if sr.ne() { - return Err(Error::Noise); - } - if sr.ore() { - return Err(Error::Overrun); - } - - unreachable!(); - } - - if enable_idle_line_detection { - // clear idle flag - let sr = sr(r).read(); - // This read also clears the error and idle interrupt flags on v1. - rdr(r).read_volatile(); - clear_interrupt_flags(r, sr); - - // enable idle interrupt - r.cr1().modify(|w| { - w.set_idleie(true); - }); - } } compiler_fence(Ordering::SeqCst); @@ -562,15 +533,11 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { s.rx_waker.register(cx.waker()); - // SAFETY: read only and we only use Rx related flags - let sr = unsafe { sr(r).read() }; + let sr = sr(r).read(); - // SAFETY: only clears Rx related flags - unsafe { - // This read also clears the error and idle interrupt flags on v1. - rdr(r).read_volatile(); - clear_interrupt_flags(r, sr); - } + // This read also clears the error and idle interrupt flags on v1. + unsafe { rdr(r).read_volatile() }; + clear_interrupt_flags(r, sr); compiler_fence(Ordering::SeqCst); @@ -677,14 +644,12 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { T::enable(); T::reset(); - unsafe { - rts.set_as_af(rts.af_num(), AFType::OutputPushPull); - cts.set_as_af(cts.af_num(), AFType::Input); - T::regs().cr3().write(|w| { - w.set_rtse(true); - w.set_ctse(true); - }); - } + rts.set_as_af(rts.af_num(), AFType::OutputPushPull); + cts.set_as_af(cts.af_num(), AFType::Input); + T::regs().cr3().write(|w| { + w.set_rtse(true); + w.set_ctse(true); + }); Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config) } @@ -704,12 +669,10 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { T::enable(); T::reset(); - unsafe { - de.set_as_af(de.af_num(), AFType::OutputPushPull); - T::regs().cr3().write(|w| { - w.set_dem(true); - }); - } + de.set_as_af(de.af_num(), AFType::OutputPushPull); + T::regs().cr3().write(|w| { + w.set_dem(true); + }); Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config) } @@ -725,10 +688,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { let r = T::regs(); - unsafe { - rx.set_as_af(rx.af_num(), AFType::Input); - tx.set_as_af(tx.af_num(), AFType::OutputPushPull); - } + rx.set_as_af(rx.af_num(), AFType::Input); + tx.set_as_af(tx.af_num(), AFType::OutputPushPull); configure(r, &config, T::frequency(), T::KIND, true, true); @@ -847,11 +808,9 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx: if div * 2 >= brr_min && kind == Kind::Uart && !cfg!(usart_v1) { over8 = true; let div = div as u32; - unsafe { - r.brr().write_value(regs::Brr(((div << 1) & !0xF) | (div & 0x07))); - #[cfg(usart_v4)] - r.presc().write(|w| w.set_prescaler(_presc_val)); - } + r.brr().write_value(regs::Brr(((div << 1) & !0xF) | (div & 0x07))); + #[cfg(usart_v4)] + r.presc().write(|w| w.set_prescaler(_presc_val)); found = Some(div); break; } @@ -860,11 +819,9 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx: if div < brr_max { let div = div as u32; - unsafe { - r.brr().write_value(regs::Brr(div)); - #[cfg(usart_v4)] - r.presc().write(|w| w.set_prescaler(_presc_val)); - } + r.brr().write_value(regs::Brr(div)); + #[cfg(usart_v4)] + r.presc().write(|w| w.set_prescaler(_presc_val)); found = Some(div); break; } @@ -883,44 +840,42 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx: pclk_freq.0 / div ); - unsafe { - r.cr2().write(|w| { - w.set_stop(match config.stop_bits { - StopBits::STOP0P5 => vals::Stop::STOP0P5, - StopBits::STOP1 => vals::Stop::STOP1, - StopBits::STOP1P5 => vals::Stop::STOP1P5, - StopBits::STOP2 => vals::Stop::STOP2, - }); + r.cr2().write(|w| { + w.set_stop(match config.stop_bits { + StopBits::STOP0P5 => vals::Stop::STOP0P5, + StopBits::STOP1 => vals::Stop::STOP1, + StopBits::STOP1P5 => vals::Stop::STOP1P5, + StopBits::STOP2 => vals::Stop::STOP2, }); - r.cr1().write(|w| { - // enable uart - w.set_ue(true); - // enable transceiver - w.set_te(enable_tx); - // enable receiver - w.set_re(enable_rx); - // configure word size - w.set_m0(if config.parity != Parity::ParityNone { - vals::M0::BIT9 - } else { - vals::M0::BIT8 - }); - // configure parity - w.set_pce(config.parity != Parity::ParityNone); - w.set_ps(match config.parity { - Parity::ParityOdd => vals::Ps::ODD, - Parity::ParityEven => vals::Ps::EVEN, - _ => vals::Ps::EVEN, - }); - #[cfg(not(usart_v1))] - w.set_over8(vals::Over8(over8 as _)); + }); + r.cr1().write(|w| { + // enable uart + w.set_ue(true); + // enable transceiver + w.set_te(enable_tx); + // enable receiver + w.set_re(enable_rx); + // configure word size + w.set_m0(if config.parity != Parity::ParityNone { + vals::M0::BIT9 + } else { + vals::M0::BIT8 + }); + // configure parity + w.set_pce(config.parity != Parity::ParityNone); + w.set_ps(match config.parity { + Parity::ParityOdd => vals::Ps::ODD, + Parity::ParityEven => vals::Ps::EVEN, + _ => vals::Ps::EVEN, }); - #[cfg(not(usart_v1))] - r.cr3().modify(|w| { - w.set_onebit(config.assume_noise_free); - }); - } + w.set_over8(vals::Over8(over8 as _)); + }); + + #[cfg(not(usart_v1))] + r.cr3().modify(|w| { + w.set_onebit(config.assume_noise_free); + }); } mod eh02 { @@ -1111,12 +1066,12 @@ use self::sealed::Kind; #[cfg(any(usart_v1, usart_v2))] fn tdr(r: crate::pac::usart::Usart) -> *mut u8 { - r.dr().ptr() as _ + r.dr().as_ptr() as _ } #[cfg(any(usart_v1, usart_v2))] fn rdr(r: crate::pac::usart::Usart) -> *mut u8 { - r.dr().ptr() as _ + r.dr().as_ptr() as _ } #[cfg(any(usart_v1, usart_v2))] @@ -1126,18 +1081,18 @@ fn sr(r: crate::pac::usart::Usart) -> crate::pac::common::Reg *mut u8 { - r.tdr().ptr() as _ + r.tdr().as_ptr() as _ } #[cfg(any(usart_v3, usart_v4))] fn rdr(r: Regs) -> *mut u8 { - r.rdr().ptr() as _ + r.rdr().as_ptr() as _ } #[cfg(any(usart_v3, usart_v4))] @@ -1147,7 +1102,7 @@ fn sr(r: Regs) -> crate::pac::common::Reg { #[cfg(any(usart_v3, usart_v4))] #[allow(unused)] -unsafe fn clear_interrupt_flags(r: Regs, sr: regs::Isr) { +fn clear_interrupt_flags(r: Regs, sr: regs::Isr) { r.icr().write(|w| *w = regs::Icr(sr.0)); } @@ -1214,7 +1169,7 @@ macro_rules! impl_usart { type Interrupt = crate::interrupt::typelevel::$irq; fn regs() -> Regs { - Regs(crate::pac::$inst.0) + unsafe { Regs::from_ptr(crate::pac::$inst.as_ptr()) } } fn state() -> &'static crate::usart::sealed::State { diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs index 511b71c7..c74d7e09 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> RingBufferedUartRx<'d, T, RxD let r = T::regs(); // clear all interrupts and DMA Rx Request - // SAFETY: only clears Rx related flags - unsafe { - r.cr1().modify(|w| { - // disable RXNE interrupt - w.set_rxneie(false); - // enable parity interrupt if not ParityNone - w.set_peie(w.pce()); - // enable idle line interrupt - w.set_idleie(true); - }); - r.cr3().modify(|w| { - // enable Error Interrupt: (Frame error, Noise error, Overrun error) - w.set_eie(true); - // enable DMA Rx Request - w.set_dmar(true); - }); - } + r.cr1().modify(|w| { + // disable RXNE interrupt + w.set_rxneie(false); + // enable parity interrupt if not ParityNone + w.set_peie(w.pce()); + // enable idle line interrupt + w.set_idleie(true); + }); + r.cr3().modify(|w| { + // enable Error Interrupt: (Frame error, Noise error, Overrun error) + w.set_eie(true); + // enable DMA Rx Request + w.set_dmar(true); + }); } /// Stop uart background receive @@ -84,23 +81,20 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma> RingBufferedUartRx<'d, T, RxD let r = T::regs(); // clear all interrupts and DMA Rx Request - // SAFETY: only clears Rx related flags - unsafe { - r.cr1().modify(|w| { - // disable RXNE interrupt - w.set_rxneie(false); - // disable parity interrupt - w.set_peie(false); - // disable idle line interrupt - w.set_idleie(false); - }); - r.cr3().modify(|w| { - // disable Error Interrupt: (Frame error, Noise error, Overrun error) - w.set_eie(false); - // disable DMA Rx Request - w.set_dmar(false); - }); - } + r.cr1().modify(|w| { + // disable RXNE interrupt + w.set_rxneie(false); + // disable parity interrupt + w.set_peie(false); + // disable idle line interrupt + w.set_idleie(false); + }); + r.cr3().modify(|w| { + // disable Error Interrupt: (Frame error, Noise error, Overrun error) + w.set_eie(false); + // disable DMA Rx Request + w.set_dmar(false); + }); compiler_fence(Ordering::SeqCst); } @@ -117,8 +111,7 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma> RingBufferedUartRx<'d, T, RxD let r = T::regs(); // Start background receive if it was not already started - // SAFETY: read only - match unsafe { r.cr3().read().dmar() } { + match r.cr3().read().dmar() { false => self.start()?, _ => {} }; @@ -213,19 +206,17 @@ fn check_for_errors(s: Sr) -> Result<(), Error> { /// Clear IDLE and return the Sr register fn clear_idle_flag(r: Regs) -> Sr { - unsafe { - // SAFETY: read only and we only use Rx related flags + // SAFETY: read only and we only use Rx related flags - let sr = sr(r).read(); + let sr = sr(r).read(); - // This read also clears the error and idle interrupt flags on v1. - rdr(r).read_volatile(); - clear_interrupt_flags(r, sr); + // This read also clears the error and idle interrupt flags on v1. + unsafe { rdr(r).read_volatile() }; + clear_interrupt_flags(r, sr); - r.cr1().modify(|w| w.set_idleie(true)); + r.cr1().modify(|w| w.set_idleie(true)); - sr - } + sr } #[cfg(all(feature = "unstable-traits", feature = "nightly"))] diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs index 7486bd37..2367127e 100644 --- a/embassy-stm32/src/usb/usb.rs +++ b/embassy-stm32/src/usb/usb.rs @@ -28,82 +28,80 @@ pub struct InterruptHandler { impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { - unsafe { - let regs = T::regs(); - //let x = regs.istr().read().0; - //trace!("USB IRQ: {:08x}", x); + let regs = T::regs(); + //let x = regs.istr().read().0; + //trace!("USB IRQ: {:08x}", x); - let istr = regs.istr().read(); + let istr = regs.istr().read(); - if istr.susp() { - //trace!("USB IRQ: susp"); - IRQ_SUSPEND.store(true, Ordering::Relaxed); - regs.cntr().modify(|w| { - w.set_fsusp(true); - w.set_lpmode(true); - }); + if istr.susp() { + //trace!("USB IRQ: susp"); + IRQ_SUSPEND.store(true, Ordering::Relaxed); + regs.cntr().modify(|w| { + w.set_fsusp(true); + w.set_lpmode(true); + }); - // Write 0 to clear. - let mut clear = regs::Istr(!0); - clear.set_susp(false); - regs.istr().write_value(clear); + // Write 0 to clear. + let mut clear = regs::Istr(!0); + clear.set_susp(false); + regs.istr().write_value(clear); - // Wake main thread. - BUS_WAKER.wake(); - } + // Wake main thread. + BUS_WAKER.wake(); + } - if istr.wkup() { - //trace!("USB IRQ: wkup"); - IRQ_RESUME.store(true, Ordering::Relaxed); - regs.cntr().modify(|w| { - w.set_fsusp(false); - w.set_lpmode(false); - }); + if istr.wkup() { + //trace!("USB IRQ: wkup"); + IRQ_RESUME.store(true, Ordering::Relaxed); + regs.cntr().modify(|w| { + w.set_fsusp(false); + w.set_lpmode(false); + }); - // Write 0 to clear. - let mut clear = regs::Istr(!0); - clear.set_wkup(false); - regs.istr().write_value(clear); + // Write 0 to clear. + let mut clear = regs::Istr(!0); + clear.set_wkup(false); + regs.istr().write_value(clear); - // Wake main thread. - BUS_WAKER.wake(); - } + // Wake main thread. + BUS_WAKER.wake(); + } - if istr.reset() { - //trace!("USB IRQ: reset"); - IRQ_RESET.store(true, Ordering::Relaxed); + if istr.reset() { + //trace!("USB IRQ: reset"); + IRQ_RESET.store(true, Ordering::Relaxed); - // Write 0 to clear. - let mut clear = regs::Istr(!0); - clear.set_reset(false); - regs.istr().write_value(clear); + // Write 0 to clear. + let mut clear = regs::Istr(!0); + clear.set_reset(false); + regs.istr().write_value(clear); - // Wake main thread. - BUS_WAKER.wake(); - } + // Wake main thread. + BUS_WAKER.wake(); + } - if istr.ctr() { - let index = istr.ep_id() as usize; - let mut epr = regs.epr(index).read(); - if epr.ctr_rx() { - if index == 0 && epr.setup() { - EP0_SETUP.store(true, Ordering::Relaxed); - } - //trace!("EP {} RX, setup={}", index, epr.setup()); - EP_OUT_WAKERS[index].wake(); + if istr.ctr() { + let index = istr.ep_id() as usize; + let mut epr = regs.epr(index).read(); + if epr.ctr_rx() { + if index == 0 && epr.setup() { + EP0_SETUP.store(true, Ordering::Relaxed); } - if epr.ctr_tx() { - //trace!("EP {} TX", index); - EP_IN_WAKERS[index].wake(); - } - epr.set_dtog_rx(false); - epr.set_dtog_tx(false); - epr.set_stat_rx(Stat(0)); - epr.set_stat_tx(Stat(0)); - epr.set_ctr_rx(!epr.ctr_rx()); - epr.set_ctr_tx(!epr.ctr_tx()); - regs.epr(index).write_value(epr); + //trace!("EP {} RX, setup={}", index, epr.setup()); + EP_OUT_WAKERS[index].wake(); } + if epr.ctr_tx() { + //trace!("EP {} TX", index); + EP_IN_WAKERS[index].wake(); + } + epr.set_dtog_rx(false); + epr.set_dtog_tx(false); + epr.set_stat_rx(Stat(0)); + epr.set_stat_tx(Stat(0)); + epr.set_ctr_rx(!epr.ctr_rx()); + epr.set_ctr_tx(!epr.ctr_tx()); + regs.epr(index).write_value(epr); } } } @@ -168,20 +166,20 @@ fn calc_out_len(len: u16) -> (u16, u16) { mod btable { use super::*; - pub(super) unsafe fn write_in(index: usize, addr: u16) { + pub(super) fn write_in(index: usize, addr: u16) { USBRAM.mem(index * 4 + 0).write_value(addr); } - pub(super) unsafe fn write_in_len(index: usize, _addr: u16, len: u16) { + pub(super) fn write_in_len(index: usize, _addr: u16, len: u16) { USBRAM.mem(index * 4 + 1).write_value(len); } - pub(super) unsafe fn write_out(index: usize, addr: u16, max_len_bits: u16) { + pub(super) fn write_out(index: usize, addr: u16, max_len_bits: u16) { USBRAM.mem(index * 4 + 2).write_value(addr); USBRAM.mem(index * 4 + 3).write_value(max_len_bits); } - pub(super) unsafe fn read_out_len(index: usize) -> u16 { + pub(super) fn read_out_len(index: usize) -> u16 { USBRAM.mem(index * 4 + 3).read() } } @@ -189,19 +187,19 @@ mod btable { mod btable { use super::*; - pub(super) unsafe fn write_in(_index: usize, _addr: u16) {} + pub(super) fn write_in(_index: usize, _addr: u16) {} - pub(super) unsafe fn write_in_len(index: usize, addr: u16, len: u16) { + pub(super) fn write_in_len(index: usize, addr: u16, len: u16) { USBRAM.mem(index * 2).write_value((addr as u32) | ((len as u32) << 16)); } - pub(super) unsafe fn write_out(index: usize, addr: u16, max_len_bits: u16) { + pub(super) fn write_out(index: usize, addr: u16, max_len_bits: u16) { USBRAM .mem(index * 2 + 1) .write_value((addr as u32) | ((max_len_bits as u32) << 16)); } - pub(super) unsafe fn read_out_len(index: usize) -> u16 { + pub(super) fn read_out_len(index: usize) -> u16 { (USBRAM.mem(index * 2 + 1).read() >> 16) as u16 } } @@ -216,7 +214,7 @@ impl EndpointBuffer { fn read(&mut self, buf: &mut [u8]) { assert!(buf.len() <= self.len as usize); for i in 0..(buf.len() + USBRAM_ALIGN - 1) / USBRAM_ALIGN { - let val = unsafe { USBRAM.mem(self.addr as usize / USBRAM_ALIGN + i).read() }; + let val = USBRAM.mem(self.addr as usize / USBRAM_ALIGN + i).read(); let n = USBRAM_ALIGN.min(buf.len() - i * USBRAM_ALIGN); buf[i * USBRAM_ALIGN..][..n].copy_from_slice(&val.to_le_bytes()[..n]); } @@ -233,7 +231,7 @@ impl EndpointBuffer { let val = u16::from_le_bytes(val); #[cfg(usbram_32_2048)] let val = u32::from_le_bytes(val); - unsafe { USBRAM.mem(self.addr as usize / USBRAM_ALIGN + i).write_value(val) }; + USBRAM.mem(self.addr as usize / USBRAM_ALIGN + i).write_value(val); } } } @@ -266,36 +264,32 @@ impl<'d, T: Instance> Driver<'d, T> { let regs = T::regs(); #[cfg(stm32l5)] - unsafe { + { crate::peripherals::PWR::enable(); crate::pac::PWR.cr2().modify(|w| w.set_usv(true)); } #[cfg(pwr_h5)] - unsafe { - crate::pac::PWR.usbscr().modify(|w| w.set_usb33sv(true)) - } + crate::pac::PWR.usbscr().modify(|w| w.set_usb33sv(true)); - unsafe { - ::enable(); - ::reset(); + ::enable(); + ::reset(); - regs.cntr().write(|w| { - w.set_pdwn(false); - w.set_fres(true); - }); + regs.cntr().write(|w| { + w.set_pdwn(false); + w.set_fres(true); + }); - #[cfg(time)] - embassy_time::block_for(embassy_time::Duration::from_millis(100)); - #[cfg(not(time))] - cortex_m::asm::delay(crate::rcc::get_freqs().sys.0 / 10); + #[cfg(time)] + embassy_time::block_for(embassy_time::Duration::from_millis(100)); + #[cfg(not(time))] + cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.0 / 10); - #[cfg(not(usb_v4))] - regs.btable().write(|w| w.set_btable(0)); + #[cfg(not(usb_v4))] + regs.btable().write(|w| w.set_btable(0)); - dp.set_as_af(dp.af_num(), AFType::OutputPushPull); - dm.set_as_af(dm.af_num(), AFType::OutputPushPull); - } + dp.set_as_af(dp.af_num(), AFType::OutputPushPull); + dm.set_as_af(dm.af_num(), AFType::OutputPushPull); // Initialize the bus so that it signals that power is available BUS_WAKER.wake(); @@ -363,7 +357,7 @@ impl<'d, T: Instance> Driver<'d, T> { let addr = self.alloc_ep_mem(len); trace!(" len_bits = {:04x}", len_bits); - unsafe { btable::write_out::(index, addr, len_bits) } + btable::write_out::(index, addr, len_bits); EndpointBuffer { addr, @@ -379,7 +373,7 @@ impl<'d, T: Instance> Driver<'d, T> { let addr = self.alloc_ep_mem(len); // ep_in_len is written when actually TXing packets. - unsafe { btable::write_in::(index, addr) } + btable::write_in::(index, addr); EndpointBuffer { addr, @@ -440,19 +434,17 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> { let regs = T::regs(); - unsafe { - regs.cntr().write(|w| { - w.set_pdwn(false); - w.set_fres(false); - w.set_resetm(true); - w.set_suspm(true); - w.set_wkupm(true); - w.set_ctrm(true); - }); + regs.cntr().write(|w| { + w.set_pdwn(false); + w.set_fres(false); + w.set_resetm(true); + w.set_suspm(true); + w.set_wkupm(true); + w.set_ctrm(true); + }); - #[cfg(any(usb_v3, usb_v4))] - regs.bcdr().write(|w| w.set_dppu(true)) - } + #[cfg(any(usb_v3, usb_v4))] + regs.bcdr().write(|w| w.set_dppu(true)); trace!("enabled"); @@ -485,7 +477,7 @@ pub struct Bus<'d, T: Instance> { impl<'d, T: Instance> driver::Bus for Bus<'d, T> { async fn poll(&mut self) -> Event { - poll_fn(move |cx| unsafe { + poll_fn(move |cx| { BUS_WAKER.register(cx.waker()); if self.inited { @@ -548,7 +540,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { match ep_addr.direction() { Direction::In => { loop { - let r = unsafe { reg.read() }; + let r = reg.read(); match r.stat_tx() { Stat::DISABLED => break, // if disabled, stall does nothing. Stat::STALL => break, // done! @@ -559,7 +551,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { }; let mut w = invariant(r); w.set_stat_tx(Stat(r.stat_tx().0 ^ want_stat.0)); - unsafe { reg.write_value(w) }; + reg.write_value(w); } } } @@ -567,7 +559,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { } Direction::Out => { loop { - let r = unsafe { reg.read() }; + let r = reg.read(); match r.stat_rx() { Stat::DISABLED => break, // if disabled, stall does nothing. Stat::STALL => break, // done! @@ -578,7 +570,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { }; let mut w = invariant(r); w.set_stat_rx(Stat(r.stat_rx().0 ^ want_stat.0)); - unsafe { reg.write_value(w) }; + reg.write_value(w); } } } @@ -589,7 +581,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { fn endpoint_is_stalled(&mut self, ep_addr: EndpointAddress) -> bool { let regs = T::regs(); - let epr = unsafe { regs.epr(ep_addr.index() as _).read() }; + let epr = regs.epr(ep_addr.index() as _).read(); match ep_addr.direction() { Direction::In => epr.stat_tx() == Stat::STALL, Direction::Out => epr.stat_rx() == Stat::STALL, @@ -600,7 +592,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { trace!("set_enabled {:x} {}", ep_addr, enabled); // This can race, so do a retry loop. let reg = T::regs().epr(ep_addr.index() as _); - trace!("EPR before: {:04x}", unsafe { reg.read() }.0); + trace!("EPR before: {:04x}", reg.read().0); match ep_addr.direction() { Direction::In => { loop { @@ -608,13 +600,13 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { false => Stat::DISABLED, true => Stat::NAK, }; - let r = unsafe { reg.read() }; + let r = reg.read(); if r.stat_tx() == want_stat { break; } let mut w = invariant(r); w.set_stat_tx(Stat(r.stat_tx().0 ^ want_stat.0)); - unsafe { reg.write_value(w) }; + reg.write_value(w); } EP_IN_WAKERS[ep_addr.index()].wake(); } @@ -624,18 +616,18 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { false => Stat::DISABLED, true => Stat::VALID, }; - let r = unsafe { reg.read() }; + let r = reg.read(); if r.stat_rx() == want_stat { break; } let mut w = invariant(r); w.set_stat_rx(Stat(r.stat_rx().0 ^ want_stat.0)); - unsafe { reg.write_value(w) }; + reg.write_value(w); } EP_OUT_WAKERS[ep_addr.index()].wake(); } } - trace!("EPR after: {:04x}", unsafe { reg.read() }.0); + trace!("EPR after: {:04x}", reg.read().0); } async fn enable(&mut self) {} @@ -685,12 +677,12 @@ impl<'d, T: Instance, D> Endpoint<'d, T, D> { fn write_data(&mut self, buf: &[u8]) { let index = self.info.addr.index(); self.buf.write(buf); - unsafe { btable::write_in_len::(index, self.buf.addr, buf.len() as _) } + btable::write_in_len::(index, self.buf.addr, buf.len() as _); } fn read_data(&mut self, buf: &mut [u8]) -> Result { let index = self.info.addr.index(); - let rx_len = unsafe { btable::read_out_len::(index) as usize } & 0x3FF; + let rx_len = btable::read_out_len::(index) as usize & 0x3FF; trace!("READ DONE, rx_len = {}", rx_len); if rx_len > buf.len() { return Err(EndpointError::BufferOverflow); @@ -711,7 +703,7 @@ impl<'d, T: Instance> driver::Endpoint for Endpoint<'d, T, In> { poll_fn(|cx| { EP_OUT_WAKERS[index].register(cx.waker()); let regs = T::regs(); - if unsafe { regs.epr(index).read() }.stat_tx() == Stat::DISABLED { + if regs.epr(index).read().stat_tx() == Stat::DISABLED { Poll::Pending } else { Poll::Ready(()) @@ -733,7 +725,7 @@ impl<'d, T: Instance> driver::Endpoint for Endpoint<'d, T, Out> { poll_fn(|cx| { EP_OUT_WAKERS[index].register(cx.waker()); let regs = T::regs(); - if unsafe { regs.epr(index).read() }.stat_rx() == Stat::DISABLED { + if regs.epr(index).read().stat_rx() == Stat::DISABLED { Poll::Pending } else { Poll::Ready(()) @@ -751,7 +743,7 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> { let stat = poll_fn(|cx| { EP_OUT_WAKERS[index].register(cx.waker()); let regs = T::regs(); - let stat = unsafe { regs.epr(index).read() }.stat_rx(); + let stat = regs.epr(index).read().stat_rx(); if matches!(stat, Stat::NAK | Stat::DISABLED) { Poll::Ready(stat) } else { @@ -767,16 +759,14 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> { let rx_len = self.read_data(buf)?; let regs = T::regs(); - unsafe { - regs.epr(index).write(|w| { - w.set_ep_type(convert_type(self.info.ep_type)); - w.set_ea(self.info.addr.index() as _); - w.set_stat_rx(Stat(Stat::NAK.0 ^ Stat::VALID.0)); - w.set_stat_tx(Stat(0)); - w.set_ctr_rx(true); // don't clear - w.set_ctr_tx(true); // don't clear - }) - }; + regs.epr(index).write(|w| { + w.set_ep_type(convert_type(self.info.ep_type)); + w.set_ea(self.info.addr.index() as _); + w.set_stat_rx(Stat(Stat::NAK.0 ^ Stat::VALID.0)); + w.set_stat_tx(Stat(0)); + w.set_ctr_rx(true); // don't clear + w.set_ctr_tx(true); // don't clear + }); trace!("READ OK, rx_len = {}", rx_len); Ok(rx_len) @@ -795,7 +785,7 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> { let stat = poll_fn(|cx| { EP_IN_WAKERS[index].register(cx.waker()); let regs = T::regs(); - let stat = unsafe { regs.epr(index).read() }.stat_tx(); + let stat = regs.epr(index).read().stat_tx(); if matches!(stat, Stat::NAK | Stat::DISABLED) { Poll::Ready(stat) } else { @@ -811,16 +801,14 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> { self.write_data(buf); let regs = T::regs(); - unsafe { - regs.epr(index).write(|w| { - w.set_ep_type(convert_type(self.info.ep_type)); - w.set_ea(self.info.addr.index() as _); - w.set_stat_tx(Stat(Stat::NAK.0 ^ Stat::VALID.0)); - w.set_stat_rx(Stat(0)); - w.set_ctr_rx(true); // don't clear - w.set_ctr_tx(true); // don't clear - }) - }; + regs.epr(index).write(|w| { + w.set_ep_type(convert_type(self.info.ep_type)); + w.set_ea(self.info.addr.index() as _); + w.set_stat_tx(Stat(Stat::NAK.0 ^ Stat::VALID.0)); + w.set_stat_rx(Stat(0)); + w.set_ctr_rx(true); // don't clear + w.set_ctr_tx(true); // don't clear + }); trace!("WRITE OK"); @@ -889,22 +877,20 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { } // Note: if this is the first AND last transfer, the above effectively // changes stat_tx like NAK -> NAK, so noop. - unsafe { - regs.epr(0).write(|w| { - w.set_ep_type(EpType::CONTROL); - w.set_stat_rx(Stat(stat_rx)); - w.set_stat_tx(Stat(stat_tx)); - w.set_ctr_rx(true); // don't clear - w.set_ctr_tx(true); // don't clear - }) - } + regs.epr(0).write(|w| { + w.set_ep_type(EpType::CONTROL); + w.set_stat_rx(Stat(stat_rx)); + w.set_stat_tx(Stat(stat_tx)); + w.set_ctr_rx(true); // don't clear + w.set_ctr_tx(true); // don't clear + }); } trace!("data_out WAITING, buf.len() = {}", buf.len()); poll_fn(|cx| { EP_OUT_WAKERS[0].register(cx.waker()); let regs = T::regs(); - if unsafe { regs.epr(0).read() }.stat_rx() == Stat::NAK { + if regs.epr(0).read().stat_rx() == Stat::NAK { Poll::Ready(()) } else { Poll::Pending @@ -919,19 +905,17 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { let rx_len = self.ep_out.read_data(buf)?; - unsafe { - regs.epr(0).write(|w| { - w.set_ep_type(EpType::CONTROL); - w.set_stat_rx(Stat(match last { - // If last, set STAT_RX=STALL. - true => Stat::NAK.0 ^ Stat::STALL.0, - // Otherwise, set STAT_RX=VALID, to allow the host to send the next packet. - false => Stat::NAK.0 ^ Stat::VALID.0, - })); - w.set_ctr_rx(true); // don't clear - w.set_ctr_tx(true); // don't clear - }) - }; + regs.epr(0).write(|w| { + w.set_ep_type(EpType::CONTROL); + w.set_stat_rx(Stat(match last { + // If last, set STAT_RX=STALL. + true => Stat::NAK.0 ^ Stat::STALL.0, + // Otherwise, set STAT_RX=VALID, to allow the host to send the next packet. + false => Stat::NAK.0 ^ Stat::VALID.0, + })); + w.set_ctr_rx(true); // don't clear + w.set_ctr_tx(true); // don't clear + }); Ok(rx_len) } @@ -960,15 +944,13 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { } // Note: if this is the first AND last transfer, the above effectively // does a change of NAK -> VALID. - unsafe { - regs.epr(0).write(|w| { - w.set_ep_type(EpType::CONTROL); - w.set_stat_rx(Stat(stat_rx)); - w.set_ep_kind(last); // set OUT_STATUS if last. - w.set_ctr_rx(true); // don't clear - w.set_ctr_tx(true); // don't clear - }) - } + regs.epr(0).write(|w| { + w.set_ep_type(EpType::CONTROL); + w.set_stat_rx(Stat(stat_rx)); + w.set_ep_kind(last); // set OUT_STATUS if last. + w.set_ctr_rx(true); // don't clear + w.set_ctr_tx(true); // don't clear + }); } trace!("WRITE WAITING"); @@ -976,7 +958,7 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { EP_IN_WAKERS[0].register(cx.waker()); EP_OUT_WAKERS[0].register(cx.waker()); let regs = T::regs(); - if unsafe { regs.epr(0).read() }.stat_tx() == Stat::NAK { + if regs.epr(0).read().stat_tx() == Stat::NAK { Poll::Ready(()) } else { Poll::Pending @@ -992,15 +974,13 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { self.ep_in.write_data(data); let regs = T::regs(); - unsafe { - regs.epr(0).write(|w| { - w.set_ep_type(EpType::CONTROL); - w.set_stat_tx(Stat(Stat::NAK.0 ^ Stat::VALID.0)); - w.set_ep_kind(last); // set OUT_STATUS if last. - w.set_ctr_rx(true); // don't clear - w.set_ctr_tx(true); // don't clear - }) - }; + regs.epr(0).write(|w| { + w.set_ep_type(EpType::CONTROL); + w.set_stat_tx(Stat(Stat::NAK.0 ^ Stat::VALID.0)); + w.set_ep_kind(last); // set OUT_STATUS if last. + w.set_ctr_rx(true); // don't clear + w.set_ctr_tx(true); // don't clear + }); trace!("WRITE OK"); @@ -1014,16 +994,14 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { self.ep_in.write_data(&[]); // Set OUT=stall, IN=accept - unsafe { - let epr = regs.epr(0).read(); - regs.epr(0).write(|w| { - w.set_ep_type(EpType::CONTROL); - w.set_stat_rx(Stat(epr.stat_rx().0 ^ Stat::STALL.0)); - w.set_stat_tx(Stat(epr.stat_tx().0 ^ Stat::VALID.0)); - w.set_ctr_rx(true); // don't clear - w.set_ctr_tx(true); // don't clear - }); - } + let epr = regs.epr(0).read(); + regs.epr(0).write(|w| { + w.set_ep_type(EpType::CONTROL); + w.set_stat_rx(Stat(epr.stat_rx().0 ^ Stat::STALL.0)); + w.set_stat_tx(Stat(epr.stat_tx().0 ^ Stat::VALID.0)); + w.set_ctr_rx(true); // don't clear + w.set_ctr_tx(true); // don't clear + }); trace!("control: accept WAITING"); // 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> { poll_fn(|cx| { EP_IN_WAKERS[0].register(cx.waker()); let regs = T::regs(); - if unsafe { regs.epr(0).read() }.stat_tx() == Stat::NAK { + if regs.epr(0).read().stat_tx() == Stat::NAK { Poll::Ready(()) } else { Poll::Pending @@ -1047,16 +1025,14 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { trace!("control: reject"); // Set IN+OUT to stall - unsafe { - let epr = regs.epr(0).read(); - regs.epr(0).write(|w| { - w.set_ep_type(EpType::CONTROL); - w.set_stat_rx(Stat(epr.stat_rx().0 ^ Stat::STALL.0)); - w.set_stat_tx(Stat(epr.stat_tx().0 ^ Stat::STALL.0)); - w.set_ctr_rx(true); // don't clear - w.set_ctr_tx(true); // don't clear - }); - } + let epr = regs.epr(0).read(); + regs.epr(0).write(|w| { + w.set_ep_type(EpType::CONTROL); + w.set_stat_rx(Stat(epr.stat_rx().0 ^ Stat::STALL.0)); + w.set_stat_tx(Stat(epr.stat_tx().0 ^ Stat::STALL.0)); + w.set_ctr_rx(true); // don't clear + w.set_ctr_tx(true); // don't clear + }); } async fn accept_set_address(&mut self, addr: u8) { @@ -1064,11 +1040,9 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { let regs = T::regs(); trace!("setting addr: {}", addr); - unsafe { - regs.daddr().write(|w| { - w.set_ef(true); - w.set_add(addr); - }) - } + regs.daddr().write(|w| { + w.set_ef(true); + w.set_add(addr); + }); } } diff --git a/embassy-stm32/src/usb_otg/mod.rs b/embassy-stm32/src/usb_otg/mod.rs index 317264cb..12e5f0e6 100644 --- a/embassy-stm32/src/usb_otg/mod.rs +++ b/embassy-stm32/src/usb_otg/mod.rs @@ -148,7 +148,7 @@ foreach_interrupt!( fn regs() -> crate::pac::otg::Otg { // OTG HS registers are a superset of FS registers - crate::pac::otg::Otg(crate::pac::USB_OTG_HS.0) + unsafe { crate::pac::otg::Otg::from_ptr(crate::pac::USB_OTG_HS.as_ptr()) } } #[cfg(feature = "nightly")] diff --git a/embassy-stm32/src/usb_otg/usb.rs b/embassy-stm32/src/usb_otg/usb.rs index 16cbf1a9..8af5c7bd 100644 --- a/embassy-stm32/src/usb_otg/usb.rs +++ b/embassy-stm32/src/usb_otg/usb.rs @@ -30,19 +30,16 @@ impl interrupt::typelevel::Handler for InterruptHandl let r = T::regs(); let state = T::state(); - // SAFETY: atomic read/write - let ints = unsafe { r.gintsts().read() }; + let ints = r.gintsts().read(); if ints.wkupint() || ints.usbsusp() || ints.usbrst() || ints.enumdne() { // Mask interrupts and notify `Bus` to process them - unsafe { r.gintmsk().write(|_| {}) }; + r.gintmsk().write(|_| {}); T::state().bus_waker.wake(); } // Handle RX - // SAFETY: atomic read with no side effects - while unsafe { r.gintsts().read().rxflvl() } { - // SAFETY: atomic "pop" register - let status = unsafe { r.grxstsp().read() }; + while r.gintsts().read().rxflvl() { + let status = r.grxstsp().read(); let ep_num = status.epnum() as usize; let len = status.bcnt() as usize; @@ -57,21 +54,15 @@ impl interrupt::typelevel::Handler for InterruptHandl if state.ep0_setup_ready.load(Ordering::Relaxed) == false { // SAFETY: exclusive access ensured by atomic bool let data = unsafe { &mut *state.ep0_setup_data.get() }; - // SAFETY: FIFO reads are exclusive to this IRQ - unsafe { - data[0..4].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes()); - data[4..8].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes()); - } + data[0..4].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes()); + data[4..8].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes()); state.ep0_setup_ready.store(true, Ordering::Release); state.ep_out_wakers[0].wake(); } else { error!("received SETUP before previous finished processing"); // discard FIFO - // SAFETY: FIFO reads are exclusive to IRQ - unsafe { - r.fifo(0).read(); - r.fifo(0).read(); - } + r.fifo(0).read(); + r.fifo(0).read(); } } vals::Pktstsd::OUT_DATA_RX => { @@ -84,8 +75,7 @@ impl interrupt::typelevel::Handler for InterruptHandl for chunk in buf.chunks_mut(4) { // RX FIFO is shared so always read from fifo(0) - // SAFETY: FIFO reads are exclusive to IRQ - let data = unsafe { r.fifo(0).read().0 }; + let data = r.fifo(0).read().0; chunk.copy_from_slice(&data.to_ne_bytes()[0..chunk.len()]); } @@ -97,8 +87,7 @@ impl interrupt::typelevel::Handler for InterruptHandl // discard FIFO data let len_words = (len + 3) / 4; for _ in 0..len_words { - // SAFETY: FIFO reads are exclusive to IRQ - unsafe { r.fifo(0).read().data() }; + r.fifo(0).read().data(); } } } @@ -114,24 +103,20 @@ impl interrupt::typelevel::Handler for InterruptHandl // IN endpoint interrupt if ints.iepint() { - // SAFETY: atomic read with no side effects - let mut ep_mask = unsafe { r.daint().read().iepint() }; + let mut ep_mask = r.daint().read().iepint(); let mut ep_num = 0; // Iterate over endpoints while there are non-zero bits in the mask while ep_mask != 0 { if ep_mask & 1 != 0 { - // SAFETY: atomic read with no side effects - let ep_ints = unsafe { r.diepint(ep_num).read() }; + let ep_ints = r.diepint(ep_num).read(); // clear all - // SAFETY: DIEPINT is exclusive to IRQ - unsafe { r.diepint(ep_num).write_value(ep_ints) }; + r.diepint(ep_num).write_value(ep_ints); // TXFE is cleared in DIEPEMPMSK if ep_ints.txfe() { - // SAFETY: DIEPEMPMSK is shared with `Endpoint` so critical section is needed for RMW - critical_section::with(|_| unsafe { + critical_section::with(|_| { r.diepempmsk().modify(|w| { w.set_ineptxfem(w.ineptxfem() & !(1 << ep_num)); }); @@ -172,8 +157,7 @@ impl interrupt::typelevel::Handler for InterruptHandl macro_rules! config_ulpi_pins { ($($pin:ident),*) => { into_ref!($($pin),*); - // NOTE(unsafe) Exclusive access to the registers - critical_section::with(|_| unsafe { + critical_section::with(|_| { $( $pin.set_as_af($pin.af_num(), AFType::OutputPushPull); #[cfg(gpio_v2)] @@ -298,10 +282,8 @@ impl<'d, T: Instance> Driver<'d, T> { ) -> Self { into_ref!(dp, dm); - unsafe { - dp.set_as_af(dp.af_num(), AFType::OutputPushPull); - dm.set_as_af(dm.af_num(), AFType::OutputPushPull); - } + dp.set_as_af(dp.af_num(), AFType::OutputPushPull); + dm.set_as_af(dm.af_num(), AFType::OutputPushPull); Self { phantom: PhantomData, @@ -508,18 +490,15 @@ pub struct Bus<'d, T: Instance> { impl<'d, T: Instance> Bus<'d, T> { fn restore_irqs() { - // SAFETY: atomic write - unsafe { - T::regs().gintmsk().write(|w| { - w.set_usbrst(true); - w.set_enumdnem(true); - w.set_usbsuspm(true); - w.set_wuim(true); - w.set_iepint(true); - w.set_oepint(true); - w.set_rxflvlm(true); - }); - } + T::regs().gintmsk().write(|w| { + w.set_usbrst(true); + w.set_enumdnem(true); + w.set_usbsuspm(true); + w.set_wuim(true); + w.set_iepint(true); + w.set_oepint(true); + w.set_rxflvlm(true); + }); } } @@ -533,8 +512,7 @@ impl<'d, T: Instance> Bus<'d, T> { let rx_fifo_size_words = RX_FIFO_EXTRA_SIZE_WORDS + ep_fifo_size(&self.ep_out); trace!("configuring rx fifo size={}", rx_fifo_size_words); - // SAFETY: register is exclusive to `Bus` with `&mut self` - unsafe { r.grxfsiz().modify(|w| w.set_rxfd(rx_fifo_size_words)) }; + r.grxfsiz().modify(|w| w.set_rxfd(rx_fifo_size_words)); // Configure TX (USB in direction) fifo size for each endpoint let mut fifo_top = rx_fifo_size_words; @@ -549,13 +527,10 @@ impl<'d, T: Instance> Bus<'d, T> { let dieptxf = if i == 0 { r.dieptxf0() } else { r.dieptxf(i - 1) }; - // SAFETY: register is exclusive to `Bus` with `&mut self` - unsafe { - dieptxf.write(|w| { - w.set_fd(ep.fifo_size_words); - w.set_sa(fifo_top); - }); - } + dieptxf.write(|w| { + w.set_fd(ep.fifo_size_words); + w.set_sa(fifo_top); + }); fifo_top += ep.fifo_size_words; } @@ -575,8 +550,7 @@ impl<'d, T: Instance> Bus<'d, T> { // Configure IN endpoints for (index, ep) in self.ep_in.iter().enumerate() { if let Some(ep) = ep { - // SAFETY: DIEPCTL is shared with `Endpoint` so critical section is needed for RMW - critical_section::with(|_| unsafe { + critical_section::with(|_| { r.diepctl(index).write(|w| { if index == 0 { w.set_mpsiz(ep0_mpsiz(ep.max_packet_size)); @@ -593,8 +567,7 @@ impl<'d, T: Instance> Bus<'d, T> { // Configure OUT endpoints for (index, ep) in self.ep_out.iter().enumerate() { if let Some(ep) = ep { - // SAFETY: DOEPCTL/DOEPTSIZ is shared with `Endpoint` so critical section is needed for RMW - critical_section::with(|_| unsafe { + critical_section::with(|_| { r.doepctl(index).write(|w| { if index == 0 { w.set_mpsiz(ep0_mpsiz(ep.max_packet_size)); @@ -618,14 +591,11 @@ impl<'d, T: Instance> Bus<'d, T> { } // Enable IRQs for allocated endpoints - // SAFETY: register is exclusive to `Bus` with `&mut self` - unsafe { - r.daintmsk().modify(|w| { - w.set_iepm(ep_irq_mask(&self.ep_in)); - // OUT interrupts not used, handled in RXFLVL - // w.set_oepm(ep_irq_mask(&self.ep_out)); - }); - } + r.daintmsk().modify(|w| { + w.set_iepm(ep_irq_mask(&self.ep_in)); + // OUT interrupts not used, handled in RXFLVL + // w.set_oepm(ep_irq_mask(&self.ep_out)); + }); } fn disable(&mut self) { @@ -634,10 +604,8 @@ impl<'d, T: Instance> Bus<'d, T> { ::disable(); #[cfg(stm32l4)] - unsafe { - crate::pac::PWR.cr2().modify(|w| w.set_usv(false)); - // Cannot disable PWR, because other peripherals might be using it - } + crate::pac::PWR.cr2().modify(|w| w.set_usv(false)); + // Cannot disable PWR, because other peripherals might be using it } } @@ -653,7 +621,7 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { T::state().bus_waker.register(cx.waker()); - let ints = unsafe { r.gintsts().read() }; + let ints = r.gintsts().read(); if ints.usbrst() { trace!("reset"); @@ -661,34 +629,27 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { self.configure_endpoints(); // Reset address - // SAFETY: DCFG is shared with `ControlPipe` so critical section is needed for RMW - critical_section::with(|_| unsafe { + critical_section::with(|_| { r.dcfg().modify(|w| { w.set_dad(0); }); }); - // SAFETY: atomic clear on rc_w1 register - unsafe { r.gintsts().write(|w| w.set_usbrst(true)) }; // clear + r.gintsts().write(|w| w.set_usbrst(true)); // clear Self::restore_irqs(); } if ints.enumdne() { trace!("enumdne"); - // SAFETY: atomic read with no side effects - let speed = unsafe { r.dsts().read().enumspd() }; + let speed = r.dsts().read().enumspd(); trace!(" speed={}", speed.0); - // SAFETY: register is only accessed by `Bus` under `&mut self` - unsafe { - r.gusbcfg().modify(|w| { - w.set_trdt(calculate_trdt(speed, T::frequency())); - }) - }; + r.gusbcfg().modify(|w| { + w.set_trdt(calculate_trdt(speed, T::frequency())); + }); - // SAFETY: atomic clear on rc_w1 register - unsafe { r.gintsts().write(|w| w.set_enumdne(true)) }; // clear + r.gintsts().write(|w| w.set_enumdne(true)); // clear Self::restore_irqs(); return Poll::Ready(Event::Reset); @@ -696,16 +657,14 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { if ints.usbsusp() { trace!("suspend"); - // SAFETY: atomic clear on rc_w1 register - unsafe { r.gintsts().write(|w| w.set_usbsusp(true)) }; // clear + r.gintsts().write(|w| w.set_usbsusp(true)); // clear Self::restore_irqs(); return Poll::Ready(Event::Suspend); } if ints.wkupint() { trace!("resume"); - // SAFETY: atomic clear on rc_w1 register - unsafe { r.gintsts().write(|w| w.set_wkupint(true)) }; // clear + r.gintsts().write(|w| w.set_wkupint(true)); // clear Self::restore_irqs(); return Poll::Ready(Event::Resume); } @@ -727,8 +686,7 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { let regs = T::regs(); match ep_addr.direction() { Direction::Out => { - // SAFETY: DOEPCTL is shared with `Endpoint` so critical section is needed for RMW - critical_section::with(|_| unsafe { + critical_section::with(|_| { regs.doepctl(ep_addr.index()).modify(|w| { w.set_stall(stalled); }); @@ -737,8 +695,7 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { T::state().ep_out_wakers[ep_addr.index()].wake(); } Direction::In => { - // SAFETY: DIEPCTL is shared with `Endpoint` so critical section is needed for RMW - critical_section::with(|_| unsafe { + critical_section::with(|_| { regs.diepctl(ep_addr.index()).modify(|w| { w.set_stall(stalled); }); @@ -758,10 +715,9 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { let regs = T::regs(); - // SAFETY: atomic read with no side effects match ep_addr.direction() { - Direction::Out => unsafe { regs.doepctl(ep_addr.index()).read().stall() }, - Direction::In => unsafe { regs.diepctl(ep_addr.index()).read().stall() }, + Direction::Out => regs.doepctl(ep_addr.index()).read().stall(), + Direction::In => regs.diepctl(ep_addr.index()).read().stall(), } } @@ -777,8 +733,7 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { let r = T::regs(); match ep_addr.direction() { Direction::Out => { - // SAFETY: DOEPCTL is shared with `Endpoint` so critical section is needed for RMW - critical_section::with(|_| unsafe { + critical_section::with(|_| { // cancel transfer if active if !enabled && r.doepctl(ep_addr.index()).read().epena() { r.doepctl(ep_addr.index()).modify(|w| { @@ -796,8 +751,7 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { T::state().ep_out_wakers[ep_addr.index()].wake(); } Direction::In => { - // SAFETY: DIEPCTL is shared with `Endpoint` so critical section is needed for RMW - critical_section::with(|_| unsafe { + critical_section::with(|_| { // cancel transfer if active if !enabled && r.diepctl(ep_addr.index()).read().epena() { r.diepctl(ep_addr.index()).modify(|w| { @@ -820,196 +774,193 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { async fn enable(&mut self) { trace!("enable"); - // SAFETY: registers are only accessed by `Bus` under `&mut self` - unsafe { - #[cfg(stm32l4)] - { - crate::peripherals::PWR::enable(); - critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true))); - } - - #[cfg(stm32f7)] - { - // Enable ULPI clock if external PHY is used - let ulpien = !self.phy_type.internal(); - critical_section::with(|_| { - crate::pac::RCC.ahb1enr().modify(|w| { - if T::HIGH_SPEED { - w.set_usb_otg_hsulpien(ulpien); - } else { - w.set_usb_otg_hsen(ulpien); - } - }); - - // Low power mode - crate::pac::RCC.ahb1lpenr().modify(|w| { - if T::HIGH_SPEED { - w.set_usb_otg_hsulpilpen(ulpien); - } else { - w.set_usb_otg_hslpen(ulpien); - } - }); - }); - } - - #[cfg(stm32h7)] - { - // If true, VDD33USB is generated by internal regulator from VDD50USB - // If false, VDD33USB and VDD50USB must be suplied directly with 3.3V (default on nucleo) - // TODO: unhardcode - let internal_regulator = false; - - // Enable USB power - critical_section::with(|_| { - crate::pac::PWR.cr3().modify(|w| { - w.set_usb33den(true); - w.set_usbregen(internal_regulator); - }) - }); - - // Wait for USB power to stabilize - while !crate::pac::PWR.cr3().read().usb33rdy() {} - - // Use internal 48MHz HSI clock. Should be enabled in RCC by default. - critical_section::with(|_| { - crate::pac::RCC - .d2ccip2r() - .modify(|w| w.set_usbsel(crate::pac::rcc::vals::Usbsel::HSI48)) - }); - - // Enable ULPI clock if external PHY is used - let ulpien = !self.phy_type.internal(); - critical_section::with(|_| { - crate::pac::RCC.ahb1enr().modify(|w| { - if T::HIGH_SPEED { - w.set_usb_otg_hs_ulpien(ulpien); - } else { - w.set_usb_otg_fs_ulpien(ulpien); - } - }); - crate::pac::RCC.ahb1lpenr().modify(|w| { - if T::HIGH_SPEED { - w.set_usb_otg_hs_ulpilpen(ulpien); - } else { - w.set_usb_otg_fs_ulpilpen(ulpien); - } - }); - }); - } - - #[cfg(stm32u5)] - { - // Enable USB power - critical_section::with(|_| { - crate::pac::RCC.ahb3enr().modify(|w| { - w.set_pwren(true); - }); - cortex_m::asm::delay(2); - - crate::pac::PWR.svmcr().modify(|w| { - w.set_usv(true); - w.set_uvmen(true); - }); - }); - - // Wait for USB power to stabilize - while !crate::pac::PWR.svmsr().read().vddusbrdy() {} - - // Select HSI48 as USB clock source. - critical_section::with(|_| { - crate::pac::RCC.ccipr1().modify(|w| { - w.set_iclksel(crate::pac::rcc::vals::Iclksel::HSI48); - }) - }); - } - - ::enable(); - ::reset(); - - T::Interrupt::unpend(); - T::Interrupt::enable(); - - let r = T::regs(); - let core_id = r.cid().read().0; - info!("Core id {:08x}", core_id); - - // Wait for AHB ready. - while !r.grstctl().read().ahbidl() {} - - // Configure as device. - r.gusbcfg().write(|w| { - // Force device mode - w.set_fdmod(true); - // Enable internal full-speed PHY - w.set_physel(self.phy_type.internal() && !self.phy_type.high_speed()); - }); - - // Configuring Vbus sense and SOF output - match core_id { - 0x0000_1200 | 0x0000_1100 => { - assert!(self.phy_type != PhyType::InternalHighSpeed); - - r.gccfg_v1().modify(|w| { - // Enable internal full-speed PHY, logic is inverted - w.set_pwrdwn(self.phy_type.internal()); - }); - - // F429-like chips have the GCCFG.NOVBUSSENS bit - r.gccfg_v1().modify(|w| { - w.set_novbussens(true); - w.set_vbusasen(false); - w.set_vbusbsen(false); - w.set_sofouten(false); - }); - } - 0x0000_2000 | 0x0000_2100 | 0x0000_2300 | 0x0000_3000 | 0x0000_3100 => { - // F446-like chips have the GCCFG.VBDEN bit with the opposite meaning - r.gccfg_v2().modify(|w| { - // Enable internal full-speed PHY, logic is inverted - w.set_pwrdwn(self.phy_type.internal() && !self.phy_type.high_speed()); - w.set_phyhsen(self.phy_type.internal() && self.phy_type.high_speed()); - }); - - r.gccfg_v2().modify(|w| { - w.set_vbden(false); - }); - - // Force B-peripheral session - r.gotgctl().modify(|w| { - w.set_bvaloen(true); - w.set_bvaloval(true); - }); - } - _ => unimplemented!("Unknown USB core id {:X}", core_id), - } - - // Soft disconnect. - r.dctl().write(|w| w.set_sdis(true)); - - // Set speed. - r.dcfg().write(|w| { - w.set_pfivl(vals::Pfivl::FRAME_INTERVAL_80); - w.set_dspd(self.phy_type.to_dspd()); - }); - - // Unmask transfer complete EP interrupt - r.diepmsk().write(|w| { - w.set_xfrcm(true); - }); - - // Unmask and clear core interrupts - Bus::::restore_irqs(); - r.gintsts().write_value(regs::Gintsts(0xFFFF_FFFF)); - - // Unmask global interrupt - r.gahbcfg().write(|w| { - w.set_gint(true); // unmask global interrupt - }); - - // Connect - r.dctl().write(|w| w.set_sdis(false)); + #[cfg(stm32l4)] + { + crate::peripherals::PWR::enable(); + critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true))); } + #[cfg(stm32f7)] + { + // Enable ULPI clock if external PHY is used + let ulpien = !self.phy_type.internal(); + critical_section::with(|_| { + crate::pac::RCC.ahb1enr().modify(|w| { + if T::HIGH_SPEED { + w.set_usb_otg_hsulpien(ulpien); + } else { + w.set_usb_otg_hsen(ulpien); + } + }); + + // Low power mode + crate::pac::RCC.ahb1lpenr().modify(|w| { + if T::HIGH_SPEED { + w.set_usb_otg_hsulpilpen(ulpien); + } else { + w.set_usb_otg_hslpen(ulpien); + } + }); + }); + } + + #[cfg(stm32h7)] + { + // If true, VDD33USB is generated by internal regulator from VDD50USB + // If false, VDD33USB and VDD50USB must be suplied directly with 3.3V (default on nucleo) + // TODO: unhardcode + let internal_regulator = false; + + // Enable USB power + critical_section::with(|_| { + crate::pac::PWR.cr3().modify(|w| { + w.set_usb33den(true); + w.set_usbregen(internal_regulator); + }) + }); + + // Wait for USB power to stabilize + while !crate::pac::PWR.cr3().read().usb33rdy() {} + + // Use internal 48MHz HSI clock. Should be enabled in RCC by default. + critical_section::with(|_| { + crate::pac::RCC + .d2ccip2r() + .modify(|w| w.set_usbsel(crate::pac::rcc::vals::Usbsel::HSI48)) + }); + + // Enable ULPI clock if external PHY is used + let ulpien = !self.phy_type.internal(); + critical_section::with(|_| { + crate::pac::RCC.ahb1enr().modify(|w| { + if T::HIGH_SPEED { + w.set_usb_otg_hs_ulpien(ulpien); + } else { + w.set_usb_otg_fs_ulpien(ulpien); + } + }); + crate::pac::RCC.ahb1lpenr().modify(|w| { + if T::HIGH_SPEED { + w.set_usb_otg_hs_ulpilpen(ulpien); + } else { + w.set_usb_otg_fs_ulpilpen(ulpien); + } + }); + }); + } + + #[cfg(stm32u5)] + { + // Enable USB power + critical_section::with(|_| { + crate::pac::RCC.ahb3enr().modify(|w| { + w.set_pwren(true); + }); + cortex_m::asm::delay(2); + + crate::pac::PWR.svmcr().modify(|w| { + w.set_usv(true); + w.set_uvmen(true); + }); + }); + + // Wait for USB power to stabilize + while !crate::pac::PWR.svmsr().read().vddusbrdy() {} + + // Select HSI48 as USB clock source. + critical_section::with(|_| { + crate::pac::RCC.ccipr1().modify(|w| { + w.set_iclksel(crate::pac::rcc::vals::Iclksel::HSI48); + }) + }); + } + + ::enable(); + ::reset(); + + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; + + let r = T::regs(); + let core_id = r.cid().read().0; + info!("Core id {:08x}", core_id); + + // Wait for AHB ready. + while !r.grstctl().read().ahbidl() {} + + // Configure as device. + r.gusbcfg().write(|w| { + // Force device mode + w.set_fdmod(true); + // Enable internal full-speed PHY + w.set_physel(self.phy_type.internal() && !self.phy_type.high_speed()); + }); + + // Configuring Vbus sense and SOF output + match core_id { + 0x0000_1200 | 0x0000_1100 => { + assert!(self.phy_type != PhyType::InternalHighSpeed); + + r.gccfg_v1().modify(|w| { + // Enable internal full-speed PHY, logic is inverted + w.set_pwrdwn(self.phy_type.internal()); + }); + + // F429-like chips have the GCCFG.NOVBUSSENS bit + r.gccfg_v1().modify(|w| { + w.set_novbussens(true); + w.set_vbusasen(false); + w.set_vbusbsen(false); + w.set_sofouten(false); + }); + } + 0x0000_2000 | 0x0000_2100 | 0x0000_2300 | 0x0000_3000 | 0x0000_3100 => { + // F446-like chips have the GCCFG.VBDEN bit with the opposite meaning + r.gccfg_v2().modify(|w| { + // Enable internal full-speed PHY, logic is inverted + w.set_pwrdwn(self.phy_type.internal() && !self.phy_type.high_speed()); + w.set_phyhsen(self.phy_type.internal() && self.phy_type.high_speed()); + }); + + r.gccfg_v2().modify(|w| { + w.set_vbden(false); + }); + + // Force B-peripheral session + r.gotgctl().modify(|w| { + w.set_bvaloen(true); + w.set_bvaloval(true); + }); + } + _ => unimplemented!("Unknown USB core id {:X}", core_id), + } + + // Soft disconnect. + r.dctl().write(|w| w.set_sdis(true)); + + // Set speed. + r.dcfg().write(|w| { + w.set_pfivl(vals::Pfivl::FRAME_INTERVAL_80); + w.set_dspd(self.phy_type.to_dspd()); + }); + + // Unmask transfer complete EP interrupt + r.diepmsk().write(|w| { + w.set_xfrcm(true); + }); + + // Unmask and clear core interrupts + Bus::::restore_irqs(); + r.gintsts().write_value(regs::Gintsts(0xFFFF_FFFF)); + + // Unmask global interrupt + r.gahbcfg().write(|w| { + w.set_gint(true); // unmask global interrupt + }); + + // Connect + r.dctl().write(|w| w.set_sdis(false)); + self.enabled = true; } @@ -1066,8 +1017,7 @@ impl<'d, T: Instance> embassy_usb_driver::Endpoint for Endpoint<'d, T, In> { T::state().ep_in_wakers[ep_index].register(cx.waker()); - // SAFETY: atomic read without side effects - if unsafe { T::regs().diepctl(ep_index).read().usbaep() } { + if T::regs().diepctl(ep_index).read().usbaep() { Poll::Ready(()) } else { Poll::Pending @@ -1088,8 +1038,7 @@ impl<'d, T: Instance> embassy_usb_driver::Endpoint for Endpoint<'d, T, Out> { T::state().ep_out_wakers[ep_index].register(cx.waker()); - // SAFETY: atomic read without side effects - if unsafe { T::regs().doepctl(ep_index).read().usbaep() } { + if T::regs().doepctl(ep_index).read().usbaep() { Poll::Ready(()) } else { Poll::Pending @@ -1124,8 +1073,7 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointOut for Endpoint<'d, T, Out> { // Release buffer state.ep_out_size[index].store(EP_OUT_BUFFER_EMPTY, Ordering::Release); - // SAFETY: DOEPCTL/DOEPTSIZ is shared with `Bus` so a critical section is needed for RMW - critical_section::with(|_| unsafe { + critical_section::with(|_| { // Receive 1 packet T::regs().doeptsiz(index).modify(|w| { 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> { poll_fn(|cx| { state.ep_in_wakers[index].register(cx.waker()); - // SAFETY: atomic read with no side effects - let diepctl = unsafe { r.diepctl(index).read() }; + let diepctl = r.diepctl(index).read(); if !diepctl.usbaep() { Poll::Ready(Err(EndpointError::Disabled)) } else if !diepctl.epena() { @@ -1181,12 +1128,10 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> { let size_words = (buf.len() + 3) / 4; - // SAFETY: atomic read with no side effects - let fifo_space = unsafe { r.dtxfsts(index).read().ineptfsav() as usize }; + let fifo_space = r.dtxfsts(index).read().ineptfsav() as usize; if size_words > fifo_space { // Not enough space in fifo, enable tx fifo empty interrupt - // SAFETY: DIEPEMPMSK is shared with IRQ so critical section is needed for RMW - critical_section::with(|_| unsafe { + critical_section::with(|_| { r.diepempmsk().modify(|w| { w.set_ineptxfem(w.ineptxfem() | (1 << index)); }); @@ -1202,18 +1147,14 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> { .await } - // SAFETY: DIEPTSIZ is exclusive to this endpoint under `&mut self` - unsafe { - // Setup transfer size - r.dieptsiz(index).write(|w| { - w.set_mcnt(1); - w.set_pktcnt(1); - w.set_xfrsiz(buf.len() as _); - }); - } + // Setup transfer size + r.dieptsiz(index).write(|w| { + w.set_mcnt(1); + w.set_pktcnt(1); + w.set_xfrsiz(buf.len() as _); + }); - // SAFETY: DIEPCTL is shared with `Bus` so a critical section is needed for RMW - critical_section::with(|_| unsafe { + critical_section::with(|_| { // Enable endpoint r.diepctl(index).modify(|w| { w.set_cnak(true); @@ -1225,8 +1166,7 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> { for chunk in buf.chunks(4) { let mut tmp = [0u8; 4]; tmp[0..chunk.len()].copy_from_slice(chunk); - // SAFETY: FIFO is exclusive to this endpoint under `&mut self` - unsafe { r.fifo(index).write_value(regs::Fifo(u32::from_ne_bytes(tmp))) }; + r.fifo(index).write_value(regs::Fifo(u32::from_ne_bytes(tmp))); } trace!("write done ep={:?}", self.info.addr); @@ -1258,17 +1198,15 @@ impl<'d, T: Instance> embassy_usb_driver::ControlPipe for ControlPipe<'d, T> { state.ep0_setup_ready.store(false, Ordering::Release); // EP0 should not be controlled by `Bus` so this RMW does not need a critical section - unsafe { - // Receive 1 SETUP packet - T::regs().doeptsiz(self.ep_out.info.addr.index()).modify(|w| { - w.set_rxdpid_stupcnt(1); - }); + // Receive 1 SETUP packet + T::regs().doeptsiz(self.ep_out.info.addr.index()).modify(|w| { + w.set_rxdpid_stupcnt(1); + }); - // Clear NAK to indicate we are ready to receive more data - T::regs().doepctl(self.ep_out.info.addr.index()).modify(|w| { - w.set_cnak(true); - }); - } + // Clear NAK to indicate we are ready to receive more data + T::regs().doepctl(self.ep_out.info.addr.index()).modify(|w| { + w.set_cnak(true); + }); trace!("SETUP received: {:?}", data); Poll::Ready(data) @@ -1313,20 +1251,18 @@ impl<'d, T: Instance> embassy_usb_driver::ControlPipe for ControlPipe<'d, T> { trace!("control: reject"); // EP0 should not be controlled by `Bus` so this RMW does not need a critical section - unsafe { - let regs = T::regs(); - regs.diepctl(self.ep_in.info.addr.index()).modify(|w| { - w.set_stall(true); - }); - regs.doepctl(self.ep_out.info.addr.index()).modify(|w| { - w.set_stall(true); - }); - } + let regs = T::regs(); + regs.diepctl(self.ep_in.info.addr.index()).modify(|w| { + w.set_stall(true); + }); + regs.doepctl(self.ep_out.info.addr.index()).modify(|w| { + w.set_stall(true); + }); } async fn accept_set_address(&mut self, addr: u8) { trace!("setting addr: {}", addr); - critical_section::with(|_| unsafe { + critical_section::with(|_| { T::regs().dcfg().modify(|w| { w.set_dad(addr); }); diff --git a/embassy-stm32/src/wdg/mod.rs b/embassy-stm32/src/wdg/mod.rs index 18ebf97d..5907a4e5 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> { let rl = reload_value(psc, timeout_us); let wdg = T::regs(); - unsafe { - wdg.kr().write(|w| w.set_key(Key::ENABLE)); - wdg.pr().write(|w| w.set_pr(Pr(pr))); - wdg.rlr().write(|w| w.set_rl(rl)); - } + wdg.kr().write(|w| w.set_key(Key::ENABLE)); + wdg.pr().write(|w| w.set_pr(Pr(pr))); + wdg.rlr().write(|w| w.set_rl(rl)); trace!( "Watchdog configured with {}us timeout, desired was {}us (PR={}, RL={})", @@ -67,11 +65,11 @@ impl<'d, T: Instance> IndependentWatchdog<'d, T> { } } - pub unsafe fn unleash(&mut self) { + pub fn unleash(&mut self) { T::regs().kr().write(|w| w.set_key(Key::START)); } - pub unsafe fn pet(&mut self) { + pub fn pet(&mut self) { T::regs().kr().write(|w| w.set_key(Key::RESET)); } } diff --git a/examples/stm32f0/src/bin/wdg.rs b/examples/stm32f0/src/bin/wdg.rs index 80e76f90..a44b1752 100644 --- a/examples/stm32f0/src/bin/wdg.rs +++ b/examples/stm32f0/src/bin/wdg.rs @@ -16,10 +16,10 @@ async fn main(_spawner: Spawner) { let mut wdg = IndependentWatchdog::new(p.IWDG, 20_000_00); info!("Watchdog start"); - unsafe { wdg.unleash() }; + wdg.unleash(); loop { Timer::after(Duration::from_secs(1)).await; - unsafe { wdg.pet() }; + wdg.pet(); } } diff --git a/examples/stm32f4/src/bin/wdt.rs b/examples/stm32f4/src/bin/wdt.rs index b2c587fa..e5d122af 100644 --- a/examples/stm32f4/src/bin/wdt.rs +++ b/examples/stm32f4/src/bin/wdt.rs @@ -17,9 +17,7 @@ async fn main(_spawner: Spawner) { let mut led = Output::new(p.PB7, Level::High, Speed::Low); let mut wdt = IndependentWatchdog::new(p.IWDG, 1_000_000); - unsafe { - wdt.unleash(); - } + wdt.unleash(); let mut i = 0; @@ -36,9 +34,7 @@ async fn main(_spawner: Spawner) { // MCU should restart in 1 second after the last pet. if i < 5 { info!("Petting watchdog"); - unsafe { - wdt.pet(); - } + wdt.pet(); } i += 1; diff --git a/examples/stm32g4/src/bin/usb_serial.rs b/examples/stm32g4/src/bin/usb_serial.rs index ecbe3a6e..c111a978 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) { let p = embassy_stm32::init(config); info!("Hello World!"); - unsafe { - pac::RCC.ccipr().write(|w| w.set_clk48sel(0b10)); - } + pac::RCC.ccipr().write(|w| w.set_clk48sel(0b10)); let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11); diff --git a/examples/stm32h5/src/bin/usb_serial.rs b/examples/stm32h5/src/bin/usb_serial.rs index 3912327e..336eed64 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) { info!("Hello World!"); - unsafe { - pac::RCC.ccipr4().write(|w| { - w.set_usbsel(pac::rcc::vals::Usbsel::HSI48); - }); - } + pac::RCC.ccipr4().write(|w| { + w.set_usbsel(pac::rcc::vals::Usbsel::HSI48); + }); // Create the driver, from the HAL. 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 1972f8ff..d360df08 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> { T::enable(); ::reset(); - unsafe { - ch1.set_speed(Speed::VeryHigh); - ch1.set_as_af(ch1.af_num(), AFType::OutputPushPull); - ch2.set_speed(Speed::VeryHigh); - ch2.set_as_af(ch1.af_num(), AFType::OutputPushPull); - ch3.set_speed(Speed::VeryHigh); - ch3.set_as_af(ch1.af_num(), AFType::OutputPushPull); - ch4.set_speed(Speed::VeryHigh); - ch4.set_as_af(ch1.af_num(), AFType::OutputPushPull); - } + ch1.set_speed(Speed::VeryHigh); + ch1.set_as_af(ch1.af_num(), AFType::OutputPushPull); + ch2.set_speed(Speed::VeryHigh); + ch2.set_as_af(ch1.af_num(), AFType::OutputPushPull); + ch3.set_speed(Speed::VeryHigh); + ch3.set_as_af(ch1.af_num(), AFType::OutputPushPull); + ch4.set_speed(Speed::VeryHigh); + ch4.set_as_af(ch1.af_num(), AFType::OutputPushPull); let mut this = Self { inner: tim }; this.set_freq(freq); this.inner.start(); - unsafe { - T::regs_gp32() - .ccmr_output(0) - .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into())); - T::regs_gp32() - .ccmr_output(0) - .modify(|w| w.set_ocm(1, OutputCompareMode::PwmMode1.into())); - T::regs_gp32() - .ccmr_output(1) - .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into())); - T::regs_gp32() - .ccmr_output(1) - .modify(|w| w.set_ocm(1, OutputCompareMode::PwmMode1.into())); - } + let r = T::regs_gp32(); + r.ccmr_output(0) + .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into())); + r.ccmr_output(0) + .modify(|w| w.set_ocm(1, OutputCompareMode::PwmMode1.into())); + r.ccmr_output(1) + .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into())); + r.ccmr_output(1) + .modify(|w| w.set_ocm(1, OutputCompareMode::PwmMode1.into())); + this } pub fn enable(&mut self, channel: Channel) { - unsafe { - T::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), true)); - } + T::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), true)); } pub fn disable(&mut self, channel: Channel) { - unsafe { - T::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), false)); - } + T::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), false)); } pub fn set_freq(&mut self, freq: Hertz) { @@ -112,11 +102,11 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> { } pub fn get_max_duty(&self) -> u32 { - unsafe { T::regs_gp32().arr().read().arr() } + T::regs_gp32().arr().read().arr() } pub fn set_duty(&mut self, channel: Channel, duty: u32) { defmt::assert!(duty < self.get_max_duty()); - unsafe { T::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(duty)) } + T::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(duty)) } } diff --git a/examples/stm32h7/src/bin/wdg.rs b/examples/stm32h7/src/bin/wdg.rs index 2b0301aa..9181dfd6 100644 --- a/examples/stm32h7/src/bin/wdg.rs +++ b/examples/stm32h7/src/bin/wdg.rs @@ -15,10 +15,10 @@ async fn main(_spawner: Spawner) { let mut wdg = IndependentWatchdog::new(p.IWDG1, 20_000_000); - unsafe { wdg.unleash() }; + wdg.unleash(); loop { Timer::after(Duration::from_secs(1)).await; - unsafe { wdg.pet() }; + wdg.pet(); } } diff --git a/examples/stm32l4/src/bin/adc.rs b/examples/stm32l4/src/bin/adc.rs index 281346e5..1771e520 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 _}; fn main() -> ! { info!("Hello World!"); - unsafe { - pac::RCC.ccipr().modify(|w| { - w.set_adcsel(0b11); - }); - pac::RCC.ahb2enr().modify(|w| w.set_adcen(true)); - } + pac::RCC.ccipr().modify(|w| { + w.set_adcsel(0b11); + }); + pac::RCC.ahb2enr().modify(|w| w.set_adcen(true)); let p = embassy_stm32::init(Default::default()); diff --git a/examples/stm32l4/src/bin/dac.rs b/examples/stm32l4/src/bin/dac.rs index d6e744aa..a36ed5d9 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 _}; fn main() -> ! { info!("Hello World!"); - unsafe { - pac::RCC.apb1enr1().modify(|w| { - w.set_dac1en(true); - }); - } + pac::RCC.apb1enr1().modify(|w| { + w.set_dac1en(true); + }); let p = embassy_stm32::init(Default::default()); diff --git a/examples/stm32wl/src/bin/lora_lorawan.rs b/examples/stm32wl/src/bin/lora_lorawan.rs index e179c5ca..805d2141 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) { config.rcc.enable_lsi = true; // enable RNG let p = embassy_stm32::init(config); - unsafe { pac::RCC.ccipr().modify(|w| w.set_rngsel(0b01)) } + pac::RCC.ccipr().modify(|w| w.set_rngsel(0b01)); let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2); diff --git a/examples/stm32wl/src/bin/random.rs b/examples/stm32wl/src/bin/random.rs index 182c607f..d8562fca 100644 --- a/examples/stm32wl/src/bin/random.rs +++ b/examples/stm32wl/src/bin/random.rs @@ -15,11 +15,9 @@ async fn main(_spawner: Spawner) { config.rcc.enable_lsi = true; //Needed for RNG to work let p = embassy_stm32::init(config); - unsafe { - pac::RCC.ccipr().modify(|w| { - w.set_rngsel(0b01); - }); - } + pac::RCC.ccipr().modify(|w| { + w.set_rngsel(0b01); + }); info!("Hello World!"); diff --git a/tests/stm32/src/bin/rtc.rs b/tests/stm32/src/bin/rtc.rs index 32d35c42..582df575 100644 --- a/tests/stm32/src/bin/rtc.rs +++ b/tests/stm32/src/bin/rtc.rs @@ -24,10 +24,8 @@ async fn main(_spawner: Spawner) { info!("Starting LSI"); - unsafe { - pac::RCC.csr().modify(|w| w.set_lsion(true)); - while !pac::RCC.csr().read().lsirdy() {} - } + pac::RCC.csr().modify(|w| w.set_lsion(true)); + while !pac::RCC.csr().read().lsirdy() {} info!("Started LSI");