diff --git a/Cargo.toml b/Cargo.toml index b7ce766..1bed7b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ authors = ["Vitaly Domnikov "] categories = ["embedded", "hardware-support", "no-std"] description = "Peripheral access API for STM32G0 series microcontrollers" documentation = "https://docs.rs/stm32g0xx-hal" -edition = "2018" +edition = "2021" keywords = ["arm", "cortex-m", "stm32g0xx", "hal"] license = "MIT/Apache-2.0" name = "stm32g0xx-hal" @@ -18,14 +18,16 @@ default-target = "thumbv6m-none-eabi" [dependencies] cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] } nb = "1.1.0" +defmt = { version = "0.3.10", optional = true } fugit = "0.3.7" embedded-hal = "1.0.0" bare-metal = "1.0.0" - +portable-atomic = { version = "1.10.0", features = ["critical-section"] } [dependencies.stm32g0] package = "stm32g0-staging" version = "0.16.0" +features = ["atomics"] [dependencies.void] default-features = false @@ -34,11 +36,9 @@ version = "1.0.2" [dev-dependencies] cortex-m-rt = "0.7.5" cortex-m-semihosting = "0.5.0" -defmt = "0.3.8" defmt-rtt = "0.4.0" panic-halt = "1.0.0" panic-semihosting = "0.6.0" -portable-atomic = {version = "1.7.0", features = ["critical-section"]} rtic = { version = "2.1.1", features = ["thumbv6-backend"] } panic-probe = "0.3.2" @@ -46,7 +46,7 @@ panic-probe = "0.3.2" default = ["i2c-blocking"] device-selected = [] rt = ["stm32g0/rt"] -defmt = ["embedded-hal/defmt-03"] +defmt = ["dep:defmt", "embedded-hal/defmt-03", "stm32g0/defmt"] stm32g030 = ["stm32g0/stm32g030", "stm32g0x0", "device-selected"] stm32g070 = ["stm32g0/stm32g070", "stm32g0x0", "device-selected"] stm32g031 = ["stm32g0/stm32g031", "stm32g0x1", "device-selected"] diff --git a/src/analog/adc.rs b/src/analog/adc.rs index 2345334..427d125 100644 --- a/src/analog/adc.rs +++ b/src/analog/adc.rs @@ -13,7 +13,8 @@ pub trait Channel { } /// ADC Result Alignment -#[derive(Eq, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Align { /// Right aligned results (least significant bits) /// @@ -29,7 +30,8 @@ pub enum Align { } /// ADC Sampling Precision -#[derive(Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Precision { /// 12 bit precision B_12 = 0b00, @@ -42,7 +44,8 @@ pub enum Precision { } /// ADC Sampling time -#[derive(Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum SampleTime { T_2 = 0b000, T_4 = 0b001, @@ -55,7 +58,8 @@ pub enum SampleTime { } // ADC Oversampling ratio -#[derive(Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum OversamplingRatio { X_2 = 0b000, X_4 = 0b001, @@ -67,20 +71,23 @@ pub enum OversamplingRatio { X_256 = 0b111, } -#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum ClockSource { Pclk(PclkDiv), Async(AsyncClockDiv), } -#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum PclkDiv { PclkD1 = 3, PclkD2 = 1, PclkD4 = 2, } -#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum AsyncClockDiv { AsyncD1 = 0, AsyncD2 = 1, @@ -94,7 +101,8 @@ pub enum AsyncClockDiv { } /// ADC injected trigger source selection -#[derive(Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum InjTrigSource { TRG_0 = 0b000, // TIM1_TRGO2 TRG_1 = 0b001, // TIM1_CC4 diff --git a/src/analog/comparator.rs b/src/analog/comparator.rs index 4e34ad4..19a1432 100644 --- a/src/analog/comparator.rs +++ b/src/analog/comparator.rs @@ -94,7 +94,8 @@ impl Config { } } -#[derive(Copy, Clone, Eq, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Hysteresis { None = 0b00, Low = 0b01, @@ -102,7 +103,8 @@ pub enum Hysteresis { High = 0b11, } -#[derive(Copy, Clone, Eq, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum PowerMode { HighSpeed = 0b00, MediumSpeed = 0b01, @@ -183,7 +185,8 @@ negative_input_pin!(COMP2, PB3, 0b0110); negative_input_pin!(COMP2, PB7, 0b0111); negative_input_pin!(COMP2, PA2, 0b1000); -#[derive(Copy, Clone, Eq, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum RefintInput { /// VRefint * 1/4 VRefintM14 = 0b0000, diff --git a/src/crc.rs b/src/crc.rs index 1c0ef4b..d4be0a9 100644 --- a/src/crc.rs +++ b/src/crc.rs @@ -44,6 +44,8 @@ impl CrcExt for CRC { } /// Polynomial settings. +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Polynomial { /// 7-bit polynomial, only the lowest 7 bits are valid L7(u8), @@ -56,6 +58,8 @@ pub enum Polynomial { } /// Bit reversal settings. +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum BitReversal { /// Reverse bits by byte ByByte, diff --git a/src/dma.rs b/src/dma.rs index ce143b8..9a90e63 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -1,9 +1,9 @@ //! Direct Memory Access Engine // TODO: add DMA2 for B1, C1 -use crate::dmamux::DmaMuxIndex; -use crate::rcc::Rcc; -use crate::stm32::DMAMUX; +use crate::dmamux::{self, DmaMuxExt, DmaMuxIndex}; +use crate::rcc::{Enable, Rcc, Reset}; +use crate::stm32::{self, DMA1, DMAMUX}; /// Extension trait to split a DMA peripheral into independent channels pub trait DmaExt { @@ -18,6 +18,8 @@ pub trait DmaExt { } /// Channel priority level +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Priority { /// Low Low = 0b00, @@ -41,6 +43,8 @@ impl From for u8 { } /// DMA transfer direction +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Direction { /// From memory to peripheral FromMemory, @@ -57,8 +61,9 @@ impl From for bool { } } -#[doc = "Peripheral size"] -#[derive(Clone, Copy, Debug, Eq, PartialEq)] +/// Peripheral size +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u8)] pub enum WordSize { #[doc = "0: 8-bit size"] @@ -76,6 +81,8 @@ impl From for u8 { } /// DMA events +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Event { /// First half of a transfer is done HalfTransfer, @@ -243,6 +250,57 @@ pub trait Channel: private::Channel { } } +/// Singleton that represents a DMA channel +pub struct C { + mux: dmamux::Channel, +} + +impl private::Channel for C { + fn ch(&self) -> &stm32::dma1::CH { + // NOTE(unsafe) $Ci grants exclusive access to this register + unsafe { (*DMA1::ptr()).ch(N as usize) } + } +} + +impl C { + pub fn mux(&mut self) -> &mut dyn dmamux::DmaMuxChannel { + &mut self.mux + } +} + +impl Channel for C { + fn select_peripheral(&mut self, index: DmaMuxIndex) { + self.mux().select_peripheral(index); + } + + fn event_occurred(&self, event: Event) -> bool { + use Event::*; + + // NOTE(unsafe) atomic read + let flags = unsafe { (*DMA1::ptr()).isr().read() }; + match event { + HalfTransfer => flags.htif(N).bit_is_set(), + TransferComplete => flags.tcif(N).bit_is_set(), + TransferError => flags.teif(N).bit_is_set(), + Any => flags.gif(N).bit_is_set(), + } + } + + fn clear_event(&mut self, event: Event) { + use Event::*; + + // NOTE(unsafe) atomic write to a stateless register + unsafe { + let _ = &(*DMA1::ptr()).ifcr().write(|w| match event { + HalfTransfer => w.chtif(N).set_bit(), + TransferComplete => w.ctcif(N).set_bit(), + TransferError => w.cteif(N).set_bit(), + Any => w.cgif(N).set_bit(), + }); + } + } +} + macro_rules! dma { ( channels: { @@ -251,11 +309,6 @@ macro_rules! dma { )+ }, ) => { - use crate::dmamux; - use crate::rcc::{Enable, Reset}; - use crate::stm32::{self, DMA1 as DMA}; - use crate::dmamux::DmaMuxExt; - /// DMA channels pub struct Channels { $( pub $chi: $Ci, )+ @@ -269,60 +322,8 @@ macro_rules! dma { } } - $( - /// Singleton that represents a DMA channel - pub struct $Ci { - mux: dmamux::Channel<$i>, - } - - impl private::Channel for $Ci { - fn ch(&self) -> &stm32::dma1::CH { - // NOTE(unsafe) $Ci grants exclusive access to this register - unsafe { &(*DMA::ptr()).ch($i) } - } - } - - impl $Ci { - pub fn mux(&mut self) -> &mut dyn dmamux::DmaMuxChannel { - &mut self.mux - } - } - - impl Channel for $Ci { - - fn select_peripheral(&mut self, index: DmaMuxIndex) { - self.mux().select_peripheral(index); - } - - fn event_occurred(&self, event: Event) -> bool { - use Event::*; - - // NOTE(unsafe) atomic read - let flags = unsafe { (*DMA::ptr()).isr().read() }; - match event { - HalfTransfer => flags.htif($i).bit_is_set(), - TransferComplete => flags.tcif($i).bit_is_set(), - TransferError => flags.teif($i).bit_is_set(), - Any => flags.gif($i).bit_is_set(), - } - } - - fn clear_event(&mut self, event: Event) { - use Event::*; - - // NOTE(unsafe) atomic write to a stateless register - unsafe { - let _ = &(*DMA::ptr()).ifcr().write(|w| match event { - HalfTransfer => w.chtif($i).set_bit(), - TransferComplete => w.ctcif($i).set_bit(), - TransferError => w.cteif($i).set_bit(), - Any => w.cgif($i).set_bit(), - }); - } - } - - } + pub type $Ci = C<$i>; )+ } } @@ -357,19 +358,19 @@ dma!( }, ); -impl DmaExt for DMA { +impl DmaExt for DMA1 { type Channels = Channels; fn reset(self, rcc: &mut Rcc) -> Self { // reset DMA - ::reset(rcc); + ::reset(rcc); self } fn split(self, rcc: &mut Rcc, dmamux: DMAMUX) -> Self::Channels { let muxchannels = dmamux.split(); // enable DMA clock - DMA::enable(rcc); + DMA1::enable(rcc); let mut channels = Channels { ch1: C1 { diff --git a/src/dmamux.rs b/src/dmamux.rs index 70ad1d2..ba328bc 100644 --- a/src/dmamux.rs +++ b/src/dmamux.rs @@ -149,13 +149,12 @@ pub trait DmaMuxChannel { fn select_peripheral(&mut self, index: DmaMuxIndex); } -pub struct Channel { - _0: (), -} +#[non_exhaustive] +pub struct Channel; -impl DmaMuxChannel for Channel { +impl DmaMuxChannel for Channel { fn select_peripheral(&mut self, index: DmaMuxIndex) { - let reg = unsafe { &(*DMAMUX::ptr()).ccr(N) }; + let reg = unsafe { &(*DMAMUX::ptr()).ccr(N as usize) }; reg.write(|w| unsafe { w.dmareq_id().bits(index.val()).ege().set_bit() }); } } @@ -193,11 +192,11 @@ impl DmaMuxExt for DMAMUX { fn split(self) -> Self::Channels { Channels { - ch0: Channel::<0> { _0: () }, - ch1: Channel::<1> { _0: () }, - ch2: Channel::<2> { _0: () }, - ch3: Channel::<3> { _0: () }, - ch4: Channel::<4> { _0: () }, + ch0: Channel::<0>, + ch1: Channel::<1>, + ch2: Channel::<2>, + ch3: Channel::<3>, + ch4: Channel::<4>, #[cfg(any( feature = "stm32g070", feature = "stm32g071", @@ -205,7 +204,7 @@ impl DmaMuxExt for DMAMUX { feature = "stm32g0b1", feature = "stm32g0c1", ))] - ch5: Channel::<5> { _0: () }, + ch5: Channel::<5>, #[cfg(any( feature = "stm32g070", feature = "stm32g071", @@ -213,7 +212,7 @@ impl DmaMuxExt for DMAMUX { feature = "stm32g0b1", feature = "stm32g0c1", ))] - ch6: Channel::<6> { _0: () }, + ch6: Channel::<6>, } } } diff --git a/src/flash/traits.rs b/src/flash/traits.rs index e862469..32c2df4 100644 --- a/src/flash/traits.rs +++ b/src/flash/traits.rs @@ -4,7 +4,8 @@ pub struct FlashPage(pub usize); /// Flash operation error -#[derive(Copy, Clone, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Error { /// Flash controller is not done yet Busy, diff --git a/src/gpio.rs b/src/gpio.rs index aca84bd..b45c942 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -63,27 +63,19 @@ macro_rules! gpio_trait { ($gpiox:ident) => { impl GpioRegExt for crate::stm32::$gpiox::RegisterBlock { fn is_low(&self, pos: u8) -> bool { - // NOTE(unsafe) atomic read with no side effects - self.idr().read().bits() & (1 << pos) == 0 + self.idr().read().idr(pos).bit_is_clear() } fn is_set_low(&self, pos: u8) -> bool { - // NOTE(unsafe) atomic read with no side effects - self.odr().read().bits() & (1 << pos) == 0 + self.odr().read().odr(pos).bit_is_clear() } fn set_high(&self, pos: u8) { - // NOTE(unsafe) atomic write to a stateless register - unsafe { - self.bsrr().write(|w| w.bits(1 << pos)); - } + self.bsrr().write(|w| w.bs(pos).set_bit()); } fn set_low(&self, pos: u8) { - // NOTE(unsafe) atomic write to a stateless register - unsafe { - self.bsrr().write(|w| w.bits(1 << (pos + 16))); - } + self.bsrr().write(|w| w.br(pos).set_bit()); } } }; @@ -157,7 +149,8 @@ impl InputPin for Pin> { } /// GPIO Pin speed selection -#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Speed { Low = 0, Medium = 1, @@ -166,7 +159,8 @@ pub enum Speed { } /// Trigger edge -#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum SignalEdge { Rising, Falling, @@ -232,13 +226,13 @@ macro_rules! gpio { impl OutputPin for $PXx> { fn set_high(&mut self) -> Result<(), Self::Error> { // NOTE(unsafe) atomic write to a stateless register - unsafe { (*$GPIOX::ptr()).bsrr().write(|w| w.bits(1 << self.i)) }; + unsafe { (*$GPIOX::ptr()).bsrr().write(|w| w.bs(self.i).set_bit()) }; Ok(()) } fn set_low(&mut self) -> Result<(), Self::Error> { // NOTE(unsafe) atomic write to a stateless register - unsafe { (*$GPIOX::ptr()).bsrr().write(|w| w.bits(1 << (self.i + 16))) }; + unsafe { (*$GPIOX::ptr()).bsrr().write(|w| w.br(self.i).set_bit()) }; Ok(()) } } @@ -251,7 +245,7 @@ macro_rules! gpio { fn is_set_low(&mut self) -> Result { // NOTE(unsafe) atomic read with no side effects - let is_set_low = unsafe { (*$GPIOX::ptr()).odr().read().bits() & (1 << self.i) == 0 }; + let is_set_low = unsafe { (*$GPIOX::ptr()).odr().read().odr(self.i).bit_is_clear() }; Ok(is_set_low) } } @@ -264,7 +258,7 @@ macro_rules! gpio { fn is_low(&mut self) -> Result { // NOTE(unsafe) atomic read with no side effects - let is_low = unsafe { (*$GPIOX::ptr()).idr().read().bits() & (1 << self.i) == 0 }; + let is_low = unsafe { (*$GPIOX::ptr()).idr().read().idr(self.i).bit_is_clear() }; Ok(is_low) } } @@ -281,7 +275,7 @@ macro_rules! gpio { fn is_low(&mut self) -> Result { // NOTE(unsafe) atomic read with no side effects - let is_low = unsafe { (*$GPIOX::ptr()).idr().read().bits() & (1 << self.i) == 0 }; + let is_low = unsafe { (*$GPIOX::ptr()).idr().read().idr(self.i).bit_is_clear() }; Ok(is_low) } } @@ -329,60 +323,40 @@ macro_rules! gpio { impl $PXi { /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self) -> $PXi> { - let offset = 2 * $i; unsafe { let gpio = &(*$GPIOX::ptr()); - gpio.pupdr().modify(|r, w| { - w.bits(r.bits() & !(0b11 << offset)) - }); - gpio.moder().modify(|r, w| { - w.bits(r.bits() & !(0b11 << offset)) - }) + gpio.pupdr().modify(|_, w| w.pupdr($i).floating()); + gpio.moder().modify(|_, w| w.moder($i).input()); }; $PXi { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self) -> $PXi> { - let offset = 2 * $i; unsafe { let gpio = &(*$GPIOX::ptr()); - gpio.pupdr().modify(|r, w| { - w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset)) - }); - gpio.moder().modify(|r, w| { - w.bits(r.bits() & !(0b11 << offset)) - }) + gpio.pupdr().modify(|_, w| w.pupdr($i).pull_down()); + gpio.moder().modify(|_, w| w.moder($i).input()); }; $PXi { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self) -> $PXi> { - let offset = 2 * $i; unsafe { let gpio = &(*$GPIOX::ptr()); - gpio.pupdr().modify(|r, w| { - w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset)) - }); - gpio.moder().modify(|r, w| { - w.bits(r.bits() & !(0b11 << offset)) - }) + gpio.pupdr().modify(|_, w| w.pupdr($i).pull_up()); + gpio.moder().modify(|_, w| w.moder($i).input()); }; $PXi { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self) -> $PXi { - let offset = 2 * $i; unsafe { let gpio = &(*$GPIOX::ptr()); - gpio.pupdr().modify(|r, w| { - w.bits(r.bits() & !(0b11 << offset)) - }); - gpio.moder().modify(|r, w| { - w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset)) - }); + gpio.pupdr().modify(|_, w| w.pupdr($i).floating()); + gpio.moder().modify(|_, w| w.moder($i).analog()); } $PXi { _mode: PhantomData } } @@ -397,18 +371,11 @@ macro_rules! gpio { /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self) -> $PXi> { - let offset = 2 * $i; unsafe { let gpio = &(*$GPIOX::ptr()); - gpio.pupdr().modify(|r, w| { - w.bits(r.bits() & !(0b11 << offset)) - }); - gpio.otyper().modify(|r, w| { - w.bits(r.bits() | (0b1 << $i)) - }); - gpio.moder().modify(|r, w| { - w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset)) - }) + gpio.pupdr().modify(|_, w| w.pupdr($i).floating()); + gpio.otyper().modify(|_, w| w.ot($i).open_drain()); + gpio.moder().modify(|_, w| w.moder($i).output()); }; $PXi { _mode: PhantomData } } @@ -423,32 +390,21 @@ macro_rules! gpio { /// Configures the pin to operate as a push pull output pin pub fn into_push_pull_output(self) -> $PXi> { - let offset = 2 * $i; unsafe { let gpio = &(*$GPIOX::ptr()); - gpio.pupdr().modify(|r, w| { - w.bits(r.bits() & !(0b11 << offset)) - }); - gpio.otyper().modify(|r, w| { - w.bits(r.bits() & !(0b1 << $i)) - }); - gpio.moder().modify(|r, w| { - w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset)) - }) + gpio.pupdr().modify(|_, w| w.pupdr($i).floating()); + gpio.otyper().modify(|_, w| w.ot($i).push_pull()); + gpio.moder().modify(|_, w| w.moder($i).output()); }; $PXi { _mode: PhantomData } } /// Configures the pin as external trigger pub fn listen(self, edge: SignalEdge, exti: &mut EXTI) -> $PXi> { - let offset = 2 * $i; unsafe { - let _ = &(*$GPIOX::ptr()).pupdr().modify(|r, w| { - w.bits(r.bits() & !(0b11 << offset)) - }); - let _ = &(*$GPIOX::ptr()).moder().modify(|r, w| { - w.bits(r.bits() & !(0b11 << offset)) - }); + let gpio = &(*$GPIOX::ptr()); + gpio.pupdr().modify(|_, w| w.pupdr($i).floating()); + gpio.moder().modify(|_, w| w.moder($i).input()); }; let offset = ($i % 4) * 8; let mask = $Pxn << offset; @@ -474,35 +430,23 @@ macro_rules! gpio { /// Set pin speed pub fn set_speed(self, speed: Speed) -> Self { - let offset = 2 * $i; unsafe { - let _ = &(*$GPIOX::ptr()).ospeedr().modify(|r, w| { - w.bits((r.bits() & !(0b11 << offset)) | ((speed as u32) << offset)) - }); - }; + (*$GPIOX::ptr()).ospeedr().modify(|_, w| w.ospeedr($i).bits(speed as u8)); + } self } #[allow(dead_code)] pub(crate) fn set_alt_mode(&self, mode: AltFunction) { - let mode = mode as u32; - let offset = 2 * $i; - let offset2 = 4 * $i; unsafe { let gpio = &(*$GPIOX::ptr()); - if offset2 < 32 { - gpio.afrl().modify(|r, w| { - w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2)) - }); + let n = $i; + if n < 8 { + gpio.afrl().modify(|_, w| w.afr(n).bits(mode as u8)); } else { - let offset2 = offset2 - 32; - gpio.afrh().modify(|r, w| { - w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2)) - }); + gpio.afrh().modify(|_, w| w.afr(n - 8).bits(mode as u8)); } - gpio.moder().modify(|r, w| { - w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset)) - }); + gpio.moder().modify(|_, w| w.moder($i).alternate()); } } @@ -510,11 +454,11 @@ macro_rules! gpio { match state { PinState::High => { // NOTE(unsafe) atomic write to a stateless register - unsafe { (*$GPIOX::ptr()).bsrr().write(|w| w.bits(1 << $i)) }; + unsafe { (*$GPIOX::ptr()).bsrr().write(|w| w.bs($i).set_bit()) }; } PinState::Low => { // NOTE(unsafe) atomic write to a stateless register - unsafe { (*$GPIOX::ptr()).bsrr().write(|w| w.bits(1 << ($i + 16))) }; + unsafe { (*$GPIOX::ptr()).bsrr().write(|w| w.br($i).set_bit()) }; } } } @@ -554,7 +498,7 @@ macro_rules! gpio { fn is_set_low(&mut self) -> Result { // NOTE(unsafe) atomic read with no side effects - let is_set_low = unsafe { (*$GPIOX::ptr()).odr().read().bits() & (1 << $i) == 0 }; + let is_set_low = unsafe { (*$GPIOX::ptr()).odr().read().odr($i).bit_is_clear() }; Ok(is_set_low) } } @@ -567,7 +511,7 @@ macro_rules! gpio { fn is_low(&mut self) -> Result { // NOTE(unsafe) atomic read with no side effects - let is_low = unsafe { (*$GPIOX::ptr()).idr().read().bits() & (1 << $i) == 0 }; + let is_low = unsafe { (*$GPIOX::ptr()).idr().read().idr($i).bit_is_clear() }; Ok(is_low) } } @@ -594,7 +538,7 @@ macro_rules! gpio { fn is_low(&mut self) -> Result { // NOTE(unsafe) atomic read with no side effects - let is_low = unsafe { (*$GPIOX::ptr()).idr().read().bits() & (1 << $i) == 0 }; + let is_low = unsafe { (*$GPIOX::ptr()).idr().read().idr($i).bit_is_clear() }; Ok(is_low) } } diff --git a/src/i2c/mod.rs b/src/i2c/mod.rs index 2967134..f0e1f29 100644 --- a/src/i2c/mod.rs +++ b/src/i2c/mod.rs @@ -13,7 +13,8 @@ use crate::rcc::*; pub use config::Config; use hal::i2c::{ErrorKind, NoAcknowledgeSource}; -#[derive(Debug, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum SlaveAddressMask { MaskNone = 0, MaskOneBit, @@ -26,7 +27,8 @@ pub enum SlaveAddressMask { } /// Denotes which event marked the end of the I2C data -#[derive(Debug, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum EndMarker { /// A stop condition was encountered Stop, @@ -41,20 +43,23 @@ pub enum I2cResult<'a> { Addressed(u16, I2cDirection), // a slave is addressed by a master } -#[derive(Debug, Clone, Copy, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum I2cDirection { MasterReadSlaveWrite = 0, MasterWriteSlaveRead = 1, } -#[derive(Debug, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Event { AddressMatch, Rxne, } /// I2C error -#[derive(Debug, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Error { Overrun, Nack, diff --git a/src/power.rs b/src/power.rs index cc94495..8ca2cee 100644 --- a/src/power.rs +++ b/src/power.rs @@ -6,6 +6,8 @@ use crate::{ stm32::PWR, }; +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum LowPowerMode { StopMode1 = 0b000, StopMode2 = 0b001, @@ -19,6 +21,8 @@ pub enum PowerMode { UltraLowPower(LowPowerMode), } +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum WakeUp { InternalLine, Line1, diff --git a/src/rcc/config.rs b/src/rcc/config.rs index 2be1758..b432e43 100644 --- a/src/rcc/config.rs +++ b/src/rcc/config.rs @@ -1,7 +1,8 @@ use crate::time::Hertz; /// Prescaler -#[derive(Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Prescaler { NotDivided, Div2, @@ -27,6 +28,8 @@ pub enum SysClockSrc { } /// Microcontroller clock output source +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum MCOSrc { LSI, PLL, @@ -37,6 +40,8 @@ pub enum MCOSrc { } /// Low-speed clocks output source +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum LSCOSrc { LSI, LSE, @@ -51,7 +56,8 @@ pub enum PLLSrc { } /// RTC clock input source -#[derive(Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum RTCSrc { LSE, LSE_BYPASS, diff --git a/src/rcc/mod.rs b/src/rcc/mod.rs index a6340dc..0552d8a 100644 --- a/src/rcc/mod.rs +++ b/src/rcc/mod.rs @@ -58,6 +58,8 @@ impl Default for Clocks { } /// Reset pin mode and remap +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum ResetMode { /// Reset Input only: a low level on the NRST pin generates system reset, internal RESET not propagated to the NSRT pin ResetInput = 0b01, diff --git a/src/rng.rs b/src/rng.rs index cbb6d46..20652f1 100644 --- a/src/rng.rs +++ b/src/rng.rs @@ -4,14 +4,16 @@ use core::mem; use crate::rcc::{Enable, Rcc, Reset}; use crate::stm32::RNG; -#[derive(Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum RngClkSource { HSI = 1, SysClock = 2, PLLQ = 3, } -#[derive(Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum RngClkDivider { NotDivided = 0, Div2 = 1, @@ -49,7 +51,8 @@ impl Default for Config { } } -#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum ErrorKind { ClockError, SeedError, diff --git a/src/rtc.rs b/src/rtc.rs index 764579e..ead2374 100644 --- a/src/rtc.rs +++ b/src/rtc.rs @@ -4,18 +4,22 @@ use crate::rcc::{RTCSrc, Rcc}; use crate::stm32::RTC; use crate::time::*; -#[derive(Debug, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum RtcHourFormat { H24, H12, } -#[derive(Debug, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum RtcCalibrationFrequency { F1Hz, F512Hz, } +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Event { WakeupTimer, AlarmA, diff --git a/src/serial/config.rs b/src/serial/config.rs index 22fc288..95136c7 100644 --- a/src/serial/config.rs +++ b/src/serial/config.rs @@ -1,21 +1,24 @@ use crate::prelude::*; use crate::time::Bps; -#[derive(Eq, PartialEq, PartialOrd, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd)] pub enum WordLength { DataBits7, DataBits8, DataBits9, } -#[derive(Eq, PartialEq, PartialOrd, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd)] pub enum Parity { ParityNone, ParityEven, ParityOdd, } -#[derive(Eq, PartialEq, PartialOrd, Clone, Copy, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd)] pub enum StopBits { #[doc = "1 stop bit"] STOP1 = 0b00, @@ -33,7 +36,8 @@ impl StopBits { } } -#[derive(Eq, PartialEq, PartialOrd, Clone, Copy, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd)] pub enum FifoThreshold { #[doc = "1/8 of its depth"] FIFO_1_BYTE = 0b000, @@ -54,7 +58,9 @@ impl FifoThreshold { self as u8 } } -#[derive(Eq, PartialEq, PartialOrd, Clone, Copy)] + +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct BasicConfig { pub(crate) baudrate: Bps, pub(crate) wordlength: WordLength, @@ -65,7 +71,8 @@ pub struct BasicConfig { pub(crate) swap: bool, } -#[derive(Eq, PartialEq, PartialOrd, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct FullConfig { pub(crate) baudrate: Bps, pub(crate) wordlength: WordLength, diff --git a/src/serial/usart.rs b/src/serial/usart.rs index 4d6af7f..7b3effe 100644 --- a/src/serial/usart.rs +++ b/src/serial/usart.rs @@ -10,7 +10,8 @@ use cortex_m::interrupt; use nb::block; /// Serial error -#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Error { /// Framing error Framing, @@ -23,6 +24,8 @@ pub enum Error { } /// Interrupt event +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Event { /// TXFIFO reaches the threshold TXFT = 1 << 27, diff --git a/src/spi.rs b/src/spi.rs index 5565c45..cd49f0e 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -9,7 +9,8 @@ pub use hal::spi::{ use nb::block; /// SPI error -#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Error { /// Overrun occurred Overrun, diff --git a/src/time.rs b/src/time.rs index 1daa6db..2028c9e 100644 --- a/src/time.rs +++ b/src/time.rs @@ -4,6 +4,7 @@ pub use fugit::{ }; /// Baudrate +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(Debug, Eq, PartialEq, PartialOrd, Clone, Copy)] pub struct Bps(pub u32); @@ -11,25 +12,31 @@ pub struct Bps(pub u32); pub type Instant = fugit::TimerInstantU32<1_000_000>; /// WeekDay (1-7) +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct WeekDay(pub u32); /// Date (1-31) +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct MonthDay(pub u32); /// Week (1-52) +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Week(pub u32); /// Month (1-12) +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Month(pub u32); /// Year +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Year(pub u32); +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Time { pub hours: u32, @@ -49,6 +56,7 @@ impl Time { } } +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Date { pub day: u32, diff --git a/src/timer/mod.rs b/src/timer/mod.rs index b3f4233..5d90b17 100644 --- a/src/timer/mod.rs +++ b/src/timer/mod.rs @@ -188,6 +188,8 @@ macro_rules! timers { } } +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum ExternalClockMode { Mode1, Mode2, diff --git a/src/timer/pwm.rs b/src/timer/pwm.rs index 0145a16..745000b 100644 --- a/src/timer/pwm.rs +++ b/src/timer/pwm.rs @@ -8,6 +8,8 @@ use crate::timer::pins::TimerPin; use crate::timer::*; use embedded_hal::pwm::{ErrorKind, ErrorType, SetDutyCycle}; +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum OutputCompareMode { Frozen = 0, MatchPos = 1, diff --git a/src/timer/qei.rs b/src/timer/qei.rs index 507dd24..da64477 100644 --- a/src/timer/qei.rs +++ b/src/timer/qei.rs @@ -10,6 +10,8 @@ use crate::timer::pins::TimerPin; use crate::timer::*; /// Counting direction +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Direction { Upcounting, Downcounting,