From 637b3183ca66c1f4b2636fe82892d50ce74d9cb2 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 30 Dec 2022 13:28:57 +0100 Subject: [PATCH 01/25] small clippy fix --- src/rtc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rtc.rs b/src/rtc.rs index b21fe08d9..2ab374fda 100644 --- a/src/rtc.rs +++ b/src/rtc.rs @@ -354,7 +354,7 @@ impl Rtcc for Rtc { fn month(&mut self) -> Result { let dr = self.rtc.dr.read(); - let mt: u8 = if dr.mt().bit() { 1 } else { 0 }; + let mt = u8::from(dr.mt().bit()); let month = bcd2_decode(mt, dr.mu().bits()); Ok(month as u8) } From e2fbfeee70b1bc01b2f66c7c98a15eb0cd593366 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 19 Feb 2023 14:47:33 +0100 Subject: [PATCH 02/25] Update dependencies (#335) --- .clippy.toml | 2 +- .github/workflows/ci.yml | 2 +- CHANGELOG.md | 6 +- Cargo.toml | 42 +++++----- README.md | 4 +- examples/dac_sine.rs | 4 - examples/gpio_erased.rs | 4 +- examples/i2c_scanner.rs | 8 +- src/adc.rs | 161 +++++++++++++++------------------------ src/adc/config.rs | 150 ++++++++++++++++++------------------ src/dac.rs | 19 ++--- src/dma.rs | 22 +++--- src/gpio.rs | 24 +++--- src/i2c.rs | 4 +- src/pwm.rs | 4 +- src/rcc.rs | 134 ++++++++++++++++---------------- src/rcc/enable.rs | 16 +--- src/serial.rs | 14 ++-- src/serial/config.rs | 16 ++-- src/spi.rs | 20 ++--- src/timer.rs | 10 +-- src/watchdog.rs | 18 ++--- testsuite/Cargo.toml | 8 +- testsuite/tests/adc.rs | 12 +-- 24 files changed, 318 insertions(+), 386 deletions(-) diff --git a/.clippy.toml b/.clippy.toml index ece14b8d2..abe19b3a0 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -1 +1 @@ -msrv = "1.54" +msrv = "1.59" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 85c10a484..efc3fa338 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,7 +57,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.54.0 + toolchain: 1.59.0 target: thumbv7em-none-eabihf override: true profile: minimal diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b3840ced..01489d3af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## Unreleased -No changes. +### Breaking changes + +- Update `stm32f3` pac to v0.15.1 ([#282]) +- Update `bxcan` pac to v0.7.0 ([#282]) +- The MSRV was bumped to 1.59 ([#227]) ## [v0.9.1] - 2022-09-07 diff --git a/Cargo.toml b/Cargo.toml index 05a50cc69..846c4c4ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -edition = "2018" +edition = "2021" authors = [ "Dylan Frankland ", "Sh3Rm4n ", @@ -19,7 +19,7 @@ exclude = [ ".markdownlint.yml" ] resolver = "2" -rust-version = "1.54" +rust-version = "1.59" [workspace] members = [ @@ -36,7 +36,7 @@ rustc-args = ["--cfg", "docsrs"] [dependencies] cfg-if = "1.0.0" cortex-m = "0.7.4" -cortex-m-rt = "0.7" +cortex-m-rt = "0.7.3" defmt = { version = ">=0.2.3, <0.4.0", optional = true } embedded-dma = "0.2.0" embedded-hal = { version = "0.2.5", features = ["unproven"] } @@ -44,23 +44,19 @@ embedded-time = "0.12.0" nb = "1.0.0" paste = "1.0.5" rtcc = { version = "0.3.0", optional = true } -stm32f3 = { version = "0.14.0", default-features = false } -bxcan = { version = "0.6.2", optional = true } +stm32f3 = { version = "0.15.1", default-features = false } +bxcan = { version = "0.7.0", optional = true } stm32-usbd = { version = "0.6.0", optional = true } void = { version = "1.0.2", default-features = false } enumset = { version = "1.0.6", optional = true} -# NOTE: Workaround for build -# $ cargo +nightly update -Z minimal-versions -# as long cortex-m depends on bare-metal 0.2.1 -bare-metal = "1.0.0" [dev-dependencies] -cortex-m-semihosting = "0.3.7" +cortex-m-semihosting = "0.5.0" defmt = "0.3.0" -defmt-rtt = "0.3.0" +defmt-rtt = "0.4.0" defmt-test = "0.3.0" panic-probe = "0.3.0" -panic-semihosting = "0.5.6" +panic-semihosting = "0.6.0" usbd-serial = "0.1.1" usb-device = "0.2.8" cortex-m-rtic = "1.0" @@ -171,44 +167,44 @@ opt-level = "s" [[example]] name = "pwm" -required-features = ["ld", "stm32f303xc"] +required-features = ["ld", "stm32f303xc", "cortex-m/critical-section-single-core"] [[example]] name = "toggle" -required-features = ["ld", "stm32f303xc"] +required-features = ["ld", "stm32f303xc", "cortex-m/critical-section-single-core"] [[example]] name = "usb_serial" -required-features = ["ld", "stm32f303xc", "usb"] +required-features = ["ld", "stm32f303xc", "usb", "cortex-m/critical-section-single-core"] [[example]] name = "spi" -required-features = ["ld", "stm32f303xc"] +required-features = ["ld", "stm32f303xc", "cortex-m/critical-section-single-core"] [[example]] name = "can" -required-features = ["ld", "rt", "can", "stm32f302xc"] +required-features = ["ld", "rt", "can", "stm32f302xc", "cortex-m/critical-section-single-core"] [[example]] name = "serial_dma" -required-features = ["ld", "rt", "stm32f303xc"] +required-features = ["ld", "rt", "stm32f303xc", "cortex-m/critical-section-single-core"] [[example]] name = "serial_echo_rtic" -required-features = ["ld", "rt", "stm32f303xc", "enumset"] +required-features = ["ld", "rt", "stm32f303xc", "enumset", "cortex-m/critical-section-single-core"] [[example]] name = "adc" -required-features = ["ld", "stm32f303xc"] +required-features = ["ld", "stm32f303xc", "cortex-m/critical-section-single-core"] [[example]] name = "i2c_scanner" -required-features = ["ld", "stm32f303xc"] +required-features = ["ld", "stm32f303xc", "cortex-m/critical-section-single-core"] [[example]] name = "gpio_erased" -required-features = ["ld", "stm32f303xc"] +required-features = ["ld", "stm32f303xc", "cortex-m/critical-section-single-core"] [[example]] name = "gpio_interrupts" -required-features = ["ld", "rt", "stm32f303xc"] +required-features = ["ld", "rt", "stm32f303xc", "cortex-m/critical-section-single-core"] diff --git a/README.md b/README.md index e25ac7a7e..4cb32e1ba 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Crate](https://img.shields.io/crates/v/stm32f3xx-hal.svg)](https://crates.io/crates/stm32f3xx-hal) [![Docs](https://docs.rs/stm32f3xx-hal/badge.svg)](https://docs.rs/stm32f3xx-hal) [![Crates.io](https://img.shields.io/crates/d/stm32f3xx-hal.svg)](https://crates.io/crates/stm32f3xx-hal) -![Minimum Supported Rust Version](https://img.shields.io/badge/rustc-1.54+-blue.svg) +![Minimum Supported Rust Version](https://img.shields.io/badge/rustc-1.59+-blue.svg) `stm32f3xx-hal` contains a multi device hardware abstraction on top of the peripheral access API for the STMicro STM32F3 series microcontrollers. The @@ -139,7 +139,7 @@ See the [examples folder](examples) for more example programs. ## Minimum Supported Rust Version (MSRV) -This crate is guaranteed to compile on stable Rust 1.54.0 and up. It *might* +This crate is guaranteed to compile on stable Rust 1.59.0 and up. It *might* compile with older versions but that may change in any new patch release. diff --git a/examples/dac_sine.rs b/examples/dac_sine.rs index 79f80e719..58c7ede77 100644 --- a/examples/dac_sine.rs +++ b/examples/dac_sine.rs @@ -28,12 +28,8 @@ fn main() -> ! { .into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper); // set up dac1, data is twelve bits, aligned right - #[cfg(not(feature = "svd-f302"))] let mut dac1 = Dac::new(dp.DAC1, &mut rcc.apb1); - #[cfg(feature = "svd-f302")] - let mut dac1 = Dac::new(dp.DAC, &mut rcc.apb1); - let mut led = true; loop { diff --git a/examples/gpio_erased.rs b/examples/gpio_erased.rs index ffb492d1e..658a26331 100644 --- a/examples/gpio_erased.rs +++ b/examples/gpio_erased.rs @@ -46,10 +46,10 @@ fn main() -> ! { .downgrade(), ]; - hprintln!("Start scanning pin array").unwrap(); + hprintln!("Start scanning pin array"); loop { for pin in pin_array.iter_mut() { - hprintln!("Value is {}", pin.is_high().unwrap()).unwrap(); + hprintln!("Value is {}", pin.is_high().unwrap()); asm::delay(1_000_000); } } diff --git a/examples/i2c_scanner.rs b/examples/i2c_scanner.rs index c371095e6..ff9a1f452 100644 --- a/examples/i2c_scanner.rs +++ b/examples/i2c_scanner.rs @@ -46,8 +46,8 @@ fn main() -> ! { &mut rcc.apb1, ); - hprintln!("Start i2c scanning...").expect("Error using hprintln."); - hprintln!().unwrap(); + hprintln!("Start i2c scanning..."); + hprintln!(); for addr in 0x00_u8..0x80 { // Write the empty array and check the slave response. @@ -63,8 +63,8 @@ fn main() -> ! { } } - hprintln!().unwrap(); - hprintln!("Done!").unwrap(); + hprintln!(); + hprintln!("Done!"); loop { asm::wfi(); diff --git a/src/adc.rs b/src/adc.rs index 8a585834d..e80c84f6c 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -33,15 +33,7 @@ use crate::{ Toggle, }; -cfg_if::cfg_if! { - if #[cfg(feature = "svd-f3x4")] { - use crate::pac::adc_common as adc1_2; - - use adc1_2::ccr::CKMODE_A; - } else { - use crate::pac::{adc1_2, adc1_2::ccr::CKMODE_A}; - } -} +use crate::pac::{adc1_2, adc1_2::ccr::CKMODE_A}; #[cfg(feature = "enumset")] use enumset::{EnumSet, EnumSetType}; @@ -365,7 +357,7 @@ where /// * The conversion mode is configured via [`Adc::set_conversion_mode`]. #[inline] pub fn start_conversion(&mut self) { - self.reg.cr.modify(|_, w| w.adstart().start()); + self.reg.cr.modify(|_, w| w.adstart().start_conversion()); } /// Configure and convert the [`Adc`] instance into [`OneShot`] mode. @@ -401,30 +393,23 @@ where if self.reg.cr.read().aden().bit() && (self.reg.cr.read().adstart().bit() || self.reg.cr.read().jadstart().bit()) { - self.reg.cr.modify(|_, w| w.adstp().stop()); + self.reg.cr.modify(|_, w| w.adstp().stop_conversion()); // In auto-injection mode (JAUTO=1), setting ADSTP bit aborts both // regular and injected conversions (do not use JADSTP) if !self.reg.cfgr.read().jauto().is_enabled() { - #[cfg(not(feature = "svd-f301"))] - self.reg.cr.modify(|_, w| w.jadstp().stop()); - #[cfg(feature = "svd-f301")] - self.reg.cr.modify(|_, w| w.jadst().set_bit()); + self.reg.cr.modify(|_, w| w.jadstp().stop_conversion()); } - #[cfg(not(feature = "svd-f301"))] while self.reg.cr.read().adstp().bit() || self.reg.cr.read().jadstp().bit() {} - // TODO(Sh3Rm4n): https://github.com/stm32-rs/stm32-rs/pull/696 - #[cfg(feature = "svd-f301")] - while self.reg.cr.read().adstp().bit() || self.reg.cr.read().jadst().bit() {} } // Software is allowed to set ADDIS only when ADEN=1 and both ADSTART=0 // and JADSTART=0 (which ensures that no conversion is ongoing) - if self.reg.cr.read().aden().is_enable() { + if self.reg.cr.read().aden().is_enabled() { // 2. Disable ADC // TODO(Sh3Rm4n): Use w.aaddis().disable() once https://github.com/stm32-rs/stm32-rs/pull/699 is merged self.reg.cr.modify(|_, w| w.addis().set_bit()); // 3. Wait for ADC being disabled - while self.reg.cr.read().aden().is_enable() {} + while self.reg.cr.read().aden().is_enabled() {} } Adc { @@ -475,9 +460,9 @@ where // ADRDY=1 was set. // This assumption is true, if the peripheral was initially enabled through // this method. - if !self.reg.cr.read().aden().is_enable() { + if !self.reg.cr.read().aden().is_enabled() { // Set ADEN=1 - self.reg.cr.modify(|_, w| w.aden().enable()); + self.reg.cr.modify(|_, w| w.aden().enabled()); // Wait until ADRDY=1 (ADRDY is set after the ADC startup time). This can be // done using the associated interrupt (setting ADRDYIE=1). while self.reg.isr.read().adrdy().is_not_ready() {} @@ -537,8 +522,8 @@ where self.reg.cr.modify(|_, w| w.advregen().intermediate()); self.reg.cr.modify(|_, w| { w.advregen().variant(match toggle { - Toggle::On => adc1::cr::ADVREGEN_A::ENABLED, - Toggle::Off => adc1::cr::ADVREGEN_A::DISABLED, + Toggle::On => adc1::cr::ADVREGEN_A::Enabled, + Toggle::Off => adc1::cr::ADVREGEN_A::Disabled, }) }); if toggle == Toggle::On && !already_on { @@ -588,34 +573,34 @@ where let cfgr = self.reg.cfgr.read(); match (cfgr.exten().variant(), cfgr.extsel().variant()) { - (EXTEN_A::DISABLED, _) | (_, None) => None, + (EXTEN_A::Disabled, _) | (_, None) => None, (edge, Some(ext)) => { let edge = match edge { - EXTEN_A::DISABLED => { + EXTEN_A::Disabled => { // SAFETY: This arm can not be reached, because of the // (EXTEN_A::DISABLED, _) arm above. unsafe { unreachable_unchecked() } } - EXTEN_A::RISINGEDGE => config::TriggerMode::RisingEdge, - EXTEN_A::FALLINGEDGE => config::TriggerMode::FallingEdge, - EXTEN_A::BOTHEDGES => config::TriggerMode::BothEdges, + EXTEN_A::RisingEdge => config::TriggerMode::RisingEdge, + EXTEN_A::FallingEdge => config::TriggerMode::FallingEdge, + EXTEN_A::BothEdges => config::TriggerMode::BothEdges, }; Some(match ext { - EXTSEL_A::HRTIM_ADCTRG1 => ExternalTrigger::HrtimAdcTrg1(edge), - EXTSEL_A::HRTIM_ADCTRG3 => ExternalTrigger::HrtimAdcTrg3(edge), - EXTSEL_A::TIM1_CC1 => ExternalTrigger::Tim1Cc1(edge), - EXTSEL_A::TIM1_CC2 => ExternalTrigger::Tim1Cc2(edge), - EXTSEL_A::TIM1_CC3 => ExternalTrigger::Tim1Cc3(edge), - EXTSEL_A::TIM2_CC2 => ExternalTrigger::Tim2Cc2(edge), - EXTSEL_A::TIM3_TRGO => ExternalTrigger::Tim3Trgo(edge), - EXTSEL_A::EXTI11 => ExternalTrigger::Exti11(edge), - EXTSEL_A::TIM1_TRGO => ExternalTrigger::Tim1Trgo(edge), - EXTSEL_A::TIM1_TRGO2 => ExternalTrigger::Tim1Trgo2(edge), - EXTSEL_A::TIM2_TRGO => ExternalTrigger::Tim2Trgo(edge), - EXTSEL_A::TIM6_TRGO => ExternalTrigger::Tim6Trgo(edge), - EXTSEL_A::TIM15_TRGO => ExternalTrigger::Tim15Trgo(edge), - EXTSEL_A::TIM3_CC4 => ExternalTrigger::Tim3Cc4(edge), + EXTSEL_A::HrtimAdctrg1 => ExternalTrigger::HrtimAdcTrg1(edge), + EXTSEL_A::HrtimAdctrg3 => ExternalTrigger::HrtimAdcTrg3(edge), + EXTSEL_A::Tim1Cc1 => ExternalTrigger::Tim1Cc1(edge), + EXTSEL_A::Tim1Cc2 => ExternalTrigger::Tim1Cc2(edge), + EXTSEL_A::Tim1Cc3 => ExternalTrigger::Tim1Cc3(edge), + EXTSEL_A::Tim2Cc2 => ExternalTrigger::Tim2Cc2(edge), + EXTSEL_A::Tim3Trgo => ExternalTrigger::Tim3Trgo(edge), + EXTSEL_A::Exti11 => ExternalTrigger::Exti11(edge), + EXTSEL_A::Tim1Trgo => ExternalTrigger::Tim1Trgo(edge), + EXTSEL_A::Tim1Trgo2 => ExternalTrigger::Tim1Trgo2(edge), + EXTSEL_A::Tim2Trgo => ExternalTrigger::Tim2Trgo(edge), + EXTSEL_A::Tim6Trgo => ExternalTrigger::Tim6Trgo(edge), + EXTSEL_A::Tim15Trgo => ExternalTrigger::Tim15Trgo(edge), + EXTSEL_A::Tim3Cc4 => ExternalTrigger::Tim3Cc4(edge), }) } } @@ -632,12 +617,12 @@ where cfgr.discen().variant(), cfgr.discnum().bits(), ) { - (CONT_A::SINGLE, DISCEN_A::DISABLED, _) => config::ConversionMode::Single, - (CONT_A::CONTINUOUS, DISCEN_A::DISABLED, _) => config::ConversionMode::Continuous, + (CONT_A::Single, DISCEN_A::Disabled, _) => config::ConversionMode::Single, + (CONT_A::Continuous, DISCEN_A::Disabled, _) => config::ConversionMode::Continuous, // It is not possible to have both discontinuous mode and continuous mode enabled. In this // case (if DISCEN=1, CONT=1), the ADC behaves as if continuous mode was disabled. // [RM0316 15.3.20] - (_, DISCEN_A::ENABLED, n) => config::ConversionMode::Discontinuous(n), + (_, DISCEN_A::Enabled, n) => config::ConversionMode::Discontinuous(n), } } @@ -647,9 +632,9 @@ where let cfgr = self.reg.cfgr.read(); use adc1::cfgr::{DMACFG_A, DMAEN_A}; match (cfgr.dmaen().variant(), cfgr.dmacfg().variant()) { - (DMAEN_A::DISABLED, _) => config::DmaMode::Disabled, - (DMAEN_A::ENABLED, DMACFG_A::ONESHOT) => config::DmaMode::OneShot, - (DMAEN_A::ENABLED, DMACFG_A::CIRCULAR) => config::DmaMode::Circular, + (DMAEN_A::Disabled, _) => config::DmaMode::Disabled, + (DMAEN_A::Enabled, DMACFG_A::OneShot) => config::DmaMode::OneShot, + (DMAEN_A::Enabled, DMACFG_A::Circular) => config::DmaMode::Circular, } } @@ -684,7 +669,7 @@ where /// * Alternativly a conversino stop is signaled via the [`Event::EndOfConversion`] event. #[inline] pub fn is_conversion_ongoing(&self) -> bool { - self.reg.cr.read().adstart().is_start() + self.reg.cr.read().adstart().is_active() } /// Get the [`channel::Id`] at a specific [`config::Sequence`] position. @@ -958,9 +943,9 @@ where pub fn set_dma_mode(&mut self, dma: config::DmaMode) { use adc1::cfgr::{DMACFG_A, DMAEN_A}; let (en, mode) = match dma { - config::DmaMode::Disabled => (DMAEN_A::DISABLED, DMACFG_A::ONESHOT), - config::DmaMode::OneShot => (DMAEN_A::ENABLED, DMACFG_A::ONESHOT), - config::DmaMode::Circular => (DMAEN_A::ENABLED, DMACFG_A::CIRCULAR), + config::DmaMode::Disabled => (DMAEN_A::Disabled, DMACFG_A::OneShot), + config::DmaMode::OneShot => (DMAEN_A::Enabled, DMACFG_A::OneShot), + config::DmaMode::Circular => (DMAEN_A::Enabled, DMACFG_A::Circular), }; self.reg @@ -989,7 +974,7 @@ where pub fn stop_conversion(&mut self) { // If no conversion is ongoing, this may lead to the stop bit never beeing reset? if self.is_conversion_ongoing() { - self.reg.cr.modify(|_, w| w.adstp().stop()); + self.reg.cr.modify(|_, w| w.adstp().stop_conversion()); } while self.reg.cr.read().adstp().bit_is_set() {} @@ -1346,7 +1331,7 @@ where // self.clear_events(); self.reg.isr.reset(); // self.start_conversion(); - self.reg.cr.modify(|_, w| w.adstart().start()); + self.reg.cr.modify(|_, w| w.adstart().start_conversion()); // while !self.is_event_triggered(Event::EndOfConversion) // && !self.is_event_triggered(Event::EndOfSequence) // {} @@ -1440,20 +1425,6 @@ macro_rules! adc { ); } }; - - // TODO(Sh3Rm4n): https://github.com/stm32-rs/stm32-rs/pull/696 - ([ $(($A:literal, $ADC:ident, $INTERRUPT:path)),+ ]) => { - paste::paste! { - adc!( - $( - []: ( - $ADC, - $INTERRUPT - ), - )+ - ); - } - }; } macro_rules! adc_common { @@ -1478,7 +1449,7 @@ macro_rules! adc_common { // No clock can be set, so we have to fallback to a default. if self.clock(clocks).is_none() { self.ccr.modify(|_, w| w - .ckmode().variant(CKMODE_A::SYNCDIV1) + .ckmode().variant(CKMODE_A::SyncDiv1) ); }; } @@ -1497,31 +1468,31 @@ macro_rules! adc_common { Some(pllclk) if !adc_pres.is_no_clock() => { pllclk / match adc_pres.variant() { - Some($ADCXYPRES_A::DIV1) => 1, - Some($ADCXYPRES_A::DIV2) => 2, - Some($ADCXYPRES_A::DIV4) => 4, - Some($ADCXYPRES_A::DIV6) => 6, - Some($ADCXYPRES_A::DIV8) => 8, - Some($ADCXYPRES_A::DIV10) => 10, - Some($ADCXYPRES_A::DIV12) => 12, - Some($ADCXYPRES_A::DIV16) => 16, - Some($ADCXYPRES_A::DIV32) => 32, - Some($ADCXYPRES_A::DIV64) => 64, - Some($ADCXYPRES_A::DIV128) => 128, - Some($ADCXYPRES_A::DIV256) => 256, - Some($ADCXYPRES_A::NOCLOCK) | None => 1, + Some($ADCXYPRES_A::Div1) => 1, + Some($ADCXYPRES_A::Div2) => 2, + Some($ADCXYPRES_A::Div4) => 4, + Some($ADCXYPRES_A::Div6) => 6, + Some($ADCXYPRES_A::Div8) => 8, + Some($ADCXYPRES_A::Div10) => 10, + Some($ADCXYPRES_A::Div12) => 12, + Some($ADCXYPRES_A::Div16) => 16, + Some($ADCXYPRES_A::Div32) => 32, + Some($ADCXYPRES_A::Div64) => 64, + Some($ADCXYPRES_A::Div128) => 128, + Some($ADCXYPRES_A::Div256) => 256, + Some($ADCXYPRES_A::NoClock) | None => 1, } } _ => { clocks.sysclk() / match self.ccr.read().ckmode().variant() { - CKMODE_A::SYNCDIV1 => 1, - CKMODE_A::SYNCDIV2 => 2, - CKMODE_A::SYNCDIV4 => 4, + CKMODE_A::SyncDiv1 => 1, + CKMODE_A::SyncDiv2 => 2, + CKMODE_A::SyncDiv4 => 4, // Asynchronous should be enabled if PLL is on. If this line of // code is reached PLL is off. Indicate that, so fallbacks can // be set. - CKMODE_A::ASYNCHRONOUS => return None, + CKMODE_A::Asynchronous => return None, } } }) @@ -1581,7 +1552,7 @@ cfg_if::cfg_if! { if #[cfg(feature = "svd-f301")] { adc_common!([(1, 1, 2)]); adc!([(1, 1, 2, Interrupt::ADC1_IRQ)]); - } else if #[cfg(not(feature = "svd-f3x4"))]{ + } else { adc_common!([(1, 2)]); adc!([(1, 1, 2, Interrupt::ADC1_2)]); } @@ -1591,19 +1562,9 @@ cfg_if::cfg_if! { // * stm32f373 will become complicated, because no ADC1_2 // See https://stm32-rs.github.io/stm32-rs/stm32f/stm32f3/index.html for an overview -#[cfg(any(feature = "svd-f302", feature = "svd-f303"))] +#[cfg(any(feature = "svd-f302", feature = "svd-f303", feature = "svd-f3x4"))] adc!([(2, 1, 2, Interrupt::ADC1_2)]); -// FIXME(Sh3Rm4n): https://github.com/stm32-rs/stm32-rs/pull/696 -// #[cfg(feature = "svd-f3x4")] -cfg_if::cfg_if! { - if #[cfg(feature = "svd-f3x4")] { - adc!([(1, ADC_COMMON, Interrupt::ADC1_2)]); - adc!([(2, ADC_COMMON, Interrupt::ADC1_2)]); - adc_common!([(1, 2, ADC_COMMON)]); - } -} - cfg_if::cfg_if! { if #[cfg(feature = "svd-f303")] { adc_common!([(3, 4)]); diff --git a/src/adc/config.rs b/src/adc/config.rs index c687b97f9..e1952a675 100644 --- a/src/adc/config.rs +++ b/src/adc/config.rs @@ -169,10 +169,10 @@ pub enum Resolution { impl From for cfgr::RES_A { fn from(r: Resolution) -> Self { match r { - Resolution::Twelve => cfgr::RES_A::BITS12, - Resolution::Ten => cfgr::RES_A::BITS10, - Resolution::Eight => cfgr::RES_A::BITS8, - Resolution::Six => cfgr::RES_A::BITS6, + Resolution::Twelve => cfgr::RES_A::Bits12, + Resolution::Ten => cfgr::RES_A::Bits10, + Resolution::Eight => cfgr::RES_A::Bits8, + Resolution::Six => cfgr::RES_A::Bits6, } } } @@ -180,10 +180,10 @@ impl From for cfgr::RES_A { impl From for Resolution { fn from(r: cfgr::RES_A) -> Self { match r { - cfgr::RES_A::BITS12 => Resolution::Twelve, - cfgr::RES_A::BITS10 => Resolution::Ten, - cfgr::RES_A::BITS8 => Resolution::Eight, - cfgr::RES_A::BITS6 => Resolution::Six, + cfgr::RES_A::Bits12 => Resolution::Twelve, + cfgr::RES_A::Bits10 => Resolution::Ten, + cfgr::RES_A::Bits8 => Resolution::Eight, + cfgr::RES_A::Bits6 => Resolution::Six, } } } @@ -242,20 +242,20 @@ pub enum ExternalTrigger { impl From for cfgr::EXTSEL_A { fn from(et: ExternalTrigger) -> Self { match et { - ExternalTrigger::Tim1Cc1(_) => cfgr::EXTSEL_A::TIM1_CC1, - ExternalTrigger::Tim1Cc2(_) => cfgr::EXTSEL_A::TIM1_CC2, - ExternalTrigger::Tim1Cc3(_) => cfgr::EXTSEL_A::TIM1_CC3, - ExternalTrigger::Tim2Cc2(_) => cfgr::EXTSEL_A::TIM2_CC2, - ExternalTrigger::Tim3Trgo(_) => cfgr::EXTSEL_A::TIM3_TRGO, - ExternalTrigger::Exti11(_) => cfgr::EXTSEL_A::EXTI11, - ExternalTrigger::HrtimAdcTrg1(_) => cfgr::EXTSEL_A::HRTIM_ADCTRG1, - ExternalTrigger::HrtimAdcTrg3(_) => cfgr::EXTSEL_A::HRTIM_ADCTRG3, - ExternalTrigger::Tim1Trgo(_) => cfgr::EXTSEL_A::TIM1_TRGO, - ExternalTrigger::Tim1Trgo2(_) => cfgr::EXTSEL_A::TIM1_TRGO2, - ExternalTrigger::Tim2Trgo(_) => cfgr::EXTSEL_A::TIM2_TRGO, - ExternalTrigger::Tim6Trgo(_) => cfgr::EXTSEL_A::TIM6_TRGO, - ExternalTrigger::Tim15Trgo(_) => cfgr::EXTSEL_A::TIM15_TRGO, - ExternalTrigger::Tim3Cc4(_) => cfgr::EXTSEL_A::TIM1_CC3, + ExternalTrigger::Tim1Cc1(_) => cfgr::EXTSEL_A::Tim1Cc1, + ExternalTrigger::Tim1Cc2(_) => cfgr::EXTSEL_A::Tim1Cc2, + ExternalTrigger::Tim1Cc3(_) => cfgr::EXTSEL_A::Tim1Cc3, + ExternalTrigger::Tim2Cc2(_) => cfgr::EXTSEL_A::Tim2Cc2, + ExternalTrigger::Tim3Trgo(_) => cfgr::EXTSEL_A::Tim3Trgo, + ExternalTrigger::Exti11(_) => cfgr::EXTSEL_A::Exti11, + ExternalTrigger::HrtimAdcTrg1(_) => cfgr::EXTSEL_A::HrtimAdctrg1, + ExternalTrigger::HrtimAdcTrg3(_) => cfgr::EXTSEL_A::HrtimAdctrg3, + ExternalTrigger::Tim1Trgo(_) => cfgr::EXTSEL_A::Tim1Trgo, + ExternalTrigger::Tim1Trgo2(_) => cfgr::EXTSEL_A::Tim1Trgo2, + ExternalTrigger::Tim2Trgo(_) => cfgr::EXTSEL_A::Tim2Trgo, + ExternalTrigger::Tim6Trgo(_) => cfgr::EXTSEL_A::Tim6Trgo, + ExternalTrigger::Tim15Trgo(_) => cfgr::EXTSEL_A::Tim15Trgo, + ExternalTrigger::Tim3Cc4(_) => cfgr::EXTSEL_A::Tim3Cc4, } } } @@ -304,9 +304,9 @@ pub enum TriggerMode { impl From for cfgr::EXTEN_A { fn from(tm: TriggerMode) -> Self { match tm { - TriggerMode::RisingEdge => cfgr::EXTEN_A::RISINGEDGE, - TriggerMode::FallingEdge => cfgr::EXTEN_A::FALLINGEDGE, - TriggerMode::BothEdges => cfgr::EXTEN_A::BOTHEDGES, + TriggerMode::RisingEdge => cfgr::EXTEN_A::RisingEdge, + TriggerMode::FallingEdge => cfgr::EXTEN_A::FallingEdge, + TriggerMode::BothEdges => cfgr::EXTEN_A::BothEdges, } } } @@ -338,8 +338,8 @@ pub enum DataAlignment { impl From for cfgr::ALIGN_A { fn from(a: DataAlignment) -> Self { match a { - DataAlignment::Right => cfgr::ALIGN_A::RIGHT, - DataAlignment::Left => cfgr::ALIGN_A::LEFT, + DataAlignment::Right => cfgr::ALIGN_A::Right, + DataAlignment::Left => cfgr::ALIGN_A::Left, } } } @@ -347,8 +347,8 @@ impl From for cfgr::ALIGN_A { impl From for DataAlignment { fn from(a: cfgr::ALIGN_A) -> Self { match a { - cfgr::ALIGN_A::RIGHT => DataAlignment::Right, - cfgr::ALIGN_A::LEFT => DataAlignment::Left, + cfgr::ALIGN_A::Right => DataAlignment::Right, + cfgr::ALIGN_A::Left => DataAlignment::Left, } } } @@ -386,8 +386,8 @@ cfg_if::cfg_if! { impl From for cr::SCAN_R { fn from(a: Scan) -> Self { match a { - Scan::Disabled => cr1::SCAN_R::DISABLED, - Scan::Enabled => cr1::SCAN_R::ENABLED, + Scan::Disabled => cr1::SCAN_R::Disabled, + Scan::Enabled => cr1::SCAN_R::Enabled, } } } @@ -395,8 +395,8 @@ cfg_if::cfg_if! { impl From for cr::SCAN_R { fn from(a: Scan) -> Self { match a { - Scan::Disabled => cr1::SCAN_R::DISABLED, - Scan::Enabled => cr1::SCAN_R::ENABLED, + Scan::Disabled => cr1::SCAN_R::Disabled, + Scan::Enabled => cr1::SCAN_R::Enabled, } } } @@ -438,8 +438,8 @@ pub enum OverrunMode { impl From for OverrunMode { fn from(a: cfgr::OVRMOD_A) -> Self { match a { - cfgr::OVRMOD_A::PRESERVE => OverrunMode::Preserve, - cfgr::OVRMOD_A::OVERWRITE => OverrunMode::Overwrite, + cfgr::OVRMOD_A::Preserve => OverrunMode::Preserve, + cfgr::OVRMOD_A::Overwrite => OverrunMode::Overwrite, } } } @@ -447,8 +447,8 @@ impl From for OverrunMode { impl From for cfgr::OVRMOD_A { fn from(a: OverrunMode) -> Self { match a { - OverrunMode::Preserve => cfgr::OVRMOD_A::PRESERVE, - OverrunMode::Overwrite => cfgr::OVRMOD_A::OVERWRITE, + OverrunMode::Preserve => cfgr::OVRMOD_A::Preserve, + OverrunMode::Overwrite => cfgr::OVRMOD_A::Overwrite, } } } @@ -545,14 +545,14 @@ impl From for f32 { impl From for SMP1_A { fn from(t: SampleTime) -> Self { match t { - SampleTime::Cycles1C5 => Self::CYCLES1_5, - SampleTime::Cycles2C5 => Self::CYCLES2_5, - SampleTime::Cycles4C5 => Self::CYCLES4_5, - SampleTime::Cycles7C5 => Self::CYCLES7_5, - SampleTime::Cycles19C5 => Self::CYCLES19_5, - SampleTime::Cycles61C5 => Self::CYCLES61_5, - SampleTime::Cycles181C5 => Self::CYCLES181_5, - SampleTime::Cycles601C5 => Self::CYCLES601_5, + SampleTime::Cycles1C5 => Self::Cycles15, + SampleTime::Cycles2C5 => Self::Cycles25, + SampleTime::Cycles4C5 => Self::Cycles45, + SampleTime::Cycles7C5 => Self::Cycles75, + SampleTime::Cycles19C5 => Self::Cycles195, + SampleTime::Cycles61C5 => Self::Cycles615, + SampleTime::Cycles181C5 => Self::Cycles1815, + SampleTime::Cycles601C5 => Self::Cycles6015, } } } @@ -560,14 +560,14 @@ impl From for SMP1_A { impl From for SMP10_A { fn from(t: SampleTime) -> Self { match t { - SampleTime::Cycles1C5 => Self::CYCLES1_5, - SampleTime::Cycles2C5 => Self::CYCLES2_5, - SampleTime::Cycles4C5 => Self::CYCLES4_5, - SampleTime::Cycles7C5 => Self::CYCLES7_5, - SampleTime::Cycles19C5 => Self::CYCLES19_5, - SampleTime::Cycles61C5 => Self::CYCLES61_5, - SampleTime::Cycles181C5 => Self::CYCLES181_5, - SampleTime::Cycles601C5 => Self::CYCLES601_5, + SampleTime::Cycles1C5 => Self::Cycles15, + SampleTime::Cycles2C5 => Self::Cycles25, + SampleTime::Cycles4C5 => Self::Cycles45, + SampleTime::Cycles7C5 => Self::Cycles75, + SampleTime::Cycles19C5 => Self::Cycles195, + SampleTime::Cycles61C5 => Self::Cycles615, + SampleTime::Cycles181C5 => Self::Cycles1815, + SampleTime::Cycles601C5 => Self::Cycles6015, } } } @@ -575,14 +575,14 @@ impl From for SMP10_A { impl From for SampleTime { fn from(t: SMP1_A) -> Self { match t { - SMP1_A::CYCLES1_5 => Self::Cycles1C5, - SMP1_A::CYCLES2_5 => Self::Cycles2C5, - SMP1_A::CYCLES4_5 => Self::Cycles4C5, - SMP1_A::CYCLES7_5 => Self::Cycles7C5, - SMP1_A::CYCLES19_5 => Self::Cycles19C5, - SMP1_A::CYCLES61_5 => Self::Cycles61C5, - SMP1_A::CYCLES181_5 => Self::Cycles181C5, - SMP1_A::CYCLES601_5 => Self::Cycles601C5, + SMP1_A::Cycles15 => Self::Cycles1C5, + SMP1_A::Cycles25 => Self::Cycles2C5, + SMP1_A::Cycles45 => Self::Cycles4C5, + SMP1_A::Cycles75 => Self::Cycles7C5, + SMP1_A::Cycles195 => Self::Cycles19C5, + SMP1_A::Cycles615 => Self::Cycles61C5, + SMP1_A::Cycles1815 => Self::Cycles181C5, + SMP1_A::Cycles6015 => Self::Cycles601C5, } } } @@ -590,14 +590,14 @@ impl From for SampleTime { impl From for SampleTime { fn from(t: SMP10_A) -> Self { match t { - SMP10_A::CYCLES1_5 => Self::Cycles1C5, - SMP10_A::CYCLES2_5 => Self::Cycles2C5, - SMP10_A::CYCLES4_5 => Self::Cycles4C5, - SMP10_A::CYCLES7_5 => Self::Cycles7C5, - SMP10_A::CYCLES19_5 => Self::Cycles19C5, - SMP10_A::CYCLES61_5 => Self::Cycles61C5, - SMP10_A::CYCLES181_5 => Self::Cycles181C5, - SMP10_A::CYCLES601_5 => Self::Cycles601C5, + SMP10_A::Cycles15 => Self::Cycles1C5, + SMP10_A::Cycles25 => Self::Cycles2C5, + SMP10_A::Cycles45 => Self::Cycles4C5, + SMP10_A::Cycles75 => Self::Cycles7C5, + SMP10_A::Cycles195 => Self::Cycles19C5, + SMP10_A::Cycles615 => Self::Cycles61C5, + SMP10_A::Cycles1815 => Self::Cycles181C5, + SMP10_A::Cycles6015 => Self::Cycles601C5, } } } @@ -779,8 +779,8 @@ pub enum ConversionMode { impl From for cfgr::CONT_A { fn from(mode: ConversionMode) -> Self { match mode { - ConversionMode::Single | ConversionMode::Discontinuous(_) => Self::SINGLE, - ConversionMode::Continuous => Self::CONTINUOUS, + ConversionMode::Single | ConversionMode::Discontinuous(_) => Self::Single, + ConversionMode::Continuous => Self::Continuous, } } } @@ -788,8 +788,8 @@ impl From for cfgr::CONT_A { impl From for cfgr::DISCEN_A { fn from(mode: ConversionMode) -> Self { match mode { - ConversionMode::Single | ConversionMode::Continuous => Self::DISABLED, - ConversionMode::Discontinuous(_) => Self::ENABLED, + ConversionMode::Single | ConversionMode::Continuous => Self::Disabled, + ConversionMode::Discontinuous(_) => Self::Enabled, } } } @@ -797,8 +797,8 @@ impl From for cfgr::DISCEN_A { impl From for ConversionMode { fn from(mode: cfgr::CONT_A) -> Self { match mode { - cfgr::CONT_A::SINGLE => ConversionMode::Single, - cfgr::CONT_A::CONTINUOUS => ConversionMode::Continuous, + cfgr::CONT_A::Single => ConversionMode::Single, + cfgr::CONT_A::Continuous => ConversionMode::Continuous, } } } diff --git a/src/dac.rs b/src/dac.rs index f619cc4ab..ab519c7fc 100644 --- a/src/dac.rs +++ b/src/dac.rs @@ -4,27 +4,18 @@ use crate::rcc::{Enable, Reset, APB1}; -#[cfg(feature = "svd-f302")] -use crate::pac::DAC; - -#[cfg(any( - feature = "svd-f301", - feature = "svd-f303", - feature = "svd-f373", - feature = "svd-f3x4", -))] -use crate::pac::DAC1 as DAC; +use crate::pac::DAC1; /// Represents a Digital to Analog Converter (DAC) peripheral. pub struct Dac { - regs: DAC, + regs: DAC1, } impl Dac { /// Initializes the DAC peripheral. - pub fn new(regs: DAC, apb1: &mut APB1) -> Self { - DAC::enable(apb1); - DAC::reset(apb1); + pub fn new(regs: DAC1, apb1: &mut APB1) -> Self { + DAC1::enable(apb1); + DAC1::reset(apb1); // Enable channel 1. regs.cr.modify(|_, w| w.en1().set_bit()); diff --git a/src/dma.rs b/src/dma.rs index 00b0c160d..9c90041c2 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -195,8 +195,8 @@ pub enum Increment { impl From for cr::PINC_A { fn from(inc: Increment) -> Self { match inc { - Increment::Enable => cr::PINC_A::ENABLED, - Increment::Disable => cr::PINC_A::DISABLED, + Increment::Enable => cr::PINC_A::Enabled, + Increment::Disable => cr::PINC_A::Disabled, } } } @@ -218,10 +218,10 @@ pub enum Priority { impl From for cr::PL_A { fn from(prio: Priority) -> Self { match prio { - Priority::Low => cr::PL_A::LOW, - Priority::Medium => cr::PL_A::MEDIUM, - Priority::High => cr::PL_A::HIGH, - Priority::VeryHigh => cr::PL_A::VERYHIGH, + Priority::Low => cr::PL_A::Low, + Priority::Medium => cr::PL_A::Medium, + Priority::High => cr::PL_A::High, + Priority::VeryHigh => cr::PL_A::VeryHigh, } } } @@ -239,8 +239,8 @@ pub enum Direction { impl From for cr::DIR_A { fn from(dir: Direction) -> Self { match dir { - Direction::FromMemory => cr::DIR_A::FROMMEMORY, - Direction::FromPeripheral => cr::DIR_A::FROMPERIPHERAL, + Direction::FromMemory => cr::DIR_A::FromMemory, + Direction::FromPeripheral => cr::DIR_A::FromPeripheral, } } } @@ -352,9 +352,9 @@ pub trait Channel: private::Channel { use cr::PSIZE_A::*; let psize = match mem::size_of::() { - 1 => BITS8, - 2 => BITS16, - 4 => BITS32, + 1 => Bits8, + 2 => Bits16, + 4 => Bits32, #[cfg(not(feature = "defmt"))] s => core::panic!("unsupported word size: {:?}", s), #[cfg(feature = "defmt")] diff --git a/src/gpio.rs b/src/gpio.rs index 45785beff..e32bc10da 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -952,10 +952,10 @@ macro_rules! gpio { r_trait! { ($GPIOX, $gpioy::moder::MODER15_A, 2); impl Moder for MODER { - fn input { INPUT } - fn output { OUTPUT } - fn alternate { ALTERNATE } - fn analog { ANALOG } + fn input { Input } + fn output { Output } + fn alternate { Alternate } + fn analog { Analog } } } @@ -965,9 +965,9 @@ macro_rules! gpio { r_trait! { ($GPIOX, $gpioy::ospeedr::OSPEEDR15_A, 2); impl Ospeedr for OSPEEDR { - fn low { LOWSPEED } - fn medium { MEDIUMSPEED } - fn high { HIGHSPEED } + fn low { LowSpeed } + fn medium { MediumSpeed } + fn high { HighSpeed } } } @@ -977,8 +977,8 @@ macro_rules! gpio { r_trait! { ($GPIOX, $gpioy::otyper::OT15_A, 1); impl Otyper for OTYPER { - fn push_pull { PUSHPULL } - fn open_drain { OPENDRAIN } + fn push_pull { PushPull } + fn open_drain { OpenDrain } } } @@ -988,9 +988,9 @@ macro_rules! gpio { r_trait! { ($GPIOX, $gpioy::pupdr::PUPDR15_A, 2); impl Pupdr for PUPDR { - fn floating { FLOATING } - fn pull_up { PULLUP } - fn pull_down { PULLDOWN } + fn floating { Floating } + fn pull_up { PullUp } + fn pull_down { PullDown } } } } diff --git a/src/i2c.rs b/src/i2c.rs index 62c978109..2d0fd5467 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -462,8 +462,8 @@ macro_rules! i2c { fn clock(clocks: &Clocks) -> Hertz { // NOTE(unsafe) atomic read with no side effects match unsafe { (*RCC::ptr()).cfgr3.read().$i2cXsw().variant() } { - I2C1SW_A::HSI => crate::rcc::HSI, - I2C1SW_A::SYSCLK => clocks.sysclk(), + I2C1SW_A::Hsi => crate::rcc::HSI, + I2C1SW_A::Sysclk => clocks.sysclk(), } } } diff --git a/src/pwm.rs b/src/pwm.rs index add6d4609..e75e326c2 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -552,12 +552,12 @@ macro_rules! pwm_pin_for_pwm_channel_private { } fn get_duty(&self) -> Self::Duty { - unsafe { (*$TIMx::ptr()).$ccrx.read().$ccrq().bits() } + unsafe { (*$TIMx::ptr()).$ccrx().read().$ccrq().bits() } } fn set_duty(&mut self, duty: Self::Duty) -> () { unsafe { - (*$TIMx::ptr()).$ccrx.modify(|_, w| w.$ccrq().bits(duty)); + (*$TIMx::ptr()).$ccrx().modify(|_, w| w.$ccrq().bits(duty)); } } } diff --git a/src/rcc.rs b/src/rcc.rs index 9365782b1..0a4664503 100644 --- a/src/rcc.rs +++ b/src/rcc.rs @@ -338,12 +338,12 @@ mod usb_clocking { // problems. [RM0316 32.5.2] if pclk1 >= 10_000_000 { match (usb_ok, sysclk) { - (true, 72_000_000) => (cfgr::USBPRE_A::DIV1_5, true), - (true, 48_000_000) => (cfgr::USBPRE_A::DIV1, true), - _ => (cfgr::USBPRE_A::DIV1, false), + (true, 72_000_000) => (cfgr::USBPRE_A::Div15, true), + (true, 48_000_000) => (cfgr::USBPRE_A::Div1, true), + _ => (cfgr::USBPRE_A::Div1, false), } } else { - (cfgr::USBPRE_A::DIV1, false) + (cfgr::USBPRE_A::Div1, false) } } @@ -423,21 +423,21 @@ fn gcd(mut a: u32, mut b: u32) -> u32 { /// Convert pll multiplier into equivalent register field type fn into_pll_mul(mul: u8) -> cfgr::PLLMUL_A { match mul { - 2 => cfgr::PLLMUL_A::MUL2, - 3 => cfgr::PLLMUL_A::MUL3, - 4 => cfgr::PLLMUL_A::MUL4, - 5 => cfgr::PLLMUL_A::MUL5, - 6 => cfgr::PLLMUL_A::MUL6, - 7 => cfgr::PLLMUL_A::MUL7, - 8 => cfgr::PLLMUL_A::MUL8, - 9 => cfgr::PLLMUL_A::MUL9, - 10 => cfgr::PLLMUL_A::MUL10, - 11 => cfgr::PLLMUL_A::MUL11, - 12 => cfgr::PLLMUL_A::MUL12, - 13 => cfgr::PLLMUL_A::MUL13, - 14 => cfgr::PLLMUL_A::MUL14, - 15 => cfgr::PLLMUL_A::MUL15, - 16 => cfgr::PLLMUL_A::MUL16, + 2 => cfgr::PLLMUL_A::Mul2, + 3 => cfgr::PLLMUL_A::Mul3, + 4 => cfgr::PLLMUL_A::Mul4, + 5 => cfgr::PLLMUL_A::Mul5, + 6 => cfgr::PLLMUL_A::Mul6, + 7 => cfgr::PLLMUL_A::Mul7, + 8 => cfgr::PLLMUL_A::Mul8, + 9 => cfgr::PLLMUL_A::Mul9, + 10 => cfgr::PLLMUL_A::Mul10, + 11 => cfgr::PLLMUL_A::Mul11, + 12 => cfgr::PLLMUL_A::Mul12, + 13 => cfgr::PLLMUL_A::Mul13, + 14 => cfgr::PLLMUL_A::Mul14, + 15 => cfgr::PLLMUL_A::Mul15, + 16 => cfgr::PLLMUL_A::Mul16, _ => crate::unreachable!(), } } @@ -445,22 +445,22 @@ fn into_pll_mul(mul: u8) -> cfgr::PLLMUL_A { /// Convert pll divisor into equivalent register field type fn into_pre_div(div: u8) -> cfgr2::PREDIV_A { match div { - 1 => cfgr2::PREDIV_A::DIV1, - 2 => cfgr2::PREDIV_A::DIV2, - 3 => cfgr2::PREDIV_A::DIV3, - 4 => cfgr2::PREDIV_A::DIV4, - 5 => cfgr2::PREDIV_A::DIV5, - 6 => cfgr2::PREDIV_A::DIV6, - 7 => cfgr2::PREDIV_A::DIV7, - 8 => cfgr2::PREDIV_A::DIV8, - 9 => cfgr2::PREDIV_A::DIV9, - 10 => cfgr2::PREDIV_A::DIV10, - 11 => cfgr2::PREDIV_A::DIV11, - 12 => cfgr2::PREDIV_A::DIV12, - 13 => cfgr2::PREDIV_A::DIV13, - 14 => cfgr2::PREDIV_A::DIV14, - 15 => cfgr2::PREDIV_A::DIV15, - 16 => cfgr2::PREDIV_A::DIV16, + 1 => cfgr2::PREDIV_A::Div1, + 2 => cfgr2::PREDIV_A::Div2, + 3 => cfgr2::PREDIV_A::Div3, + 4 => cfgr2::PREDIV_A::Div4, + 5 => cfgr2::PREDIV_A::Div5, + 6 => cfgr2::PREDIV_A::Div6, + 7 => cfgr2::PREDIV_A::Div7, + 8 => cfgr2::PREDIV_A::Div8, + 9 => cfgr2::PREDIV_A::Div9, + 10 => cfgr2::PREDIV_A::Div10, + 11 => cfgr2::PREDIV_A::Div11, + 12 => cfgr2::PREDIV_A::Div12, + 13 => cfgr2::PREDIV_A::Div13, + 14 => cfgr2::PREDIV_A::Div14, + 15 => cfgr2::PREDIV_A::Div15, + 16 => cfgr2::PREDIV_A::Div16, _ => crate::unreachable!(), } } @@ -638,9 +638,9 @@ impl CFGR { crate::assert!(sysclk <= 72_000_000); let pll_src = if self.hse.is_some() { - cfgr::PLLSRC_A::HSE_DIV_PREDIV + cfgr::PLLSRC_A::HseDivPrediv } else { - cfgr::PLLSRC_A::HSI_DIV2 + cfgr::PLLSRC_A::HsiDiv2 }; // Convert into register bit field types @@ -703,9 +703,9 @@ impl CFGR { // Select hardware clock source of the PLL // TODO Check whether HSI_DIV2 could be useful let pll_src = if self.hse.is_some() { - cfgr::PLLSRC_A::HSE_DIV_PREDIV + cfgr::PLLSRC_A::HseDivPrediv } else { - cfgr::PLLSRC_A::HSI_DIV_PREDIV + cfgr::PLLSRC_A::HseDivPrediv }; // Convert into register bit field types @@ -739,20 +739,20 @@ impl CFGR { // directly from neither the internal rc (8 Mhz) nor the external // Oscillator (max 32 Mhz), without using the PLL. (Some(sysclk), Some(hse)) if sysclk == hse && self.pll_bypass => { - (hse, cfgr::SW_A::HSE, None) + (hse, cfgr::SW_A::Hse, None) } // No need to use the PLL (Some(sysclk), None) if sysclk == HSI.integer() && self.pll_bypass => { - (HSI.integer(), cfgr::SW_A::HSI, None) + (HSI.integer(), cfgr::SW_A::Hsi, None) } (Some(sysclk), _) => { let (sysclk, pll_config) = self.calc_pll(sysclk); - (sysclk, cfgr::SW_A::PLL, Some(pll_config)) + (sysclk, cfgr::SW_A::Pll, Some(pll_config)) } // Use HSE as system clock - (None, Some(hse)) => (hse, cfgr::SW_A::HSE, None), + (None, Some(hse)) => (hse, cfgr::SW_A::Hse, None), // Use HSI as system clock - (None, None) => (HSI.integer(), cfgr::SW_A::HSI, None), + (None, None) => (HSI.integer(), cfgr::SW_A::Hsi, None), } } @@ -772,17 +772,17 @@ impl CFGR { let (hpre_bits, hpre) = self.hclk - .map_or((cfgr::HPRE_A::DIV1, 1), |hclk| match sysclk / hclk { + .map_or((cfgr::HPRE_A::Div1, 1), |hclk| match sysclk / hclk { 0 => crate::unreachable!(), - 1 => (cfgr::HPRE_A::DIV1, 1), - 2 => (cfgr::HPRE_A::DIV2, 2), - 3..=5 => (cfgr::HPRE_A::DIV4, 4), - 6..=11 => (cfgr::HPRE_A::DIV8, 8), - 12..=39 => (cfgr::HPRE_A::DIV16, 16), - 40..=95 => (cfgr::HPRE_A::DIV64, 64), - 96..=191 => (cfgr::HPRE_A::DIV128, 128), - 192..=383 => (cfgr::HPRE_A::DIV256, 256), - _ => (cfgr::HPRE_A::DIV512, 512), + 1 => (cfgr::HPRE_A::Div1, 1), + 2 => (cfgr::HPRE_A::Div2, 2), + 3..=5 => (cfgr::HPRE_A::Div4, 4), + 6..=11 => (cfgr::HPRE_A::Div8, 8), + 12..=39 => (cfgr::HPRE_A::Div16, 16), + 40..=95 => (cfgr::HPRE_A::Div64, 64), + 96..=191 => (cfgr::HPRE_A::Div128, 128), + 192..=383 => (cfgr::HPRE_A::Div256, 256), + _ => (cfgr::HPRE_A::Div512, 512), }); let hclk: u32 = sysclk / hpre; @@ -791,13 +791,13 @@ impl CFGR { let (mut ppre1_bits, mut ppre1) = self.pclk1 - .map_or((cfgr::PPRE1_A::DIV1, 1), |pclk1| match hclk / pclk1 { + .map_or((cfgr::PPRE1_A::Div1, 1), |pclk1| match hclk / pclk1 { 0 => crate::unreachable!(), - 1 => (cfgr::PPRE1_A::DIV1, 1), - 2 => (cfgr::PPRE1_A::DIV2, 2), - 3..=5 => (cfgr::PPRE1_A::DIV4, 4), - 6..=11 => (cfgr::PPRE1_A::DIV8, 8), - _ => (cfgr::PPRE1_A::DIV16, 16), + 1 => (cfgr::PPRE1_A::Div1, 1), + 2 => (cfgr::PPRE1_A::Div2, 2), + 3..=5 => (cfgr::PPRE1_A::Div4, 4), + 6..=11 => (cfgr::PPRE1_A::Div8, 8), + _ => (cfgr::PPRE1_A::Div16, 16), }); let mut pclk1 = hclk / u32::from(ppre1); @@ -807,7 +807,7 @@ impl CFGR { // As hclk highest value is 72.MHz() // dividing by 2 should always be sufficient if self.pclk1.is_none() && pclk1 > 36_000_000 { - ppre1_bits = cfgr::PPRE1_A::DIV2; + ppre1_bits = cfgr::PPRE1_A::Div2; ppre1 = 2; pclk1 = hclk / u32::from(ppre1); } @@ -816,13 +816,13 @@ impl CFGR { let (ppre2_bits, ppre2) = self.pclk2 - .map_or((cfgr::PPRE2_A::DIV1, 1), |pclk2| match hclk / pclk2 { + .map_or((cfgr::PPRE2_A::Div1, 1), |pclk2| match hclk / pclk2 { 0 => crate::unreachable!(), - 1 => (cfgr::PPRE2_A::DIV1, 1), - 2 => (cfgr::PPRE2_A::DIV2, 2), - 3..=5 => (cfgr::PPRE2_A::DIV4, 4), - 6..=11 => (cfgr::PPRE2_A::DIV8, 8), - _ => (cfgr::PPRE2_A::DIV16, 16), + 1 => (cfgr::PPRE2_A::Div1, 1), + 2 => (cfgr::PPRE2_A::Div2, 2), + 3..=5 => (cfgr::PPRE2_A::Div4, 4), + 6..=11 => (cfgr::PPRE2_A::Div8, 8), + _ => (cfgr::PPRE2_A::Div16, 16), }); let pclk2 = hclk / u32::from(ppre2); diff --git a/src/rcc/enable.rs b/src/rcc/enable.rs index 78c0c9315..b16c3deb9 100644 --- a/src/rcc/enable.rs +++ b/src/rcc/enable.rs @@ -121,9 +121,9 @@ bus! { ADC1_2 => (AHB, adc1en, adc1rst), // 28 } -#[cfg(feature = "svd-f3x4")] +#[cfg(any(feature = "svd-f302", feature = "svd-f303", feature = "svd-f3x4"))] bus! { - ADC_COMMON => (AHB, adc12en, adc12rst), + ADC1_2 => (AHB, adc12en, adc12rst), // 28 } #[cfg(any(feature = "svd-f302", feature = "svd-f303"))] @@ -134,7 +134,6 @@ bus! { UART4 => (APB1, uart4en, uart4rst), // 19 UART5 => (APB1, uart5en, uart5rst), // 20 GPIOG => (AHB, iopgen, iopgrst), // 23 - ADC1_2 => (AHB, adc12en, adc12rst), // 28 } #[cfg(any( @@ -147,21 +146,10 @@ bus! { TIM1 => (APB2, tim1en, tim1rst), // 11 } -#[cfg(any( - feature = "svd-f301", - feature = "svd-f303", - feature = "svd-f373", - feature = "svd-f3x4" -))] bus! { DAC1 => (APB1, dac1en, dac1rst), // 29 } -#[cfg(any(feature = "svd-f302",))] -bus! { - DAC => (APB1, dac1en, dac1rst), // 29 -} - #[cfg(any(feature = "svd-f303", feature = "svd-f373", feature = "svd-f3x4"))] bus! { TIM7 => (APB1, tim7en, tim7rst), // 5 diff --git a/src/serial.rs b/src/serial.rs index d41b2f1ee..db231dd9c 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -491,9 +491,9 @@ where // and partiy bits together so the actual amount depends on the parity // selection. let (m0, ps, pce) = match config.parity { - Parity::None => (M_A::BIT8, PS_A::EVEN, PCE_A::DISABLED), - Parity::Even => (M_A::BIT9, PS_A::EVEN, PCE_A::ENABLED), - Parity::Odd => (M_A::BIT9, PS_A::ODD, PCE_A::ENABLED), + Parity::None => (M_A::Bit8, PS_A::Even, PCE_A::Disabled), + Parity::Even => (M_A::Bit9, PS_A::Even, PCE_A::Enabled), + Parity::Odd => (M_A::Bit9, PS_A::Odd, PCE_A::Enabled), }; usart @@ -1342,10 +1342,10 @@ macro_rules! usart_var_clock { fn clock(clocks: &Clocks) -> Hertz { // NOTE(unsafe): atomic read with no side effects match unsafe {(*RCC::ptr()).cfgr3.read().$usartXsw().variant()} { - USART1SW_A::PCLK => <$USARTX as rcc::BusClock>::clock(clocks), - USART1SW_A::HSI => crate::rcc::HSI, - USART1SW_A::SYSCLK => clocks.sysclk(), - USART1SW_A::LSE => crate::rcc::LSE, + USART1SW_A::Pclk => <$USARTX as rcc::BusClock>::clock(clocks), + USART1SW_A::Hsi => crate::rcc::HSI, + USART1SW_A::Sysclk => clocks.sysclk(), + USART1SW_A::Lse => crate::rcc::LSE, } } } diff --git a/src/serial/config.rs b/src/serial/config.rs index 89b9af3c4..4212fe22e 100644 --- a/src/serial/config.rs +++ b/src/serial/config.rs @@ -22,10 +22,10 @@ pub enum StopBits { impl From for STOP_A { fn from(stopbit: StopBits) -> Self { match stopbit { - StopBits::Stop0P5 => STOP_A::STOP0P5, - StopBits::Stop1 => STOP_A::STOP1, - StopBits::Stop1P5 => STOP_A::STOP1P5, - StopBits::Stop2 => STOP_A::STOP2, + StopBits::Stop0P5 => STOP_A::Stop0p5, + StopBits::Stop1 => STOP_A::Stop1, + StopBits::Stop1P5 => STOP_A::Stop1p5, + StopBits::Stop2 => STOP_A::Stop2, } } } @@ -33,10 +33,10 @@ impl From for STOP_A { impl From for StopBits { fn from(stopbit: STOP_A) -> Self { match stopbit { - STOP_A::STOP0P5 => StopBits::Stop0P5, - STOP_A::STOP1 => StopBits::Stop1, - STOP_A::STOP1P5 => StopBits::Stop1P5, - STOP_A::STOP2 => StopBits::Stop2, + STOP_A::Stop0p5 => StopBits::Stop0P5, + STOP_A::Stop1 => StopBits::Stop1, + STOP_A::Stop1p5 => StopBits::Stop1P5, + STOP_A::Stop2 => StopBits::Stop2, } } } diff --git a/src/spi.rs b/src/spi.rs index 5584234ba..2942e7fba 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -161,13 +161,13 @@ pub trait Word { impl Word for u8 { fn register_config() -> (FRXTH_A, DS_A) { - (FRXTH_A::QUARTER, DS_A::EIGHTBIT) + (FRXTH_A::Quarter, DS_A::EightBit) } } impl Word for u16 { fn register_config() -> (FRXTH_A, DS_A) { - (FRXTH_A::HALF, DS_A::SIXTEENBIT) + (FRXTH_A::Half, DS_A::SixteenBit) } } @@ -309,14 +309,14 @@ where use spi1::cr1::BR_A; match SPI::clock(&clocks).0 / (freq.integer() * *freq.scaling_factor()) { 0 => crate::unreachable!(), - 1..=2 => BR_A::DIV2, - 3..=5 => BR_A::DIV4, - 6..=11 => BR_A::DIV8, - 12..=23 => BR_A::DIV16, - 24..=39 => BR_A::DIV32, - 40..=95 => BR_A::DIV64, - 96..=191 => BR_A::DIV128, - _ => BR_A::DIV256, + 1..=2 => BR_A::Div2, + 3..=5 => BR_A::Div4, + 6..=11 => BR_A::Div8, + 12..=23 => BR_A::Div16, + 24..=39 => BR_A::Div32, + 40..=95 => BR_A::Div64, + 96..=191 => BR_A::Div128, + _ => BR_A::Div256, } } diff --git a/src/timer.rs b/src/timer.rs index 0bfc188a0..e776a0516 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -431,9 +431,9 @@ macro_rules! timer { #[inline] fn set_arr(&mut self, arr: u16) { - // TODO (sh3rm4n) - // self.tim.arr.write(|w| { w.arr().bits(arr) }); - self.arr.write(|w| unsafe { w.bits(u32::from(arr)) }); + // SAFETY: For easier compatibility between timers write to whole register + #[allow(unused_unsafe)] + self.arr.write(|w| unsafe { w.arr().bits(arr.into()) }); } } }; @@ -450,12 +450,12 @@ macro_rules! timer_var_clock { match unsafe {(*RCC::ptr()).cfgr3.read().$timXsw().variant()} { // PCLK2 is really the wrong name, as depending on the type of chip, it is // pclk1 or pclk2. This distinction is however not made in stm32f3. - crate::pac::rcc::cfgr3::TIM1SW_A::PCLK2 => { + crate::pac::rcc::cfgr3::TIM1SW_A::Pclk2 => { // Conditional mutliplier after APB prescaler is used. // See RM0316 Fig 13. ::timer_clock(clocks) } - crate::pac::rcc::cfgr3::TIM1SW_A::PLL => { + crate::pac::rcc::cfgr3::TIM1SW_A::Pll => { if let Some(pllclk) = clocks.pllclk() { pllclk * 2 } else { diff --git a/src/watchdog.rs b/src/watchdog.rs index 83d21ed0c..ee35c8565 100644 --- a/src/watchdog.rs +++ b/src/watchdog.rs @@ -18,7 +18,7 @@ use crate::time::rate::Kilohertz; /// Frequency of the watchdog peripheral clock const LSI: Kilohertz = Kilohertz(40); // const MAX_PRESCALER: u8 = 0b0111; -const MAX_PRESCALER: PR_A = PR_A::DIVIDEBY256; +const MAX_PRESCALER: PR_A = PR_A::DivideBy256; const MAX_RELOAD: u32 = 0x0FFF; /// Independent Watchdog Peripheral @@ -43,13 +43,13 @@ impl fmt::Debug for IndependentWatchDog { fn into_division_value(psc: PR_A) -> u32 { match psc { - PR_A::DIVIDEBY4 => 4, - PR_A::DIVIDEBY8 => 8, - PR_A::DIVIDEBY16 => 16, - PR_A::DIVIDEBY32 => 32, - PR_A::DIVIDEBY64 => 64, - PR_A::DIVIDEBY128 => 128, - PR_A::DIVIDEBY256 | PR_A::DIVIDEBY256BIS => 256, + PR_A::DivideBy4 => 4, + PR_A::DivideBy8 => 8, + PR_A::DivideBy16 => 16, + PR_A::DivideBy32 => 32, + PR_A::DivideBy64 => 64, + PR_A::DivideBy128 => 128, + PR_A::DivideBy256 | PR_A::DivideBy256bis => 256, } } @@ -71,7 +71,7 @@ impl IndependentWatchDog { /// Find and setup the next best prescaler and reload value for the selected timeout fn setup(&self, timeout: Milliseconds) { let mut reload: u32 = - timeout.integer() * LSI.integer() / into_division_value(PR_A::DIVIDEBY4); + timeout.integer().saturating_mul(LSI.integer()) / into_division_value(PR_A::DivideBy4); // Reload is potentially to high to be stored in the register. // The goal of this loop is to find the maximum possible reload value, diff --git a/testsuite/Cargo.toml b/testsuite/Cargo.toml index badb292ef..8c76ec91c 100644 --- a/testsuite/Cargo.toml +++ b/testsuite/Cargo.toml @@ -1,5 +1,5 @@ [package] -edition = "2018" +edition = "2021" name = "testsuite" publish = false version = "0.0.0" @@ -53,10 +53,10 @@ harness = false [dependencies] cfg-if = "1.0" -cortex-m = "0.7.0" -cortex-m-rt = "0.7.1" +cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] } +cortex-m-rt = "0.7.3" defmt = "0.3.0" -defmt-rtt = "0.3.0" +defmt-rtt = "0.4.0" defmt-test = "0.3.0" enumset = { version = "1.0.6" } # TODO: Set stm32f303xc as default, but make it overwritable diff --git a/testsuite/tests/adc.rs b/testsuite/tests/adc.rs index c6f537c15..87c17d518 100644 --- a/testsuite/tests/adc.rs +++ b/testsuite/tests/adc.rs @@ -80,11 +80,11 @@ mod tests { unsafe { (*pac::RCC::ptr()) .cfgr2 - .modify(|_, w| w.adc12pres().variant(pac::rcc::cfgr2::ADC12PRES_A::DIV64)) + .modify(|_, w| w.adc12pres().variant(pac::rcc::cfgr2::ADC12PRES_A::Div64)) }; dp.ADC1_2 .ccr - .modify(|_, w| w.ckmode().variant(pac::adc1_2::ccr::CKMODE_A::ASYNCHRONOUS)); + .modify(|_, w| w.ckmode().variant(pac::adc1_2::ccr::CKMODE_A::Asynchronous)); let mut common_adc = CommonAdc::new(dp.ADC1_2, &clocks, &mut rcc.ahb); defmt::info!( @@ -399,10 +399,6 @@ fn ADC1_2() { .modify(|_, w| w.eos().clear().eoc().clear()); (isr.eos(), isr.eoc()) }; - COUNTER - .0 - .fetch_add(u32::from(eos.bits()), Ordering::Acquire); - COUNTER - .1 - .fetch_add(u32::from(eoc.bits()), Ordering::Release); + COUNTER.0.fetch_add(u32::from(eos.bit()), Ordering::Acquire); + COUNTER.1.fetch_add(u32::from(eoc.bit()), Ordering::Release); } From 4455280edeef87d3bcc531860a3b4d58957e756c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Vi=C3=B6l?= Date: Sun, 19 Feb 2023 14:49:29 +0100 Subject: [PATCH 03/25] Fix changelog --- CHANGELOG.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01489d3af..fdb649794 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,9 +16,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Breaking changes -- Update `stm32f3` pac to v0.15.1 ([#282]) -- Update `bxcan` pac to v0.7.0 ([#282]) -- The MSRV was bumped to 1.59 ([#227]) +- Update `stm32f3` pac to v0.15.1 ([#335]) +- Update `bxcan` pac to v0.7.0 ([#335]) +- The MSRV was bumped to 1.59 ([#335]) ## [v0.9.1] - 2022-09-07 @@ -570,6 +570,7 @@ let clocks = rcc [defmt]: https://github.com/knurling-rs/defmt [filter]: https://defmt.ferrous-systems.com/filtering.html +[#335]: https://github.com/stm32-rs/stm32f3xx-hal/pull/335 [#322]: https://github.com/stm32-rs/stm32f3xx-hal/pull/322 [#318]: https://github.com/stm32-rs/stm32f3xx-hal/pull/318 [#317]: https://github.com/stm32-rs/stm32f3xx-hal/pull/317 From 1831d8fecdec3f9992973747f0adac999709f228 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 28 Dec 2022 20:38:34 +0100 Subject: [PATCH 04/25] use non-deprecated ..._opt chrono API The functions `from_ymd` and `from_hms` were deprecated in 0.4.23 in favour of the `_opt` variants --- src/rtc.rs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/rtc.rs b/src/rtc.rs index 2ab374fda..8f7e67fe0 100644 --- a/src/rtc.rs +++ b/src/rtc.rs @@ -179,11 +179,10 @@ impl DateTimeAccess for Rtc { let hours = hours_to_u8(self.hours()?)?; Ok( - NaiveDate::from_ymd(year.into(), month.into(), day.into()).and_hms( - hours.into(), - minutes.into(), - seconds.into(), - ), + NaiveDate::from_ymd_opt(year.into(), month.into(), day.into()) + .unwrap() + .and_hms_opt(hours.into(), minutes.into(), seconds.into()) + .unwrap(), ) } } @@ -333,11 +332,7 @@ impl Rtcc for Rtc { let minutes = self.minutes()?; let hours = hours_to_u8(self.hours()?)?; - Ok(NaiveTime::from_hms( - hours.into(), - minutes.into(), - seconds.into(), - )) + Ok(NaiveTime::from_hms_opt(hours.into(), minutes.into(), seconds.into()).unwrap()) } fn weekday(&mut self) -> Result { @@ -370,7 +365,7 @@ impl Rtcc for Rtc { let month = self.month()?; let year = self.year()?; - Ok(NaiveDate::from_ymd(year.into(), month.into(), day.into())) + Ok(NaiveDate::from_ymd_opt(year.into(), month.into(), day.into()).unwrap()) } } From e3005da37cd7a5c01c17ec707f1d4970bccc2210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Vi=C3=B6l?= Date: Sun, 19 Feb 2023 13:35:19 +0100 Subject: [PATCH 05/25] Add error handling --- src/rtc.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/rtc.rs b/src/rtc.rs index 8f7e67fe0..2bbd2212c 100644 --- a/src/rtc.rs +++ b/src/rtc.rs @@ -18,6 +18,8 @@ use rtcc::{DateTimeAccess, Datelike, Hours, NaiveDate, NaiveDateTime, NaiveTime, pub enum Error { /// Invalid input error InvalidInputData, + /// Invalid register data, failed to convert to rtcc Type + InvalidRtcData, } /// Real Time Clock peripheral @@ -178,12 +180,10 @@ impl DateTimeAccess for Rtc { let minutes = self.minutes()?; let hours = hours_to_u8(self.hours()?)?; - Ok( - NaiveDate::from_ymd_opt(year.into(), month.into(), day.into()) - .unwrap() - .and_hms_opt(hours.into(), minutes.into(), seconds.into()) - .unwrap(), - ) + NaiveDate::from_ymd_opt(year.into(), month.into(), day.into()) + .ok_or(Error::InvalidRtcData)? + .and_hms_opt(hours.into(), minutes.into(), seconds.into()) + .ok_or(Error::InvalidRtcData) } } @@ -332,7 +332,8 @@ impl Rtcc for Rtc { let minutes = self.minutes()?; let hours = hours_to_u8(self.hours()?)?; - Ok(NaiveTime::from_hms_opt(hours.into(), minutes.into(), seconds.into()).unwrap()) + NaiveTime::from_hms_opt(hours.into(), minutes.into(), seconds.into()) + .ok_or(Error::InvalidRtcData) } fn weekday(&mut self) -> Result { @@ -365,7 +366,7 @@ impl Rtcc for Rtc { let month = self.month()?; let year = self.year()?; - Ok(NaiveDate::from_ymd_opt(year.into(), month.into(), day.into()).unwrap()) + NaiveDate::from_ymd_opt(year.into(), month.into(), day.into()).ok_or(Error::InvalidRtcData) } } @@ -379,13 +380,13 @@ fn bcd2_encode(word: u32) -> Result<(u8, u8), Error> { let l = match (word / 10).try_into() { Ok(v) => v, Err(_) => { - return Err(Error::InvalidInputData); + return Err(Error::InvalidRtcData); } }; let r = match (word % 10).try_into() { Ok(v) => v, Err(_) => { - return Err(Error::InvalidInputData); + return Err(Error::InvalidRtcData); } }; From f163f88c1a51f0a2e6945510cb3ee495b77f5852 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Vi=C3=B6l?= Date: Sun, 4 Dec 2022 14:40:41 +0100 Subject: [PATCH 06/25] Deprecate Toggle use Switch --- CHANGELOG.md | 4 ++++ examples/serial_echo_rtic.rs | 8 ++++---- src/adc.rs | 24 ++++++++++++------------ src/gpio.rs | 10 +++++----- src/lib.rs | 36 +++++++++++++++++++++++++++++++----- src/serial.rs | 12 ++++++------ 6 files changed, 62 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fdb649794..042149322 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Update `stm32f3` pac to v0.15.1 ([#335]) - Update `bxcan` pac to v0.7.0 ([#335]) - The MSRV was bumped to 1.59 ([#335]) +- Deprecate `Toggle` enum and use `Switch` instead for better naming purposes + ([#334]) + - Add `impl From for Switch` to reduce churn. ## [v0.9.1] - 2022-09-07 @@ -571,6 +574,7 @@ let clocks = rcc [filter]: https://defmt.ferrous-systems.com/filtering.html [#335]: https://github.com/stm32-rs/stm32f3xx-hal/pull/335 +[#334]: https://github.com/stm32-rs/stm32f3xx-hal/pull/334 [#322]: https://github.com/stm32-rs/stm32f3xx-hal/pull/322 [#318]: https://github.com/stm32-rs/stm32f3xx-hal/pull/318 [#317]: https://github.com/stm32-rs/stm32f3xx-hal/pull/317 diff --git a/examples/serial_echo_rtic.rs b/examples/serial_echo_rtic.rs index 0e7aac75a..3b2cf71ec 100644 --- a/examples/serial_echo_rtic.rs +++ b/examples/serial_echo_rtic.rs @@ -19,7 +19,7 @@ mod app { pac, prelude::*, serial::{Event, Serial}, - Toggle, + Switch, }; use systick_monotonic::*; @@ -81,7 +81,7 @@ mod app { pins.1.internal_pull_up(&mut gpioa.pupdr, true); let mut serial: SerialType = Serial::new(cx.device.USART1, pins, 19200.Bd(), clocks, &mut rcc.apb2); - serial.configure_interrupt(Event::ReceiveDataRegisterNotEmpty, Toggle::On); + serial.configure_interrupt(Event::ReceiveDataRegisterNotEmpty, Switch::On); rprintln!("post init"); @@ -100,12 +100,12 @@ mod app { if serial.is_event_triggered(Event::ReceiveDataRegisterNotEmpty) { dir.set_high().unwrap(); - serial.configure_interrupt(Event::ReceiveDataRegisterNotEmpty, Toggle::Off); + serial.configure_interrupt(Event::ReceiveDataRegisterNotEmpty, Switch::Off); match serial.read() { Ok(byte) => { serial.write(byte).unwrap(); rprintln!("{:?}", char::from_u32(byte.into()).unwrap_or('?')); - serial.configure_interrupt(Event::TransmissionComplete, Toggle::On); + serial.configure_interrupt(Event::TransmissionComplete, Switch::On); } Err(_error) => rprintln!("irq error"), }; diff --git a/src/adc.rs b/src/adc.rs index e80c84f6c..a8cd9aac0 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -30,7 +30,7 @@ use crate::{ pac::{self, adc1, Interrupt}, rcc::{Clocks, Enable, AHB}, time::{duration::Microseconds, fixed_point::FixedPoint, rate::Hertz}, - Toggle, + Switch, }; use crate::pac::{adc1_2, adc1_2::ccr::CKMODE_A}; @@ -493,7 +493,7 @@ where // TODO(Sh3Rm4n): Would about concurrent calibrations between related ADCs? // int_ref: &mut VoltageInternalReference, ) { - self.configure_voltage_regulator(Toggle::On, clocks); + self.configure_voltage_regulator(Switch::On, clocks); self.reg .cr @@ -512,21 +512,21 @@ where asm::delay(cpu_cycles); // When the internal voltage regulator is disabled, the internal analog calibration is kept - self.configure_voltage_regulator(Toggle::Off, clocks); + self.configure_voltage_regulator(Switch::Off, clocks); } /// Enable the interal voltage generator Blocks until regulator is enabled. - fn configure_voltage_regulator(&mut self, toggle: impl Into, clocks: &Clocks) { + fn configure_voltage_regulator(&mut self, toggle: impl Into, clocks: &Clocks) { let already_on = self.reg.cr.read().advregen().is_enabled(); let toggle = toggle.into(); self.reg.cr.modify(|_, w| w.advregen().intermediate()); self.reg.cr.modify(|_, w| { w.advregen().variant(match toggle { - Toggle::On => adc1::cr::ADVREGEN_A::Enabled, - Toggle::Off => adc1::cr::ADVREGEN_A::Disabled, + Switch::On => adc1::cr::ADVREGEN_A::Enabled, + Switch::Off => adc1::cr::ADVREGEN_A::Disabled, }) }); - if toggle == Toggle::On && !already_on { + if toggle == Switch::On && !already_on { let wait = MAX_ADVREGEN_STARTUP.integer() * clocks.sysclk().integer() * ::SCALING_FACTOR; @@ -1103,20 +1103,20 @@ where /// Enable the interrupt for the specified [`Event`]. #[inline] pub fn enable_interrupt(&mut self, event: Event) { - self.configure_interrupt(event, Toggle::On); + self.configure_interrupt(event, Switch::On); } /// Disable the interrupt for the specified [`Event`]. #[inline] pub fn disable_interrupt(&mut self, event: Event) { - self.configure_interrupt(event, Toggle::Off); + self.configure_interrupt(event, Switch::Off); } /// Enable or disable the interrupt for the specified [`Event`]. #[inline] - pub fn configure_interrupt(&mut self, event: Event, enable: impl Into) { - // Do a round way trip to be convert Into -> bool - let enable: Toggle = enable.into(); + pub fn configure_interrupt(&mut self, event: Event, enable: impl Into) { + // Do a round way trip to be convert Into -> bool + let enable: Switch = enable.into(); let enable: bool = enable.into(); match event { Event::AdcReady => self.reg.ier.modify(|_, w| w.adrdyie().bit(enable)), diff --git a/src/gpio.rs b/src/gpio.rs index e32bc10da..1ff27c063 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -66,7 +66,7 @@ use crate::{ hal::digital::v2::OutputPin, pac::{Interrupt, EXTI}, rcc::AHB, - Toggle, + Switch, }; use crate::hal::digital::v2::{toggleable, InputPin, StatefulOutputPin}; @@ -623,10 +623,10 @@ where /// /// Remeber to also configure the interrupt pin on /// the SysCfg site, with [`crate::syscfg::SysCfg::select_exti_interrupt_source()`] - pub fn configure_interrupt(&mut self, exti: &mut EXTI, enable: impl Into) { + pub fn configure_interrupt(&mut self, exti: &mut EXTI, enable: impl Into) { const BITWIDTH: u8 = 1; - let enable: Toggle = enable.into(); + let enable: Switch = enable.into(); let enable: bool = enable.into(); let index = self.index.index(); @@ -642,12 +642,12 @@ where /// Remeber to also configure the interrupt pin on /// the SysCfg site, with [`crate::syscfg::SysCfg::select_exti_interrupt_source()`] pub fn enable_interrupt(&mut self, exti: &mut EXTI) { - self.configure_interrupt(exti, Toggle::On) + self.configure_interrupt(exti, Switch::On) } /// Disable external interrupts from this pin pub fn disable_interrupt(&mut self, exti: &mut EXTI) { - self.configure_interrupt(exti, Toggle::Off) + self.configure_interrupt(exti, Switch::Off) } /// Clear the interrupt pending bit for this pin diff --git a/src/lib.rs b/src/lib.rs index d4b67cf0b..1c70cac91 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -274,6 +274,8 @@ cfg_if! { // TODO: Maybe move to some mod like "util"? #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[deprecated(since = "0.10.0", note = "Use Switch instead")] +#[allow(deprecated)] pub enum Toggle { /// Toggle something on / enable a thing. On, @@ -281,17 +283,41 @@ pub enum Toggle { Off, } -impl From for bool { +/// Switch something on or off. +/// +/// Convenience enum and wrapper around a bool, which more explicit about the intention to enable +/// or disable something, in comparison to `true` or `false`. +// TODO: Maybe move to some mod like "util"? +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Switch { + /// Switch something on / enable a thing. + On, + /// Switch something off / disable a thing. + Off, +} + +#[allow(deprecated)] +impl From for Switch { fn from(toggle: Toggle) -> Self { - matches!(toggle, Toggle::On) + match toggle { + Toggle::On => Switch::On, + Toggle::Off => Switch::Off, + } + } +} + +impl From for bool { + fn from(switch: Switch) -> Self { + matches!(switch, Switch::On) } } -impl From for Toggle { +impl From for Switch { fn from(b: bool) -> Self { match b { - true => Toggle::On, - false => Toggle::Off, + true => Switch::On, + false => Switch::Off, } } } diff --git a/src/serial.rs b/src/serial.rs index db231dd9c..2e9a741a2 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -24,7 +24,7 @@ use crate::{ }, rcc::{self, Clocks}, time::rate::*, - Toggle, + Switch, }; #[allow(unused_imports)] @@ -623,20 +623,20 @@ where /// Enable the interrupt for the specified [`Event`]. #[inline] pub fn enable_interrupt(&mut self, event: Event) { - self.configure_interrupt(event, Toggle::On); + self.configure_interrupt(event, Switch::On); } /// Disable the interrupt for the specified [`Event`]. #[inline] pub fn disable_interrupt(&mut self, event: Event) { - self.configure_interrupt(event, Toggle::Off); + self.configure_interrupt(event, Switch::Off); } /// Enable or disable the interrupt for the specified [`Event`]. #[inline] - pub fn configure_interrupt(&mut self, event: Event, enable: impl Into) { - // Do a round way trip to be convert Into -> bool - let enable: Toggle = enable.into(); + pub fn configure_interrupt(&mut self, event: Event, enable: impl Into) { + // Do a round way trip to be convert Into -> bool + let enable: Switch = enable.into(); let enable: bool = enable.into(); match event { Event::TransmitDataRegisterEmtpy => self.usart.cr1.modify(|_, w| w.txeie().bit(enable)), From 574902323fd3860e7c8722a2d9f1b8820ec472dc Mon Sep 17 00:00:00 2001 From: Rafael Bachmann Date: Sun, 1 Jan 2023 11:35:43 +0100 Subject: [PATCH 07/25] Minor clippy and deprecation fixes --- Cargo.toml | 93 +++++++++++++++++++---------------------- src/serial.rs | 4 +- testsuite/tests/uart.rs | 3 +- 3 files changed, 46 insertions(+), 54 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 846c4c4ac..ce0f83cdf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ edition = "2021" authors = [ "Dylan Frankland ", "Sh3Rm4n ", - "Jan Teske " + "Jan Teske ", ] categories = ["embedded", "hardware-support", "no-std"] description = "Peripheral access API for STM32F3 series microcontrollers" @@ -14,26 +14,20 @@ readme = "README.md" repository = "https://github.com/stm32-rs/stm32f3xx-hal" documentation = "https://docs.rs/stm32f3xx-hal" version = "0.9.1" -exclude = [ - "codegen", - ".markdownlint.yml" -] +exclude = ["codegen", ".markdownlint.yml"] resolver = "2" rust-version = "1.59" -[workspace] -members = [ - ".", - "testsuite", - "codegen" -] - [package.metadata.docs.rs] features = ["stm32f303xc", "rt", "usb", "can", "enumset"] targets = ["thumbv7em-none-eabihf"] rustc-args = ["--cfg", "docsrs"] +[workspace] +members = [".", "testsuite", "codegen"] + [dependencies] +bxcan = { version = "0.7.0", optional = true } cfg-if = "1.0.0" cortex-m = "0.7.4" cortex-m-rt = "0.7.3" @@ -41,47 +35,50 @@ defmt = { version = ">=0.2.3, <0.4.0", optional = true } embedded-dma = "0.2.0" embedded-hal = { version = "0.2.5", features = ["unproven"] } embedded-time = "0.12.0" +enumset = { version = "1.0.6", optional = true } nb = "1.0.0" paste = "1.0.5" rtcc = { version = "0.3.0", optional = true } -stm32f3 = { version = "0.15.1", default-features = false } -bxcan = { version = "0.7.0", optional = true } stm32-usbd = { version = "0.6.0", optional = true } +stm32f3 = { version = "0.15.1", default-features = false } void = { version = "1.0.2", default-features = false } -enumset = { version = "1.0.6", optional = true} [dev-dependencies] +cortex-m-rtic = "1.0" cortex-m-semihosting = "0.5.0" defmt = "0.3.0" defmt-rtt = "0.4.0" defmt-test = "0.3.0" panic-probe = "0.3.0" -panic-semihosting = "0.6.0" -usbd-serial = "0.1.1" -usb-device = "0.2.8" -cortex-m-rtic = "1.0" -systick-monotonic = "1.0" panic-rtt-target = { version = "0.1", features = ["cortex-m"] } +panic-semihosting = "0.6.0" rtt-target = { version = "0.3.1", features = ["cortex-m"] } +systick-monotonic = "1.0" +usb-device = "0.2.8" +usbd-serial = "0.1.1" [build-dependencies] slice-group-by = "0.3.0" [features] +can = ["bxcan"] default = ["rt", "ld", "usb", "can", "rtc", "enumset"] +defmt-debug = ["defmt"] + +defmt-default = ["defmt"] +defmt-error = ["defmt"] +defmt-info = ["defmt"] +defmt-trace = ["defmt"] +defmt-warn = ["defmt"] device-selected = [] direct-call-deprecated = [] -ld = [] -rt = ["stm32f3/rt"] -can = ["bxcan"] -usb = ["stm32-usbd"] -rtc = ["rtcc"] -svd-f301 = ["stm32f3/stm32f301"] -svd-f302 = ["stm32f3/stm32f302"] -svd-f303 = ["stm32f3/stm32f303"] -svd-f373 = ["stm32f3/stm32f373"] -svd-f3x4 = ["stm32f3/stm32f3x4"] +gpio-f302 = [] +gpio-f303 = [] +gpio-f303e = [] +gpio-f333 = [] +gpio-f373 = [] +ld = [] mem-4 = [] mem-6 = [] @@ -90,20 +87,14 @@ mem-b = [] mem-c = [] mem-d = [] mem-e = [] - -gpio-f302 = [] -gpio-f303 = [] -gpio-f303e = [] -gpio-f333 = [] -gpio-f373 = [] +rt = ["stm32f3/rt"] +rtc = ["rtcc"] # Any changes here should be mirrored in README.md, build.rs, src/lib.rs, and # .github/workflows/ci.yml. stm32f301 = ["svd-f301", "direct-call-deprecated"] stm32f301x6 = ["stm32f301", "mem-6", "gpio-f302", "device-selected"] stm32f301x8 = ["stm32f301", "mem-8", "gpio-f302", "device-selected"] -stm32f318 = ["svd-f301", "direct-call-deprecated"] -stm32f318x8 = ["stm32f318", "mem-8", "gpio-f302", "device-selected"] stm32f302 = ["svd-f302", "direct-call-deprecated"] stm32f302x6 = ["stm32f302", "mem-6", "gpio-f302", "device-selected"] stm32f302x8 = ["stm32f302", "mem-8", "gpio-f302", "device-selected"] @@ -118,29 +109,31 @@ stm32f303xb = ["stm32f303", "mem-b", "gpio-f303", "device-selected"] stm32f303xc = ["stm32f303", "mem-c", "gpio-f303", "device-selected"] stm32f303xd = ["stm32f303", "mem-d", "gpio-f303e", "device-selected"] stm32f303xe = ["stm32f303", "mem-e", "gpio-f303e", "device-selected"] +stm32f318 = ["svd-f301", "direct-call-deprecated"] +stm32f318x8 = ["stm32f318", "mem-8", "gpio-f302", "device-selected"] stm32f328 = ["svd-f303", "direct-call-deprecated"] stm32f328x8 = ["stm32f328", "mem-8", "gpio-f333", "device-selected"] +stm32f334 = ["svd-f3x4", "direct-call-deprecated"] +stm32f334x4 = ["stm32f334", "mem-4", "gpio-f333", "device-selected"] +stm32f334x6 = ["stm32f334", "mem-6", "gpio-f333", "device-selected"] +stm32f334x8 = ["stm32f334", "mem-8", "gpio-f333", "device-selected"] stm32f358 = ["svd-f303", "direct-call-deprecated"] stm32f358xc = ["stm32f358", "mem-c", "gpio-f303", "device-selected"] -stm32f398 = ["svd-f303", "direct-call-deprecated"] -stm32f398xe = ["stm32f398", "mem-e", "gpio-f303e", "device-selected"] stm32f373 = ["svd-f373", "direct-call-deprecated"] stm32f373x8 = ["stm32f373", "mem-8", "gpio-f373", "device-selected"] stm32f373xb = ["stm32f373", "mem-b", "gpio-f373", "device-selected"] stm32f373xc = ["stm32f373", "mem-c", "gpio-f373", "device-selected"] stm32f378 = ["svd-f373", "direct-call-deprecated"] stm32f378xc = ["stm32f378", "mem-c", "gpio-f373", "device-selected"] -stm32f334 = ["svd-f3x4", "direct-call-deprecated"] -stm32f334x4 = ["stm32f334", "mem-4", "gpio-f333", "device-selected"] -stm32f334x6 = ["stm32f334", "mem-6", "gpio-f333", "device-selected"] -stm32f334x8 = ["stm32f334", "mem-8", "gpio-f333", "device-selected"] +stm32f398 = ["svd-f303", "direct-call-deprecated"] +stm32f398xe = ["stm32f398", "mem-e", "gpio-f303e", "device-selected"] -defmt-default = ["defmt"] -defmt-trace = ["defmt"] -defmt-debug = ["defmt"] -defmt-info = ["defmt"] -defmt-warn = ["defmt"] -defmt-error = ["defmt"] +svd-f301 = ["stm32f3/stm32f301"] +svd-f302 = ["stm32f3/stm32f302"] +svd-f303 = ["stm32f3/stm32f303"] +svd-f373 = ["stm32f3/stm32f373"] +svd-f3x4 = ["stm32f3/stm32f3x4"] +usb = ["stm32-usbd"] # cargo build/run [profile.dev] diff --git a/src/serial.rs b/src/serial.rs index db231dd9c..8c01ed502 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -579,7 +579,7 @@ where /// /// ## Embedded HAL /// - /// To have a more managed way to read from the serial use the [`embeded_hal::serial::Read`] + /// To have a more managed way to read from the serial use the [`embedded_hal::serial::Read`] /// trait implementation. #[doc(alias = "RDR")] pub fn read_data_register(&self) -> Option { @@ -947,7 +947,7 @@ where /// up to the interrupt handler. /// /// To read out the content of the read register without internal error handling, use - /// [`Serial::read()`]. + /// [`embedded_hal::serial::Read`]. /// ... // -> According to this API it should be skipped. fn read(&mut self) -> nb::Result { diff --git a/testsuite/tests/uart.rs b/testsuite/tests/uart.rs index a48946b35..31fe5c219 100644 --- a/testsuite/tests/uart.rs +++ b/testsuite/tests/uart.rs @@ -28,7 +28,6 @@ use hal::interrupt; use defmt::{assert, assert_eq, unwrap}; -use core::array::IntoIter; use core::sync::atomic::{AtomicBool, Ordering}; static INTERRUPT_FIRED: AtomicBool = AtomicBool::new(false); @@ -183,7 +182,7 @@ mod tests { fn send_receive_split(state: &mut super::State) { let (mut tx, mut rx) = unwrap!(state.serial1.take()).split(); - for i in IntoIter::new(TEST_MSG) { + for i in TEST_MSG { defmt::unwrap!(nb::block!(tx.write(i))); let c = unwrap!(nb::block!(rx.read())); assert_eq!(c, i); From 604e2993f13d261ffb0007ad85a99c116a50c4a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Vi=C3=B6l?= Date: Sun, 19 Feb 2023 21:15:29 +0100 Subject: [PATCH 08/25] Add missing adc channels --- CHANGELOG.md | 5 +++++ codegen/tools/adc_channel.py | 31 ++++++++++++++++++++++++++++++- codegen/tools/adc_channel.sh | 8 +++++--- src/adc/channel.rs | 27 +++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 042149322..ac29ba6d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ([#334]) - Add `impl From for Switch` to reduce churn. +### Added + +- Add missing ADC channels ([#337]) + ## [v0.9.1] - 2022-09-07 ### Added @@ -573,6 +577,7 @@ let clocks = rcc [defmt]: https://github.com/knurling-rs/defmt [filter]: https://defmt.ferrous-systems.com/filtering.html +[#337]: https://github.com/stm32-rs/stm32f3xx-hal/pull/337 [#335]: https://github.com/stm32-rs/stm32f3xx-hal/pull/335 [#334]: https://github.com/stm32-rs/stm32f3xx-hal/pull/334 [#322]: https://github.com/stm32-rs/stm32f3xx-hal/pull/322 diff --git a/codegen/tools/adc_channel.py b/codegen/tools/adc_channel.py index 3c5ef15ef..db1cd53b0 100644 --- a/codegen/tools/adc_channel.py +++ b/codegen/tools/adc_channel.py @@ -38,6 +38,35 @@ "stm32f334": r".*STM32F334.*\.xml", } +def channel_to_id(channel: int) -> str: + id_ = "Id::" + match channel: + case 0: + return id_ + "Zero" + case 1: + return id_ + "One" + case 2: + return id_ + "Two" + case 3: + return id_ + "Three" + case 4: return id_ + "Four" + case 5: return id_ + "Five" + case 6: return id_ + "Six" + case 7: return id_ + "Seven" + case 8: return id_ + "Eight" + case 9: return id_ + "Nine" + case 10: return id_ + "Ten" + case 11: return id_ + "Eleven" + case 12: return id_ + "Twelve" + case 13: return id_ + "Thirteen" + case 14: return id_ + "Fourteen" + case 15: return id_ + "Fifteen" + case 16: return id_ + "Sixteen" + case 17: return id_ + "Seventeen" + case 18: return id_ + "Eighteen" + + raise Exception(f"Channel: \"{channel}\" does not exists") + def main(): chip_post = {} @@ -52,7 +81,7 @@ def main(): (adc, channel) = pin[i].split("_") except IndexError: continue - adc_list.append((adc, int(channel))) + adc_list.append((adc, channel_to_id(int(channel)))) pins.append((pin[0], adc_list)) chip_post[chip_name] = pins diff --git a/codegen/tools/adc_channel.sh b/codegen/tools/adc_channel.sh index 09b717351..d9af96aca 100644 --- a/codegen/tools/adc_channel.sh +++ b/codegen/tools/adc_channel.sh @@ -14,9 +14,11 @@ for xml in /opt/stm32cubemx/db/mcu/STM32F3*.xml; do xq '.Mcu.Pin[] | select(.Signal[]?."@Name"? | startswith("ADC")) | [."@Name", (.Signal[]? | select(."@Name" | startswith("ADC")))."@Name"] - | @csv' --raw-output < $xml \ - | rg -v EXTI \ - | rg -v OSC32 \ + | @csv' --raw-output \ + < "$xml" \ + | sed -e 's/,"ADC[[:digit:]]_EXTI[[:digit:]]\+"//g' \ + | sed -e 's/-OSC32_OUT//g' \ + | rg 'IN' \ | rg -v 'jq:' \ | sed 's/IN//g' \ | sort -u \ diff --git a/src/adc/channel.rs b/src/adc/channel.rs index f18ea3339..53387d073 100644 --- a/src/adc/channel.rs +++ b/src/adc/channel.rs @@ -152,6 +152,7 @@ cfg_if::cfg_if! { (PA6, [(ADC1, Id::Ten)]), (PA7, [(ADC1, Id::Fifteen)]), (PB0, [(ADC1, Id::Eleven)]), + (PB11, [(ADC1, Id::Fourteen)]), (PB13, [(ADC1, Id::Thirteen)]), (PB1, [(ADC1, Id::Twelve)]), (PC0, [(ADC1, Id::Six)]), @@ -169,6 +170,7 @@ cfg_if::cfg_if! { (PA6, [(ADC1, Id::Ten)]), (PA7, [(ADC1, Id::Fifteen)]), (PB0, [(ADC1, Id::Eleven)]), + (PB11, [(ADC1, Id::Fourteen)]), (PB13, [(ADC1, Id::Thirteen)]), (PB1, [(ADC1, Id::Twelve)]), (PC0, [(ADC1, Id::Six)]), @@ -220,6 +222,7 @@ cfg_if::cfg_if! { channel!([ (PA0, [(ADC1, Id::One)]), (PA1, [(ADC1, Id::Two)]), + (PA2, [(ADC1, Id::Three)]), (PA3, [(ADC1, Id::Four)]), (PA4, [(ADC2, Id::One)]), (PA5, [(ADC2, Id::Two)]), @@ -229,9 +232,12 @@ cfg_if::cfg_if! { (PB12, [(ADC4, Id::Three)]), (PB13, [(ADC3, Id::Five)]), (PB14, [(ADC4, Id::Four)]), + (PB15, [(ADC4, Id::Five)]), (PB1, [(ADC3, Id::One)]), + (PB2, [(ADC2, Id::Twelve)]), (PC0, [(ADC1, Id::Six), (ADC2, Id::Six)]), (PC1, [(ADC1, Id::Seven), (ADC2, Id::Seven)]), + (PC2, [(ADC1, Id::Eight), (ADC2, Id::Eight)]), (PC3, [(ADC1, Id::Nine), (ADC2, Id::Nine)]), (PC4, [(ADC2, Id::Five)]), (PC5, [(ADC2, Id::Eleven)]), @@ -247,6 +253,7 @@ cfg_if::cfg_if! { (PA5, [(ADC2, Id::Two)]), (PA6, [(ADC2, Id::Three)]), (PA7, [(ADC2, Id::Four)]), + (PB11, [(ADC1, Id::Fourteen), (ADC2, Id::Fourteen)]), (PB2, [(ADC2, Id::Twelve)]), (PC0, [(ADC1, Id::Six), (ADC2, Id::Six)]), (PC1, [(ADC1, Id::Seven), (ADC2, Id::Seven)]), @@ -261,29 +268,37 @@ cfg_if::cfg_if! { channel!([ (PA0, [(ADC1, Id::One)]), (PA1, [(ADC1, Id::Two)]), + (PA2, [(ADC1, Id::Three)]), (PA3, [(ADC1, Id::Four)]), (PA4, [(ADC2, Id::One)]), (PA5, [(ADC2, Id::Two)]), (PA6, [(ADC2, Id::Three)]), (PA7, [(ADC2, Id::Four)]), (PB0, [(ADC3, Id::Twelve)]), + (PB11, [(ADC1, Id::Fourteen), (ADC2, Id::Fourteen)]), (PB12, [(ADC4, Id::Three)]), (PB13, [(ADC3, Id::Five)]), (PB14, [(ADC4, Id::Four)]), + (PB15, [(ADC4, Id::Five)]), (PB1, [(ADC3, Id::One)]), + (PB2, [(ADC2, Id::Twelve)]), (PC0, [(ADC1, Id::Six), (ADC2, Id::Six)]), (PC1, [(ADC1, Id::Seven), (ADC2, Id::Seven)]), + (PC2, [(ADC1, Id::Eight), (ADC2, Id::Eight)]), (PC3, [(ADC1, Id::Nine), (ADC2, Id::Nine)]), (PC4, [(ADC2, Id::Five)]), (PC5, [(ADC2, Id::Eleven)]), (PD10, [(ADC3, Id::Seven), (ADC4, Id::Seven)]), + (PD11, [(ADC3, Id::Eight), (ADC4, Id::Eight)]), (PD12, [(ADC3, Id::Nine), (ADC4, Id::Nine)]), (PD13, [(ADC3, Id::Ten), (ADC4, Id::Ten)]), (PD14, [(ADC3, Id::Eleven), (ADC4, Id::Eleven)]), (PD9, [(ADC4, Id::Thirteen)]), + (PE11, [(ADC3, Id::Fifteen)]), (PE12, [(ADC3, Id::Sixteen)]), (PE7, [(ADC3, Id::Thirteen)]), (PE8, [(ADC3, Id::Six), (ADC4, Id::Six)]), + (PF2, [(ADC1, Id::Ten), (ADC2, Id::Ten)]), ]); } else if #[cfg(feature = "stm32f328")] { channel!([ @@ -306,6 +321,7 @@ cfg_if::cfg_if! { channel!([ (PA0, [(ADC1, Id::One)]), (PA1, [(ADC1, Id::Two)]), + (PA2, [(ADC1, Id::Three)]), (PA3, [(ADC1, Id::Four)]), (PA4, [(ADC2, Id::One)]), (PA5, [(ADC2, Id::Two)]), @@ -315,9 +331,11 @@ cfg_if::cfg_if! { (PB12, [(ADC4, Id::Three)]), (PB13, [(ADC3, Id::Five)]), (PB14, [(ADC4, Id::Four)]), + (PB15, [(ADC4, Id::Five)]), (PB1, [(ADC3, Id::One)]), (PC0, [(ADC1, Id::Six), (ADC2, Id::Six)]), (PC1, [(ADC1, Id::Seven), (ADC2, Id::Seven)]), + (PC2, [(ADC1, Id::Eight), (ADC2, Id::Eight)]), (PC3, [(ADC1, Id::Nine), (ADC2, Id::Nine)]), (PC4, [(ADC2, Id::Five)]), (PC5, [(ADC2, Id::Eleven)]), @@ -327,34 +345,42 @@ cfg_if::cfg_if! { channel!([ (PA0, [(ADC1, Id::One)]), (PA1, [(ADC1, Id::Two)]), + (PA2, [(ADC1, Id::Three)]), (PA3, [(ADC1, Id::Four)]), (PA4, [(ADC2, Id::One)]), (PA5, [(ADC2, Id::Two)]), (PA6, [(ADC2, Id::Three)]), (PA7, [(ADC2, Id::Four)]), (PB0, [(ADC3, Id::Twelve)]), + (PB11, [(ADC1, Id::Fourteen), (ADC2, Id::Fourteen)]), (PB12, [(ADC4, Id::Three)]), (PB13, [(ADC3, Id::Five)]), (PB14, [(ADC4, Id::Four)]), + (PB15, [(ADC4, Id::Five)]), (PB1, [(ADC3, Id::One)]), (PC0, [(ADC1, Id::Six), (ADC2, Id::Six)]), (PC1, [(ADC1, Id::Seven), (ADC2, Id::Seven)]), + (PC2, [(ADC1, Id::Eight), (ADC2, Id::Eight)]), (PC3, [(ADC1, Id::Nine), (ADC2, Id::Nine)]), (PC4, [(ADC2, Id::Five)]), (PC5, [(ADC2, Id::Eleven)]), (PD10, [(ADC3, Id::Seven), (ADC4, Id::Seven)]), + (PD11, [(ADC3, Id::Eight), (ADC4, Id::Eight)]), (PD12, [(ADC3, Id::Nine), (ADC4, Id::Nine)]), (PD13, [(ADC3, Id::Ten), (ADC4, Id::Ten)]), (PD14, [(ADC3, Id::Eleven), (ADC4, Id::Eleven)]), (PD8, [(ADC4, Id::Twelve)]), (PD9, [(ADC4, Id::Thirteen)]), (PE10, [(ADC3, Id::Fourteen)]), + (PE11, [(ADC3, Id::Fifteen)]), (PE12, [(ADC3, Id::Sixteen)]), (PE13, [(ADC3, Id::Three)]), (PE14, [(ADC4, Id::One)]), + (PE15, [(ADC4, Id::Two)]), (PE7, [(ADC3, Id::Thirteen)]), (PE8, [(ADC3, Id::Six), (ADC4, Id::Six)]), (PE9, [(ADC3, Id::Two)]), + (PF2, [(ADC1, Id::Ten), (ADC2, Id::Ten)]), ]); } else if #[cfg(feature = "stm32f373")] { channel!([ @@ -382,6 +408,7 @@ cfg_if::cfg_if! { (PB12, [(ADC2, Id::Thirteen)]), (PB13, [(ADC1, Id::Thirteen)]), (PB14, [(ADC2, Id::Fourteen)]), + (PB15, [(ADC2, Id::Fifteen)]), (PB1, [(ADC1, Id::Twelve)]), (PB2, [(ADC2, Id::Twelve)]), (PC3, [(ADC1, Id::Nine), (ADC2, Id::Nine)]), From 87ba9d035eabe1766c6e5ff87d484551f44ed674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Vi=C3=B6l?= Date: Sun, 19 Feb 2023 23:00:11 +0100 Subject: [PATCH 09/25] Fix timer panic on high frequencies Make the calculation more robust against overflows and wrong settings --- CHANGELOG.md | 2 ++ src/timer.rs | 18 +++++++++++------- testsuite/tests/timer.rs | 14 +++++++++----- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ac29ba6d7..c045a14bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Missing `MosiPin` impl for `PB5` ([#322]) - Read valid data from data register even if reception of next character has started ([#317]) +- Fix wrong timer frequency calculation and unexpected panics ([#338]) ## [v0.9.0] - 2022-03-06 @@ -577,6 +578,7 @@ let clocks = rcc [defmt]: https://github.com/knurling-rs/defmt [filter]: https://defmt.ferrous-systems.com/filtering.html +[#338]: https://github.com/stm32-rs/stm32f3xx-hal/pull/338 [#337]: https://github.com/stm32-rs/stm32f3xx-hal/pull/337 [#335]: https://github.com/stm32-rs/stm32f3xx-hal/pull/335 [#334]: https://github.com/stm32-rs/stm32f3xx-hal/pull/334 diff --git a/src/timer.rs b/src/timer.rs index e776a0516..3bda5d835 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -10,8 +10,6 @@ //! //! [examples/adc.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.9.1/examples/adc.rs -use core::convert::{From, TryFrom}; - use crate::pac::{DCB, DWT}; #[cfg(feature = "enumset")] use enumset::{EnumSet, EnumSetType}; @@ -279,13 +277,19 @@ where let timeout: Self::Time = timeout.into(); let clock = TIM::clock(&self.clocks); - let ticks = clock.integer() * *timeout.scaling_factor() * timeout.integer(); + let ticks = clock.integer().saturating_mul(timeout.integer()) * *timeout.scaling_factor(); - let psc = crate::unwrap!(u16::try_from((ticks - 1) / (1 << 16)).ok()); - self.tim.set_psc(psc); + let psc: u32 = (ticks.saturating_sub(1)) / (1 << 16); + self.tim.set_psc(crate::unwrap!(u16::try_from(psc).ok())); - let arr = crate::unwrap!(u16::try_from(ticks / u32::from(psc + 1)).ok()); - self.tim.set_arr(arr); + let mut arr = ticks / psc.saturating_add(1); + // If the set frequency is to high to get a meaningful timer resolution, + // set arr to one, so the timer can at least do something and code waiting + // on it is not stuck. + if psc == 0 && arr == 0 { + arr = 1; + } + self.tim.set_arr(crate::unwrap!(u16::try_from(arr).ok())); // Ensure that the below procedure does not create an unexpected interrupt. let is_update_interrupt_active = self.is_interrupt_configured(Event::Update); diff --git a/testsuite/tests/timer.rs b/testsuite/tests/timer.rs index 9e0a61dbe..e142eea31 100644 --- a/testsuite/tests/timer.rs +++ b/testsuite/tests/timer.rs @@ -77,7 +77,8 @@ mod tests { defmt::trace!("{}", state.mono_timer); let freqcyc = state.mono_timer.frequency().integer(); - let durations: [duration::Generic; 5] = [ + let durations: [duration::Generic; 6] = [ + 100.nanoseconds().into(), 100.microseconds().into(), 1.milliseconds().into(), 100.milliseconds().into(), @@ -86,11 +87,12 @@ mod tests { // 100.seconds().into(), ]; - for dur in durations { + for (i, dur) in durations.into_iter().enumerate() { defmt::trace!("Duration: {}", defmt::Debug2Format(&dur)); timer.start(dur); - assert!(!timer.is_event_triggered(Event::Update)); + // Wait one cycle, so the start function overhead is not that big. + unwrap!(nb::block!(timer.wait()).ok()); // call instant after start, because starting the timer is the last thing done in the // start function, and therefor no overhead is added to the timing. let instant = state.mono_timer.now(); @@ -106,8 +108,10 @@ mod tests { let deviation = (ratio - 1.).abs(); // Deviation is high for smaller timer duration. Higher duration are pretty accurate. - // TODO: Maybe the allowed deviation should changed depending on the duration? - defmt::assert!(deviation < 11e-02); + defmt::trace!("deviation: {}", deviation); + if i > 0 { + defmt::assert!(deviation < 1e-02); + } } state.timer = Some(timer); } From 7fb37050af355a6411c8904a089621ddf82237ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Vi=C3=B6l?= Date: Mon, 20 Feb 2023 08:52:08 +0100 Subject: [PATCH 10/25] Fix changelog --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c045a14bb..cf3c84316 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Add missing ADC channels ([#337]) +### Fixed + +- Fix wrong timer frequency calculation and unexpected panics ([#338]) + ## [v0.9.1] - 2022-09-07 ### Added @@ -38,7 +42,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Missing `MosiPin` impl for `PB5` ([#322]) - Read valid data from data register even if reception of next character has started ([#317]) -- Fix wrong timer frequency calculation and unexpected panics ([#338]) ## [v0.9.0] - 2022-03-06 From 96d51e2e2fdc6939f1fafc36bc48163479bfce7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Vi=C3=B6l?= Date: Mon, 20 Feb 2023 10:18:12 +0100 Subject: [PATCH 11/25] Sync with backport release --- CHANGELOG.md | 15 +++++++++++++++ Cargo.toml | 2 +- README.md | 15 +++++++-------- release.toml | 2 +- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf3c84316..32d6df1fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,20 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Fix wrong timer frequency calculation and unexpected panics ([#338]) +## [v0.9.2] - 2023-02-20 + +### Added + +- Add missing ADC channels ([#337]) + +### Fixed + +- Fix wrong timer frequency calculation and unexpected panics ([#338]) + +### Changed + +- The MSRV was bumped to 1.59 ([#340]) + ## [v0.9.1] - 2022-09-07 ### Added @@ -581,6 +595,7 @@ let clocks = rcc [defmt]: https://github.com/knurling-rs/defmt [filter]: https://defmt.ferrous-systems.com/filtering.html +[#340]: https://github.com/stm32-rs/stm32f3xx-hal/pull/340 [#338]: https://github.com/stm32-rs/stm32f3xx-hal/pull/338 [#337]: https://github.com/stm32-rs/stm32f3xx-hal/pull/337 [#335]: https://github.com/stm32-rs/stm32f3xx-hal/pull/335 diff --git a/Cargo.toml b/Cargo.toml index ce0f83cdf..849ad150f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ name = "stm32f3xx-hal" readme = "README.md" repository = "https://github.com/stm32-rs/stm32f3xx-hal" documentation = "https://docs.rs/stm32f3xx-hal" -version = "0.9.1" +version = "0.9.2" exclude = ["codegen", ".markdownlint.yml"] resolver = "2" rust-version = "1.59" diff --git a/README.md b/README.md index 4cb32e1ba..f94378eba 100644 --- a/README.md +++ b/README.md @@ -47,17 +47,16 @@ Almost all of the implementation was shamelessly adapted from the Cargo.toml: ```toml -[package] -# ... -resolver = "2" - [dependencies] -cortex-m = "0.7.2" -cortex-m-rt = { version = "0.6.13", features = ["device"] } -# Panic behaviour, see https://crates.io/keywords/panic-impl for alternatives +# Only set the critical section feature, if you are using a bare-metal platform +# without any RTOS +# See https://github.com/rust-embedded/critical-section for further details. +cortex-m = { version = "0.7.4", features = ["critical-section-single-core"]} +cortex-m-rt = { version = "0.7.3", features = ["device"] } +# Panic behavior, see https://crates.io/keywords/panic-impl for alternatives panic-halt = "0.2.0" # Replace stm32f303xc with your target chip, see next section for more info -stm32f3xx-hal = { version = "0.9.1", features = ["ld", "rt", "stm32f303xc"] } +stm32f3xx-hal = { version = "0.9.2", features = ["ld", "rt", "stm32f303xc"] } ``` We also need to tell Rust about target architecture and how to link our diff --git a/release.toml b/release.toml index 403f28be6..d20aabd7e 100644 --- a/release.toml +++ b/release.toml @@ -1,8 +1,8 @@ # cargo-release configuration tag-message = "{{version}}" -dev-version = false pre-release-commit-message = "Release v{{version}}" +consolidate-commits = false push-remote = "upstream" # Change the changelog's `Unreleased` section to refer to this release and From a8db75ee8702a49080182dfecafef2eef77f3944 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 22 Nov 2023 22:06:15 +0100 Subject: [PATCH 12/25] Fix undefined behavior compile error (#346) --- CHANGELOG.md | 3 +++ Cargo.toml | 1 + src/spi.rs | 21 ++++++++++++++------- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32d6df1fc..e03f47916 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Deprecate `Toggle` enum and use `Switch` instead for better naming purposes ([#334]) - Add `impl From for Switch` to reduce churn. +- Fix undefined behavior in SPI implementation ([#346]) + - Add `num_traits::PrimInt` bounds to `Word` ### Added @@ -595,6 +597,7 @@ let clocks = rcc [defmt]: https://github.com/knurling-rs/defmt [filter]: https://defmt.ferrous-systems.com/filtering.html +[#346]: https://github.com/stm32-rs/stm32f3xx-hal/pull/346 [#340]: https://github.com/stm32-rs/stm32f3xx-hal/pull/340 [#338]: https://github.com/stm32-rs/stm32f3xx-hal/pull/338 [#337]: https://github.com/stm32-rs/stm32f3xx-hal/pull/337 diff --git a/Cargo.toml b/Cargo.toml index 849ad150f..55b64fd8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ embedded-hal = { version = "0.2.5", features = ["unproven"] } embedded-time = "0.12.0" enumset = { version = "1.0.6", optional = true } nb = "1.0.0" +num-traits = { version = "0.2.17", default-features = false} paste = "1.0.5" rtcc = { version = "0.3.0", optional = true } stm32-usbd = { version = "0.6.0", optional = true } diff --git a/src/spi.rs b/src/spi.rs index 2942e7fba..139322636 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -6,7 +6,7 @@ //! //! [examples/spi.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.9.1/examples/spi.rs -use core::{fmt, marker::PhantomData, ops::Deref, ptr}; +use core::{fmt, marker::PhantomData, ops::Deref}; use crate::hal::blocking::spi; use crate::hal::spi::FullDuplex; @@ -24,6 +24,7 @@ use crate::{ rcc::{self, Clocks}, time::rate, }; +use num_traits::{AsPrimitive, PrimInt}; /// SPI error #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -337,6 +338,8 @@ where // SckPin could technically be omitted, though not advisable. Miso: MisoPin, Mosi: MosiPin, + Word: PrimInt + Into + 'static, + u32: AsPrimitive, { type Error = Error; @@ -350,9 +353,9 @@ where } else if sr.crcerr().is_no_match() { nb::Error::Other(Error::Crc) } else if sr.rxne().is_not_empty() { - let read_ptr = &self.spi.dr as *const _ as *const Word; - // NOTE(unsafe) read from register owned by this Spi struct - let value = unsafe { ptr::read_volatile(read_ptr) }; + let read_ptr = core::ptr::addr_of!(self.spi.dr) as *const Word; + // SAFETY: Read from register owned by this Spi struct + let value = unsafe { core::ptr::read_volatile(read_ptr) }; return Ok(value); } else { nb::Error::WouldBlock @@ -369,9 +372,9 @@ where } else if sr.crcerr().is_no_match() { nb::Error::Other(Error::Crc) } else if sr.txe().is_empty() { - let write_ptr = &self.spi.dr as *const _ as *mut Word; - // NOTE(unsafe) write to register owned by this Spi struct - unsafe { ptr::write_volatile(write_ptr, word) }; + let write_ptr = core::ptr::addr_of!(self.spi.dr) as *mut Word; + // SAFETY: Write to register owned by this Spi struct + unsafe { core::ptr::write_volatile(write_ptr, word) }; return Ok(()); } else { nb::Error::WouldBlock @@ -384,6 +387,8 @@ where SPI: Instance, Miso: MisoPin, Mosi: MosiPin, + Word: PrimInt + Into + 'static, + u32: AsPrimitive, { } @@ -392,6 +397,8 @@ where SPI: Instance, Miso: MisoPin, Mosi: MosiPin, + Word: PrimInt + Into + 'static, + u32: AsPrimitive, { } From 9ca5e01815e7ab6ed3d91c4aabef2f6027b39ba4 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 22 Nov 2023 22:16:12 +0100 Subject: [PATCH 13/25] Apply clippy suggestions (#347) --- CHANGELOG.md | 2 + build.rs | 18 ++--- src/adc.rs | 26 ++++--- src/adc/config.rs | 8 +- src/dac.rs | 2 +- src/delay.rs | 12 +-- src/dma.rs | 11 ++- src/flash.rs | 2 + src/gpio.rs | 36 ++++----- src/i2c.rs | 84 ++++++++++++--------- src/lib.rs | 11 +-- src/pwm.rs | 9 ++- src/rcc.rs | 35 +++++++-- src/rcc/enable.rs | 1 + src/rtc.rs | 163 ++++++++++++++++++++++------------------ src/serial.rs | 84 ++++++++++++--------- src/serial/config.rs | 3 + src/signature.rs | 10 +++ src/spi/config.rs | 6 +- src/syscfg.rs | 3 +- src/timer.rs | 14 ++-- src/timer/interrupts.rs | 2 +- src/usb.rs | 6 +- src/watchdog.rs | 3 + 24 files changed, 331 insertions(+), 220 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e03f47916..1b7326337 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - Add missing ADC channels ([#337]) +- Add many `#[must_use]` instances ([#347]) ### Fixed @@ -598,6 +599,7 @@ let clocks = rcc [filter]: https://defmt.ferrous-systems.com/filtering.html [#346]: https://github.com/stm32-rs/stm32f3xx-hal/pull/346 +[#347]: https://github.com/stm32-rs/stm32f3xx-hal/pull/347 [#340]: https://github.com/stm32-rs/stm32f3xx-hal/pull/340 [#338]: https://github.com/stm32-rs/stm32f3xx-hal/pull/338 [#337]: https://github.com/stm32-rs/stm32f3xx-hal/pull/337 diff --git a/build.rs b/build.rs index ea1e78c57..1794aa95a 100644 --- a/build.rs +++ b/build.rs @@ -63,7 +63,8 @@ fn check_device_feature() { std::process::exit(1); } - let device_variants: HashSet = DEVICE_VARIANTS.iter().map(|s| s.to_string()).collect(); + let device_variants: HashSet = + DEVICE_VARIANTS.iter().map(|s| (*s).to_string()).collect(); // get all selected features via env variables let selected_features: HashSet = env::vars() @@ -90,7 +91,7 @@ fn check_device_feature() { // pretty print all avaliable devices for line in device_variants { for device in line { - eprint!("{} ", device); + eprint!("{device} "); } eprintln!(); } @@ -185,24 +186,17 @@ This may be due to incorrect feature configuration in Cargo.toml or stm32f3xx-ha writeln!(file, "MEMORY {{").unwrap(); writeln!( file, - " FLASH (rx) : ORIGIN = 0x8000000, LENGTH = {}K", - flash + " FLASH (rx) : ORIGIN = 0x8000000, LENGTH = {flash}K" ) .unwrap(); if ccmram > 0 { writeln!( file, - " CCMRAM (rwx) : ORIGIN = 0x10000000, LENGTH = {}K", - ccmram + " CCMRAM (rwx) : ORIGIN = 0x10000000, LENGTH = {ccmram}K" ) .unwrap(); } - writeln!( - file, - " RAM (rwx) : ORIGIN = 0x20000000, LENGTH = {}K", - ram - ) - .unwrap(); + writeln!(file, " RAM (rwx) : ORIGIN = 0x20000000, LENGTH = {ram}K").unwrap(); writeln!(file, "}}").unwrap(); println!("cargo:rustc-link-search={}", out_dir.display()); } diff --git a/src/adc.rs b/src/adc.rs index a8cd9aac0..66689e465 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -4,7 +4,7 @@ //! //! Check out [examples/adc.rs]. //! -//! It can be built for the STM32F3Discovery running +//! It can be built for the `STM32F3Discovery` running //! `cargo build --example adc --features=stm32f303xc` //! //! [examples/adc.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.9.1/examples/adc.rs @@ -97,6 +97,7 @@ pub struct TemperatureSensor { /// /// This peripheral can control different parts, like enabling internal sensors (like temperature sensor) /// or enable dual channel mode (which is not supported yet.) +#[allow(clippy::module_name_repetitions)] pub struct CommonAdc { reg: ADC, } @@ -348,7 +349,7 @@ where // TODO(Sh3Rm4n): Check against and integrate to DMA #[inline] pub fn data_register_address(&self) -> u32 { - &self.reg.dr as *const _ as u32 + core::ptr::addr_of!(self.reg.dr) as u32 } /// Manually start a conversion sequence. @@ -629,8 +630,9 @@ where /// Get the current configured DMA mode. #[inline] pub fn dma_mode(&self) -> config::DmaMode { - let cfgr = self.reg.cfgr.read(); use adc1::cfgr::{DMACFG_A, DMAEN_A}; + + let cfgr = self.reg.cfgr.read(); match (cfgr.dmaen().variant(), cfgr.dmacfg().variant()) { (DMAEN_A::Disabled, _) => config::DmaMode::Disabled, (DMAEN_A::Enabled, DMACFG_A::OneShot) => config::DmaMode::OneShot, @@ -872,7 +874,7 @@ where /// Set the overrun mode #[inline] pub fn set_overrun_mode(&mut self, mode: config::OverrunMode) { - self.reg.cfgr.modify(|_, w| w.ovrmod().variant(mode.into())) + self.reg.cfgr.modify(|_, w| w.ovrmod().variant(mode.into())); } /// Sets the sampling resolution. @@ -1090,7 +1092,7 @@ where /// the end of a single conversion of a "slot" is notfied via [`Event::EndOfConversion`]. #[inline] pub fn set_sequence_length(&mut self, sequence: config::Sequence) { - self.reg.sqr1.modify(|_, w| w.l().bits(sequence.into())) + self.reg.sqr1.modify(|_, w| w.l().bits(sequence.into())); } // TODO(Sh3Rm4n): Implement, when injection mode is implemented. @@ -1125,16 +1127,16 @@ where Event::EndOfSequence => self.reg.ier.modify(|_, w| w.eosie().bit(enable)), Event::Overrun => self.reg.ier.modify(|_, w| w.ovrie().bit(enable)), Event::InjectedChannelEndOfConversion => { - self.reg.ier.modify(|_, w| w.jeocie().bit(enable)) + self.reg.ier.modify(|_, w| w.jeocie().bit(enable)); } Event::InjectedChannelEndOfSequence => { - self.reg.ier.modify(|_, w| w.jeosie().bit(enable)) + self.reg.ier.modify(|_, w| w.jeosie().bit(enable)); } Event::AnalogWatchdog1 => self.reg.ier.modify(|_, w| w.awd1ie().bit(enable)), Event::AnalogWatchdog2 => self.reg.ier.modify(|_, w| w.awd2ie().bit(enable)), Event::AnalogWatchdog3 => self.reg.ier.modify(|_, w| w.awd3ie().bit(enable)), Event::InjectedContextQueueOverfow => { - self.reg.ier.modify(|_, w| w.jqovfie().bit(enable)) + self.reg.ier.modify(|_, w| w.jqovfie().bit(enable)); } }; } @@ -1266,8 +1268,8 @@ where #[cfg(feature = "svd-f373")] self.set_scan(config::Scan::Disabled); - let is_eoc_enabled = self.is_interrupt_configured(Event::EndOfConversion); - let is_eos_enabled = self.is_interrupt_configured(Event::EndOfSequence); + let is_end_of_conversion_enabled = self.is_interrupt_configured(Event::EndOfConversion); + let is_end_of_sequence_enabled = self.is_interrupt_configured(Event::EndOfSequence); self.disable_interrupt(Event::EndOfConversion); self.disable_interrupt(Event::EndOfSequence); @@ -1297,8 +1299,8 @@ where } self.set_sequence_length(seq_len); - self.configure_interrupt(Event::EndOfSequence, is_eos_enabled); - self.configure_interrupt(Event::EndOfConversion, is_eoc_enabled); + self.configure_interrupt(Event::EndOfSequence, is_end_of_sequence_enabled); + self.configure_interrupt(Event::EndOfConversion, is_end_of_conversion_enabled); #[cfg(feature = "svd-f373")] self.set_scan(config::Scan::Disabled); diff --git a/src/adc/config.rs b/src/adc/config.rs index e1952a675..35ed07384 100644 --- a/src/adc/config.rs +++ b/src/adc/config.rs @@ -464,7 +464,7 @@ impl Default for OverrunMode { /// Each channel can be sampled with a different sample time. /// There is always an overhead of 13 ADC clock cycles. /// -/// E.g. For SampleTime::T19C5 the total conversion time (in ADC clock cycles) is +/// E.g. For `SampleTime::T19C5` the total conversion time (in ADC clock cycles) is /// 13 + 19 = 32 ADC Clock Cycles /// /// # Related functions @@ -834,12 +834,14 @@ pub struct Config { impl Config { /// Change the resolution + #[must_use] pub fn resolution(mut self, resolution: Resolution) -> Self { self.resolution = resolution; self } /// Set the align mode + #[must_use] pub fn align(mut self, align: DataAlignment) -> Self { self.data_alignment = align; self @@ -853,24 +855,28 @@ impl Config { } /// Set the overrun mode + #[must_use] pub fn overrun_mode(mut self, mode: OverrunMode) -> Self { self.overrun = mode; self } /// Set the conversion mode + #[must_use] pub fn conversion_mode(mut self, mode: ConversionMode) -> Self { self.conversion = mode; self } /// Enable external trigger and the trigger source + #[must_use] pub fn external_trigger(mut self, trigger: Option) -> Self { self.external_trigger = trigger; self } /// Enable DMA and the operation mode, in which DMA will transfer data from the ADC peripheral. + #[must_use] pub fn dma_mode(mut self, dma: DmaMode) -> Self { self.dma = dma; self diff --git a/src/dac.rs b/src/dac.rs index ab519c7fc..07d196711 100644 --- a/src/dac.rs +++ b/src/dac.rs @@ -32,6 +32,6 @@ impl Dac { unsafe { w.dacc1dhr().bits(data) } - }) + }); } } diff --git a/src/delay.rs b/src/delay.rs index e4eff94a7..4caa88369 100644 --- a/src/delay.rs +++ b/src/delay.rs @@ -16,7 +16,7 @@ use crate::rcc::Clocks; use crate::time::duration::{Microseconds, Milliseconds}; use crate::time::fixed_point::FixedPoint; -/// System timer (SysTick) as a delay provider +/// System timer (`SysTick`) as a delay provider pub struct Delay { clocks: Clocks, syst: SYST, @@ -39,7 +39,7 @@ impl fmt::Debug for Delay { } impl Delay { - /// Configures the system timer (SysTick) as a delay provider + /// Configures the system timer (`SysTick`) as a delay provider /// /// # Limitations /// @@ -49,6 +49,7 @@ impl Delay { /// /// For accuracy purposes and because this is a blocking, busy-waiting function, /// if delays in the second to minute range are needed, use timers instead. + #[must_use] pub fn new(mut syst: SYST, clocks: Clocks) -> Self { syst.set_clock_source(SystClkSource::Core); @@ -68,7 +69,8 @@ impl Delay { &mut self.syst } - /// Releases the system timer (SysTick) resource + /// Releases the system timer (`SysTick`) resource + #[must_use] pub fn free(self) -> SYST { self.syst } @@ -131,13 +133,13 @@ impl DelayUs for Delay { impl DelayUs for Delay { fn delay_us(&mut self, us: u16) { - self.delay_us(u32::from(us)) + self.delay_us(u32::from(us)); } } impl DelayUs for Delay { fn delay_us(&mut self, us: u8) { - self.delay_us(u32::from(us)) + self.delay_us(u32::from(us)); } } diff --git a/src/dma.rs b/src/dma.rs index 9c90041c2..211462d0d 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -28,6 +28,7 @@ use core::{ use enumset::EnumSetType; /// Extension trait to split a DMA peripheral into independent channels +#[allow(clippy::module_name_repetitions)] pub trait DmaExt { /// The type to split the DMA into type Channels; @@ -134,12 +135,20 @@ impl Transfer { } /// Is this transfer complete? + /// + /// # Panics + /// + /// Panics if no transfer is ongoing. pub fn is_complete(&self) -> bool { let inner = crate::unwrap!(self.inner.as_ref()); inner.channel.is_event_triggered(Event::TransferComplete) } /// Stop this transfer and return ownership over its parts + /// + /// # Panics + /// + /// Panics no transfer is ongoing. pub fn stop(mut self) -> (B, C, T) { let mut inner = crate::unwrap!(self.inner.take()); inner.stop(); @@ -349,7 +358,7 @@ pub trait Channel: private::Channel { /// /// Panics if the word size is not one of 8, 16, or 32 bits. fn set_word_size(&mut self) { - use cr::PSIZE_A::*; + use cr::PSIZE_A::{Bits16, Bits32, Bits8}; let psize = match mem::size_of::() { 1 => Bits8, diff --git a/src/flash.rs b/src/flash.rs index b4fdc3e24..31600b610 100644 --- a/src/flash.rs +++ b/src/flash.rs @@ -7,6 +7,7 @@ use crate::pac::{flash, FLASH}; impl crate::private::Sealed for FLASH {} /// Extension trait to constrain the [`FLASH`] peripheral +#[allow(clippy::module_name_repetitions)] pub trait FlashExt: crate::private::Sealed { /// Constrains the [`FLASH`] peripheral. /// @@ -38,6 +39,7 @@ pub struct ACR { } impl ACR { + #[allow(clippy::unused_self)] pub(crate) fn acr(&mut self) -> &flash::ACR { // SAFETY: This proxy grants exclusive access to this register unsafe { &(*FLASH::ptr()).acr } diff --git a/src/gpio.rs b/src/gpio.rs index 1ff27c063..0a1a75521 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -19,7 +19,7 @@ //! let pa0 = gpioa.pa0.into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper); //! ``` //! -//! And finally, you can use the functions from the [InputPin] or [OutputPin] traits in +//! And finally, you can use the functions from the [`InputPin`] or [`OutputPin`] traits in //! `embedded_hal` //! //! For a complete example, see [examples/toggle.rs] @@ -30,18 +30,18 @@ //! //! Each GPIO pin can be set to various modes by corresponding `into_...` method: //! -//! - **Input**: The output buffer is disabled and the schmitt trigger input is activated -//! - **Output**: Both the output buffer and the schmitt trigger input is enabled -//! - **PushPull**: Output which either drives the pin high or low -//! - **OpenDrain**: Output which leaves the gate floating, or pulls it to ground in drain +//! - `Input`: The output buffer is disabled and the schmitt trigger input is activated +//! - `Output`: Both the output buffer and the schmitt trigger input is enabled +//! - `PushPull`: Output which either drives the pin high or low +//! - `OpenDrain`: Output which leaves the gate floating, or pulls it to ground in drain //! mode. Can be used as an input in the `open` configuration -//! - **Alternate**: Pin mode required when the pin is driven by other peripherals. The schmitt +//! - `Alternate`: Pin mode required when the pin is driven by other peripherals. The schmitt //! trigger input is activated. The Output buffer is automatically enabled and disabled by //! peripherals. Output behavior is same as the output mode -//! - **PushPull**: Output which either drives the pin high or low -//! - **OpenDrain**: Output which leaves the gate floating, or pulls it to ground in drain +//! - `PushPull`: Output which either drives the pin high or low +//! - `OpenDrain`: Output which leaves the gate floating, or pulls it to ground in drain //! mode -//! - **Analog**: Pin mode required for ADC, DAC, OPAMP, and COMP peripherals. It is also suitable +//! - `Analog`: Pin mode required for ADC, DAC, OPAMP, and COMP peripherals. It is also suitable //! for minimize energy consumption as the output buffer and the schmitt trigger input is disabled //! //! ### Output Speed @@ -72,6 +72,7 @@ use crate::{ use crate::hal::digital::v2::{toggleable, InputPin, StatefulOutputPin}; /// Extension trait to split a GPIO peripheral in independent pins and registers +#[allow(clippy::module_name_repetitions)] pub trait GpioExt { /// The Parts to split the GPIO peripheral into type Parts; @@ -226,7 +227,6 @@ impl marker::Index for Ux { pub struct U; impl marker::Index for U { - #[inline(always)] fn index(&self) -> u8 { X } @@ -606,9 +606,9 @@ where const BITWIDTH: u8 = 1; let index = self.index.index(); let (rise, fall) = match edge { - Edge::Rising => (true as u32, false as u32), - Edge::Falling => (false as u32, true as u32), - Edge::RisingFalling => (true as u32, true as u32), + Edge::Rising => (u32::from(true), u32::from(false)), + Edge::Falling => (u32::from(false), u32::from(true)), + Edge::RisingFalling => (u32::from(true), u32::from(true)), }; // SAFETY: Unguarded write to the register, but behind a &mut unsafe { @@ -622,7 +622,7 @@ where /// # Note /// /// Remeber to also configure the interrupt pin on - /// the SysCfg site, with [`crate::syscfg::SysCfg::select_exti_interrupt_source()`] + /// the `SysCfg` site, with [`crate::syscfg::SysCfg::select_exti_interrupt_source()`] pub fn configure_interrupt(&mut self, exti: &mut EXTI, enable: impl Into) { const BITWIDTH: u8 = 1; @@ -640,14 +640,14 @@ where /// # Note /// /// Remeber to also configure the interrupt pin on - /// the SysCfg site, with [`crate::syscfg::SysCfg::select_exti_interrupt_source()`] + /// the `SysCfg` site, with [`crate::syscfg::SysCfg::select_exti_interrupt_source()`] pub fn enable_interrupt(&mut self, exti: &mut EXTI) { - self.configure_interrupt(exti, Switch::On) + self.configure_interrupt(exti, Switch::On); } /// Disable external interrupts from this pin pub fn disable_interrupt(&mut self, exti: &mut EXTI) { - self.configure_interrupt(exti, Switch::Off) + self.configure_interrupt(exti, Switch::Off); } /// Clear the interrupt pending bit for this pin @@ -777,7 +777,7 @@ macro_rules! gpio_trait { }; } -/// Implement private::{Moder, Ospeedr, Otyper, Pupdr} traits for each opaque register structs +/// Implement `private::{Moder, Ospeedr, Otyper, Pupdr}` traits for each opaque register structs macro_rules! r_trait { ( ($GPIOX:ident, $gpioy:ident::$xr:ident::$enum:ident, $bitwidth:expr); diff --git a/src/i2c.rs b/src/i2c.rs index 2d0fd5467..6afef8353 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -13,7 +13,10 @@ use crate::{ hal::blocking::i2c::{Read, Write, WriteRead}, pac::{i2c1::RegisterBlock, rcc::cfgr3::I2C1SW_A, I2C1, RCC}, rcc::{self, Clocks}, - time::rate::*, + time::{ + fixed_point::FixedPoint, + rate::{Extensions, Hertz}, + }, }; #[cfg(not(feature = "gpio-f333"))] @@ -111,6 +114,10 @@ macro_rules! busy_wait { impl I2c { /// Configures the I2C peripheral to work in master mode + /// + /// # Panics + /// + /// Panics if frequency `freq` can not be configured for the periphery. pub fn new( i2c: I2C, pins: (SCL, SDA), @@ -138,13 +145,13 @@ impl I2c { // t_SCL ~= t_SYNC1 + t_SYNC2 + t_SCLL + t_SCLH let i2cclk = I2C::clock(&clocks).0; let ratio = i2cclk / freq.integer() - 4; - let (presc, scll, sclh, sdadel, scldel) = if freq >= 100.kHz() { + let (presc, scl_low, scl_high, sdadel, scldel) = if freq >= 100.kHz() { // fast-mode or fast-mode plus // here we pick SCLL + 1 = 2 * (SCLH + 1) let presc = ratio / 387; - let sclh = ((ratio / (presc + 1)) - 3) / 3; - let scll = 2 * (sclh + 1) - 1; + let scl_high = ((ratio / (presc + 1)) - 3) / 3; + let scl_low = 2 * (scl_high + 1) - 1; let (sdadel, scldel) = if freq > 400.kHz() { // fast-mode plus @@ -160,40 +167,40 @@ impl I2c { (sdadel, scldel) }; - (presc, scll, sclh, sdadel, scldel) + (presc, scl_low, scl_high, sdadel, scldel) } else { // standard-mode // here we pick SCLL = SCLH let presc = ratio / 514; - let sclh = ((ratio / (presc + 1)) - 2) / 2; - let scll = sclh; + let scl_high = ((ratio / (presc + 1)) - 2) / 2; + let scl_low = scl_high; let sdadel = i2cclk / 2_000_000 / (presc + 1); let scldel = i2cclk / 800_000 / (presc + 1) - 1; - (presc, scll, sclh, sdadel, scldel) + (presc, scl_low, scl_high, sdadel, scldel) }; crate::assert!(presc < 16); crate::assert!(scldel < 16); crate::assert!(sdadel < 16); - let sclh = crate::unwrap!(u8::try_from(sclh).ok()); - let scll = crate::unwrap!(u8::try_from(scll).ok()); + let scl_high = crate::unwrap!(u8::try_from(scl_high).ok()); + let scl_low = crate::unwrap!(u8::try_from(scl_low).ok()); // Configure for "fast mode" (400 KHz) // NOTE(write): writes all non-reserved bits. i2c.timingr.write(|w| { w.presc() - .bits(presc as u8) + .bits(crate::unwrap!(u8::try_from(presc))) .sdadel() - .bits(sdadel as u8) + .bits(crate::unwrap!(u8::try_from(sdadel))) .scldel() - .bits(scldel as u8) + .bits(crate::unwrap!(u8::try_from(scldel))) .scll() - .bits(scll) + .bits(scl_low) .sclh() - .bits(sclh) + .bits(scl_high) }); // Enable the peripheral @@ -243,15 +250,16 @@ where self.i2c.cr2.modify(|_, w| { if i == 0 { w.add10().bit7(); - w.sadd().bits((addr << 1) as u16); + w.sadd() + .bits(u16::from(crate::unwrap!(addr.checked_shl(1)))); w.rd_wrn().read(); w.start().start(); } - w.nbytes().bits(buffer.len() as u8); - if i != end { - w.reload().not_completed() - } else { + w.nbytes().bits(crate::unwrap!(u8::try_from(buffer.len()))); + if i == end { w.reload().completed().autoend().automatic() + } else { + w.reload().not_completed() } }); @@ -294,7 +302,8 @@ where // 0 byte write self.i2c.cr2.modify(|_, w| { w.add10().bit7(); - w.sadd().bits((addr << 1) as u16); + w.sadd() + .bits(u16::from(crate::unwrap!(addr.checked_shl(1)))); w.rd_wrn().write(); w.nbytes().bits(0); w.reload().completed(); @@ -310,15 +319,16 @@ where self.i2c.cr2.modify(|_, w| { if i == 0 { w.add10().bit7(); - w.sadd().bits((addr << 1) as u16); + w.sadd() + .bits(u16::from(crate::unwrap!(addr.checked_shl(1)))); w.rd_wrn().write(); w.start().start(); } - w.nbytes().bits(bytes.len() as u8); - if i != end { - w.reload().not_completed() - } else { + w.nbytes().bits(crate::unwrap!(u8::try_from(bytes.len()))); + if i == end { w.reload().completed().autoend().automatic() + } else { + w.reload().not_completed() } }); @@ -371,15 +381,16 @@ where self.i2c.cr2.modify(|_, w| { if i == 0 { w.add10().bit7(); - w.sadd().bits((addr << 1) as u16); + w.sadd() + .bits(u16::from(crate::unwrap!(addr.checked_shl(1)))); w.rd_wrn().write(); w.start().start(); } - w.nbytes().bits(bytes.len() as u8); - if i != end { - w.reload().not_completed() - } else { + w.nbytes().bits(crate::unwrap!(u8::try_from(bytes.len()))); + if i == end { w.reload().completed().autoend().software() + } else { + w.reload().not_completed() } }); @@ -412,15 +423,16 @@ where self.i2c.cr2.modify(|_, w| { if i == 0 { w.add10().bit7(); - w.sadd().bits((addr << 1) as u16); + w.sadd() + .bits(u16::from(crate::unwrap!(addr.checked_shl(1)))); w.rd_wrn().read(); w.start().start(); } - w.nbytes().bits(buffer.len() as u8); - if i != end { - w.reload().not_completed() - } else { + w.nbytes().bits(crate::unwrap!(u8::try_from(buffer.len()))); + if i == end { w.reload().completed().autoend().automatic() + } else { + w.reload().not_completed() } }); diff --git a/src/lib.rs b/src/lib.rs index 1c70cac91..e06a022ab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,7 @@ # `stm32f3xx-hal` `stm32f3xx-hal` contains a multi device hardware abstraction on top of the - peripheral access API for the STMicro [STM32F3][stm] series microcontrollers. + peripheral access API for the `STMicro` [STM32F3][stm] series microcontrollers. ## Philosophie @@ -63,7 +63,7 @@ * stm32f373x8, stm32f373xb, stm32f373xc, stm32f378xc * stm32f334x4, stm32f334x6, stm32f334x8 - Example: The STM32F3Discovery board has a STM32F303VCT6 chip. + Example: The `STM32F3Discovery` board has a STM32F303VCT6 chip. So you need to specify `stm32f303xc` in your `Cargo.toml` (note that VC → xc). For more information, see the [README][]. @@ -315,9 +315,10 @@ impl From for bool { impl From for Switch { fn from(b: bool) -> Self { - match b { - true => Switch::On, - false => Switch::Off, + if b { + Switch::On + } else { + Switch::Off } } } diff --git a/src/pwm.rs b/src/pwm.rs index e75e326c2..cd5518ee7 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -162,7 +162,7 @@ use crate::{ hal::PwmPin, pac::{TIM15, TIM16, TIM17, TIM2}, rcc::{Clocks, Enable, Reset}, - time::rate::*, + time::{fixed_point::FixedPoint, rate::Hertz}, }; #[cfg(any( @@ -263,6 +263,7 @@ pub struct WithNPins {} /// If there are no pins supplied, it cannot be enabled. #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[allow(clippy::module_name_repetitions)] pub struct PwmChannel { timx_chy: PhantomData, pin_status: PhantomData, @@ -280,6 +281,7 @@ macro_rules! pwm_timer_private { /// a resolution of 9000. This allows the servo to be set in increments /// of exactly one degree. #[allow(unused_parens)] + #[must_use] pub fn $timx(tim: $TIMx, res: $res, freq: Hertz, clocks: &Clocks) -> ($(PwmChannel<$TIMx_CHy, NoPins>),+) { // Power the timer and reset it to ensure a clean state // We use unsafe here to abstract away this implementation detail @@ -317,6 +319,7 @@ macro_rules! pwm_timer_private { tim.egr.write(|w| w.ug().set_bit()); // Enable outputs (STM32 Break Timer Specific) + #[allow(clippy::redundant_closure_call)] $enable_break_timer(&tim); // Enable the Timer @@ -366,6 +369,7 @@ macro_rules! pwm_channel_pin { /// is called. /// /// The pin is consumed and cannot be returned. + #[must_use] pub fn $output_to_pzv( self, _p: $gpioz::$PZv>, @@ -395,6 +399,7 @@ macro_rules! pwm_channel_pin { /// can be used (as long as they are compatible). /// /// The pin is consumed and cannot be returned. + #[must_use] pub fn $output_to_pzv( self, _p: $gpioz::$PZv>, @@ -1096,7 +1101,7 @@ macro_rules! tim5 { } // TODO: This timer is also present in stm32f378 -#[cfg(any(feature = "stm32f373"))] +#[cfg(feature = "stm32f373")] tim5!(); // TIM8 diff --git a/src/rcc.rs b/src/rcc.rs index 0a4664503..7ae0375be 100644 --- a/src/rcc.rs +++ b/src/rcc.rs @@ -61,14 +61,16 @@ use crate::pac::{ RCC, }; -use core::convert::TryInto; - use crate::flash::ACR; -use crate::time::rate::*; +use crate::time::{ + fixed_point::FixedPoint, + rate::{Hertz, Megahertz}, +}; impl crate::private::Sealed for RCC {} /// Extension trait that constrains the []`RCC`] peripheral +#[allow(clippy::module_name_repetitions)] pub trait RccExt: crate::private::Sealed { /// Constrains the [`RCC`] peripheral. /// @@ -186,6 +188,7 @@ bus_struct! { } /// Bus associated to peripheral +#[allow(clippy::module_name_repetitions)] pub trait RccBus: crate::Sealed { /// The underlying bus peripheral type Bus; @@ -352,13 +355,15 @@ mod usb_clocking { } } -/// Backup Domain Control register (RCC_BDCR) +/// Backup Domain Control register (`RCC_BDCR`) pub struct BDCR { _0: (), } impl BDCR { #[allow(unused)] + #[allow(clippy::unused_self)] + #[must_use] pub(crate) fn bdcr(&mut self) -> &rcc::BDCR { // NOTE(unsafe) this proxy grants exclusive access to this register unsafe { &(*RCC::ptr()).bdcr } @@ -474,6 +479,7 @@ impl CFGR { /// # Panics /// /// Panics if conversion from `Megahertz` to `Hertz` produces a value greater then `u32::MAX`. + #[must_use] pub fn use_hse(mut self, freq: Megahertz) -> Self { let freq: Hertz = crate::expect!(freq.try_into(), "ConversionError"); self.hse = Some(freq.integer()); @@ -481,6 +487,7 @@ impl CFGR { } /// Set this to disallow bypass the PLLCLK for the systemclock generation. + #[must_use] pub fn use_pll(mut self) -> Self { self.pll_bypass = false; self @@ -492,6 +499,7 @@ impl CFGR { /// `OSC_OUT` pin is free and can be used as GPIO. /// /// No effect if `HSE` is not enabled. + #[must_use] pub fn bypass_hse(mut self) -> Self { self.hse_bypass = true; self @@ -503,6 +511,7 @@ impl CFGR { /// when `HSE` clock failure is detected. /// /// No effect if `HSE` is not enabled. + #[must_use] pub fn enable_css(mut self) -> Self { self.css = true; self @@ -513,6 +522,7 @@ impl CFGR { /// # Panics /// /// Panics if conversion from `Megahertz` to `Hertz` produces a value greater then `u32::MAX`. + #[must_use] pub fn hclk(mut self, freq: Megahertz) -> Self { let freq: Hertz = crate::expect!(freq.try_into(), "ConversionError"); self.hclk = Some(freq.integer()); @@ -529,6 +539,7 @@ impl CFGR { /// # Panics /// /// Panics if conversion from `Megahertz` to `Hertz` produces a value greater then `u32::MAX`. + #[must_use] pub fn pclk1(mut self, freq: Megahertz) -> Self { let freq: Hertz = crate::expect!(freq.try_into(), "ConversionError"); self.pclk1 = Some(freq.integer()); @@ -551,6 +562,7 @@ impl CFGR { /// # Panics /// /// Panics if conversion from `Megahertz` to `Hertz` produces a value greater then `u32::MAX`. + #[must_use] pub fn pclk2(mut self, freq: Megahertz) -> Self { let freq: Hertz = crate::expect!(freq.try_into(), "ConversionError"); self.pclk2 = Some(freq.integer()); @@ -576,6 +588,7 @@ impl CFGR { /// # Panics /// /// Panics if conversion from `Megahertz` to `Hertz` produces a value greater then `u32::MAX`. + #[must_use] pub fn sysclk(mut self, freq: Megahertz) -> Self { let freq: Hertz = crate::expect!(freq.try_into(), "ConversionError"); self.sysclk = Some(freq.integer()); @@ -644,7 +657,9 @@ impl CFGR { }; // Convert into register bit field types + #[allow(clippy::cast_possible_truncation)] let pll_mul_bits = into_pll_mul(pll_mul as u8); + #[allow(clippy::cast_possible_truncation)] let pll_div_bits = pll_div.map(|pll_div| into_pre_div(pll_div as u8)); ( @@ -709,7 +724,9 @@ impl CFGR { }; // Convert into register bit field types + #[allow(clippy::cast_possible_truncation)] let pll_mul_bits = into_pll_mul(pll_mul as u8); + #[allow(clippy::cast_possible_truncation)] let pll_div_bits = into_pre_div(pll_div as u8); ( @@ -722,7 +739,7 @@ impl CFGR { ) } - /// Get the system clock, the system clock source and the pll_options, if needed. + /// Get the system clock, the system clock source and the `pll_options`, if needed. /// /// The system clock source is determined by the chosen system clock and the provided hardware /// clock. @@ -942,31 +959,37 @@ impl defmt::Format for Clocks { // With that in place, some places of macro magic are not needed anymore. impl Clocks { /// Returns the frequency of the AHB + #[must_use] pub fn hclk(&self) -> Hertz { self.hclk } /// Returns the frequency of the APB1 + #[must_use] pub fn pclk1(&self) -> Hertz { self.pclk1 } /// Returns the frequency of the APB2 + #[must_use] pub fn pclk2(&self) -> Hertz { self.pclk2 } /// Returns the prescaler of the APB1 + #[must_use] pub fn ppre1(&self) -> u8 { self.ppre1 } /// Returns the prescaler of the APB2 + #[must_use] pub fn ppre2(&self) -> u8 { self.ppre2 } /// Returns the system (core) frequency + #[must_use] pub fn sysclk(&self) -> Hertz { self.sysclk } @@ -974,6 +997,7 @@ impl Clocks { /// Returns the PLL clock if configured, else it returns `None`. /// /// The PLL clock is a source of the system clock, but it is not necessarily configured to be one. + #[must_use] pub fn pllclk(&self) -> Option { if self.pll_bypass { None @@ -993,6 +1017,7 @@ impl Clocks { /// overrun/underrun problems. [RM0316 32.5.2][RM0316] /// /// [RM0316]: https://www.st.com/resource/en/reference_manual/dm00043574.pdf + #[must_use] pub fn usbclk_valid(&self) -> bool { self.usbclk_valid } diff --git a/src/rcc/enable.rs b/src/rcc/enable.rs index b16c3deb9..bfa07fd1e 100644 --- a/src/rcc/enable.rs +++ b/src/rcc/enable.rs @@ -1,3 +1,4 @@ +#[allow(clippy::wildcard_imports)] use super::*; macro_rules! bus_enable { diff --git a/src/rtc.rs b/src/rtc.rs index 2bbd2212c..55f63b8ab 100644 --- a/src/rtc.rs +++ b/src/rtc.rs @@ -82,6 +82,7 @@ impl Rtc { } /// Reads current hour format selection + #[must_use] pub fn is_24h_fmt(&self) -> bool { self.rtc.cr.read().fmt().bit() } @@ -100,6 +101,7 @@ impl Rtc { } /// Release the RTC peripheral + #[must_use] pub fn free(self) -> RTC { // TODO(Sh3Rm4n): Disable peripheral before releasing it. self.rtc @@ -130,39 +132,37 @@ impl Rtc { } } +// TODO: check conditional compilation because of Chrono impl DateTimeAccess for Rtc { type Error = Error; fn set_datetime(&mut self, date: &NaiveDateTime) -> Result<(), Self::Error> { - if date.year() < 1970 { - return Err(Error::InvalidInputData); - } - self.set_24h_fmt(); - let (yt, yu) = bcd2_encode((date.year() - 1970) as u32)?; - let (mt, mu) = bcd2_encode(date.month())?; - let (dt, du) = bcd2_encode(date.day())?; + let (year_tens, year_units) = + bcd2_encode(u32::try_from(date.year() - 1970).map_err(|_| Error::InvalidInputData)?)?; + let (month_tens, month_units) = bcd2_encode(date.month())?; + let (day_tens, day_units) = bcd2_encode(date.day())?; - let (ht, hu) = bcd2_encode(date.hour())?; - let (mnt, mnu) = bcd2_encode(date.minute())?; - let (st, su) = bcd2_encode(date.second())?; + let (hour_tens, hour_units) = bcd2_encode(date.hour())?; + let (minutes_tens, minutes_units) = bcd2_encode(date.minute())?; + let (second_tens, second_units) = bcd2_encode(date.second())?; self.rtc.dr.write(|w| { - w.dt().bits(dt); - w.du().bits(du); - w.mt().bit(mt > 0); - w.mu().bits(mu); - w.yt().bits(yt); - w.yu().bits(yu) + w.dt().bits(day_tens); + w.du().bits(day_units); + w.mt().bit(month_tens > 0); + w.mu().bits(month_units); + w.yt().bits(year_tens); + w.yu().bits(year_units) }); self.rtc.tr.write(|w| { - w.ht().bits(ht); - w.hu().bits(hu); - w.mnt().bits(mnt); - w.mnu().bits(mnu); - w.st().bits(st); - w.su().bits(su); + w.ht().bits(hour_tens); + w.hu().bits(hour_units); + w.mnt().bits(minutes_tens); + w.mnu().bits(minutes_units); + w.st().bits(second_tens); + w.su().bits(second_units); w.pm().clear_bit() }); @@ -188,20 +188,21 @@ impl DateTimeAccess for Rtc { } impl Rtcc for Rtc { - /// set time using NaiveTime (ISO 8601 time without timezone) + /// Set time using `NaiveTime` (ISO 8601 time without timezone) + /// /// Hour format is 24h fn set_time(&mut self, time: &NaiveTime) -> Result<(), Self::Error> { self.set_24h_fmt(); - let (ht, hu) = bcd2_encode(time.hour())?; - let (mnt, mnu) = bcd2_encode(time.minute())?; - let (st, su) = bcd2_encode(time.second())?; + let (hour_tens, hour_units) = bcd2_encode(time.hour())?; + let (minutes_tens, minutes_units) = bcd2_encode(time.minute())?; + let (seconds_tens, seconds_units) = bcd2_encode(time.second())?; self.rtc.tr.write(|w| { - w.ht().bits(ht); - w.hu().bits(hu); - w.mnt().bits(mnt); - w.mnu().bits(mnu); - w.st().bits(st); - w.su().bits(su); + w.ht().bits(hour_tens); + w.hu().bits(hour_units); + w.mnt().bits(minutes_tens); + w.mnu().bits(minutes_units); + w.st().bits(seconds_tens); + w.su().bits(seconds_units); w.pm().clear_bit() }); @@ -212,8 +213,11 @@ impl Rtcc for Rtc { if seconds > 59 { return Err(Error::InvalidInputData); } - let (st, su) = bcd2_encode(seconds as u32)?; - self.modify(|rtc| rtc.tr.modify(|_, w| w.st().bits(st).su().bits(su))); + let (seconds_tens, seconds_units) = bcd2_encode(u32::from(seconds))?; + self.modify(|rtc| { + rtc.tr + .modify(|_, w| w.st().bits(seconds_tens).su().bits(seconds_units)); + }); Ok(()) } @@ -222,20 +226,25 @@ impl Rtcc for Rtc { if minutes > 59 { return Err(Error::InvalidInputData); } - let (mnt, mnu) = bcd2_encode(minutes as u32)?; - self.modify(|rtc| rtc.tr.modify(|_, w| w.mnt().bits(mnt).mnu().bits(mnu))); + let (minutes_tens, minutes_units) = bcd2_encode(u32::from(minutes))?; + self.modify(|rtc| { + rtc.tr + .modify(|_, w| w.mnt().bits(minutes_tens).mnu().bits(minutes_units)); + }); Ok(()) } fn set_hours(&mut self, hours: Hours) -> Result<(), Self::Error> { - let (ht, hu) = hours_to_register(hours)?; + let (hour_tens, hour_units) = hours_to_register(hours)?; match hours { - Hours::H24(_h) => self.set_24h_fmt(), - Hours::AM(_h) | Hours::PM(_h) => self.set_12h_fmt(), + Hours::H24(_) => self.set_24h_fmt(), + Hours::AM(_) | Hours::PM(_) => self.set_12h_fmt(), } - self.rtc.tr.modify(|_, w| w.ht().bits(ht).hu().bits(hu)); + self.rtc + .tr + .modify(|_, w| w.ht().bits(hour_tens).hu().bits(hour_units)); Ok(()) } @@ -253,8 +262,11 @@ impl Rtcc for Rtc { if !(1..=31).contains(&day) { return Err(Error::InvalidInputData); } - let (dt, du) = bcd2_encode(day as u32)?; - self.modify(|rtc| rtc.dr.modify(|_, w| w.dt().bits(dt).du().bits(du))); + let (day_tens, day_units) = bcd2_encode(u32::from(day))?; + self.modify(|rtc| { + rtc.dr + .modify(|_, w| w.dt().bits(day_tens).du().bits(day_units)); + }); Ok(()) } @@ -263,8 +275,11 @@ impl Rtcc for Rtc { if !(1..=12).contains(&month) { return Err(Error::InvalidInputData); } - let (mt, mu) = bcd2_encode(month as u32)?; - self.modify(|rtc| rtc.dr.modify(|_, w| w.mt().bit(mt > 0).mu().bits(mu))); + let (month_tens, month_units) = bcd2_encode(u32::from(month))?; + self.modify(|rtc| { + rtc.dr + .modify(|_, w| w.mt().bit(month_tens > 0).mu().bits(month_units)); + }); Ok(()) } @@ -273,29 +288,26 @@ impl Rtcc for Rtc { if !(1970..=2038).contains(&year) { return Err(Error::InvalidInputData); } - let (yt, yu) = bcd2_encode(year as u32)?; - self.modify(|rtc| rtc.dr.modify(|_, w| w.yt().bits(yt).yu().bits(yu))); + let (year_tens, yu) = bcd2_encode(u32::from(year))?; + self.modify(|rtc| rtc.dr.modify(|_, w| w.yt().bits(year_tens).yu().bits(yu))); Ok(()) } - /// Set the date using NaiveDate (ISO 8601 calendar date without timezone). - /// WeekDay is set using the `set_weekday` method + /// Set the date using `NaiveDate` (ISO 8601 calendar date without timezone). + /// `WeekDay` is set using the `set_weekday` method fn set_date(&mut self, date: &NaiveDate) -> Result<(), Self::Error> { - if date.year() < 1970 { - return Err(Error::InvalidInputData); - } - - let (yt, yu) = bcd2_encode((date.year() - 1970) as u32)?; - let (mt, mu) = bcd2_encode(date.month())?; - let (dt, du) = bcd2_encode(date.day())?; + let (year_tens, yu) = + bcd2_encode(u32::try_from(date.year() - 1970).map_err(|_| Error::InvalidInputData)?)?; + let (month_tens, month_units) = bcd2_encode(date.month())?; + let (day_tens, day_units) = bcd2_encode(date.day())?; self.rtc.dr.write(|w| { - w.dt().bits(dt); - w.du().bits(du); - w.mt().bit(mt > 0); - w.mu().bits(mu); - w.yt().bits(yt); + w.dt().bits(day_tens); + w.du().bits(day_units); + w.mt().bit(month_tens > 0); + w.mu().bits(month_units); + w.yt().bits(year_tens); w.yu().bits(yu) }); @@ -305,25 +317,26 @@ impl Rtcc for Rtc { fn seconds(&mut self) -> Result { let tr = self.rtc.tr.read(); let seconds = bcd2_decode(tr.st().bits(), tr.su().bits()); - Ok(seconds as u8) + u8::try_from(seconds).map_err(|_| Error::InvalidRtcData) } fn minutes(&mut self) -> Result { let tr = self.rtc.tr.read(); let minutes = bcd2_decode(tr.mnt().bits(), tr.mnu().bits()); - Ok(minutes as u8) + u8::try_from(minutes).map_err(|_| Error::InvalidRtcData) } fn hours(&mut self) -> Result { let tr = self.rtc.tr.read(); let hours = bcd2_decode(tr.ht().bits(), tr.hu().bits()); + let hours = u8::try_from(hours).map_err(|_| Error::InvalidRtcData)?; if self.is_24h_fmt() { - return Ok(Hours::H24(hours as u8)); + return Ok(Hours::H24(hours)); } if !tr.pm().bit() { - return Ok(Hours::AM(hours as u8)); + return Ok(Hours::AM(hours)); } - Ok(Hours::PM(hours as u8)) + Ok(Hours::PM(hours)) } fn time(&mut self) -> Result { @@ -339,26 +352,26 @@ impl Rtcc for Rtc { fn weekday(&mut self) -> Result { let dr = self.rtc.dr.read(); let weekday = bcd2_decode(dr.wdu().bits(), 0x00); - Ok(weekday as u8) + u8::try_from(weekday).map_err(|_| Error::InvalidRtcData) } fn day(&mut self) -> Result { let dr = self.rtc.dr.read(); let day = bcd2_decode(dr.dt().bits(), dr.du().bits()); - Ok(day as u8) + u8::try_from(day).map_err(|_| Error::InvalidRtcData) } fn month(&mut self) -> Result { let dr = self.rtc.dr.read(); - let mt = u8::from(dr.mt().bit()); - let month = bcd2_decode(mt, dr.mu().bits()); - Ok(month as u8) + let month_tens = u8::from(dr.mt().bit()); + let month = bcd2_decode(month_tens, dr.mu().bits()); + u8::try_from(month).map_err(|_| Error::InvalidRtcData) } fn year(&mut self) -> Result { let dr = self.rtc.dr.read(); let year = bcd2_decode(dr.yt().bits(), dr.yu().bits()); - Ok(year as u16) + u16::try_from(year).map_err(|_| Error::InvalidRtcData) } fn date(&mut self) -> Result { @@ -394,14 +407,14 @@ fn bcd2_encode(word: u32) -> Result<(u8, u8), Error> { } fn bcd2_decode(fst: u8, snd: u8) -> u32 { - (fst * 10 + snd).into() + u32::from(fst) * 10 + u32::from(snd) } fn hours_to_register(hours: Hours) -> Result<(u8, u8), Error> { match hours { - Hours::H24(h) => Ok(bcd2_encode(h as u32))?, - Hours::AM(h) => Ok(bcd2_encode((h - 1) as u32))?, - Hours::PM(h) => Ok(bcd2_encode((h + 11) as u32))?, + Hours::H24(h) => Ok(bcd2_encode(u32::from(h)))?, + Hours::AM(h) => Ok(bcd2_encode(u32::from(h - 1)))?, + Hours::PM(h) => Ok(bcd2_encode(u32::from(h + 11)))?, } } diff --git a/src/serial.rs b/src/serial.rs index 8513141fb..bf9e37239 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -23,7 +23,8 @@ use crate::{ Interrupt, USART1, USART2, USART3, }, rcc::{self, Clocks}, - time::rate::*, + time::fixed_point::FixedPoint, + time::rate::{Baud, Hertz}, Switch, }; @@ -227,14 +228,14 @@ pub enum BaudTable { impl From for Baud { fn from(baud: BaudTable) -> Self { match baud { - BaudTable::Bd1200 => Baud(1200), - BaudTable::Bd9600 => Baud(9600), - BaudTable::Bd19200 => Baud(19200), - BaudTable::Bd38400 => Baud(38400), - BaudTable::Bd57600 => Baud(57600), - BaudTable::Bd115200 => Baud(115200), - BaudTable::Bd230400 => Baud(230400), - BaudTable::Bd460800 => Baud(460800), + BaudTable::Bd1200 => Baud(1_200), + BaudTable::Bd9600 => Baud(9_600), + BaudTable::Bd19200 => Baud(19_200), + BaudTable::Bd38400 => Baud(38_400), + BaudTable::Bd57600 => Baud(57_600), + BaudTable::Bd115200 => Baud(115_200), + BaudTable::Bd230400 => Baud(230_400), + BaudTable::Bd460800 => Baud(460_800), } } } @@ -248,14 +249,14 @@ impl TryFrom for BaudTable { type Error = TryFromBaudError; fn try_from(baud: Baud) -> Result { Ok(match baud { - Baud(1200) => BaudTable::Bd1200, - Baud(9600) => BaudTable::Bd9600, - Baud(19200) => BaudTable::Bd19200, - Baud(38400) => BaudTable::Bd38400, - Baud(57600) => BaudTable::Bd57600, - Baud(115200) => BaudTable::Bd115200, - Baud(230400) => BaudTable::Bd230400, - Baud(460800) => BaudTable::Bd460800, + Baud(1_200) => BaudTable::Bd1200, + Baud(9_600) => BaudTable::Bd9600, + Baud(19_200) => BaudTable::Bd19200, + Baud(38_400) => BaudTable::Bd38400, + Baud(57_600) => BaudTable::Bd57600, + Baud(115_200) => BaudTable::Bd115200, + Baud(230_400) => BaudTable::Bd230400, + Baud(460_800) => BaudTable::Bd460800, _ => return Err(TryFromBaudError(())), }) } @@ -458,6 +459,10 @@ where Usart: Instance, { /// Configures a USART peripheral to provide serial communication + /// + /// # Panics + /// + /// Panics if the configured baud rate is impossible for the hardware to setup. pub fn new( usart: Usart, pins: (Tx, Rx), @@ -471,7 +476,7 @@ where Rx: RxPin, Config: Into, { - use config::*; + use config::Parity; let config = config.into(); @@ -484,7 +489,12 @@ where let brr = Usart::clock(&clocks).integer() / config.baudrate.integer(); crate::assert!(brr >= 16, "impossible baud rate"); - usart.brr.write(|w| w.brr().bits(brr as u16)); + usart.brr.write(|w| { + w.brr().bits( + // NOTE(unsafe): safe because of assert before + unsafe { u16::try_from(brr).unwrap_unchecked() }, + ) + }); // We currently support only eight data bits as supporting a full-blown // configuration gets complicated pretty fast. The USART counts data @@ -586,6 +596,7 @@ where if self.usart.isr.read().busy().bit_is_set() { return None; } + #[allow(clippy::cast_possible_truncation)] Some(self.usart.rdr.read().rdr().bits() as u8) } @@ -643,12 +654,12 @@ where Event::CtsInterrupt => self.usart.cr3.modify(|_, w| w.ctsie().bit(enable)), Event::TransmissionComplete => self.usart.cr1.modify(|_, w| w.tcie().bit(enable)), Event::ReceiveDataRegisterNotEmpty => { - self.usart.cr1.modify(|_, w| w.rxneie().bit(enable)) + self.usart.cr1.modify(|_, w| w.rxneie().bit(enable)); } Event::ParityError => self.usart.cr1.modify(|_, w| w.peie().bit(enable)), Event::LinBreak => self.usart.cr2.modify(|_, w| w.lbdie().bit(enable)), Event::NoiseError | Event::OverrunError | Event::FramingError => { - self.usart.cr3.modify(|_, w| w.eie().bit(enable)) + self.usart.cr3.modify(|_, w| w.eie().bit(enable)); } Event::Idle => self.usart.cr1.modify(|_, w| w.idleie().bit(enable)), Event::CharacterMatch => self.usart.cr1.modify(|_, w| w.cmie().bit(enable)), @@ -812,7 +823,6 @@ where /// /// If the character is matched [`Event::CharacterMatch`] is generated, /// which can fire an interrupt, if enabled via [`Serial::configure_interrupt()`] - #[inline(always)] pub fn set_match_character(&mut self, char: u8) { // Note: This bit field can only be written when reception is disabled (RE = 0) or the // USART is disabled @@ -823,7 +833,6 @@ where } /// Read out the configured match character. - #[inline(always)] pub fn match_character(&self) -> u8 { self.usart.cr2.read().add().bits() } @@ -848,11 +857,11 @@ where /// - This value must only be programmed once per received character. /// - Can be written on the fly. If the new value is lower than or equal to the counter, /// the RTOF flag is set. - /// - Values higher than 24 bits are truncated to 24 bit max (16_777_216). + /// - Values higher than 24 bits are truncated to 24 bit max (`16_777_216`). pub fn set_receiver_timeout(&mut self, value: Option) { if let Some(value) = value { self.usart.cr2.modify(|_, w| w.rtoen().enabled()); - self.usart.rtor.modify(|_, w| w.rto().bits(value)) + self.usart.rtor.modify(|_, w| w.rto().bits(value)); } else { self.usart.cr2.modify(|_, w| w.rtoen().disabled()); } @@ -921,6 +930,7 @@ where usart.rqr.write(|w| w.rxfrq().set_bit()); nb::Error::Other(Error::Overrun) } else if isr.rxne().bit_is_set() { + #[allow(clippy::cast_possible_truncation)] return Ok(usart.rdr.read().bits() as u8); } else { nb::Error::WouldBlock @@ -1072,9 +1082,9 @@ where // NOTE(unsafe) usage of a valid peripheral address unsafe { channel.set_peripheral_address( - &self.usart().rdr as *const _ as u32, + core::ptr::addr_of!(self.usart().rdr) as u32, dma::Increment::Disable, - ) + ); }; dma::Transfer::start_write(buffer, channel, self) @@ -1103,9 +1113,9 @@ where // NOTE(unsafe) usage of a valid peripheral address unsafe { channel.set_peripheral_address( - &self.usart().tdr as *const _ as u32, + core::ptr::addr_of!(self.usart().tdr) as u32, dma::Increment::Disable, - ) + ); }; dma::Transfer::start_read(buffer, channel, self) @@ -1164,8 +1174,10 @@ where { // NOTE(unsafe) usage of a valid peripheral address unsafe { - channel - .set_peripheral_address(&self.usart.rdr as *const _ as u32, dma::Increment::Disable) + channel.set_peripheral_address( + core::ptr::addr_of!(self.usart.rdr) as u32, + dma::Increment::Disable, + ); }; dma::Transfer::start_write(buffer, channel, self) @@ -1180,8 +1192,10 @@ where { // NOTE(unsafe) usage of a valid peripheral address unsafe { - channel - .set_peripheral_address(&self.usart.tdr as *const _ as u32, dma::Increment::Disable) + channel.set_peripheral_address( + core::ptr::addr_of!(self.usart.tdr) as u32, + dma::Increment::Disable, + ); }; dma::Transfer::start_read(buffer, channel, self) @@ -1195,13 +1209,13 @@ where fn enable_dma(&mut self) { self.usart .cr3 - .modify(|_, w| w.dmar().enabled().dmat().enabled()) + .modify(|_, w| w.dmar().enabled().dmat().enabled()); } fn disable_dma(&mut self) { self.usart .cr3 - .modify(|_, w| w.dmar().disabled().dmat().disabled()) + .modify(|_, w| w.dmar().disabled().dmat().disabled()); } } diff --git a/src/serial/config.rs b/src/serial/config.rs index 4212fe22e..197170dd4 100644 --- a/src/serial/config.rs +++ b/src/serial/config.rs @@ -87,18 +87,21 @@ pub struct Config { impl Config { /// Sets the given baudrate. + #[must_use] pub fn baudrate(mut self, baudrate: impl Into) -> Self { self.baudrate = baudrate.into(); self } /// Sets the given parity. + #[must_use] pub fn parity(mut self, parity: Parity) -> Self { self.parity = parity; self } /// Sets the stop bits to `stopbits`. + #[must_use] pub fn stopbits(mut self, stopbits: StopBits) -> Self { self.stopbits = stopbits; self diff --git a/src/signature.rs b/src/signature.rs index a52bca4c9..26594a9cb 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -14,6 +14,7 @@ macro_rules! define_ptr_type { } /// Returns a wrapped reference to the value in flash memory + #[must_use] pub fn get() -> &'static Self { unsafe { &*Self::ptr() } } @@ -71,33 +72,40 @@ fn bcd_to_num(bcd_num: u16) -> u16 { impl Uid { /// X coordinate on wafer in BCD format + #[must_use] pub fn x_bcd(&self) -> u16 { self.x } /// X coordinate on wafer + #[must_use] pub fn x(&self) -> u16 { bcd_to_num(self.x) } /// Y coordinate on wafer in BCD format + #[must_use] pub fn y_bcd(&self) -> u16 { self.y } /// Y coordinate on wafer + #[must_use] pub fn y(&self) -> u16 { bcd_to_num(self.y) } /// Wafer number + #[must_use] pub fn wafer_number(&self) -> u8 { self.waf } /// Lot number + #[must_use] pub fn lot_number(&self) -> &str { // Lets ignore the last byte, because it is a '\0' character. + // TODO: change to core::ffi::CStr unsafe { str::from_utf8_unchecked(&self.lot[..6]) } } } @@ -110,11 +118,13 @@ define_ptr_type!(FlashSize, 0x1FFF_F7CC); impl FlashSize { /// Read flash size in kilobytes + #[must_use] pub fn kilo_bytes(&self) -> u16 { self.0 } /// Read flash size in bytes + #[must_use] pub fn bytes(&self) -> usize { usize::from(self.kilo_bytes()) * 1024 } diff --git a/src/spi/config.rs b/src/spi/config.rs index 7a67d7091..dec5cdcd0 100644 --- a/src/spi/config.rs +++ b/src/spi/config.rs @@ -16,7 +16,7 @@ use crate::time::rate::Generic; /// let config = Config::default(); /// ```` /// -/// [`Spi`](super::Spi) defaults to [`spi::MODE_0`] and a frequency of 1 MHz. +/// [`Spi`](super::Spi) defaults to [`spi::MODE_0`] and a frequency of 1 `MHz`. /// /// ``` /// # use stm32f3xx_hal::spi::config::Config; @@ -46,11 +46,13 @@ pub struct Config { impl Config { /// Set the operating frequency of the SPI + #[must_use] pub fn frequency(mut self, frequency: impl Into>) -> Self { self.frequency = frequency.into(); self } /// Set the Operation Mode + #[must_use] pub fn mode(mut self, mode: Mode) -> Self { self.mode = mode; self @@ -71,7 +73,7 @@ impl fmt::Debug for Config { f.debug_struct("Config") .field("frequency", &format_args!("{:?}", self.frequency)) - .field("mode", &format_args!("MODE_{}", mode)) + .field("mode", &format_args!("MODE_{mode}")) .finish() } } diff --git a/src/syscfg.rs b/src/syscfg.rs index 1b14906ee..5b68fac19 100644 --- a/src/syscfg.rs +++ b/src/syscfg.rs @@ -52,7 +52,6 @@ impl fmt::Debug for SysCfg { impl Deref for SysCfg { type Target = SYSCFG; - #[inline(always)] fn deref(&self) -> &Self::Target { &self.0 } @@ -80,7 +79,7 @@ impl SysCfg { { const BITWIDTH: u8 = 4; let index = pin.index.index() % 4; - let extigpionr = pin.gpio.port_index() as u32; + let extigpionr = u32::from(pin.gpio.port_index()); match pin.index.index() { // SAFETY: These are all unguarded writes directly to the register, // without leveraging the safety of stm32f3 generated values. diff --git a/src/timer.rs b/src/timer.rs index 3bda5d835..1e79aeb99 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -24,6 +24,7 @@ use crate::time::{duration, fixed_point::FixedPoint, rate::Hertz}; mod interrupts; /// A monotonic nondecreasing timer. +#[allow(clippy::module_name_repetitions)] #[derive(Debug, Clone, Copy)] pub struct MonoTimer { frequency: Hertz, @@ -55,11 +56,13 @@ impl MonoTimer { } /// Returns the frequency at which the monotonic timer is operating at + #[must_use] pub fn frequency(&self) -> Hertz { self.frequency } /// Returns an `Instant` corresponding to "now" + #[must_use] pub fn now(&self) -> Instant { Instant { now: DWT::cycle_count(), @@ -76,6 +79,7 @@ pub struct Instant { impl Instant { /// Ticks elapsed since the `Instant` was created + #[must_use] pub fn elapsed(self) -> u32 { DWT::cycle_count().wrapping_sub(self.now) } @@ -110,7 +114,7 @@ where TIM::enable(apb); TIM::reset(apb); - Timer { clocks, tim } + Timer { tim, clocks } } /// Stops the timer @@ -304,7 +308,7 @@ where self.clear_event(Event::Update); if is_update_interrupt_active { - self.configure_interrupt(Event::Update, true) + self.configure_interrupt(Event::Update, true); } // start counter @@ -314,11 +318,11 @@ where /// Wait until [`Event::Update`] / the timer has elapsed /// and than clear the event. fn wait(&mut self) -> nb::Result<(), Void> { - if !self.tim.is_sr_uief_set() { - Err(nb::Error::WouldBlock) - } else { + if self.tim.is_sr_uief_set() { self.clear_event(Event::Update); Ok(()) + } else { + Err(nb::Error::WouldBlock) } } } diff --git a/src/timer/interrupts.rs b/src/timer/interrupts.rs index d97c98cec..96a4256a5 100644 --- a/src/timer/interrupts.rs +++ b/src/timer/interrupts.rs @@ -84,7 +84,7 @@ pub(crate) const TIM8_TYPES: InterruptTypes = InterruptTypes { capture_compare: Interrupt::TIM8_CC, }; -#[cfg(all(feature = "svd-f303"))] +#[cfg(feature = "svd-f303")] pub(crate) const TIM20_TYPES: InterruptTypes = InterruptTypes { r#break: Interrupt::TIM20_BRK, update: Interrupt::TIM20_UP, diff --git a/src/usb.rs b/src/usb.rs index 5ff014d6a..488747367 100644 --- a/src/usb.rs +++ b/src/usb.rs @@ -16,6 +16,7 @@ use stm32_usbd::UsbPeripheral; use crate::gpio; use crate::gpio::gpioa::{PA11, PA12}; +#[allow(clippy::module_name_repetitions)] pub use stm32_usbd::UsbBus; /// Trait implemented by all pins that can be the "D-" pin for the USB peripheral @@ -78,7 +79,7 @@ where unsafe impl Sync for Peripheral {} unsafe impl UsbPeripheral for Peripheral { - const REGISTERS: *const () = USB::ptr() as *const (); + const REGISTERS: *const () = USB::ptr().cast::<()>(); const DP_PULL_UP_FEATURE: bool = false; const EP_MEMORY: *const () = 0x4000_6000 as _; #[cfg(any(feature = "stm32f303xb", feature = "stm32f303xc"))] @@ -107,8 +108,9 @@ unsafe impl UsbPeripheral for Peripheral>, Dp = PA12>> = UsbBus>; diff --git a/src/watchdog.rs b/src/watchdog.rs index ee35c8565..95252ef39 100644 --- a/src/watchdog.rs +++ b/src/watchdog.rs @@ -59,6 +59,7 @@ impl IndependentWatchDog { /// Call [`start`](WatchdogEnable::start) to start the watchdog. /// /// See [`WatchdogEnable`] and [`Watchdog`] for more info. + #[must_use] pub fn new(iwdg: IWDG) -> Self { IndependentWatchDog { iwdg } } @@ -98,6 +99,7 @@ impl IndependentWatchDog { self.access_registers(|iwdg| { iwdg.pr.modify(|_, w| w.pr().bits(psc)); + #[allow(clippy::cast_possible_truncation)] iwdg.rlr.modify(|_, w| w.rl().bits(reload as u16)); }); @@ -120,6 +122,7 @@ impl IndependentWatchDog { } /// Returns the currently set interval + #[must_use] pub fn interval(&self) -> Milliseconds { // If the prescaler was changed wait until the change procedure is finished. while self.iwdg.sr.read().pvu().bit() {} From f428bb6548d015b574cd33517489a24b7d57de4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nanoma=C5=A1ine=20sinko?= <18175585+dpralas@users.noreply.github.com> Date: Fri, 24 Nov 2023 10:31:42 +0100 Subject: [PATCH 14/25] Add channel impls for pins PE9 and PE10 when using stm32f303xe feature (#345) --- CHANGELOG.md | 2 ++ src/adc/channel.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b7326337..10c2ab0a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Add missing ADC channels ([#337]) - Add many `#[must_use]` instances ([#347]) +- Add missing ADC channels ([#345]) ### Fixed @@ -598,6 +599,7 @@ let clocks = rcc [defmt]: https://github.com/knurling-rs/defmt [filter]: https://defmt.ferrous-systems.com/filtering.html +[#345]: https://github.com/stm32-rs/stm32f3xx-hal/pull/345 [#346]: https://github.com/stm32-rs/stm32f3xx-hal/pull/346 [#347]: https://github.com/stm32-rs/stm32f3xx-hal/pull/347 [#340]: https://github.com/stm32-rs/stm32f3xx-hal/pull/340 diff --git a/src/adc/channel.rs b/src/adc/channel.rs index 53387d073..caf7ab566 100644 --- a/src/adc/channel.rs +++ b/src/adc/channel.rs @@ -294,6 +294,8 @@ cfg_if::cfg_if! { (PD13, [(ADC3, Id::Ten), (ADC4, Id::Ten)]), (PD14, [(ADC3, Id::Eleven), (ADC4, Id::Eleven)]), (PD9, [(ADC4, Id::Thirteen)]), + (PE9, [(ADC3, Id::Two)]), + (PE10, [(ADC3, Id::Fourteen)]), (PE11, [(ADC3, Id::Fifteen)]), (PE12, [(ADC3, Id::Sixteen)]), (PE7, [(ADC3, Id::Thirteen)]), From ce7ebb12aa0cd1672dce8dad772631c2e44573b4 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Nov 2023 08:30:32 +0100 Subject: [PATCH 15/25] Deprecate pwm implementation (#352) --- CHANGELOG.md | 8 ++++++++ examples/pwm.rs | 5 +++++ src/pwm.rs | 1 + 3 files changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10c2ab0a9..dc75059f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Fix wrong timer frequency calculation and unexpected panics ([#338]) +### Changed + +- The PWM implementation was deprecated. There is not yet an alternative + implementation, but it is hard to maintain the current implementation + and not easy to verify if it is really a safe implementation. + It is also not consistent with the rest of the crates API. ([#352]) + ## [v0.9.2] - 2023-02-20 ### Added @@ -599,6 +606,7 @@ let clocks = rcc [defmt]: https://github.com/knurling-rs/defmt [filter]: https://defmt.ferrous-systems.com/filtering.html +[#352]: https://github.com/stm32-rs/stm32f3xx-hal/pull/352 [#345]: https://github.com/stm32-rs/stm32f3xx-hal/pull/345 [#346]: https://github.com/stm32-rs/stm32f3xx-hal/pull/346 [#347]: https://github.com/stm32-rs/stm32f3xx-hal/pull/347 diff --git a/examples/pwm.rs b/examples/pwm.rs index 3a00c49d7..a354c91ec 100644 --- a/examples/pwm.rs +++ b/examples/pwm.rs @@ -17,6 +17,7 @@ use hal::flash::FlashExt; use hal::gpio::GpioExt; use hal::pac; use hal::prelude::*; +#[allow(deprecated)] use hal::pwm::{tim16, tim2, tim3, tim8}; use hal::rcc::RccExt; @@ -70,6 +71,7 @@ fn main() -> ! { // TIM3 // // A four channel general purpose timer that's broadly available + #[allow(deprecated)] let tim3_channels = tim3( dp.TIM3, 1280, // resolution of duty cycle @@ -119,6 +121,7 @@ fn main() -> ! { // TIM2 // // A 32-bit timer, so we can set a larger resolution + #[allow(deprecated)] let tim2_channels = tim2( dp.TIM2, 160000, // resolution of duty cycle @@ -134,6 +137,7 @@ fn main() -> ! { // // A single channel timer, so it doesn't return a tuple. We can // just use it directly + #[allow(deprecated)] let mut tim16_ch1 = tim16( dp.TIM16, 1280, // resolution of duty cycle @@ -148,6 +152,7 @@ fn main() -> ! { // // An advanced timer with complementary outputs, so we can output // to complementary pins (works just like standard pins) + #[allow(deprecated)] let tim8_channels = tim8( dp.TIM8, 1280, // resolution of duty cycle diff --git a/src/pwm.rs b/src/pwm.rs index cd5518ee7..dc4bece8d 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -282,6 +282,7 @@ macro_rules! pwm_timer_private { /// of exactly one degree. #[allow(unused_parens)] #[must_use] + #[deprecated(since = "0.10.0", note = "needs refactoring and might violate safety rules conflicting with the timer API")] pub fn $timx(tim: $TIMx, res: $res, freq: Hertz, clocks: &Clocks) -> ($(PwmChannel<$TIMx_CHy, NoPins>),+) { // Power the timer and reset it to ensure a clean state // We use unsafe here to abstract away this implementation detail From 483a8e59572e7dd346dc36e7ed6da2fc7a07878c Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Nov 2023 09:10:57 +0100 Subject: [PATCH 16/25] Update github actions (#355) --- .github/workflows/cargo.yml | 25 +++++ .github/workflows/changelog.yml | 20 ++++ .github/workflows/ci.yml | 163 ++------------------------------ .github/workflows/clippy.yml | 21 ++++ .github/workflows/codegen.yml | 20 ++++ .github/workflows/markdown.yml | 31 ++++++ .github/workflows/msrv.yml | 39 ++++++++ .github/workflows/rustfmt.yml | 20 ++++ CHANGELOG.md | 4 +- 9 files changed, 188 insertions(+), 155 deletions(-) create mode 100644 .github/workflows/cargo.yml create mode 100644 .github/workflows/changelog.yml create mode 100644 .github/workflows/clippy.yml create mode 100644 .github/workflows/codegen.yml create mode 100644 .github/workflows/markdown.yml create mode 100644 .github/workflows/msrv.yml create mode 100644 .github/workflows/rustfmt.yml diff --git a/.github/workflows/cargo.yml b/.github/workflows/cargo.yml new file mode 100644 index 000000000..515133509 --- /dev/null +++ b/.github/workflows/cargo.yml @@ -0,0 +1,25 @@ +name: rust format + +on: + push: + branches: [master] + pull_request: + merge_group: + + check-doc: + name: Check Documentation Build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + toolchain: nightly + target: thumbv7em-none-eabihf + - run: cargo doc --features=stm32f303xc + + cargo-deny: + name: Cargo Deny + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: EmbarkStudios/cargo-deny-action@v1 diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml new file mode 100644 index 000000000..87d77ef4e --- /dev/null +++ b/.github/workflows/changelog.yml @@ -0,0 +1,20 @@ +on: + pull_request_target: + types: [labeled, unlabeled, opened, synchronize, reopened] + +name: Changelog check + +jobs: + changelog: + name: Changelog check + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Changelog updated + uses: Zomzog/changelog-checker@v1.3.0 + with: + fileName: CHANGELOG.md + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index efc3fa338..d3cc7654e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,6 +4,7 @@ on: push: branches: [master] pull_request: + merge_group: jobs: check: @@ -38,177 +39,31 @@ jobs: # - stm32f334x6 # - stm32f334x8 steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable with: toolchain: stable target: thumbv7em-none-eabihf - override: true - profile: minimal - run: cargo build --features=${{ matrix.mcu }} --lib --examples - # This is our MSRV. However this is only for documentation - # purposes and should be increased if newer features are used. - # This should not stop anyone from bumping the MSRV. - check-msrv: - name: Check MSRV - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 - with: - toolchain: 1.59.0 - target: thumbv7em-none-eabihf - override: true - profile: minimal - - uses: actions-rs/cargo@v1 - with: - command: check - args: --features=stm32f303xc,stm32-usbd,rt,can,ld --lib - - check-min-deps: - name: Check Minimal Dependency Versions - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - target: thumbv7em-none-eabihf - override: true - profile: minimal - - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly - target: thumbv7em-none-eabihf - profile: minimal - - run: cargo +nightly update -Z minimal-versions - - uses: actions-rs/cargo@v1 - with: - command: check - args: --features=stm32f303xc,stm32-usbd,rt,can,ld --lib --examples - check-minimal-feature-set: name: Check minimal feature set runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable with: toolchain: stable target: thumbv7em-none-eabihf - override: true - profile: minimal - - uses: actions-rs/cargo@v1 - with: - command: check - args: --no-default-features --features=stm32f303xc --lib --examples + - run: cargo check --no-default-features --features=stm32f303xc --lib --examples build-testsuite: name: Build Testsuite runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable with: toolchain: stable target: thumbv7em-none-eabihf - override: true - profile: minimal - - uses: actions-rs/cargo@v1 - with: - command: test - args: -p testsuite --no-run - - check-doc: - name: Check Documentation Build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly - target: thumbv7em-none-eabihf - override: true - profile: minimal - - uses: actions-rs/cargo@v1 - with: - command: doc - args: --features=stm32f303xc - - clippy: - name: Clippy - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - target: thumbv7em-none-eabihf - override: true - profile: minimal - components: clippy - - uses: actions-rs/clippy-check@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - args: > - --features=stm32f303xc --lib --examples - -- -D warnings - - rustfmt: - name: Rustfmt - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - profile: minimal - components: rustfmt - - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --all -- --check - - codegen: - name: Check Codegen - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - profile: minimal - components: rustfmt - - run: cargo check --target "x86_64-unknown-linux-gnu" -p codegen - - markdown-lint: - name: Markdown Lint - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: nosborn/github-action-markdown-cli@v2.0.0 - with: - files: . - config_file: .markdownlint.yml - ignore_files: target/ - - link-checker: - name: Link Checker - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Check URLs in documentation - uses: lycheeverse/lychee-action@v1.0.8 - with: - args: --verbose --no-progress "**/*.md" "**/*.rs" "Cargo.toml" "**/Cargo.toml" -h accept=text/html - - cargo-deny: - name: Cargo Deny - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: EmbarkStudios/cargo-deny-action@v1 + - run: cargo test -p testsuite --no-run diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml new file mode 100644 index 000000000..3e3118a8f --- /dev/null +++ b/.github/workflows/clippy.yml @@ -0,0 +1,21 @@ +name: clippy + +on: + push: + branches: [master] + pull_request: + merge_group: + +jobs: + clippy: + name: Clippy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + target: thumbv7em-none-eabihf + components: clippy + - run: cargo clippy --features=stm32f303xc --lib --examples -- -D warnings + diff --git a/.github/workflows/codegen.yml b/.github/workflows/codegen.yml new file mode 100644 index 000000000..01e935d93 --- /dev/null +++ b/.github/workflows/codegen.yml @@ -0,0 +1,20 @@ +name: codegen +on: + push: + branches: [master] + pull_request: + merge_group: + +jobs: + codegen: + name: Check Codegen + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + component: clippy + target: x86_64-unknown-linux-gnu + - run: cargo clippy -p codegen --target x86_64-unknown-linux-gnu + diff --git a/.github/workflows/markdown.yml b/.github/workflows/markdown.yml new file mode 100644 index 000000000..164df0371 --- /dev/null +++ b/.github/workflows/markdown.yml @@ -0,0 +1,31 @@ +name: markdown + +on: + push: + branches: [master] + pull_request: + merge_group: + +jobs: + markdown-lint: + name: Markdown Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: nosborn/github-action-markdown-cli@v3.3.0 + with: + files: . + config_file: .markdownlint.yml + ignore_files: target/ + + link-checker: + name: Link Checker + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Check URLs in documentation + uses: lycheeverse/lychee-action@v1.8.0 + with: + args: --verbose --no-progress "**/*.md" "**/*.rs" "Cargo.toml" "**/Cargo.toml" -h accept=text/html + diff --git a/.github/workflows/msrv.yml b/.github/workflows/msrv.yml new file mode 100644 index 000000000..c7fd6e911 --- /dev/null +++ b/.github/workflows/msrv.yml @@ -0,0 +1,39 @@ +name: MSRV + +on: + push: + branches: [master] + pull_request: + merge_group: + +jobs: + # This is our MSRV. However this is only for documentation + # purposes and should be increased if newer features are used. + # This should not stop anyone from bumping the MSRV. + check-msrv: + name: Check MSRV + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + toolchain: 1.59.0 + target: thumbv7em-none-eabihf + - run: cargo check --features=stm32f303xc,stm32-usbd,rt,can,ld --lib + + check-min-deps: + name: Check Minimal Dependency Versions + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + target: thumbv7em-none-eabihf + - uses: dtolnay/rust-toolchain@stable + with: + toolchain: nightly + target: thumbv7em-none-eabihf + - run: cargo +nightly update -Z minimal-versions + - run: cargo check --features=stm32f303xc,stm32-usbd,rt,can,ld --lib --examples + diff --git a/.github/workflows/rustfmt.yml b/.github/workflows/rustfmt.yml new file mode 100644 index 000000000..4f65f58b7 --- /dev/null +++ b/.github/workflows/rustfmt.yml @@ -0,0 +1,20 @@ +name: rust format + +on: + push: + branches: [master] + pull_request: + merge_group: + +jobs: + rustfmt: + name: Rustfmt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + components: rustfmt + - run: cargo fmt --all --check + diff --git a/CHANGELOG.md b/CHANGELOG.md index dc75059f3..c28d8e85f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Add `impl From for Switch` to reduce churn. - Fix undefined behavior in SPI implementation ([#346]) - Add `num_traits::PrimInt` bounds to `Word` +- Remove `Serial::split`, which possibly creates two mutable references two + one Serial instance, which could've caused UB. The use case of this function + was hard to find out anyway. ([#352]) ### Added @@ -722,7 +725,6 @@ let clocks = rcc [v0.9.1]: https://github.com/stm32-rs/stm32f3xx-hal/releases/tag/v0.9.1 [v0.9.0]: https://github.com/stm32-rs/stm32f3xx-hal/releases/tag/v0.9.0 [v0.8.1]: https://github.com/stm32-rs/stm32f3xx-hal/releases/tag/v0.8.1 -[v0.8.1]: https://github.com/stm32-rs/stm32f3xx-hal/releases/tag/v0.8.1 [v0.8.0]: https://github.com/stm32-rs/stm32f3xx-hal/releases/tag/v0.8.0 [v0.7.0]: https://github.com/stm32-rs/stm32f3xx-hal/releases/tag/v0.7.0 [v0.6.1]: https://github.com/stm32-rs/stm32f3xx-hal/releases/tag/v0.6.1 From 0525d2de979d3084f2ec98dd271bc61991f95a00 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Nov 2023 09:17:34 +0100 Subject: [PATCH 17/25] Remove Serial::split (#351) --- CHANGELOG.md | 3 +- src/dma.rs | 6 - src/serial.rs | 333 ---------------------------------------- testsuite/tests/uart.rs | 29 +--- 4 files changed, 10 insertions(+), 361 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c28d8e85f..939ecfb9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,7 +26,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Add `num_traits::PrimInt` bounds to `Word` - Remove `Serial::split`, which possibly creates two mutable references two one Serial instance, which could've caused UB. The use case of this function - was hard to find out anyway. ([#352]) + was hard to find out anyway. ([#351]) ### Added @@ -610,6 +610,7 @@ let clocks = rcc [filter]: https://defmt.ferrous-systems.com/filtering.html [#352]: https://github.com/stm32-rs/stm32f3xx-hal/pull/352 +[#351]: https://github.com/stm32-rs/stm32f3xx-hal/pull/351 [#345]: https://github.com/stm32-rs/stm32f3xx-hal/pull/345 [#346]: https://github.com/stm32-rs/stm32f3xx-hal/pull/346 [#347]: https://github.com/stm32-rs/stm32f3xx-hal/pull/347 diff --git a/src/dma.rs b/src/dma.rs index 211462d0d..96bcc315d 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -571,8 +571,6 @@ dma!( 2: { 1,2,3,4,5 } ); /// Marker trait mapping DMA targets to their channels pub trait OnChannel: Target + crate::private::Sealed {} -use crate::serial::{RxPin, TxPin}; - macro_rules! on_channel { ( $( @@ -581,10 +579,6 @@ macro_rules! on_channel { ) => { $( $( - impl crate::private::Sealed for serial::Tx<$USART, Pin> {} - impl OnChannel<$dma::$TxChannel> for serial::Tx<$USART, Pin> where Pin: TxPin<$USART> {} - impl crate::private::Sealed for serial::Rx<$USART, Pin> {} - impl OnChannel<$dma::$RxChannel> for serial::Rx<$USART, Pin> where Pin: RxPin<$USART> {} impl crate::private::Sealed for serial::Serial<$USART, (Tx, Rx)> {} impl OnChannel<$dma::$TxChannel> for serial::Serial<$USART, (Tx, Rx)> {} impl OnChannel<$dma::$RxChannel> for serial::Serial<$USART, (Tx, Rx)> {} diff --git a/src/serial.rs b/src/serial.rs index bf9e37239..ae8b62068 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -17,7 +17,6 @@ use crate::{ gpio::{gpioa, gpiob, gpioc, AF7}, hal::{blocking, serial, serial::Write}, pac::{ - self, rcc::cfgr3::USART1SW_A, usart1::{cr1::M_A, cr1::PCE_A, cr1::PS_A, RegisterBlock}, Interrupt, USART1, USART2, USART3, @@ -36,7 +35,6 @@ use cfg_if::cfg_if; use enumset::{EnumSet, EnumSetType}; use crate::dma; -use cortex_m::interrupt; /// Interrupt and status events. /// @@ -332,128 +330,6 @@ pub struct Serial { pins: Pins, } -mod split { - use super::Instance; - /// Serial receiver - #[derive(Debug)] - #[cfg_attr(feature = "defmt", derive(defmt::Format))] - pub struct Rx { - usart: Usart, - pub(crate) pin: Pin, - } - - /// Serial transmitter - #[derive(Debug)] - #[cfg_attr(feature = "defmt", derive(defmt::Format))] - pub struct Tx { - usart: Usart, - pub(crate) pin: Pin, - } - - impl Tx - where - Usart: Instance, - Pin: super::TxPin, - { - pub(crate) fn new(usart: Usart, pin: Pin) -> Self { - Tx { usart, pin } - } - - /// Destruct [`Tx`] to regain access to underlying USART and pin. - pub(crate) fn free(self) -> (Usart, Pin) { - (self.usart, self.pin) - } - } - - impl Tx - where - Usart: Instance, - { - /// Get a reference to internal usart peripheral - /// - /// # Safety - /// - /// This is unsafe, because the creation of this struct - /// is only possible by splitting the the USART peripheral - /// into Tx and Rx, which are internally both pointing - /// to the same peripheral. - /// - /// Therefor, if getting a mutuable reference to the peripheral - /// or changing any of it's configuration, the exclusivity - /// is no longer guaranteed by the type system. - /// - /// Ensure that the Tx and Rx implemtation only do things with - /// the peripheral, which do not effect the other. - pub(crate) unsafe fn usart(&self) -> &Usart { - &self.usart - } - - /// Get a reference to internal usart peripheral - /// - /// # Saftey - /// - /// Same as in [`Self::usart()`]. - #[allow(dead_code)] - pub(crate) unsafe fn usart_mut(&mut self) -> &mut Usart { - &mut self.usart - } - } - - impl Rx - where - Usart: Instance, - Pin: super::RxPin, - { - pub(crate) fn new(usart: Usart, pin: Pin) -> Self { - Rx { usart, pin } - } - - /// Destruct [`Rx`] to regain access to the underlying pin. - /// - /// The USART is omitted, as it is returnend from Tx already to avoid - /// beeing able to crate a duplicate reference to the same underlying - /// peripheral. - pub(crate) fn free(self) -> Pin { - self.pin - } - } - - impl Rx - where - Usart: Instance, - { - /// Get a reference to internal usart peripheral - /// - /// # Safety - /// - /// This is unsafe, because the creation of this struct - /// is only possible by splitting the the USART peripheral - /// into Tx and Rx, which are internally both pointing - /// to the same peripheral. - /// - /// Therefor, if getting a mutuable reference to the peripheral - /// or changing any of it's configuration, the exclusivity - /// is no longer guaranteed by the type system. - /// - /// Ensure that the Tx and Rx implemtation only do things with - /// the peripheral, which do not effect the other. - pub(crate) unsafe fn usart(&self) -> &Usart { - &self.usart - } - - /// Get a reference to internal usart peripheral - /// - /// # Saftey - /// - /// Same as in [`Self::usart()`]. - pub(crate) unsafe fn usart_mut(&mut self) -> &mut Usart { - &mut self.usart - } - } -} - -pub use split::{Rx, Tx}; - impl Serial where Usart: Instance, @@ -543,35 +419,6 @@ where .modify(|_, w| w.ue().disabled().re().disabled().te().disabled()); (self.usart, self.pins) } - - /// Joins previously [`Serial::split()`] serial. - /// - /// This is often needed to access methods only implemented for [`Serial`] - /// but not for [`Tx`] nor [`Rx`]. - /// - /// # Example - /// - /// ``` - /// let dp = pac::Peripherals::take().unwrap(); - /// - /// (tx, rx) = Serial::new(dp.USART1, ...).split(); - /// - /// // Do something with tx and rx - /// - /// serial = Serial::join(tx, rx); - /// ``` - pub fn join(tx: split::Tx, rx: split::Rx) -> Self - where - Tx: TxPin, - Rx: RxPin, - { - let (usart, tx_pin) = tx.free(); - let rx_pin = rx.free(); - Self { - usart, - pins: (tx_pin, rx_pin), - } - } } impl Serial @@ -965,19 +812,6 @@ where } } -impl serial::Read for Rx -where - Usart: Instance, - Pin: RxPin, -{ - type Error = Error; - - /// This implementation shares the same effects as the [`Serial`]s [`serial::Read`] implemenation. - fn read(&mut self) -> nb::Result { - eh_read(unsafe { self.usart_mut() }) - } -} - impl serial::Write for Serial where Usart: Instance, @@ -1022,145 +856,6 @@ impl blocking::serial::write::Default for Serial serial::Write for Tx -where - Usart: Instance, - Pin: TxPin, -{ - // NOTE(Infallible) See section "29.7 USART interrupts"; the only possible errors during - // transmission are: clear to send (which is disabled in this case) errors and - // framing errors (which only occur in SmartCard mode); neither of these apply to - // our hardware configuration - type Error = Infallible; - - fn flush(&mut self) -> nb::Result<(), Infallible> { - let isr = unsafe { self.usart().isr.read() }; - - if isr.tc().bit_is_set() { - Ok(()) - } else { - Err(nb::Error::WouldBlock) - } - } - - fn write(&mut self, byte: u8) -> nb::Result<(), Infallible> { - // NOTE(unsafe) atomic read with no side effects - let isr = unsafe { self.usart().isr.read() }; - - if isr.txe().bit_is_set() { - // NOTE(unsafe) atomic write to stateless register - unsafe { self.usart().tdr.write(|w| w.tdr().bits(u16::from(byte))) }; - Ok(()) - } else { - Err(nb::Error::WouldBlock) - } - } -} - -impl fmt::Write for Tx -where - Tx: serial::Write, -{ - fn write_str(&mut self, s: &str) -> fmt::Result { - s.bytes() - .try_for_each(|c| nb::block!(self.write(c))) - .map_err(|_| fmt::Error) - } -} - -impl Rx -where - Usart: Instance + Dma, -{ - /// Fill the buffer with received data using DMA. - pub fn read_exact(self, buffer: B, mut channel: C) -> dma::Transfer - where - Self: dma::OnChannel, - B: dma::WriteBuffer + 'static, - C: dma::Channel, - { - // NOTE(unsafe) usage of a valid peripheral address - unsafe { - channel.set_peripheral_address( - core::ptr::addr_of!(self.usart().rdr) as u32, - dma::Increment::Disable, - ); - }; - - dma::Transfer::start_write(buffer, channel, self) - } -} - -impl blocking::serial::write::Default for Tx -where - Usart: Instance, - Pin: TxPin, -{ -} - -impl Tx -where - Usart: Instance + Dma, - Pin: TxPin, -{ - /// Transmit all data in the buffer using DMA. - pub fn write_all(self, buffer: B, mut channel: C) -> dma::Transfer - where - Self: dma::OnChannel, - B: dma::ReadBuffer + 'static, - C: dma::Channel, - { - // NOTE(unsafe) usage of a valid peripheral address - unsafe { - channel.set_peripheral_address( - core::ptr::addr_of!(self.usart().tdr) as u32, - dma::Increment::Disable, - ); - }; - - dma::Transfer::start_read(buffer, channel, self) - } -} - -impl dma::Target for Rx -where - Usart: Instance + Dma, -{ - fn enable_dma(&mut self) { - // NOTE(unsafe) critical section prevents races - interrupt::free(|_| unsafe { - self.usart().cr3.modify(|_, w| w.dmar().enabled()); - }); - } - - fn disable_dma(&mut self) { - // NOTE(unsafe) critical section prevents races - interrupt::free(|_| unsafe { - self.usart().cr3.modify(|_, w| w.dmar().disabled()); - }); - } -} - -impl dma::Target for Tx -where - Usart: Instance + Dma, - Pin: TxPin, -{ - fn enable_dma(&mut self) { - // NOTE(unsafe) critical section prevents races - interrupt::free(|_| unsafe { - self.usart().cr3.modify(|_, w| w.dmat().enabled()); - }); - } - - fn disable_dma(&mut self) { - // NOTE(unsafe) critical section prevents races - interrupt::free(|_| unsafe { - self.usart().cr3.modify(|_, w| w.dmat().disabled()); - }); - } -} - impl Serial where Usart: Instance + Dma, @@ -1259,34 +954,6 @@ macro_rules! usart { const INTERRUPT: Interrupt = $INTERRUPT; } - impl Serial<$USARTX, (Tx, Rx)> - where Tx: TxPin<$USARTX>, Rx: RxPin<$USARTX> { - /// Splits the [`Serial`] abstraction into a transmitter and a receiver half. - /// - /// This allows using [`Tx`] and [`Rx`] related actions to - /// be handled independently and even use these safely in different - /// contexts (like interrupt routines) without needing to do synchronization work - /// between them. - pub fn split(self) -> (split::Tx<$USARTX, Tx>, split::Rx<$USARTX, Rx>) { - // NOTE(unsafe): This essentially duplicates the USART peripheral - // - // As RX and TX both do have direct access to the peripheral, - // they must guarantee to only do atomic operations on the peripheral - // registers to avoid data races. - // - // Tx and Rx won't access the same registers anyways, - // as they have independent responsibilities, which are NOT represented - // in the type system. - let (tx, rx) = unsafe { - ( - pac::Peripherals::steal().$USARTX, - pac::Peripherals::steal().$USARTX, - ) - }; - (split::Tx::new(tx, self.pins.0), split::Rx::new(rx, self.pins.1)) - } - } - #[cfg(feature = "defmt")] impl defmt::Format for Serial<$USARTX, Pins> { fn format(&self, f: defmt::Formatter) { diff --git a/testsuite/tests/uart.rs b/testsuite/tests/uart.rs index 31fe5c219..8a2fd933c 100644 --- a/testsuite/tests/uart.rs +++ b/testsuite/tests/uart.rs @@ -178,19 +178,6 @@ mod tests { } } - #[test] - fn send_receive_split(state: &mut super::State) { - let (mut tx, mut rx) = unwrap!(state.serial1.take()).split(); - - for i in TEST_MSG { - defmt::unwrap!(nb::block!(tx.write(i))); - let c = unwrap!(nb::block!(rx.read())); - assert_eq!(c, i); - } - - state.serial1 = Some(Serial::join(tx, rx)); - } - #[test] fn test_overrun(state: &mut super::State) { let (usart, pins) = unwrap!(state.serial1.take()).free(); @@ -340,20 +327,20 @@ mod tests { #[test] fn send_receive_wrong_baud(state: &mut super::State) { - let (mut tx_slow, mut rx_slow) = unwrap!(state.serial_slow.take()).split(); - let (mut tx_fast, mut rx_fast) = unwrap!(state.serial_fast.take()).split(); + let mut usart_slow = unwrap!(state.serial_slow.take()); + let mut usart_fast = unwrap!(state.serial_fast.take()); // provoke an error (framing) - unwrap!(nb::block!(tx_slow.write(b'a'))); - let c = nb::block!(rx_fast.read()); + unwrap!(nb::block!(usart_slow.write(b'a'))); + let c = nb::block!(usart_fast.read()); defmt::debug!("{}", c); assert!(matches!(c, Err(Error::Framing))); // provoke an error (this does not seem to be absolutely deterministic // and we've seen multiple error variants in the wild, including // receiving the wrong but valid character) - unwrap!(nb::block!(tx_fast.write(b'a'))); - let result = nb::block!(rx_slow.read()); + unwrap!(nb::block!(usart_fast.write(b'a'))); + let result = nb::block!(usart_slow.read()); defmt::debug!("{}", result); assert!(match result { Ok(c) => { @@ -364,8 +351,8 @@ mod tests { Err(_) => false, }); - state.serial_slow = Some(Serial::join(tx_slow, rx_slow)); - state.serial_fast = Some(Serial::join(tx_fast, rx_fast)); + state.serial_slow = Some(usart_slow); + state.serial_fast = Some(usart_fast); } // TODO: Currently, this is a limited test, just to see, that From b4bb14c1d18518f31dcd224532d64b4d8db66e25 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Nov 2023 09:21:50 +0100 Subject: [PATCH 18/25] Use probe-rs instead of deprecated probe-run (#353) --- .cargo/config.toml | 2 +- testsuite/README.md | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index a20d9768d..5f4ae2d94 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -10,7 +10,7 @@ [target.thumbv7em-none-eabihf] # runner = "arm-none-eabi-gdb" # Chip can be set via `--chip STM32F303VCTx` or `export PROBE_RUN_CHIP=STM32F303VCTx` -runner = "probe-run --chip STM32F303VCTx --connect-under-reset" +runner = "probe-rs run --chip STM32F303VCTx --connect-under-reset" rustflags = [ "-C", "link-arg=--nmagic", "-C", "link-arg=-Tlink.x", diff --git a/testsuite/README.md b/testsuite/README.md index c7ca3c716..dd901758d 100644 --- a/testsuite/README.md +++ b/testsuite/README.md @@ -4,7 +4,11 @@ Tests are run via the integration test pattern and are executed on a target chip, rather than on a host system. First, install -[probe-run](https://crates.io/crates/probe-run) via `cargo install probe-run`. +[probe-rs](https://crates.io/crates/probe-rs) via + +```sh +cargo install probe-rs --features cli +``` Currently the tests are written for the `stm32f303xc` with the STM32F3Discovery Board in mind. They expect that several pins are wired together as hinted in From 22de3d03dc019dc21b54ce35b9f51fc0747aa02f Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Nov 2023 09:23:45 +0100 Subject: [PATCH 19/25] Enforce documenting unsafe code (#348) --- src/adc.rs | 47 ++++++++++++++++++++++----------------- src/can.rs | 2 ++ src/dac.rs | 2 ++ src/dma.rs | 58 +++++++++++++++++++++++++++++------------------- src/gpio.rs | 22 +++++++++++------- src/i2c.rs | 2 +- src/lib.rs | 3 +++ src/pwm.rs | 4 ++++ src/rcc.rs | 10 ++++++--- src/rtc.rs | 5 +++-- src/serial.rs | 8 +++---- src/signature.rs | 46 +++++++++++++++++++++++++------------- src/syscfg.rs | 20 +++++++++-------- src/timer.rs | 2 +- src/usb.rs | 5 +++++ 15 files changed, 149 insertions(+), 87 deletions(-) diff --git a/src/adc.rs b/src/adc.rs index 66689e465..e2b1b645f 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -1025,23 +1025,26 @@ where } // Set the channel in the right sequence field - match sequence { - config::Sequence::One => self.reg.sqr1.modify(|_, w| w.sq1().bits(channel.into())), - config::Sequence::Two => self.reg.sqr1.modify(|_, w| w.sq2().bits(channel.into())), - config::Sequence::Three => self.reg.sqr1.modify(|_, w| w.sq3().bits(channel.into())), - config::Sequence::Four => self.reg.sqr1.modify(|_, w| w.sq4().bits(channel.into())), - config::Sequence::Five => self.reg.sqr2.modify(|_, w| w.sq5().bits(channel.into())), - config::Sequence::Six => self.reg.sqr2.modify(|_, w| w.sq6().bits(channel.into())), - config::Sequence::Seven => self.reg.sqr2.modify(|_, w| w.sq7().bits(channel.into())), - config::Sequence::Eight => self.reg.sqr2.modify(|_, w| w.sq8().bits(channel.into())), - config::Sequence::Nine => self.reg.sqr2.modify(|_, w| w.sq9().bits(channel.into())), - config::Sequence::Ten => self.reg.sqr3.modify(|_, w| w.sq10().bits(channel.into())), - config::Sequence::Eleven => self.reg.sqr3.modify(|_, w| w.sq11().bits(channel.into())), - config::Sequence::Twelve => self.reg.sqr3.modify(|_, w| w.sq12().bits(channel.into())), - config::Sequence::Thirteen => self.reg.sqr3.modify(|_, w| w.sq13().bits(channel.into())), - config::Sequence::Fourteen => self.reg.sqr3.modify(|_, w| w.sq14().bits(channel.into())), - config::Sequence::Fifteen => self.reg.sqr4.modify(|_, w| w.sq15().bits(channel.into())), - config::Sequence::Sixteen => self.reg.sqr4.modify(|_, w| w.sq16().bits(channel.into())), + // SAFETY: the channel.into() implementation ensures that those are valid values + unsafe { + match sequence { + config::Sequence::One => self.reg.sqr1.modify(|_, w| w.sq1().bits(channel.into())), + config::Sequence::Two => self.reg.sqr1.modify(|_, w| w.sq2().bits(channel.into())), + config::Sequence::Three => self.reg.sqr1.modify(|_, w| w.sq3().bits(channel.into())), + config::Sequence::Four => self.reg.sqr1.modify(|_, w| w.sq4().bits(channel.into())), + config::Sequence::Five => self.reg.sqr2.modify(|_, w| w.sq5().bits(channel.into())), + config::Sequence::Six => self.reg.sqr2.modify(|_, w| w.sq6().bits(channel.into())), + config::Sequence::Seven => self.reg.sqr2.modify(|_, w| w.sq7().bits(channel.into())), + config::Sequence::Eight => self.reg.sqr2.modify(|_, w| w.sq8().bits(channel.into())), + config::Sequence::Nine => self.reg.sqr2.modify(|_, w| w.sq9().bits(channel.into())), + config::Sequence::Ten => self.reg.sqr3.modify(|_, w| w.sq10().bits(channel.into())), + config::Sequence::Eleven => self.reg.sqr3.modify(|_, w| w.sq11().bits(channel.into())), + config::Sequence::Twelve => self.reg.sqr3.modify(|_, w| w.sq12().bits(channel.into())), + config::Sequence::Thirteen => self.reg.sqr3.modify(|_, w| w.sq13().bits(channel.into())), + config::Sequence::Fourteen => self.reg.sqr3.modify(|_, w| w.sq14().bits(channel.into())), + config::Sequence::Fifteen => self.reg.sqr4.modify(|_, w| w.sq15().bits(channel.into())), + config::Sequence::Sixteen => self.reg.sqr4.modify(|_, w| w.sq16().bits(channel.into())), + } } } @@ -1323,10 +1326,14 @@ where /// Synchronously record a single sample of `pin`. fn read(&mut self, _pin: &mut Pin) -> nb::Result { + // NOTE: as ADC is not configurable (`OneShot` does not implement `Configurable`), we can't + // use the public methods to configure the ADC but have to fallback to the lower level + // methods. + // self.set_pin_sequence_position(config::Sequence::One, pin); - self.reg - .sqr1 - .modify(|_, w| unsafe { w.sq1().bits(Pin::channel().into()) }); + self.reg.sqr1.modify(|_, w| + // SAFETY: channel().into() ensure the right channel value + unsafe { w.sq1().bits(Pin::channel().into()) }); // Wait for the sequence to complete diff --git a/src/can.rs b/src/can.rs index 913d1c0a7..ce2c4637e 100644 --- a/src/can.rs +++ b/src/can.rs @@ -68,10 +68,12 @@ where } } +// SAFETY: Can has ownership of the CAN peripheral and the pointer is pointing to the CAN peripheral unsafe impl bxcan::Instance for Can { const REGISTERS: *mut RegisterBlock = pac::CAN::ptr() as *mut _; } +// SAFETY: The peripheral does own it's associated filter banks unsafe impl bxcan::FilterOwner for Can { const NUM_FILTER_BANKS: u8 = 28; } diff --git a/src/dac.rs b/src/dac.rs index 07d196711..a7e7b45e0 100644 --- a/src/dac.rs +++ b/src/dac.rs @@ -29,6 +29,8 @@ impl Dac { pub fn write_data(&mut self, data: u16) { self.regs.dhr12r1.write(|w| { #[allow(unused_unsafe)] + // SAFETY: Direct write to register for easier sharing between different stm32f3xx svd + // generated API unsafe { w.dacc1dhr().bits(data) } diff --git a/src/dma.rs b/src/dma.rs index 96bcc315d..089b38bde 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -64,21 +64,26 @@ impl Transfer { B: WriteBuffer + 'static, T: OnChannel, { - // NOTE(unsafe) We don't know the concrete type of `buffer` here, all + // SAFETY: We don't know the concrete type of `buffer` here, all // we can use are its `WriteBuffer` methods. Hence the only `&mut self` // method we can call is `write_buffer`, which is allowed by // `WriteBuffer`'s safety requirements. let (ptr, len) = unsafe { buffer.write_buffer() }; let len = crate::expect!(u16::try_from(len).ok(), "buffer is too large"); - // NOTE(unsafe) We are using the address of a 'static WriteBuffer here, + // SAFETY: We are using the address of a 'static WriteBuffer here, // which is guaranteed to be safe for DMA. unsafe { channel.set_memory_address(ptr as u32, Increment::Enable) }; channel.set_transfer_length(len); channel.set_word_size::(); channel.set_direction(Direction::FromPeripheral); - unsafe { Self::start(buffer, channel, target) } + // SAFTEY: we take ownership of the buffer, which is 'static as well, so it lives long + // enough (at least longer that the DMA transfer itself) + #[allow(clippy::undocumented_unsafe_blocks)] + unsafe { + Self::start(buffer, channel, target) + } } /// Start a DMA read transfer. @@ -91,21 +96,26 @@ impl Transfer { B: ReadBuffer + 'static, T: OnChannel, { - // NOTE(unsafe) We don't know the concrete type of `buffer` here, all + // SAFETY: We don't know the concrete type of `buffer` here, all // we can use are its `ReadBuffer` methods. Hence there are no // `&mut self` methods we can call, so we are safe according to // `ReadBuffer`'s safety requirements. let (ptr, len) = unsafe { buffer.read_buffer() }; let len = crate::expect!(u16::try_from(len).ok(), "buffer is too large"); - // NOTE(unsafe) We are using the address of a 'static ReadBuffer here, + // SAFETY: We are using the address of a 'static ReadBuffer here, // which is guaranteed to be safe for DMA. unsafe { channel.set_memory_address(ptr as u32, Increment::Enable) }; channel.set_transfer_length(len); channel.set_word_size::(); channel.set_direction(Direction::FromMemory); - unsafe { Self::start(buffer, channel, target) } + // SAFTEY: We take ownership of the buffer, which is 'static as well, so it lives long + // enough (at least longer that the DMA transfer itself) + #[allow(clippy::undocumented_unsafe_blocks)] + unsafe { + Self::start(buffer, channel, target) + } } /// # Safety @@ -315,7 +325,10 @@ pub trait Channel: private::Channel { unsafe fn set_peripheral_address(&mut self, address: u32, inc: Increment) { crate::assert!(!self.is_enabled()); - self.ch().par.write(|w| w.pa().bits(address)); + // SAFETY: If the caller does ensure, that address is valid address, this should be safe + unsafe { + self.ch().par.write(|w| w.pa().bits(address)); + } self.ch().cr.modify(|_, w| w.pinc().variant(inc.into())); } @@ -335,7 +348,10 @@ pub trait Channel: private::Channel { unsafe fn set_memory_address(&mut self, address: u32, inc: Increment) { crate::assert!(!self.is_enabled()); - self.ch().mar.write(|w| w.ma().bits(address)); + // SAFETY: If the caller does ensure, that address is valid address, this should be safe + unsafe { + self.ch().mar.write(|w| w.ma().bits(address)); + } self.ch().cr.modify(|_, w| w.minc().variant(inc.into())); } @@ -500,35 +516,31 @@ macro_rules! dma { impl private::Channel for $Ci { fn ch(&self) -> &pac::dma1::CH { - // NOTE(unsafe) $Ci grants exclusive access to this register + // SAFETY: $Ci grants exclusive access to this register unsafe { &(*$DMAx::ptr()).$chi } } } impl Channel for $Ci { fn is_event_triggered(&self, event: Event) -> bool { - use Event::*; - - // NOTE(unsafe) atomic read + // SAFETY: atomic read let flags = unsafe { (*$DMAx::ptr()).isr.read() }; match event { - HalfTransfer => flags.$htifi().bit_is_set(), - TransferComplete => flags.$tcifi().bit_is_set(), - TransferError => flags.$teifi().bit_is_set(), - Any => flags.$gifi().bit_is_set(), + Event::HalfTransfer => flags.$htifi().bit_is_set(), + Event::TransferComplete => flags.$tcifi().bit_is_set(), + Event::TransferError => flags.$teifi().bit_is_set(), + Event::Any => flags.$gifi().bit_is_set(), } } fn clear_event(&mut self, event: Event) { - use Event::*; - - // NOTE(unsafe) atomic write to a stateless register + // SAFETY: atomic write to a stateless register unsafe { (*$DMAx::ptr()).ifcr.write(|w| match event { - HalfTransfer => w.$chtifi().set_bit(), - TransferComplete => w.$ctcifi().set_bit(), - TransferError => w.$cteifi().set_bit(), - Any => w.$cgifi().set_bit(), + Event::HalfTransfer => w.$chtifi().set_bit(), + Event::TransferComplete => w.$ctcifi().set_bit(), + Event::TransferError => w.$cteifi().set_bit(), + Event::Any => w.$cgifi().set_bit(), }); } } diff --git a/src/gpio.rs b/src/gpio.rs index 0a1a75521..68869f2e6 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -181,13 +181,13 @@ impl defmt::Format for Gpiox { } } -// # SAFETY +// SAFETY: // As Gpiox uses `dyn GpioRegExt` pointer internally, `Send` is not auto-implemented. // But since GpioExt does only do atomic operations without side-effects we can assume // that it safe to `Send` this type. unsafe impl Send for Gpiox {} -// # SAFETY +// SAFETY: // As Gpiox uses `dyn GpioRegExt` pointer internally, `Sync` is not auto-implemented. // But since GpioExt does only do atomic operations without side-effects we can assume // that it safe to `Send` this type. @@ -500,13 +500,13 @@ where type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { - // NOTE(unsafe) atomic write to a stateless register + // SAFETY: atomic write to a stateless register unsafe { (*self.gpio.ptr()).set_high(self.index.index()) }; Ok(()) } fn set_low(&mut self) -> Result<(), Self::Error> { - // NOTE(unsafe) atomic write to a stateless register + // SAFETY: atomic write to a stateless register unsafe { (*self.gpio.ptr()).set_low(self.index.index()) }; Ok(()) } @@ -525,7 +525,7 @@ where } fn is_low(&self) -> Result { - // NOTE(unsafe) atomic read with no side effects + // SAFETY: atomic read with no side effects Ok(unsafe { (*self.gpio.ptr()).is_low(self.index.index()) }) } } @@ -540,7 +540,7 @@ where } fn is_set_low(&self) -> Result { - // NOTE(unsafe) atomic read with no side effects + // SAFETY: atomic read with no side effects Ok(unsafe { (*self.gpio.ptr()).is_set_low(self.index.index()) }) } } @@ -763,13 +763,13 @@ macro_rules! gpio_trait { #[inline(always)] fn set_high(&self, i: u8) { - // NOTE(unsafe, write) atomic write to a stateless register + // SAFETY: atomic write to a stateless register unsafe { self.bsrr.write(|w| w.bits(1 << i)) }; } #[inline(always)] fn set_low(&self, i: u8) { - // NOTE(unsafe, write) atomic write to a stateless register + // SAFETY: atomic write to a stateless register unsafe { self.bsrr.write(|w| w.bits(1 << (16 + i))) }; } } @@ -792,6 +792,8 @@ macro_rules! r_trait { #[inline] fn $fn(&mut self, i: u8) { let value = $gpioy::$xr::$enum::$VARIANT as u32; + // SAFETY: The &mut abstracts all accesses to the register itself, + // which makes sure that this register accesss is exclusive unsafe { crate::modify_at!((*$GPIOX::ptr()).$xr, $bitwidth, i, value) }; } )+ @@ -931,6 +933,8 @@ macro_rules! gpio { #[inline] fn afx(&mut self, i: u8, x: u8) { const BITWIDTH: u8 = 4; + // SAFETY: the abstraction of AFRL should ensure exclusive access in addition + // to the &mut exclusive reference unsafe { crate::modify_at!((*$GPIOX::ptr()).afrh, BITWIDTH, i - 8, x as u32) }; } } @@ -942,6 +946,8 @@ macro_rules! gpio { #[inline] fn afx(&mut self, i: u8, x: u8) { const BITWIDTH: u8 = 4; + // SAFETY: the abstraction of AFRL should ensure exclusive access in addition + // to the &mut exclusive reference unsafe { crate::modify_at!((*$GPIOX::ptr()).afrl, BITWIDTH, i, x as u32) }; } } diff --git a/src/i2c.rs b/src/i2c.rs index 6afef8353..9a4391441 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -472,7 +472,7 @@ macro_rules! i2c { $( impl Instance for $I2CX { fn clock(clocks: &Clocks) -> Hertz { - // NOTE(unsafe) atomic read with no side effects + // SAFETY: atomic read of valid pointer with no side effects match unsafe { (*RCC::ptr()).cfgr3.read().$i2cXsw().variant() } { I2C1SW_A::Hsi => crate::rcc::HSI, I2C1SW_A::Sysclk => clocks.sysclk(), diff --git a/src/lib.rs b/src/lib.rs index e06a022ab..a581a3a70 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -123,6 +123,9 @@ #![no_std] #![allow(clippy::upper_case_acronyms)] #![warn(missing_docs)] +#![warn(clippy::missing_safety_doc)] +#![warn(clippy::undocumented_unsafe_blocks)] +#![warn(unsafe_op_in_unsafe_fn)] #![deny(macro_use_extern_crate)] #![cfg_attr(nightly, deny(rustdoc::broken_intra_doc_links))] #![cfg_attr(docsrs, feature(doc_cfg))] diff --git a/src/pwm.rs b/src/pwm.rs index dc4bece8d..f2489feed 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -155,6 +155,10 @@ [examples/pwm.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.6.1/examples/pwm.rs */ +// FIXME: this PWM module needs refactoring to ensure that no UB / race conditiotns is caused by unsafe acces to +// mmaped registers. +#![allow(clippy::undocumented_unsafe_blocks)] + use core::marker::PhantomData; use crate::{ diff --git a/src/rcc.rs b/src/rcc.rs index 7ae0375be..382a20596 100644 --- a/src/rcc.rs +++ b/src/rcc.rs @@ -167,13 +167,15 @@ macro_rules! bus_struct { #[allow(unused)] fn enr(&self) -> &rcc::$EN { - // NOTE(unsafe) this proxy grants exclusive access to this register + // FIXME: this should still be shared carefully + // SAFETY: this proxy grants exclusive access to this register unsafe { &(*RCC::ptr()).$en } } #[allow(unused)] fn rstr(&self) -> &rcc::$RST { - // NOTE(unsafe) this proxy grants exclusive access to this register + // FIXME: this should still be shared carefully + // SAFETY: this proxy grants exclusive access to this register unsafe { &(*RCC::ptr()).$rst } } } @@ -365,7 +367,7 @@ impl BDCR { #[allow(clippy::unused_self)] #[must_use] pub(crate) fn bdcr(&mut self) -> &rcc::BDCR { - // NOTE(unsafe) this proxy grants exclusive access to this register + // SAFETY: this proxy grants exclusive access to this register unsafe { &(*RCC::ptr()).bdcr } } } @@ -860,6 +862,8 @@ impl CFGR { let (usbpre, usbclk_valid) = usb_clocking::is_valid(sysclk, self.hse, pclk1, &pll_config); + // SAFETY: RCC ptr is guaranteed to be valid. This funciton is the first, which uses the + // RCC peripheral: RCC.constrain() -> Rcc -> CFGR let rcc = unsafe { &*RCC::ptr() }; // enable HSE and wait for it to be ready diff --git a/src/rtc.rs b/src/rtc.rs index 55f63b8ab..d6d41a97b 100644 --- a/src/rtc.rs +++ b/src/rtc.rs @@ -115,8 +115,8 @@ impl Rtc { F: FnMut(&mut RTC), { // Disable write protection - self.rtc.wpr.write(|w| unsafe { w.bits(0xCA) }); - self.rtc.wpr.write(|w| unsafe { w.bits(0x53) }); + self.rtc.wpr.write(|w| w.key().bits(0xCA)); + self.rtc.wpr.write(|w| w.key().bits(0x53)); // Enter init mode let isr = self.rtc.isr.read(); if isr.initf().bit_is_clear() { @@ -253,6 +253,7 @@ impl Rtcc for Rtc { if !(1..=7).contains(&weekday) { return Err(Error::InvalidInputData); } + // SAFETY: check above ensures, that the weekday number is in the valid range (0x01 - 0x07) self.modify(|rtc| rtc.dr.modify(|_, w| unsafe { w.wdu().bits(weekday) })); Ok(()) diff --git a/src/serial.rs b/src/serial.rs index ae8b62068..7af493f42 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -367,7 +367,7 @@ where crate::assert!(brr >= 16, "impossible baud rate"); usart.brr.write(|w| { w.brr().bits( - // NOTE(unsafe): safe because of assert before + // SAFETY: safe because of assert before unsafe { u16::try_from(brr).unwrap_unchecked() }, ) }); @@ -867,7 +867,7 @@ where B: dma::WriteBuffer + 'static, C: dma::Channel, { - // NOTE(unsafe) usage of a valid peripheral address + // SAFETY: RDR is valid peripheral address, safe to dereference and pass to the DMA unsafe { channel.set_peripheral_address( core::ptr::addr_of!(self.usart.rdr) as u32, @@ -885,7 +885,7 @@ where B: dma::ReadBuffer + 'static, C: dma::Channel, { - // NOTE(unsafe) usage of a valid peripheral address + // SAFETY: TDR is valid peripheral address, safe to dereference and pass to the DMA unsafe { channel.set_peripheral_address( core::ptr::addr_of!(self.usart.tdr) as u32, @@ -1021,7 +1021,7 @@ macro_rules! usart_var_clock { $( impl Instance for $USARTX { fn clock(clocks: &Clocks) -> Hertz { - // NOTE(unsafe): atomic read with no side effects + // SAFETY: The read instruction of the RCC.cfgr3 register should be atomic match unsafe {(*RCC::ptr()).cfgr3.read().$usartXsw().variant()} { USART1SW_A::Pclk => <$USARTX as rcc::BusClock>::clock(clocks), USART1SW_A::Hsi => crate::rcc::HSI, diff --git a/src/signature.rs b/src/signature.rs index 26594a9cb..d97f16ef7 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -4,22 +4,22 @@ use core::fmt; use core::str; +const UID_PTR: u32 = 0x1FFF_F7AC; + use core::convert::TryInto; -macro_rules! define_ptr_type { - ($name: ident, $ptr: expr) => { - impl $name { - fn ptr() -> *const Self { - $ptr as *const _ - } - - /// Returns a wrapped reference to the value in flash memory - #[must_use] - pub fn get() -> &'static Self { - unsafe { &*Self::ptr() } - } - } - }; +impl Uid { + fn ptr() -> *const Self { + UID_PTR as *const _ + } + + /// Returns a wrapped reference to the value in flash memory + #[must_use] + pub fn get() -> &'static Self { + // SAFETY: The Uid pointer is definitly correct and as it is only ever shared immutable + // mutliple references to it are fine. + unsafe { &*Self::ptr() } + } } /// Uniqure Device ID register @@ -30,7 +30,6 @@ pub struct Uid { waf: u8, lot: [u8; 7], } -define_ptr_type!(Uid, 0x1FFF_F7AC); #[cfg(feature = "defmt")] impl defmt::Format for Uid { @@ -106,6 +105,7 @@ impl Uid { pub fn lot_number(&self) -> &str { // Lets ignore the last byte, because it is a '\0' character. // TODO: change to core::ffi::CStr + // SAFETY: It is assumed that the lot number only contains valid ASCII characters unsafe { str::from_utf8_unchecked(&self.lot[..6]) } } } @@ -114,7 +114,21 @@ impl Uid { #[derive(Debug)] #[repr(C)] pub struct FlashSize(u16); -define_ptr_type!(FlashSize, 0x1FFF_F7CC); + +const FLASH_PTR: u32 = 0x1FFF_F7CC; +impl FlashSize { + fn ptr() -> *const Self { + FLASH_PTR as *const _ + } + + /// Returns a wrapped reference to the value in flash memory + #[must_use] + pub fn get() -> &'static Self { + // SAFETY: The FlashSize pointer is definitly correct and as it is only ever shared immutable + // mutliple references to it are fine. + unsafe { &*Self::ptr() } + } +} impl FlashSize { /// Read flash size in kilobytes diff --git a/src/syscfg.rs b/src/syscfg.rs index 5b68fac19..f30928d5d 100644 --- a/src/syscfg.rs +++ b/src/syscfg.rs @@ -80,14 +80,16 @@ impl SysCfg { const BITWIDTH: u8 = 4; let index = pin.index.index() % 4; let extigpionr = u32::from(pin.gpio.port_index()); - match pin.index.index() { - // SAFETY: These are all unguarded writes directly to the register, - // without leveraging the safety of stm32f3 generated values. - 0..=3 => unsafe { crate::modify_at!(self.exticr1, BITWIDTH, index, extigpionr) }, - 4..=7 => unsafe { crate::modify_at!(self.exticr2, BITWIDTH, index, extigpionr) }, - 8..=11 => unsafe { crate::modify_at!(self.exticr3, BITWIDTH, index, extigpionr) }, - 12..=15 => unsafe { crate::modify_at!(self.exticr4, BITWIDTH, index, extigpionr) }, - _ => crate::unreachable!(), - }; + // SAFETY: These are all unguarded writes directly to the register, + // without leveraging the safety of stm32f3 generated values. + unsafe { + match pin.index.index() { + 0..=3 => crate::modify_at!(self.exticr1, BITWIDTH, index, extigpionr), + 4..=7 => crate::modify_at!(self.exticr2, BITWIDTH, index, extigpionr), + 8..=11 => crate::modify_at!(self.exticr3, BITWIDTH, index, extigpionr), + 12..=15 => crate::modify_at!(self.exticr4, BITWIDTH, index, extigpionr), + _ => crate::unreachable!(), + }; + } } } diff --git a/src/timer.rs b/src/timer.rs index 1e79aeb99..36da63521 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -439,8 +439,8 @@ macro_rules! timer { #[inline] fn set_arr(&mut self, arr: u16) { - // SAFETY: For easier compatibility between timers write to whole register #[allow(unused_unsafe)] + // SAFETY: For easier compatibility between timers write to whole register self.arr.write(|w| unsafe { w.arr().bits(arr.into()) }); } } diff --git a/src/usb.rs b/src/usb.rs index 488747367..b40e4b4aa 100644 --- a/src/usb.rs +++ b/src/usb.rs @@ -76,8 +76,11 @@ where } } +// SAFETY: Implementation of Peripheral is thread-safe by using cricitcal sections to ensure +// mutually exclusive access to the USB peripheral unsafe impl Sync for Peripheral {} +// SAFETY: The Peirpheral has the same register block layout as STM32 USBFS unsafe impl UsbPeripheral for Peripheral { const REGISTERS: *const () = USB::ptr().cast::<()>(); const DP_PULL_UP_FEATURE: bool = false; @@ -92,6 +95,8 @@ unsafe impl UsbPeripheral for Peripheral Date: Tue, 28 Nov 2023 09:36:13 +0100 Subject: [PATCH 20/25] Use critical section instead of interrupt::free (#350) --- CHANGELOG.md | 5 +++++ Cargo.toml | 1 + examples/adc.rs | 6 +++--- examples/gpio_interrupts.rs | 9 +++++---- src/adc.rs | 2 +- src/usb.rs | 2 +- 6 files changed, 16 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 939ecfb9d..795edcb23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). implementation, but it is hard to maintain the current implementation and not easy to verify if it is really a safe implementation. It is also not consistent with the rest of the crates API. ([#352]) +- Use [critical-section] crate instead of `interrupt_free`, which is not always + sound. ([#350]) + +[critical-section]: https://github.com/rust-embedded/critical-section ## [v0.9.2] - 2023-02-20 @@ -611,6 +615,7 @@ let clocks = rcc [#352]: https://github.com/stm32-rs/stm32f3xx-hal/pull/352 [#351]: https://github.com/stm32-rs/stm32f3xx-hal/pull/351 +[#350]: https://github.com/stm32-rs/stm32f3xx-hal/pull/350 [#345]: https://github.com/stm32-rs/stm32f3xx-hal/pull/345 [#346]: https://github.com/stm32-rs/stm32f3xx-hal/pull/346 [#347]: https://github.com/stm32-rs/stm32f3xx-hal/pull/347 diff --git a/Cargo.toml b/Cargo.toml index 55b64fd8a..e2ce040d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ bxcan = { version = "0.7.0", optional = true } cfg-if = "1.0.0" cortex-m = "0.7.4" cortex-m-rt = "0.7.3" +critical-section = "1.1.2" defmt = { version = ">=0.2.3, <0.4.0", optional = true } embedded-dma = "0.2.0" embedded-hal = { version = "0.2.5", features = ["unproven"] } diff --git a/examples/adc.rs b/examples/adc.rs index 7e0174548..9c43d0698 100644 --- a/examples/adc.rs +++ b/examples/adc.rs @@ -9,8 +9,8 @@ use panic_probe as _; use core::cell::RefCell; use cortex_m::asm; -use cortex_m::interrupt::Mutex; use cortex_m_rt::entry; +use critical_section::Mutex; use embedded_hal::adc::OneShot; use stm32f3xx_hal::{ @@ -99,7 +99,7 @@ fn main() -> ! { // Start a timer which fires regularly to wake up from `asm::wfi` timer.start(500.milliseconds()); // Put the timer in the global context. - cortex_m::interrupt::free(|cs| { + critical_section::with(|cs| { TIMER.borrow(cs).replace(Some(timer)); }); @@ -133,7 +133,7 @@ fn main() -> ! { #[interrupt] fn TIM2() { // Just handle the pending interrupt event. - cortex_m::interrupt::free(|cs| { + critical_section::with(|cs| { TIMER // Unlock resource for use in critical section .borrow(cs) diff --git a/examples/gpio_interrupts.rs b/examples/gpio_interrupts.rs index c835ec5f1..bf0701bf6 100644 --- a/examples/gpio_interrupts.rs +++ b/examples/gpio_interrupts.rs @@ -5,8 +5,9 @@ use core::cell::RefCell; use panic_semihosting as _; -use cortex_m::{asm, interrupt::Mutex, peripheral::NVIC}; +use cortex_m::{asm, peripheral::NVIC}; use cortex_m_rt::entry; +use critical_section::Mutex; use stm32f3xx_hal::{ gpio::{self, Edge, Input, Output, PushPull}, @@ -38,7 +39,7 @@ fn main() -> ! { led.toggle().expect("unable to toggle led in configuration"); // Move the ownership of the led to the global LED - cortex_m::interrupt::free(|cs| *LED.borrow(cs).borrow_mut() = Some(led)); + critical_section::with(|cs| *LED.borrow(cs).borrow_mut() = Some(led)); // Configuring the user button to trigger an interrupt when the button is pressed. let mut user_button = gpioa @@ -50,7 +51,7 @@ fn main() -> ! { let interrupt_num = user_button.interrupt(); // hal::pac::Interrupt::EXTI0 // Moving ownership to the global BUTTON so we can clear the interrupt pending bit. - cortex_m::interrupt::free(|cs| *BUTTON.borrow(cs).borrow_mut() = Some(user_button)); + critical_section::with(|cs| *BUTTON.borrow(cs).borrow_mut() = Some(user_button)); unsafe { NVIC::unmask(interrupt_num) }; @@ -67,7 +68,7 @@ fn main() -> ! { // This may be called more than once per button press from the user since the button may not be debounced. #[interrupt] fn EXTI0() { - cortex_m::interrupt::free(|cs| { + critical_section::with(|cs| { // Toggle the LED LED.borrow(cs) .borrow_mut() diff --git a/src/adc.rs b/src/adc.rs index e2b1b645f..d74e1eb8d 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -133,7 +133,7 @@ where { /// Releases the common ADC peripheral pub fn free(self, _adcs: &::Childs) -> ADC { - cortex_m::interrupt::free(|_| { + critical_section::with(|_| { // SAFETY: Guaranteed to be the only instance left, which has control over the // `ADC`perpherals, and criticala section ensure that no race condition happens // on the `Bus` peripheral. diff --git a/src/usb.rs b/src/usb.rs index b40e4b4aa..f0aef6a8f 100644 --- a/src/usb.rs +++ b/src/usb.rs @@ -97,7 +97,7 @@ unsafe impl UsbPeripheral for Peripheral Date: Tue, 28 Nov 2023 09:40:33 +0100 Subject: [PATCH 21/25] Remove Toggle enum (#354) --- CHANGELOG.md | 1 + src/lib.rs | 27 +-------------------------- 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 795edcb23..2e865180c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Deprecate `Toggle` enum and use `Switch` instead for better naming purposes ([#334]) - Add `impl From for Switch` to reduce churn. +- Remove `Toggle` enum and use `Switch` instead for better naming purposes - Fix undefined behavior in SPI implementation ([#346]) - Add `num_traits::PrimInt` bounds to `Word` - Remove `Serial::split`, which possibly creates two mutable references two diff --git a/src/lib.rs b/src/lib.rs index a581a3a70..63997311b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -270,22 +270,6 @@ cfg_if! { } } -/// Toggle something on or off. -/// -/// Convenience enum and wrapper around a bool, which more explicit about the intention to enable -/// or disable something, in comparison to `true` or `false`. -// TODO: Maybe move to some mod like "util"? -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -#[deprecated(since = "0.10.0", note = "Use Switch instead")] -#[allow(deprecated)] -pub enum Toggle { - /// Toggle something on / enable a thing. - On, - /// Toggle something off / disable a thing. - Off, -} - /// Switch something on or off. /// /// Convenience enum and wrapper around a bool, which more explicit about the intention to enable @@ -293,6 +277,7 @@ pub enum Toggle { // TODO: Maybe move to some mod like "util"? #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[doc(alias = "Toggle")] pub enum Switch { /// Switch something on / enable a thing. On, @@ -300,16 +285,6 @@ pub enum Switch { Off, } -#[allow(deprecated)] -impl From for Switch { - fn from(toggle: Toggle) -> Self { - match toggle { - Toggle::On => Switch::On, - Toggle::Off => Switch::Off, - } - } -} - impl From for bool { fn from(switch: Switch) -> Self { matches!(switch, Switch::On) From 4e1a257d4615fab0e676bfb30b01e8ae07e8f876 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Nov 2023 10:19:35 +0100 Subject: [PATCH 22/25] Extend ticks calculation in timer start from u32 to u64 (#356) Supersedes #343 Fixes #342 Co-authored-by: Anton Patrushev --- CHANGELOG.md | 2 ++ src/timer.rs | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e865180c..9ead6ebf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Fix wrong timer frequency calculation and unexpected panics ([#338]) +- Fixed integer saturation in Timer::start, see #342 ([#356]) ### Changed @@ -614,6 +615,7 @@ let clocks = rcc [defmt]: https://github.com/knurling-rs/defmt [filter]: https://defmt.ferrous-systems.com/filtering.html +[#356]: https://github.com/stm32-rs/stm32f3xx-hal/pull/356 [#352]: https://github.com/stm32-rs/stm32f3xx-hal/pull/352 [#351]: https://github.com/stm32-rs/stm32f3xx-hal/pull/351 [#350]: https://github.com/stm32-rs/stm32f3xx-hal/pull/350 diff --git a/src/timer.rs b/src/timer.rs index 36da63521..f92fab597 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -281,9 +281,10 @@ where let timeout: Self::Time = timeout.into(); let clock = TIM::clock(&self.clocks); - let ticks = clock.integer().saturating_mul(timeout.integer()) * *timeout.scaling_factor(); + let ticks = u64::from(clock.integer()).saturating_mul(u64::from(timeout.integer())) + * *timeout.scaling_factor(); - let psc: u32 = (ticks.saturating_sub(1)) / (1 << 16); + let psc = ticks.saturating_sub(1) / (1 << 16); self.tim.set_psc(crate::unwrap!(u16::try_from(psc).ok())); let mut arr = ticks / psc.saturating_add(1); From 9fe84c0e966db370753153273df8a7ca26c5551e Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Nov 2023 10:21:38 +0100 Subject: [PATCH 23/25] Update dependecies (#349) --- .github/workflows/msrv.yml | 13 ++++------- CHANGELOG.md | 9 +++++++- Cargo.toml | 45 +++++++++++++++++--------------------- README.md | 4 ++-- codegen/Cargo.toml | 2 +- testsuite/Cargo.toml | 12 +++++----- 6 files changed, 41 insertions(+), 44 deletions(-) diff --git a/.github/workflows/msrv.yml b/.github/workflows/msrv.yml index c7fd6e911..b6fdfd009 100644 --- a/.github/workflows/msrv.yml +++ b/.github/workflows/msrv.yml @@ -1,8 +1,6 @@ name: MSRV on: - push: - branches: [master] pull_request: merge_group: @@ -17,23 +15,20 @@ jobs: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable with: - toolchain: 1.59.0 + toolchain: 1.60.0 target: thumbv7em-none-eabihf - - run: cargo check --features=stm32f303xc,stm32-usbd,rt,can,ld --lib + - run: cargo check --features=stm32f303xc,usb,rt,can,ld --lib check-min-deps: name: Check Minimal Dependency Versions runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable - with: - toolchain: stable - target: thumbv7em-none-eabihf - uses: dtolnay/rust-toolchain@stable with: toolchain: nightly target: thumbv7em-none-eabihf - run: cargo +nightly update -Z minimal-versions - - run: cargo check --features=stm32f303xc,stm32-usbd,rt,can,ld --lib --examples + - run: cargo tree + - run: cargo check --features=stm32f303xc,usb,rt,can,ld --lib --examples diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ead6ebf3..38a7c0c7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Update `stm32f3` pac to v0.15.1 ([#335]) - Update `bxcan` pac to v0.7.0 ([#335]) -- The MSRV was bumped to 1.59 ([#335]) - Deprecate `Toggle` enum and use `Switch` instead for better naming purposes ([#334]) - Add `impl From for Switch` to reduce churn. @@ -28,6 +27,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Remove `Serial::split`, which possibly creates two mutable references two one Serial instance, which could've caused UB. The use case of this function was hard to find out anyway. ([#351]) +- Remove `defmt-*` features (`defmt` feature is still available), to finalize + migration from `defmt-0.2.x` -> `defmt-0.3.x`. ([#349]) +- Removed implicit `stm32-usbd` feature (use `usb` instead) ([#349]) ### Added @@ -48,6 +50,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). It is also not consistent with the rest of the crates API. ([#352]) - Use [critical-section] crate instead of `interrupt_free`, which is not always sound. ([#350]) + It is also not consistent with the rest of the crates API. +- Use [critical-section] crate instead of `interrupt_free`, which is not always + sound. +- The MSRV was bumped to 1.60 ([#349]) [critical-section]: https://github.com/rust-embedded/critical-section @@ -619,6 +625,7 @@ let clocks = rcc [#352]: https://github.com/stm32-rs/stm32f3xx-hal/pull/352 [#351]: https://github.com/stm32-rs/stm32f3xx-hal/pull/351 [#350]: https://github.com/stm32-rs/stm32f3xx-hal/pull/350 +[#349]: https://github.com/stm32-rs/stm32f3xx-hal/pull/349 [#345]: https://github.com/stm32-rs/stm32f3xx-hal/pull/345 [#346]: https://github.com/stm32-rs/stm32f3xx-hal/pull/346 [#347]: https://github.com/stm32-rs/stm32f3xx-hal/pull/347 diff --git a/Cargo.toml b/Cargo.toml index e2ce040d9..ca03fc65d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ documentation = "https://docs.rs/stm32f3xx-hal" version = "0.9.2" exclude = ["codegen", ".markdownlint.yml"] resolver = "2" -rust-version = "1.59" +rust-version = "1.60" [package.metadata.docs.rs] features = ["stm32f303xc", "rt", "usb", "can", "enumset"] @@ -29,49 +29,44 @@ members = [".", "testsuite", "codegen"] [dependencies] bxcan = { version = "0.7.0", optional = true } cfg-if = "1.0.0" -cortex-m = "0.7.4" +cortex-m = "0.7.7" cortex-m-rt = "0.7.3" critical-section = "1.1.2" defmt = { version = ">=0.2.3, <0.4.0", optional = true } embedded-dma = "0.2.0" -embedded-hal = { version = "0.2.5", features = ["unproven"] } -embedded-time = "0.12.0" -enumset = { version = "1.0.6", optional = true } -nb = "1.0.0" +embedded-hal = { version = "0.2.7", features = ["unproven"] } +embedded-time = "0.12.1" +enumset = { version = "1.1.3", optional = true } +nb = "1.1.0" num-traits = { version = "0.2.17", default-features = false} -paste = "1.0.5" +paste = "1.0.14" rtcc = { version = "0.3.0", optional = true } stm32-usbd = { version = "0.6.0", optional = true } stm32f3 = { version = "0.15.1", default-features = false } void = { version = "1.0.2", default-features = false } [dev-dependencies] -cortex-m-rtic = "1.0" +cortex-m-rtic = "1.1" cortex-m-semihosting = "0.5.0" -defmt = "0.3.0" +defmt = "0.3.5" defmt-rtt = "0.4.0" -defmt-test = "0.3.0" -panic-probe = "0.3.0" -panic-rtt-target = { version = "0.1", features = ["cortex-m"] } +defmt-test = "0.3.1" +panic-probe = "0.3.1" +panic-rtt-target = { version = "0.1.2", features = ["cortex-m"] } panic-semihosting = "0.6.0" -rtt-target = { version = "0.3.1", features = ["cortex-m"] } +rtt-target = { version = "0.4.0" } systick-monotonic = "1.0" -usb-device = "0.2.8" -usbd-serial = "0.1.1" +usb-device = "0.3.1" +usbd-serial = "0.2.0" [build-dependencies] -slice-group-by = "0.3.0" +slice-group-by = "0.3.1" [features] -can = ["bxcan"] +can = ["dep:bxcan"] default = ["rt", "ld", "usb", "can", "rtc", "enumset"] -defmt-debug = ["defmt"] +defmt = ["dep:defmt"] -defmt-default = ["defmt"] -defmt-error = ["defmt"] -defmt-info = ["defmt"] -defmt-trace = ["defmt"] -defmt-warn = ["defmt"] device-selected = [] direct-call-deprecated = [] @@ -90,7 +85,7 @@ mem-c = [] mem-d = [] mem-e = [] rt = ["stm32f3/rt"] -rtc = ["rtcc"] +rtc = ["dep:rtcc"] # Any changes here should be mirrored in README.md, build.rs, src/lib.rs, and # .github/workflows/ci.yml. @@ -135,7 +130,7 @@ svd-f302 = ["stm32f3/stm32f302"] svd-f303 = ["stm32f3/stm32f303"] svd-f373 = ["stm32f3/stm32f373"] svd-f3x4 = ["stm32f3/stm32f3x4"] -usb = ["stm32-usbd"] +usb = ["dep:stm32-usbd"] # cargo build/run [profile.dev] diff --git a/README.md b/README.md index f94378eba..c94bd392a 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Crate](https://img.shields.io/crates/v/stm32f3xx-hal.svg)](https://crates.io/crates/stm32f3xx-hal) [![Docs](https://docs.rs/stm32f3xx-hal/badge.svg)](https://docs.rs/stm32f3xx-hal) [![Crates.io](https://img.shields.io/crates/d/stm32f3xx-hal.svg)](https://crates.io/crates/stm32f3xx-hal) -![Minimum Supported Rust Version](https://img.shields.io/badge/rustc-1.59+-blue.svg) +![Minimum Supported Rust Version](https://img.shields.io/badge/rustc-1.60+-blue.svg) `stm32f3xx-hal` contains a multi device hardware abstraction on top of the peripheral access API for the STMicro STM32F3 series microcontrollers. The @@ -138,7 +138,7 @@ See the [examples folder](examples) for more example programs. ## Minimum Supported Rust Version (MSRV) -This crate is guaranteed to compile on stable Rust 1.59.0 and up. It *might* +This crate is guaranteed to compile on stable Rust 1.60.0 and up. It *might* compile with older versions but that may change in any new patch release. diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml index 63eeae588..dac3cce61 100644 --- a/codegen/Cargo.toml +++ b/codegen/Cargo.toml @@ -9,7 +9,7 @@ edition = "2018" anyhow = "1" once_cell = "1" regex = "1" -serde-xml-rs = "0.4" +serde-xml-rs = "0.6" [dependencies.structopt] version = "0.3" diff --git a/testsuite/Cargo.toml b/testsuite/Cargo.toml index 8c76ec91c..b8d12ede5 100644 --- a/testsuite/Cargo.toml +++ b/testsuite/Cargo.toml @@ -55,15 +55,15 @@ harness = false cfg-if = "1.0" cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.3" -defmt = "0.3.0" +defmt = "0.3.5" defmt-rtt = "0.4.0" -defmt-test = "0.3.0" -enumset = { version = "1.0.6" } +defmt-test = "0.3.1" +enumset = { version = "1.1.3" } # TODO: Set stm32f303xc as default, but make it overwritable stm32f3xx-hal = { path = "..", features = ["defmt"]} -panic-probe = { version = "0.3.0", features = ["print-defmt"] } -nb = "1.0.0" -num-traits = { version = "0.2.14", default-features = false } +panic-probe = { version = "0.3.1", features = ["print-defmt"] } +nb = "1.1.0" +num-traits = { version = "0.2.17", default-features = false } [features] # enable all defmt logging levels From a0cfead5f958edf82c8dbc61c205a66cc14e0941 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Nov 2023 10:29:30 +0100 Subject: [PATCH 24/25] Fix changelog (#357) --- CHANGELOG.md | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38a7c0c7b..ee1f6e8fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,9 +18,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Update `stm32f3` pac to v0.15.1 ([#335]) - Update `bxcan` pac to v0.7.0 ([#335]) -- Deprecate `Toggle` enum and use `Switch` instead for better naming purposes - ([#334]) - - Add `impl From for Switch` to reduce churn. - Remove `Toggle` enum and use `Switch` instead for better naming purposes - Fix undefined behavior in SPI implementation ([#346]) - Add `num_traits::PrimInt` bounds to `Word` @@ -33,14 +30,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added -- Add missing ADC channels ([#337]) +- Add missing ADC channels ([#337] & [#345]) - Add many `#[must_use]` instances ([#347]) -- Add missing ADC channels ([#345]) ### Fixed - Fix wrong timer frequency calculation and unexpected panics ([#338]) -- Fixed integer saturation in Timer::start, see #342 ([#356]) +- Fixed integer saturation in Timer::start, see [#342] ([#356]) ### Changed @@ -51,8 +47,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Use [critical-section] crate instead of `interrupt_free`, which is not always sound. ([#350]) It is also not consistent with the rest of the crates API. -- Use [critical-section] crate instead of `interrupt_free`, which is not always - sound. - The MSRV was bumped to 1.60 ([#349]) [critical-section]: https://github.com/rust-embedded/critical-section @@ -629,11 +623,11 @@ let clocks = rcc [#345]: https://github.com/stm32-rs/stm32f3xx-hal/pull/345 [#346]: https://github.com/stm32-rs/stm32f3xx-hal/pull/346 [#347]: https://github.com/stm32-rs/stm32f3xx-hal/pull/347 +[#342]: https://github.com/stm32-rs/stm32f3xx-hal/issues/342 [#340]: https://github.com/stm32-rs/stm32f3xx-hal/pull/340 [#338]: https://github.com/stm32-rs/stm32f3xx-hal/pull/338 [#337]: https://github.com/stm32-rs/stm32f3xx-hal/pull/337 [#335]: https://github.com/stm32-rs/stm32f3xx-hal/pull/335 -[#334]: https://github.com/stm32-rs/stm32f3xx-hal/pull/334 [#322]: https://github.com/stm32-rs/stm32f3xx-hal/pull/322 [#318]: https://github.com/stm32-rs/stm32f3xx-hal/pull/318 [#317]: https://github.com/stm32-rs/stm32f3xx-hal/pull/317 From b0cead18208099b94a085fb634d0db4e75ac6e4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Vi=C3=B6l?= Date: Thu, 30 Nov 2023 21:11:26 +0100 Subject: [PATCH 25/25] Release v0.10.0 --- CHANGELOG.md | 7 ++++++- Cargo.toml | 2 +- README.md | 2 +- src/adc.rs | 4 ++-- src/can.rs | 2 +- src/dma.rs | 2 +- src/gpio.rs | 4 ++-- src/i2c.rs | 2 +- src/lib.rs | 2 +- src/spi.rs | 4 ++-- src/timer.rs | 2 +- src/usb.rs | 2 +- src/watchdog.rs | 2 +- 13 files changed, 21 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee1f6e8fd..d357e1f7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## Unreleased +No changes. + +## [v0.10.0] - 2023-11-30 + ### Breaking changes - Update `stm32f3` pac to v0.15.1 ([#335]) @@ -732,7 +736,8 @@ let clocks = rcc [#2]: https://github.com/stm32-rs/stm32f3xx-hal/pull/2 -[v0.9.1]: https://github.com/stm32-rs/stm32f3xx-hal/releases/tag/v0.9.1 +[v0.10.0]: https://github.com/stm32-rs/stm32f3xx-hal/releases/tag/v0.10.0 +[v0.9.2]: https://github.com/stm32-rs/stm32f3xx-hal/releases/tag/v0.9.2 [v0.9.0]: https://github.com/stm32-rs/stm32f3xx-hal/releases/tag/v0.9.0 [v0.8.1]: https://github.com/stm32-rs/stm32f3xx-hal/releases/tag/v0.8.1 [v0.8.0]: https://github.com/stm32-rs/stm32f3xx-hal/releases/tag/v0.8.0 diff --git a/Cargo.toml b/Cargo.toml index ca03fc65d..55fbfa75b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ name = "stm32f3xx-hal" readme = "README.md" repository = "https://github.com/stm32-rs/stm32f3xx-hal" documentation = "https://docs.rs/stm32f3xx-hal" -version = "0.9.2" +version = "0.10.0" exclude = ["codegen", ".markdownlint.yml"] resolver = "2" rust-version = "1.60" diff --git a/README.md b/README.md index c94bd392a..755de5f98 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ cortex-m-rt = { version = "0.7.3", features = ["device"] } # Panic behavior, see https://crates.io/keywords/panic-impl for alternatives panic-halt = "0.2.0" # Replace stm32f303xc with your target chip, see next section for more info -stm32f3xx-hal = { version = "0.9.2", features = ["ld", "rt", "stm32f303xc"] } +stm32f3xx-hal = { version = "0.10.0", features = ["ld", "rt", "stm32f303xc"] } ``` We also need to tell Rust about target architecture and how to link our diff --git a/src/adc.rs b/src/adc.rs index d74e1eb8d..13f6b0e12 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -7,7 +7,7 @@ //! It can be built for the `STM32F3Discovery` running //! `cargo build --example adc --features=stm32f303xc` //! -//! [examples/adc.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.9.1/examples/adc.rs +//! [examples/adc.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.10.0/examples/adc.rs use core::ops::Deref; use core::{convert::TryInto, marker::PhantomData}; @@ -256,7 +256,7 @@ macro_rules! sp_pins { /// /// Code example can be seen in [examples/adc.rs]. /// - /// [examples/adc.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.9.1/examples/adc.rs + /// [examples/adc.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.10.0/examples/adc.rs /// [RM0316]: https://www.st.com/resource/en/reference_manual/dm00094349.pdf // FIXME(Sh3Rm4n): Soundness hole: Still mutliple sensor objects can be created. // An idea might be to split out the sensors from CommonAdc similar to the diff --git a/src/can.rs b/src/can.rs index ce2c4637e..cb9ee181d 100644 --- a/src/can.rs +++ b/src/can.rs @@ -9,7 +9,7 @@ //! //! A usage example of the can peripheral can be found at [examples/can.rs] //! -//! [examples/can.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.9.1/examples/can.rs +//! [examples/can.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.10.0/examples/can.rs use crate::gpio::{gpioa, gpiob}; use crate::gpio::{PushPull, AF9}; diff --git a/src/dma.rs b/src/dma.rs index 089b38bde..01f771c90 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -6,7 +6,7 @@ //! //! An example how to use DMA for serial, can be found at [examples/serial_dma.rs] //! -//! [examples/serial_dma.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.9.1/examples/serial_dma.rs +//! [examples/serial_dma.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.10.0/examples/serial_dma.rs // To learn about most of the ideas implemented here, check out the DMA section // of the Embedonomicon: https://docs.rust-embedded.org/embedonomicon/dma.html diff --git a/src/gpio.rs b/src/gpio.rs index 68869f2e6..81ba0fdb4 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -58,7 +58,7 @@ //! //! [InputPin]: embedded_hal::digital::v2::InputPin //! [OutputPin]: embedded_hal::digital::v2::OutputPin -//! [examples/toggle.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.9.1/examples/toggle.rs +//! [examples/toggle.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.10.0/examples/toggle.rs use core::{convert::Infallible, marker::PhantomData}; @@ -322,7 +322,7 @@ impl crate::private::Sealed for Pin {} /// /// See [examples/gpio_erased.rs] as an example. /// -/// [examples/gpio_erased.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.9.1/examples/gpio_erased.rs +/// [examples/gpio_erased.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.10.0/examples/gpio_erased.rs pub type PXx = Pin; impl Pin, Mode> { diff --git a/src/i2c.rs b/src/i2c.rs index 9a4391441..b456944f1 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -4,7 +4,7 @@ //! //! A usage example of the i2c peripheral can be found at [examples/i2c_scanner.rs] //! -//! [examples/i2c_scanner.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.9.1/examples/i2c_scanner.rs +//! [examples/i2c_scanner.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.10.0/examples/i2c_scanner.rs use core::{convert::TryFrom, ops::Deref}; diff --git a/src/lib.rs b/src/lib.rs index 63997311b..5ccf95126 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -68,7 +68,7 @@ For more information, see the [README][]. - [README]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.9.1/README.md#selecting-the-right-chip + [README]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.10.0/README.md#selecting-the-right-chip ### `ld` diff --git a/src/spi.rs b/src/spi.rs index 139322636..bf2e2b08d 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -4,7 +4,7 @@ //! //! A usage example of the can peripheral can be found at [examples/spi.rs] //! -//! [examples/spi.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.9.1/examples/spi.rs +//! [examples/spi.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.10.0/examples/spi.rs use core::{fmt, marker::PhantomData, ops::Deref}; @@ -196,7 +196,7 @@ impl Spi { /// /// ``` /// - /// To get a better example, look [here](https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.9.1/examples/spi.rs). + /// To get a better example, look [here](https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.10.0/examples/spi.rs). /// // TODO(Sh3Rm4n): See alternative modes provided besides FullDuplex (as listed in Stm32CubeMx). pub fn new( diff --git a/src/timer.rs b/src/timer.rs index f92fab597..372b1bde9 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -8,7 +8,7 @@ //! Check out [examples/adc.rs], where a [`Periodic`] timer is used to wake //! up the main-loop regularly. //! -//! [examples/adc.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.9.1/examples/adc.rs +//! [examples/adc.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.10.0/examples/adc.rs use crate::pac::{DCB, DWT}; #[cfg(feature = "enumset")] diff --git a/src/usb.rs b/src/usb.rs index f0aef6a8f..653988522 100644 --- a/src/usb.rs +++ b/src/usb.rs @@ -6,7 +6,7 @@ //! //! See [examples/usb_serial.rs] for a usage example. //! -//! [examples/usb_serial.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.9.1/examples/usb_serial.rs +//! [examples/usb_serial.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.10.0/examples/usb_serial.rs use core::fmt; diff --git a/src/watchdog.rs b/src/watchdog.rs index 95252ef39..dd4fb807d 100644 --- a/src/watchdog.rs +++ b/src/watchdog.rs @@ -4,7 +4,7 @@ //! //! A usage example of the watchdog can be found at [examples/can.rs] //! -//! [examples/can.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.9.1/examples/can.rs +//! [examples/can.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.10.0/examples/can.rs use core::fmt; use embedded_time::fixed_point::FixedPoint;