diff --git a/Cargo.toml b/Cargo.toml index 56d19f3b..4e881f93 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,7 +58,7 @@ optional = true [dev-dependencies] cortex-m-rt = "0.7.2" defmt-rtt = "0.4.0" -cortex-m-rtic = "0.5.8" +cortex-m-rtic = "1.1.4" cortex-m-semihosting = "0.3.5" panic-probe = { version = "0.3.0", features = ["print-defmt"] } panic-semihosting = "0.5.3" @@ -101,3 +101,7 @@ debug = false codegen-units = 1 incremental = false lto = true + +[[example]] +name = "flash_with_rtic" +required-features = ["stm32g474"] \ No newline at end of file diff --git a/examples/can-echo.rs b/examples/can-echo.rs index 89911b8e..f10512bf 100644 --- a/examples/can-echo.rs +++ b/examples/can-echo.rs @@ -120,7 +120,7 @@ fn main() -> ! { loop { if let Ok(rxheader) = block!(can.receive0(&mut buffer)) { - block!(can.transmit(rxheader.unwrap().to_tx_header(None), &mut buffer)).unwrap(); + block!(can.transmit(rxheader.unwrap().to_tx_header(None), &buffer)).unwrap(); } } } diff --git a/examples/comp.rs b/examples/comp.rs new file mode 100644 index 00000000..abfa16ba --- /dev/null +++ b/examples/comp.rs @@ -0,0 +1,69 @@ +//! ## Origin +//! +//! This code has been taken from the stm32g0xx-hal project and modified slightly to support +//! STM32G4xx MCUs. + +//#![deny(warnings)] +#![deny(unsafe_code)] +#![no_main] +#![no_std] + +mod utils; +extern crate cortex_m_rt as rt; + +use rt::entry; + +#[cfg(not(feature = "stm32g474"))] +#[entry] +fn main() -> ! { + loop {} // TODO: add support for more devices +} + +#[cfg(feature = "stm32g474")] +#[entry] +fn main() -> ! { + use hal::comparator::{ComparatorExt, ComparatorSplit, Config, Hysteresis, RefintInput}; + use hal::gpio::GpioExt; + use hal::prelude::OutputPin; + use hal::rcc::RccExt; + use hal::stm32; + use stm32g4xx_hal as hal; + + let dp = stm32::Peripherals::take().expect("cannot take peripherals"); + let mut rcc = dp.RCC.constrain(); + + let gpioa = dp.GPIOA.split(&mut rcc); + + let (comp1, comp2, ..) = dp.COMP.split(&mut rcc); + + let pa1 = gpioa.pa1.into_analog(); + let pa0 = gpioa.pa0.into_analog(); + let comp1 = comp1.comparator(&pa1, pa0, Config::default(), &rcc.clocks); + let comp1 = comp1.enable(); + + // led1 pa1 will be updated manually when to match comp1 value + let mut led1 = gpioa.pa5.into_push_pull_output(); + + let pa7 = gpioa.pa7.into_analog(); + let comp2 = comp2.comparator( + &pa7, + RefintInput::VRefintM12, + Config::default() + .hysteresis(Hysteresis::None) + .output_inverted(), + &rcc.clocks, + ); + let led2 = gpioa.pa12.into_push_pull_output(); + // Configure PA12 to the comparator's alternate function so it gets + // changed directly by the comparator. + comp2.output_pin(led2); + let _comp2 = comp2.enable().lock(); + + loop { + // Read comp1 output and update led1 accordingly + match comp1.output() { + true => led1.set_high().unwrap(), + false => led1.set_low().unwrap(), + } + } +} diff --git a/examples/comp_w_dac.rs b/examples/comp_w_dac.rs new file mode 100644 index 00000000..5d33d619 --- /dev/null +++ b/examples/comp_w_dac.rs @@ -0,0 +1,81 @@ +// #![deny(warnings)] +#![deny(unsafe_code)] +#![no_main] +#![no_std] + +mod utils; +extern crate cortex_m_rt as rt; + +use rt::entry; + +#[cfg(not(feature = "stm32g474"))] +#[entry] +fn main() -> ! { + loop {} // TODO: add support for more devices +} + +#[cfg(feature = "stm32g474")] +#[entry] +fn main() -> ! { + use embedded_hal::Direction; + use hal::comparator::{self, ComparatorExt, ComparatorSplit}; + use hal::dac::{Dac1IntSig1, DacExt, DacOut}; + use hal::delay::SYSTDelayExt; + use hal::gpio::GpioExt; + use hal::rcc::RccExt; + use hal::stm32; + use stm32g4xx_hal as hal; + + let dp = stm32::Peripherals::take().expect("cannot take peripherals"); + let cp = cortex_m::Peripherals::take().expect("cannot take core peripherals"); + + let mut rcc = dp.RCC.constrain(); + let mut delay = cp.SYST.delay(&rcc.clocks); + + let gpioa = dp.GPIOA.split(&mut rcc); + + // Set up DAC to output to pa4 and to internal signal Dac1IntSig1 + // which just so happens is compatible with comp1 + let dac1ch1 = dp.DAC1.constrain((gpioa.pa4, Dac1IntSig1), &mut rcc); + let mut dac = dac1ch1.calibrate_buffer(&mut delay).enable(); + + let (comp1, _comp2, ..) = dp.COMP.split(&mut rcc); + let pa1 = gpioa.pa1.into_analog(); + + // Set up comparator with pa1 as positive, and the DAC as negative input + let comp = comp1.comparator( + &pa1, + &dac, + comparator::Config::default().hysteresis(comparator::Hysteresis::None), + &rcc.clocks, + ); + + let led2 = gpioa.pa0.into_push_pull_output(); + // Configure PA12 to the comparator's alternate function so it gets + // changed directly by the comparator. + comp.output_pin(led2); + let _comp1 = comp.enable().lock(); + + let mut dir = Direction::Upcounting; + let mut val = 0; + + // Manually step the DAC's value to produce a triangle wave + // + // This will produce a pwm-like signal at pa0 with the duty controlled by pa1 + // where + // * 0V at p1 => 0% duty + // * VDDA at p1 => 100% duty + loop { + dac.set_value(val); + match val { + 0 => dir = Direction::Upcounting, + 4095 => dir = Direction::Downcounting, + _ => (), + }; + + match dir { + Direction::Upcounting => val += 1, + Direction::Downcounting => val -= 1, + } + } +} diff --git a/examples/dac.rs b/examples/dac.rs new file mode 100644 index 00000000..7348f703 --- /dev/null +++ b/examples/dac.rs @@ -0,0 +1,61 @@ +//! ## Origin +//! +//! This code has been taken from the stm32g0xx-hal project and modified to support +//! STM32G4xx MCUs. + +// #![deny(warnings)] +#![deny(unsafe_code)] +#![no_main] +#![no_std] + +use embedded_hal::Direction; +use hal::dac::{DacExt, DacOut, GeneratorConfig}; +use hal::delay::SYSTDelayExt; +use hal::gpio::GpioExt; +use hal::rcc::RccExt; +use stm32g4xx_hal as hal; +mod utils; +extern crate cortex_m_rt as rt; + +use hal::stm32; +use rt::entry; + +#[entry] +fn main() -> ! { + let dp = stm32::Peripherals::take().expect("cannot take peripherals"); + let cp = cortex_m::Peripherals::take().expect("cannot take core peripherals"); + + let mut rcc = dp.RCC.constrain(); + let mut delay = cp.SYST.delay(&rcc.clocks); + + let gpioa = dp.GPIOA.split(&mut rcc); + let (dac1ch1, dac1ch2) = dp.DAC1.constrain((gpioa.pa4, gpioa.pa5), &mut rcc); + + // dac_manual will have its value set manually + let mut dac_manual = dac1ch1.calibrate_buffer(&mut delay).enable(); + + // dac_generator will have its value set automatically from its internal noise generator + let mut dac_generator = dac1ch2.enable_generator(GeneratorConfig::noise(11)); + + let mut dir = Direction::Upcounting; + let mut val = 0; + + loop { + // This will pull out a new value from the noise generator and apply it to the DAC + dac_generator.trigger(); + + // This will manually set the DAC's value + dac_manual.set_value(val); + match val { + 0 => dir = Direction::Upcounting, + 4095 => dir = Direction::Downcounting, + _ => (), + }; + + // Step manually set value as a triangle wave + match dir { + Direction::Upcounting => val += 1, + Direction::Downcounting => val -= 1, + } + } +} diff --git a/examples/flash_with_rtic.rs b/examples/flash_with_rtic.rs index bf236eb3..3f42240c 100644 --- a/examples/flash_with_rtic.rs +++ b/examples/flash_with_rtic.rs @@ -16,8 +16,6 @@ mod app { const LOG_LEVEL: log::LevelFilter = log::LevelFilter::Info; - use panic_halt as _; // you can put a breakpoint on `rust_begin_unwind` to catch panics - // Resources shared between tasks #[shared] struct Shared {} diff --git a/examples/hello.rs b/examples/hello.rs index 990f05f2..63210f39 100644 --- a/examples/hello.rs +++ b/examples/hello.rs @@ -16,7 +16,7 @@ use utils::logger::println; #[entry] fn main() -> ! { - let _ = println!("Hello, STM32G4!"); + println!("Hello, STM32G4!"); #[allow(clippy::empty_loop)] loop {} diff --git a/examples/i2c-bme680.rs b/examples/i2c-bme680.rs index 83de035e..2fa8a9c0 100644 --- a/examples/i2c-bme680.rs +++ b/examples/i2c-bme680.rs @@ -52,15 +52,15 @@ fn main() -> ! { .with_run_gas(true) .build(); - let profile_dur = dev.get_profile_dur(&settings.0).unwrap(); + let _profile_dur = dev.get_profile_dur(&settings.0).unwrap(); dev.set_sensor_settings(&mut delayer, settings).unwrap(); dev.set_sensor_mode(&mut delayer, PowerMode::ForcedMode) .unwrap(); - let sensor_settings = dev.get_sensor_settings(settings.1); + let _sensor_settings = dev.get_sensor_settings(settings.1); loop { delay.delay_ms(500u32); - let power_mode = dev.get_sensor_mode(); + let _power_mode = dev.get_sensor_mode(); dev.set_sensor_mode(&mut delayer, PowerMode::ForcedMode) .unwrap(); let (data, _state) = dev.get_sensor_data(&mut delayer).unwrap(); diff --git a/examples/opamp.rs b/examples/opamp.rs index 4952c5a7..473ba538 100644 --- a/examples/opamp.rs +++ b/examples/opamp.rs @@ -58,7 +58,7 @@ fn main() -> ! { ); // Configure op with pa7 as non-inverting input and set gain to x4 - let mut opamp2 = opamp2.pga( + let opamp2 = opamp2.pga( pa7, PgaModeInternal::gain(NonInvertingGain::Gain4), Option::>::None, // Do not route output to any external pin, use internal AD instead @@ -72,7 +72,7 @@ fn main() -> ! { loop { // Here we can sample the output of opamp2 as if it was a regular AD pin let sample = adc.convert( - &mut opamp2, + &opamp2, stm32g4xx_hal::adc::config::SampleTime::Cycles_640_5, ); @@ -87,6 +87,8 @@ fn main() -> ! { let (_opamp1, _pa1, _mode, _some_pa2) = _opamp1.disable(); let (_opamp2, _pa7, _mode, _none) = opamp2.disable(); - loop {} + loop { + delay.delay_ms(100); + } } } diff --git a/examples/pwm.rs b/examples/pwm.rs index 8ed1d511..9d2ca8e8 100644 --- a/examples/pwm.rs +++ b/examples/pwm.rs @@ -10,11 +10,15 @@ use hal::prelude::*; use hal::stm32; use hal::time::RateExtU32; use stm32g4xx_hal as hal; -mod utils; extern crate cortex_m_rt as rt; +#[macro_use] +mod utils; + #[entry] fn main() -> ! { + utils::logger::init(); + let dp = stm32::Peripherals::take().expect("cannot take peripherals"); let mut rcc = dp.RCC.constrain(); let gpioa = dp.GPIOA.split(&mut rcc); diff --git a/examples/spi-sd.rs b/examples/spi-sd.rs index 57a29799..37af1233 100644 --- a/examples/spi-sd.rs +++ b/examples/spi-sd.rs @@ -5,34 +5,30 @@ extern crate embedded_sdmmc; +use fugit::RateExtU32; use hal::gpio::gpiob::PB14; use hal::gpio::gpiob::PB15; -use hal::gpio::gpiof::PF8; use hal::gpio::gpiof::PF9; use hal::gpio::Alternate; use hal::gpio::AF5; use hal::prelude::*; use hal::rcc::Config; use hal::spi; -use hal::stm32; + use hal::stm32::Peripherals; -use hal::time::RateExtU32; -use hal::timer::Timer; use stm32g4xx_hal as hal; -use embedded_sdmmc::{ - Block, BlockCount, BlockDevice, BlockIdx, Controller, Error, Mode, TimeSource, Timestamp, - VolumeIdx, -}; +use embedded_sdmmc::{TimeSource, Timestamp}; use cortex_m_rt::entry; -use log::info; #[macro_use] mod utils; #[entry] fn main() -> ! { + utils::logger::init(); + let dp = Peripherals::take().unwrap(); let rcc = dp.RCC.constrain(); let mut rcc = rcc.freeze(Config::hsi()); @@ -49,7 +45,7 @@ fn main() -> ! { let miso: PB14> = gpiob.pb14.into_alternate(); let mosi: PB15> = gpiob.pb15.into_alternate(); - let mut spi = dp + let spi = dp .SPI2 .spi((sck, miso, mosi), spi::MODE_0, 400.kHz(), &mut rcc); @@ -70,6 +66,8 @@ fn main() -> ! { let mut cont = embedded_sdmmc::Controller::new(embedded_sdmmc::SdMmcSpi::new(spi, cs), Clock); - cont.device().init(); + cont.device().init().unwrap(); + + #[allow(clippy::empty_loop)] loop {} } diff --git a/examples/utils/logger.rs b/examples/utils/logger.rs index e11b73b2..4de3d943 100644 --- a/examples/utils/logger.rs +++ b/examples/utils/logger.rs @@ -5,7 +5,13 @@ cfg_if::cfg_if! { pub use defmt::println as println; } else { pub use log::{info, trace, warn, debug, error}; - pub use cortex_m_semihosting::hprintln as println; + + #[allow(unused_macros)] + macro_rules! println { + ($($tt:tt)*) => { + $crate::cortex_m_semihosting::hprintln!($($tt,)*).unwrap(); + }; + } } } diff --git a/src/adc.rs b/src/adc.rs index b0c5225e..52908d0e 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -571,7 +571,7 @@ pub mod config { } /// Sets the input type per channel - #[derive(Debug, Clone, Copy)] + #[derive(Debug, Clone, Copy, Default)] pub struct DifferentialSelection(pub(crate) u32); impl DifferentialSelection { /// Set pin to Single-Ended or Differential @@ -614,12 +614,6 @@ pub mod config { } } - impl Default for DifferentialSelection { - fn default() -> Self { - DifferentialSelection(0) - } - } - /// Configuration for the adc. /// There are some additional parameters on the adc peripheral that can be /// added here when needed but this covers several basic usecases. diff --git a/src/can.rs b/src/can.rs index c4db270a..b70eb04d 100644 --- a/src/can.rs +++ b/src/can.rs @@ -12,6 +12,7 @@ mod sealed { } /// Select an FDCAN Clock Source +#[allow(clippy::upper_case_acronyms)] #[allow(dead_code)] enum FdCanClockSource { /// Select HSE as the FDCAN clock source diff --git a/src/comparator.rs b/src/comparator.rs new file mode 100644 index 00000000..d0597ea7 --- /dev/null +++ b/src/comparator.rs @@ -0,0 +1,645 @@ +//! Comparator +//! +//! ## Origin +//! +//! This code has been taken from the stm32g0xx-hal project and modified slightly to support +//! STM32G4xx MCUs. + +use core::marker::PhantomData; + +use crate::dac; +use crate::exti::{Event as ExtiEvent, ExtiExt}; +use crate::gpio::{ + gpioa::{PA0, PA1, PA11, PA12, PA2, PA3, PA4, PA5, PA6, PA7}, + gpiob::{PB0, PB1, PB14, PB15, PB2, PB6, PB7, PB8, PB9}, + gpioc::PC2, + gpiof::PF4, + Analog, OpenDrain, Output, PushPull, SignalEdge, AF2, AF3, AF8, +}; + +#[cfg(any( + feature = "stm32g473", + feature = "stm32g483", + feature = "stm32g474", + feature = "stm32g484" +))] +use crate::gpio::{ + gpioa::{PA10, PA8, PA9}, + gpiob::{PB10, PB11, PB12, PB13}, + gpioc::{PC6, PC7, PC8}, + gpiod::{PD10, PD11, PD12, PD13, PD14, PD15}, + AF7, +}; + +use crate::gpio::gpioc::{PC0, PC1}; +use crate::gpio::gpioe::{PE7, PE8}; +use crate::gpio::gpiof::PF1; +use crate::rcc::{Clocks, Rcc}; +use crate::stm32::{COMP, EXTI}; + +/// Enabled Comparator (type state) +pub struct Enabled; + +/// Enabled and locked (config is read only) +pub struct Locked; + +/// Disabled Comparator (type state) +pub struct Disabled; + +pub trait ED {} +impl ED for Enabled {} +impl ED for Disabled {} + +pub trait EnabledState {} +impl EnabledState for Enabled {} +impl EnabledState for Locked {} + +macro_rules! impl_comp { + ($($t:ident: $reg_t:ident, $reg:ident,)+) => {$( + pub struct $t { + _rb: PhantomData<()>, + } + + impl $t { + pub fn csr(&self) -> &$crate::stm32::comp::$reg_t { + // SAFETY: The COMP1 type is only constructed with logical ownership of + // these registers. + &unsafe { &*COMP::ptr() }.$reg + } + } + )+}; +} + +impl_comp! { + COMP1: C1CSR, c1csr, + COMP2: C2CSR, c2csr, + COMP3: C3CSR, c3csr, + COMP4: C4CSR, c4csr, +} +#[cfg(any( + feature = "stm32g473", + feature = "stm32g483", + feature = "stm32g474", + feature = "stm32g484" +))] +impl_comp! { + COMP5: C5CSR, c5csr, + COMP6: C6CSR, c6csr, + COMP7: C7CSR, c7csr, +} + +// TODO: Split COMP in PAC + +#[derive(Copy, Clone, Eq, PartialEq)] +pub struct Config { + //power_mode: PowerMode, + hysteresis: Hysteresis, + inverted: bool, + //output_xor: bool, +} + +impl Default for Config { + fn default() -> Self { + Self { + hysteresis: Hysteresis::None, + inverted: false, + //power_mode: PowerMode::HighSpeed, + //output_xor: false, + } + } +} + +impl Config { + pub fn hysteresis(mut self, hysteresis: Hysteresis) -> Self { + self.hysteresis = hysteresis; + self + } + + pub fn output_inverted(mut self) -> Self { + self.inverted = true; + self + } + + pub fn output_polarity(mut self, inverted: bool) -> Self { + self.inverted = inverted; + self + } +} + +#[derive(Copy, Clone, Eq, PartialEq)] +pub enum Hysteresis { + None = 0b000, + H10mV = 0b001, + H20mV = 0b010, + H30mV = 0b011, + H40mV = 0b100, + H50mV = 0b101, + H60mV = 0b110, + H70mV = 0b111, +} + +/// Comparator positive input +pub trait PositiveInput { + fn setup(&self, comp: &C); +} + +/// Comparator negative input +pub trait NegativeInput { + /// Does this input use the internal reference Vrefint + /// + /// This only true for RefintInput + const USE_VREFINT: bool; + + /// Does this input rely on dividing Vrefint using an internal resistor divider + /// + /// This is only relevant for `RefintInput` other than `RefintInput::VRefint` + fn use_resistor_divider(&self) -> bool; + + fn setup(&self, comp: &C); +} + +macro_rules! positive_input_pin { + ($COMP:ident, $pin_0:ident, $pin_1:ident) => { + impl PositiveInput<$COMP> for &$pin_0 { + fn setup(&self, comp: &$COMP) { + comp.csr().modify(|_, w| w.inpsel().bit(false)) + } + } + + impl PositiveInput<$COMP> for &$pin_1 { + fn setup(&self, comp: &$COMP) { + comp.csr().modify(|_, w| w.inpsel().bit(true)) + } + } + }; +} + +positive_input_pin!(COMP1, PA1, PB1); +positive_input_pin!(COMP2, PA7, PA3); +positive_input_pin!(COMP3, PA0, PC1); +positive_input_pin!(COMP4, PB0, PE7); + +#[cfg(any( + feature = "stm32g473", + feature = "stm32g483", + feature = "stm32g474", + feature = "stm32g484" +))] +positive_input_pin!(COMP5, PB13, PD12); + +#[cfg(any( + feature = "stm32g473", + feature = "stm32g483", + feature = "stm32g474", + feature = "stm32g484" +))] +positive_input_pin!(COMP6, PB11, PD11); + +#[cfg(any( + feature = "stm32g473", + feature = "stm32g483", + feature = "stm32g474", + feature = "stm32g484" +))] +positive_input_pin!(COMP7, PB14, PD14); + +macro_rules! negative_input_pin_helper { + ($COMP:ident, $input:ty, $bits:expr) => { + impl NegativeInput<$COMP> for $input { + const USE_VREFINT: bool = false; + + fn use_resistor_divider(&self) -> bool { + false + } + + fn setup(&self, comp: &$COMP) { + comp.csr().modify(|_, w| unsafe { w.inmsel().bits($bits) }) + } + } + }; +} + +macro_rules! negative_input_pin { + ($($COMP:ident: $pin_0:ty, $pin_1:ty,)+) => {$( + negative_input_pin_helper!($COMP, $pin_0, 0b110); + negative_input_pin_helper!($COMP, $pin_1, 0b111); + )+}; +} + +negative_input_pin! { + COMP1: PA4, PA0, + COMP2: PA5, PA2, + COMP3: PF1, PC0, + COMP4: PE8, PB2, +} + +#[cfg(any( + feature = "stm32g473", + feature = "stm32g483", + feature = "stm32g474", + feature = "stm32g484" +))] +negative_input_pin! { + COMP5: PB10, PD13, + COMP6: PD10, PB15, + COMP7: PD15, PB12, +} + +#[derive(Copy, Clone, Eq, PartialEq)] +pub enum RefintInput { + /// VRefint * 1/4 + VRefintM14 = 0b000, + /// VRefint * 1/2 + VRefintM12 = 0b001, + /// VRefint * 3/4 + VRefintM34 = 0b010, + /// VRefint + VRefint = 0b011, +} + +macro_rules! refint_input { + ($($COMP:ident, )+) => {$( + impl NegativeInput<$COMP> for RefintInput { + const USE_VREFINT: bool = true; + + fn use_resistor_divider(&self) -> bool { + *self != RefintInput::VRefint + } + + fn setup(&self, comp: &$COMP) { + comp.csr() + .modify(|_, w| unsafe { w.inmsel().bits(*self as u8) }) + } + } + )+}; +} + +refint_input!(COMP1, COMP2, COMP3, COMP4,); + +#[cfg(any( + feature = "stm32g473", + feature = "stm32g483", + feature = "stm32g474", + feature = "stm32g484" +))] +refint_input!(COMP5, COMP6, COMP7,); + +macro_rules! dac_input_helper { + ($COMP:ident: $channel:ident, $MODE:ident, $bits:expr) => { + impl NegativeInput<$COMP> for &dac::$channel<{ dac::$MODE }, ED> { + const USE_VREFINT: bool = false; + + fn use_resistor_divider(&self) -> bool { + false + } + + fn setup(&self, comp: &$COMP) { + comp.csr().modify(|_, w| unsafe { w.inmsel().bits($bits) }) + } + } + }; +} + +macro_rules! dac_input { + ($COMP:ident: $channel:ident, $bits:expr) => { + dac_input_helper!($COMP: $channel, M_MIX_SIG, $bits); + dac_input_helper!($COMP: $channel, M_INT_SIG, $bits); + }; +} + +dac_input!(COMP1: Dac3Ch1, 0b100); +dac_input!(COMP1: Dac1Ch1, 0b101); + +dac_input!(COMP2: Dac3Ch2, 0b100); +dac_input!(COMP2: Dac1Ch2, 0b101); + +dac_input!(COMP3: Dac3Ch1, 0b100); +dac_input!(COMP3: Dac1Ch1, 0b101); + +dac_input!(COMP4: Dac3Ch2, 0b100); +dac_input!(COMP4: Dac1Ch1, 0b101); + +#[cfg(any( + feature = "stm32g473", + feature = "stm32g483", + feature = "stm32g474", + feature = "stm32g484" +))] +dac_input!(COMP5: Dac4Ch1, 0b100); +#[cfg(any( + feature = "stm32g473", + feature = "stm32g483", + feature = "stm32g474", + feature = "stm32g484" +))] +dac_input!(COMP5: Dac1Ch2, 0b101); + +#[cfg(any( + feature = "stm32g473", + feature = "stm32g483", + feature = "stm32g474", + feature = "stm32g484" +))] +dac_input!(COMP6: Dac4Ch2, 0b100); +#[cfg(any( + feature = "stm32g473", + feature = "stm32g483", + feature = "stm32g474", + feature = "stm32g484" +))] +dac_input!(COMP6: Dac2Ch1, 0b101); + +#[cfg(any( + feature = "stm32g473", + feature = "stm32g483", + feature = "stm32g474", + feature = "stm32g484" +))] +dac_input!(COMP7: Dac4Ch1, 0b100); +#[cfg(any( + feature = "stm32g473", + feature = "stm32g483", + feature = "stm32g474", + feature = "stm32g484" +))] +dac_input!(COMP7: Dac2Ch1, 0b101); + +pub struct Comparator { + regs: C, + _enabled: PhantomData, +} + +pub trait ComparatorExt { + /// Initializes a comparator + fn comparator, N: NegativeInput>( + self, + positive_input: P, + negative_input: N, + config: Config, + clocks: &Clocks, + ) -> Comparator; +} + +macro_rules! impl_comparator { + ($COMP:ty, $comp:ident, $Event:expr) => { + impl ComparatorExt<$COMP> for $COMP { + fn comparator, N: NegativeInput<$COMP>>( + self, + positive_input: P, + negative_input: N, + config: Config, + clocks: &Clocks, + ) -> Comparator<$COMP, Disabled> { + positive_input.setup(&self); + negative_input.setup(&self); + // Delay for scaler voltage bridge initialization for certain negative inputs + let voltage_scaler_delay = clocks.sys_clk.raw() / (1_000_000 / 200); // 200us + cortex_m::asm::delay(voltage_scaler_delay); + self.csr().modify(|_, w| unsafe { + w.hyst() + .bits(config.hysteresis as u8) + .scalen() + .bit(N::USE_VREFINT) + .brgen() + .bit(negative_input.use_resistor_divider()) + .pol() + .bit(config.inverted) + }); + + Comparator { + regs: self, + _enabled: PhantomData, + } + } + } + + impl Comparator<$COMP, Disabled> { + /// Initializes a comparator + pub fn $comp, N: NegativeInput<$COMP>>( + comp: $COMP, + positive_input: P, + negative_input: N, + config: Config, + clocks: &Clocks, + ) -> Self { + comp.comparator(positive_input, negative_input, config, clocks) + } + + /// Enables the comparator + pub fn enable(self) -> Comparator<$COMP, Enabled> { + self.regs.csr().modify(|_, w| w.en().set_bit()); + Comparator { + regs: self.regs, + _enabled: PhantomData, + } + } + + /// Enables raising the `ADC_COMP` interrupt at the specified output signal edge + pub fn listen(&self, edge: SignalEdge, exti: &EXTI) { + exti.listen($Event, edge); + } + } + + impl Comparator<$COMP, ED> { + /// Returns the value of the output of the comparator + pub fn output(&self) -> bool { + self.regs.csr().read().value().bit_is_set() + } + } + + impl Comparator<$COMP, Enabled> { + pub fn lock(self) -> Comparator<$COMP, Locked> { + // Setting this bit turns all other bits into read only until restart + self.regs.csr().modify(|_, w| w.lock().set_bit()); + Comparator { + regs: self.regs, + _enabled: PhantomData, + } + } + + /// Disables the comparator + pub fn disable(self) -> Comparator<$COMP, Disabled> { + self.regs.csr().modify(|_, w| w.en().clear_bit()); + Comparator { + regs: self.regs, + _enabled: PhantomData, + } + } + } + + impl Comparator<$COMP, ED> { + /// Disables raising interrupts for the output signal + pub fn unlisten(&self, exti: &EXTI) { + exti.unlisten($Event); + } + + /// Returns `true` if the output signal interrupt is pending for the `edge` + pub fn is_pending(&self, exti: &EXTI) -> bool { + exti.is_pending($Event) + } + + /// Unpends the output signal interrupt + pub fn unpend(&self, exti: &EXTI) { + exti.unpend($Event); + } + + /// Configures a GPIO pin to output the signal of the comparator + /// + /// Multiple GPIO pins may be configured as the output simultaneously. + pub fn output_pin>(&self, pin: P) { + pin.setup(); + } + } + }; +} + +impl_comparator!(COMP1, comp1, ExtiEvent::COMP1); +impl_comparator!(COMP2, comp2, ExtiEvent::COMP2); +impl_comparator!(COMP3, comp1, ExtiEvent::COMP3); +impl_comparator!(COMP4, comp2, ExtiEvent::COMP4); + +#[cfg(any( + feature = "stm32g473", + feature = "stm32g483", + feature = "stm32g474", + feature = "stm32g484" +))] +impl_comparator!(COMP5, comp1, ExtiEvent::COMP5); + +#[cfg(any( + feature = "stm32g473", + feature = "stm32g483", + feature = "stm32g474", + feature = "stm32g484" +))] +impl_comparator!(COMP6, comp2, ExtiEvent::COMP6); + +#[cfg(any( + feature = "stm32g473", + feature = "stm32g483", + feature = "stm32g474", + feature = "stm32g484" +))] +impl_comparator!(COMP7, comp2, ExtiEvent::COMP7); + +#[cfg(not(any( + feature = "stm32g473", + feature = "stm32g483", + feature = "stm32g474", + feature = "stm32g484" +)))] +type Comparators = (COMP1, COMP2, COMP3, COMP4); + +#[cfg(any( + feature = "stm32g473", + feature = "stm32g483", + feature = "stm32g474", + feature = "stm32g484" +))] +type Comparators = (COMP1, COMP2, COMP3, COMP4, COMP5, COMP6, COMP7); + +/// Enables the comparator peripheral, and splits the [`COMP`] into independent [`COMP1`] and [`COMP2`] +pub fn split(_comp: COMP, rcc: &mut Rcc) -> Comparators { + // Enable COMP, SYSCFG, VREFBUF clocks + rcc.rb.apb2enr.modify(|_, w| w.syscfgen().set_bit()); + + // Reset COMP, SYSCFG, VREFBUF + rcc.rb.apb2rstr.modify(|_, w| w.syscfgrst().set_bit()); + rcc.rb.apb2rstr.modify(|_, w| w.syscfgrst().clear_bit()); + + ( + COMP1 { _rb: PhantomData }, + COMP2 { _rb: PhantomData }, + COMP3 { _rb: PhantomData }, + COMP4 { _rb: PhantomData }, + #[cfg(any( + feature = "stm32g473", + feature = "stm32g483", + feature = "stm32g474", + feature = "stm32g484" + ))] + COMP5 { _rb: PhantomData }, + #[cfg(any( + feature = "stm32g473", + feature = "stm32g483", + feature = "stm32g474", + feature = "stm32g484" + ))] + COMP6 { _rb: PhantomData }, + #[cfg(any( + feature = "stm32g473", + feature = "stm32g483", + feature = "stm32g474", + feature = "stm32g484" + ))] + COMP7 { _rb: PhantomData }, + ) +} + +pub trait ComparatorSplit { + /// Enables the comparator peripheral, and splits the [`COMP`] into independent [`COMP1`] and [`COMP2`] + fn split(self, rcc: &mut Rcc) -> Comparators; +} + +impl ComparatorSplit for COMP { + fn split(self, rcc: &mut Rcc) -> Comparators { + split(self, rcc) + } +} + +pub trait OutputPin { + fn setup(self); +} + +#[allow(unused_macros)] // TODO: add support for more devices +macro_rules! output_pin { + ($COMP:ident, $pin:ident, $AF:ident, $mode_t:ident, $into:ident) => { + impl OutputPin<$COMP> for $pin> { + fn setup(self) { + self.$into::<$AF>(); + } + } + }; + ($($COMP:ident: $pin:ident, $AF:ident,)+) => {$( + output_pin!($COMP, $pin, $AF, PushPull, into_alternate); + output_pin!($COMP, $pin, $AF, OpenDrain, into_alternate_open_drain); + )+}; +} + +output_pin! { + COMP1: PA0, AF8, + COMP1: PA6, AF8, + COMP1: PA11, AF8, + COMP1: PB8, AF8, + COMP1: PF4, AF2, + + COMP2: PA2, AF8, + COMP2: PA7, AF8, + COMP2: PA12, AF8, + COMP2: PB9, AF8, + + COMP3: PB7, AF8, + COMP3: PB15, AF3, + COMP3: PC2, AF3, + + COMP4: PB1, AF8, + COMP4: PB6, AF8, + COMP4: PB14, AF8, +} + +#[cfg(any( + feature = "stm32g473", + feature = "stm32g483", + feature = "stm32g474", + feature = "stm32g484", +))] +output_pin! { + COMP5: PA9, AF8, + COMP5: PC7, AF7, + + COMP6: PA10, AF8, + COMP6: PC6, AF7, + + COMP7: PA8, AF8, + COMP7: PC8, AF7, +} diff --git a/src/dac.rs b/src/dac.rs new file mode 100644 index 00000000..109374c0 --- /dev/null +++ b/src/dac.rs @@ -0,0 +1,354 @@ +//! DAC +//! +//! ## Origin +//! +//! This code has been taken from the stm32g0xx-hal project and modified to support +//! STM32G4xx MCUs. + +use core::marker::PhantomData; +use core::mem::MaybeUninit; + +use crate::gpio::gpioa::{PA4, PA5, PA6}; +use crate::gpio::DefaultMode; +use crate::rcc::{self, *}; +use crate::stm32::{DAC1, DAC2, DAC3, DAC4, RCC}; +use hal::blocking::delay::DelayUs; + +pub trait DacOut { + fn set_value(&mut self, val: V); + fn get_value(&mut self) -> V; +} + +pub struct GeneratorConfig { + mode: u8, + amp: u8, +} + +impl GeneratorConfig { + pub fn triangle(amplitude: u8) -> Self { + Self { + mode: 0b10, + amp: amplitude, + } + } + + pub fn sawtooth(amplitude: u8) -> Self { + Self { + mode: 0b11, + amp: amplitude, + } + } + + pub fn noise(seed: u8) -> Self { + Self { + mode: 0b01, + amp: seed, + } + } +} + +/// Enabled DAC (type state) +pub struct Enabled; +// / Enabled DAC without output buffer (type state) +//pub struct EnabledUnbuffered; +/// Enabled DAC wave generator (type state) +pub struct WaveGenerator; +/// Disabled DAC (type state) +pub struct Disabled; + +pub trait ED {} +impl ED for Enabled {} +//impl ED for EnabledUnbuffered {} +impl ED for WaveGenerator {} +impl ED for Disabled {} + +macro_rules! impl_dac { + ($DACxCHy:ident) => { + pub struct $DACxCHy { + _enabled: PhantomData, + } + }; +} + +impl_dac!(Dac1Ch1); +impl_dac!(Dac1Ch2); +impl_dac!(Dac2Ch1); // DAC2 only has 1 channel +impl_dac!(Dac3Ch1); +impl_dac!(Dac3Ch2); +impl_dac!(Dac4Ch1); +impl_dac!(Dac4Ch2); + +/// Trait for GPIO pins that can be converted to DAC output pins +pub trait Pins { + type Output; +} + +/// Dac output mode: external pin only +pub const M_EXT_PIN: u8 = 0b000; + +/// Dac output mode: internal signal and external pin +pub const M_MIX_SIG: u8 = 0b001; + +/// Dac output mode: internal signal only +pub const M_INT_SIG: u8 = 0b011; + +pub struct Dac1IntSig1; +pub struct Dac1IntSig2; +pub struct Dac2IntSig1; +pub struct Dac3IntSig1; +pub struct Dac3IntSig2; +pub struct Dac4IntSig1; +pub struct Dac4IntSig2; + +macro_rules! impl_pin_for_dac { + ($DAC:ident: $pin:ty, $output:ty) => { + #[allow(unused_parens)] + impl Pins<$DAC> for $pin { + #[allow(unused_parens)] + type Output = $output; + } + }; +} + +// Implement all combinations of ch2 for the specified ch1 on DAC1 +macro_rules! impl_dac1_ch2_combos { + ($($pin_ch1:ty, $output_ch1:ty)*) => { + $(impl_pin_for_dac!(DAC1: $pin_ch1, // ch2: Not used + $output_ch1 + );)* + impl_pin_for_dac!(DAC1: ($($pin_ch1,)* PA5), // ch2: Ext pin + ($($output_ch1,)* Dac1Ch2) + ); + impl_pin_for_dac!(DAC1: ($($pin_ch1,)* Dac1IntSig2), // ch2: Internal + ($($output_ch1,)* Dac1Ch2) + ); + impl_pin_for_dac!(DAC1: ($($pin_ch1,)* (PA5, Dac1IntSig2)),// ch2: Mixed + ($($output_ch1,)* Dac1Ch2) + ); + }; +} + +impl_dac1_ch2_combos!(); // ch1: Not used +impl_dac1_ch2_combos!(PA4, Dac1Ch1); // ch1: Ext pin +impl_dac1_ch2_combos!(Dac1IntSig1, Dac1Ch1); // ch1: Internal +impl_dac1_ch2_combos!((PA4, Dac1IntSig1), Dac1Ch1); // ch1: Mixed + +// DAC2 +impl_pin_for_dac!(DAC2: PA6, Dac2Ch1); // ch1: Ext pin +impl_pin_for_dac!(DAC2: Dac2IntSig1, Dac2Ch1); // ch1: Internal +impl_pin_for_dac!(DAC2: (PA6, Dac2IntSig1), Dac2Ch1); // ch1: Mixed + +// DAC3 int +impl_pin_for_dac!(DAC3: Dac3IntSig1, Dac3Ch1); +impl_pin_for_dac!(DAC3: Dac3IntSig2, Dac3Ch2); +impl_pin_for_dac!( + DAC3: (Dac3IntSig1, Dac3IntSig2), + (Dac3Ch1, Dac3Ch2) +); + +// DAC4 int +impl_pin_for_dac!(DAC4: Dac4IntSig1, Dac4Ch1); +impl_pin_for_dac!(DAC4: Dac4IntSig2, Dac4Ch2); +impl_pin_for_dac!( + DAC4: (Dac4IntSig1, Dac4IntSig2), + (Dac4Ch1, Dac4Ch2) +); + +pub fn dac(_dac: DAC, _pins: PINS, _rcc: &mut Rcc) -> PINS::Output +where + DAC: rcc::Enable + rcc::Reset, + PINS: Pins, +{ + unsafe { + let rcc_ptr = &(*RCC::ptr()); + DAC::enable(rcc_ptr); + DAC::reset(rcc_ptr); + } + + #[allow(clippy::uninit_assumed_init)] + unsafe { + MaybeUninit::uninit().assume_init() + } +} + +macro_rules! dac_helper { + ($($CX:ident: $DAC:ty: ( + $en:ident, + $cen:ident, + $cal_flag:ident, + $trim:ident, + $mode:ident, + $dhrx:ident, + $dac_dor:ident, + $daccxdhr:ident, + $wave:ident, + $mamp:ident, + $ten:ident, + $swtrig:ident + ),)+) => { + $( + impl $CX { + /// TODO: The DAC does not seem to work unless `calibrate_buffer` has been callen + /// even when only using dac output internally + pub fn enable(self) -> $CX { + let dac = unsafe { &(*<$DAC>::ptr()) }; + + dac.dac_mcr.modify(|_, w| unsafe { w.$mode().bits(MODE_BITS) }); + dac.dac_cr.modify(|_, w| w.$en().set_bit()); + + $CX { + _enabled: PhantomData, + } + } + + pub fn enable_generator(self, config: GeneratorConfig) -> $CX { + let dac = unsafe { &(*<$DAC>::ptr()) }; + + dac.dac_mcr.modify(|_, w| unsafe { w.$mode().bits(MODE_BITS) }); + dac.dac_cr.modify(|_, w| unsafe { + w.$wave().bits(config.mode); + w.$ten().set_bit(); + w.$mamp().bits(config.amp); + w.$en().set_bit() + }); + + $CX { + _enabled: PhantomData, + } + } + } + + impl $CX { + /// Calibrate the DAC output buffer by performing a "User + /// trimming" operation. It is useful when the VDDA/VREF+ + /// voltage or temperature differ from the factory trimming + /// conditions. + /// + /// The calibration is only valid when the DAC channel is + /// operating with the buffer enabled. If applied in other + /// modes it has no effect. + /// + /// After the calibration operation, the DAC channel is + /// disabled. + pub fn calibrate_buffer(self, delay: &mut T) -> $CX + where + T: DelayUs, + { + let dac = unsafe { &(*<$DAC>::ptr()) }; + dac.dac_cr.modify(|_, w| w.$en().clear_bit()); + dac.dac_mcr.modify(|_, w| unsafe { w.$mode().bits(0) }); + dac.dac_cr.modify(|_, w| w.$cen().set_bit()); + let mut trim = 0; + while true { + dac.dac_ccr.modify(|_, w| unsafe { w.$trim().bits(trim) }); + delay.delay_us(64_u32); + if dac.dac_sr.read().$cal_flag().bit() { + break; + } + trim += 1; + } + dac.dac_cr.modify(|_, w| w.$cen().clear_bit()); + + $CX { + _enabled: PhantomData, + } + } + + /// Disable the DAC channel + pub fn disable(self) -> $CX { + let dac = unsafe { &(*<$DAC>::ptr()) }; + dac.dac_cr.modify(|_, w| unsafe { + w.$en().clear_bit().$wave().bits(0).$ten().clear_bit() + }); + + $CX { + _enabled: PhantomData, + } + } + } + + /// DacOut implementation available in any Enabled/Disabled + /// state + impl DacOut for $CX { + fn set_value(&mut self, val: u16) { + let dac = unsafe { &(*<$DAC>::ptr()) }; + dac.$dhrx.write(|w| unsafe { w.bits(val as u32) }); + } + + fn get_value(&mut self) -> u16 { + let dac = unsafe { &(*<$DAC>::ptr()) }; + dac.$dac_dor.read().bits() as u16 + } + } + + /// Wave generator state implementation + impl $CX { + pub fn trigger(&mut self) { + let dac = unsafe { &(*<$DAC>::ptr()) }; + dac.dac_swtrgr.write(|w| { w.$swtrig().set_bit() }); + } + } + )+ + }; +} + +macro_rules! dac { + ($($DAC:ident ch1: $DACxCH1:ident $(, ch2: $DACxCH2:ident)*)+) => {$( + dac_helper!{$DACxCH1: $DAC: ( + en1, + cen1, + cal_flag1, + otrim1, + mode1, + dac_dhr12r1, + dac_dor1, + dacc1dhr, + wave1, + mamp1, + ten1, + swtrig1 + ), + $($DACxCH2: $DAC: ( + en2, + cen2, + cal_flag2, + otrim2, + mode2, + dac_dhr12r2, + dac_dor2, + dacc2dhr, + wave2, + mamp2, + ten2, + swtrig2 + ),)*} + )+}; +} + +pub trait DacExt: Sized { + fn constrain(self, pins: PINS, rcc: &mut Rcc) -> PINS::Output + where + PINS: Pins; +} + +macro_rules! impl_dac_ext { + ($($DAC:ty, )+) => {$( + impl DacExt for $DAC { + fn constrain(self, pins: PINS, rcc: &mut Rcc) -> PINS::Output + where + PINS: Pins<$DAC>, + { + dac(self, pins, rcc) + } + } + )+}; +} + +impl_dac_ext!(DAC1, DAC2, DAC3, DAC4,); + +dac!( + DAC1 ch1: Dac1Ch1, ch2: Dac1Ch2 + DAC2 ch1: Dac2Ch1 + DAC3 ch1: Dac3Ch1, ch2: Dac3Ch2 + DAC4 ch1: Dac4Ch1, ch2: Dac4Ch2 +); diff --git a/src/dma/config.rs b/src/dma/config.rs index 2bffb564..21b3bd02 100644 --- a/src/dma/config.rs +++ b/src/dma/config.rs @@ -4,22 +4,18 @@ use super::Bits; /// the same software priority level, the stream with the lower number takes /// priority over the stream with the higher number. For example, Stream 2 /// takes priority over Stream 4. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Default)] pub enum Priority { /// Low priority. Low, /// Medium priority. + #[default] Medium, /// High priority. High, /// Very high priority. VeryHigh, } -impl Default for Priority { - fn default() -> Self { - Priority::Medium - } -} impl Bits for Priority { fn bits(self) -> u8 { diff --git a/src/dma/mux.rs b/src/dma/mux.rs index 3aeaa61c..968f345c 100644 --- a/src/dma/mux.rs +++ b/src/dma/mux.rs @@ -1,3 +1,4 @@ +#[allow(clippy::upper_case_acronyms)] pub enum DmaMuxResources { DMAMUXReqG0 = 1, DMAMUXReqG1 = 2, diff --git a/src/dma/transfer.rs b/src/dma/transfer.rs index febaf1f4..168d70cc 100644 --- a/src/dma/transfer.rs +++ b/src/dma/transfer.rs @@ -313,7 +313,7 @@ where { /// Return the number of elements available to read pub fn elements_available(&mut self) -> usize { - let blen = unsafe { self.transfer.buf.static_write_buffer().1 } as usize; + let blen = unsafe { self.transfer.buf.static_write_buffer().1 }; let ndtr = STREAM::get_number_of_transfers() as usize; let pos_at = self.r_pos; @@ -341,7 +341,7 @@ where &mut self, dat: &mut [>::MemSize], ) -> usize { - let blen = unsafe { self.transfer.buf.static_write_buffer().1 } as usize; + let blen = unsafe { self.transfer.buf.static_write_buffer().1 }; let pos = self.r_pos; let read = dat.len(); diff --git a/src/flash.rs b/src/flash.rs index 99657872..26b60484 100644 --- a/src/flash.rs +++ b/src/flash.rs @@ -59,6 +59,7 @@ pub struct FlashWriter<'a, const SECTOR_SZ_KB: u32> { verify: bool, } impl<'a, const SECTOR_SZ_KB: u32> FlashWriter<'a, SECTOR_SZ_KB> { + #[allow(unused)] fn unlock_options(&mut self) -> Result<()> { // Check if flash is busy while self.flash.sr.sr().read().bsy().bit_is_set() {} @@ -142,12 +143,12 @@ impl<'a, const SECTOR_SZ_KB: u32> FlashWriter<'a, SECTOR_SZ_KB> { if offset .checked_add(length as u32) .ok_or(Error::LengthTooLong)? - > self.flash_sz.kbytes() as u32 + > self.flash_sz.kbytes() { return Err(Error::LengthTooLong); } - if force_padding == false && length % 8 != 0 { + if !force_padding && length % 8 != 0 { return Err(Error::ArrayMustBeDivisibleBy8); } @@ -164,7 +165,7 @@ impl<'a, const SECTOR_SZ_KB: u32> FlashWriter<'a, SECTOR_SZ_KB> { // Set Page Erase self.flash.cr.cr().modify(|_, w| w.per().set_bit()); - let page = start_offset / (SECTOR_SZ_KB as u32); + let page = start_offset / SECTOR_SZ_KB; // Write address bits // NOTE(unsafe) This sets the page address in the Address Register. @@ -206,7 +207,7 @@ impl<'a, const SECTOR_SZ_KB: u32> FlashWriter<'a, SECTOR_SZ_KB> { let size = SECTOR_SZ_KB; let start = start_offset & !(size - 1); for idx in (start..start + size).step_by(2) { - let write_address = (FLASH_START + idx as u32) as *const u16; + let write_address = (FLASH_START + idx) as *const u16; let verify: u16 = unsafe { core::ptr::read_volatile(write_address) }; if verify != 0xFFFF { return Err(Error::VerifyError); @@ -237,7 +238,7 @@ impl<'a, const SECTOR_SZ_KB: u32> FlashWriter<'a, SECTOR_SZ_KB> { pub fn read(&self, offset: u32, length: usize) -> Result<&[u8]> { self.valid_address(offset)?; - if offset + length as u32 > self.flash_sz.kbytes() as u32 { + if offset + length as u32 > self.flash_sz.kbytes() { return Err(Error::LengthTooLong); } @@ -281,9 +282,7 @@ impl<'a, const SECTOR_SZ_KB: u32> FlashWriter<'a, SECTOR_SZ_KB> { // Check if there is enough data to make 2 words, if there isn't, pad the data with 0xFF if idx + 8 > data.len() { let mut tmp_buffer = [255u8; 8]; - for jdx in idx..data.len() { - tmp_buffer[jdx] = data[idx + jdx]; - } + tmp_buffer[idx..data.len()].copy_from_slice(&data[(idx + idx)..(data.len() + idx)]); let tmp_dword = u64::from_le_bytes(tmp_buffer); word1 = tmp_dword as u32; word2 = (tmp_dword >> 32) as u32; @@ -392,6 +391,7 @@ pub struct Parts { pub(crate) cr: CR, /// Opaque ECCR register + #[allow(unused)] pub(crate) eccr: ECCR, /// Opaque KEYR register @@ -410,9 +410,11 @@ pub struct Parts { pub(crate) _pcrop1er: PCROP1ER, /// Opaque PDKEYR register + #[allow(unused)] pub(crate) pdkeyr: PDKEYR, /// Opaque SEC1R register + #[allow(unused)] pub(crate) sec1r: SEC1R, /// Opaque SR register diff --git a/src/lib.rs b/src/lib.rs index 43640ce6..ab3508c7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -63,8 +63,9 @@ pub use crate::stm32::interrupt; pub mod adc; pub mod bb; pub mod can; +pub mod comparator; // pub mod crc; -// pub mod dac; +pub mod dac; pub mod delay; pub mod dma; pub mod exti; diff --git a/src/pwm.rs b/src/pwm.rs index ad65463a..4cfd69e8 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -1080,8 +1080,6 @@ fn calculate_deadtime(base_freq: Hertz, deadtime: NanoSecond) -> (u8, u8) { let deadtime_ticks = deadtime_ticks as u64 * 429497; let deadtime_ticks = (deadtime_ticks >> 32) as u32; - let deadtime_ticks = deadtime_ticks as u32; - // Choose CR1 CKD divider of 1, 2, or 4 to determine tDTS let (deadtime_ticks, ckd) = match deadtime_ticks { t if t <= 1008 => (deadtime_ticks, 1), diff --git a/src/rcc/config.rs b/src/rcc/config.rs index 1f54d923..5dec5a5b 100644 --- a/src/rcc/config.rs +++ b/src/rcc/config.rs @@ -71,11 +71,11 @@ pub enum PllMDiv { impl PllMDiv { pub fn divisor(&self) -> u32 { - (self.clone() as u32) + 1 + (*self as u32) + 1 } pub fn register_setting(&self) -> u8 { - self.clone() as u8 + *self as u8 } } @@ -90,11 +90,11 @@ pub enum PllQDiv { impl PllQDiv { pub fn divisor(&self) -> u32 { - ((self.clone() as u32) + 1) * 2 + ((*self as u32) + 1) * 2 } pub fn register_setting(&self) -> u8 { - self.clone() as u8 + *self as u8 } } @@ -109,11 +109,11 @@ pub enum PllRDiv { impl PllRDiv { pub fn divisor(&self) -> u32 { - ((self.clone() as u32) + 1) * 2 + ((*self as u32) + 1) * 2 } pub fn register_setting(&self) -> u8 { - self.clone() as u8 + *self as u8 } } @@ -158,11 +158,11 @@ pub enum PllPDiv { impl PllPDiv { pub fn divisor(&self) -> u32 { - self.clone() as u32 + *self as u32 } pub fn register_setting(&self) -> u8 { - self.clone() as u8 + *self as u8 } } @@ -293,11 +293,11 @@ pub enum PllNMul { impl PllNMul { pub fn multiplier(&self) -> u32 { - self.clone() as u32 + *self as u32 } pub fn register_setting(&self) -> u8 { - self.clone() as u8 + *self as u8 } } diff --git a/src/timer.rs b/src/timer.rs index 47584e76..eae92497 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -150,6 +150,7 @@ impl MonoTimer { dwt.enable_cycle_counter(); // now the CYCCNT counter can't be stopped or reset + #[allow(clippy::drop_non_drop)] drop(dwt); MonoTimer {