diff --git a/src/crc.rs b/src/crc.rs index 1943205..fa1bd68 100644 --- a/src/crc.rs +++ b/src/crc.rs @@ -21,7 +21,6 @@ use crate::rcc::{Enable, Rcc, Reset}; use crate::stm32::CRC; use core::hash::Hasher; -use core::ptr; /// Extension trait to constrain the CRC peripheral. pub trait CrcExt { @@ -175,9 +174,10 @@ impl Crc { let crc = unsafe { &(*CRC::ptr()) }; for byte in data { unsafe { - // Workaround with svd2rust, it does not generate the byte interface to the DR - // register - ptr::write_volatile(&crc.dr as *const _ as *mut u8, *byte); + core::ptr::write_volatile( + core::cell::UnsafeCell::raw_get(&crc.dr as *const _ as _), + byte, + ) } } } diff --git a/src/dma.rs b/src/dma.rs index 7c29812..1cb74fb 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -165,6 +165,11 @@ pub trait Channel: private::Channel { self.ch().ndtr.write(|w| unsafe { w.ndt().bits(len) }); } + /// Get the number of words left to transfer. + fn get_transfer_remaining(&mut self) -> u16 { + self.ch().ndtr.read().ndt().bits() + } + /// Set the word size. fn set_word_size(&mut self, wsize: WordSize) { self.ch().cr.modify(|_, w| unsafe { diff --git a/src/exti.rs b/src/exti.rs index 83cbb6f..509e5f3 100644 --- a/src/exti.rs +++ b/src/exti.rs @@ -169,7 +169,7 @@ impl ExtiExt for EXTI { SignalEdge::Rising => self.rpr1.read().bits() & mask != 0, SignalEdge::Falling => self.fpr1.read().bits() & mask != 0, SignalEdge::All => { - (self.rpr1.read().bits() & mask != 0) && (self.fpr1.read().bits() & mask != 0) + (self.rpr1.read().bits() & mask != 0) || (self.fpr1.read().bits() & mask != 0) } } } diff --git a/src/gpio.rs b/src/gpio.rs index c77dc65..c2755a4 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -445,9 +445,9 @@ macro_rules! gpio { let _ = &(*$GPIOX::ptr()).pupdr.modify(|r, w| { w.bits(r.bits() & !(0b11 << offset)) }); - &(*$GPIOX::ptr()).moder.modify(|r, w| { + let _ = &(*$GPIOX::ptr()).moder.modify(|r, w| { w.bits(r.bits() & !(0b11 << offset)) - }) + }); }; let offset = ($i % 4) * 8; let mask = $Pxn << offset; @@ -475,9 +475,9 @@ macro_rules! gpio { pub fn set_speed(self, speed: Speed) -> Self { let offset = 2 * $i; unsafe { - &(*$GPIOX::ptr()).ospeedr.modify(|r, w| { + let _ = &(*$GPIOX::ptr()).ospeedr.modify(|r, w| { w.bits((r.bits() & !(0b11 << offset)) | ((speed as u32) << offset)) - }) + }); }; self } diff --git a/src/rtc.rs b/src/rtc.rs index 1b4bf35..32a1e3c 100644 --- a/src/rtc.rs +++ b/src/rtc.rs @@ -193,10 +193,10 @@ impl Rtc { pub fn set_alarm_a(&mut self, alarm: impl Into) { let alarm = alarm.into(); - let (dt, du) = bcd2_encode(alarm.day.unwrap_or_default() as u32); - let (ht, hu) = bcd2_encode(alarm.hours.unwrap_or_default() as u32); - let (mt, mu) = bcd2_encode(alarm.minutes.unwrap_or_default() as u32); - let (st, su) = bcd2_encode(alarm.seconds.unwrap_or_default() as u32); + let (dt, du) = bcd2_encode(alarm.day.unwrap_or_default()); + let (ht, hu) = bcd2_encode(alarm.hours.unwrap_or_default()); + let (mt, mu) = bcd2_encode(alarm.minutes.unwrap_or_default()); + let (st, su) = bcd2_encode(alarm.seconds.unwrap_or_default()); self.modify(|rb| { rb.alrmassr.write(|w| unsafe { @@ -226,10 +226,10 @@ impl Rtc { } pub fn set_alarm_b(&mut self, alarm: Alarm) { - let (dt, du) = bcd2_encode(alarm.day.unwrap_or_default() as u32); - let (ht, hu) = bcd2_encode(alarm.hours.unwrap_or_default() as u32); - let (mt, mu) = bcd2_encode(alarm.minutes.unwrap_or_default() as u32); - let (st, su) = bcd2_encode(alarm.seconds.unwrap_or_default() as u32); + let (dt, du) = bcd2_encode(alarm.day.unwrap_or_default()); + let (ht, hu) = bcd2_encode(alarm.hours.unwrap_or_default()); + let (mt, mu) = bcd2_encode(alarm.minutes.unwrap_or_default()); + let (st, su) = bcd2_encode(alarm.seconds.unwrap_or_default()); self.modify(|rb| { rb.alrmbssr.write(|w| unsafe { @@ -387,7 +387,7 @@ fn bcd2_encode(word: u32) -> (u8, u8) { bcd_high += 1; value -= 10; } - let bcd_low = ((bcd_high << 4) | value) as u8; + let bcd_low = (bcd_high << 4) | value; (bcd_high, bcd_low) } diff --git a/src/spi.rs b/src/spi.rs index bab5130..099194b 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -2,7 +2,7 @@ use crate::gpio::*; use crate::rcc::*; use crate::stm32::{SPI1, SPI2}; use crate::time::Hertz; -use core::ptr; +use core::{cell, ptr}; pub use hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; /// SPI error @@ -264,8 +264,9 @@ macro_rules! spi { } else if sr.crcerr().bit_is_set() { nb::Error::Other(Error::Crc) } else if sr.txe().bit_is_set() { - // NOTE(write_volatile) see note above - unsafe { ptr::write_volatile(&self.spi.dr as *const _ as *mut u8, byte) } + unsafe { + ptr::write_volatile(cell::UnsafeCell::raw_get(&self.spi.dr as *const _ as _), byte) + } return Ok(()); } else { nb::Error::WouldBlock diff --git a/src/timer/pwm.rs b/src/timer/pwm.rs index fe5ecfa..ea6c497 100644 --- a/src/timer/pwm.rs +++ b/src/timer/pwm.rs @@ -68,7 +68,39 @@ impl Pwm { } macro_rules! pwm { - ($($TIMX:ident: ($timX:ident, $arr:ident $(,$arr_h:ident)*),)+) => { + (b16, $TIMX:ident: ($timX:ident, $arr:ident)) => { + impl Pwm<$TIMX> { + /// Set only period register + pub fn set_period_register(&mut self, period: u16) { + unsafe { + self.tim.arr.write(|w| w.$arr().bits(period as u16)); + } + } + + /// Get value of period register, this is often times the same as max duty cycle + pub fn get_period_register(&self) -> u16 { + self.tim.arr.read().$arr().bits() as u16 + } + } + }; + + (b32, $TIMX:ident: ($timX:ident, $arr:ident, $arr_h:ident)) => { + impl Pwm<$TIMX> { + /// Set only period register + pub fn set_period_register(&mut self, period: u32) { + unsafe { + self.tim.arr.write(|w| w.bits(period)); + } + } + + /// Get value of period register, this is often times the same as max duty cycle + pub fn get_period_register(&self) -> u32 { + self.tim.arr.read().bits() + } + } + }; + + ($($bits:ident, $TIMX:ident: ($timX:ident, $arr:ident$( ,$arr_h:ident)*),)+) => { $( impl PwmExt for $TIMX { fn pwm(self, freq: Hertz, rcc: &mut Rcc) -> Pwm { @@ -99,6 +131,8 @@ macro_rules! pwm { pwm } + pwm!($bits, $TIMX: ($timX, $arr $(,$arr_h)*)); + impl Pwm<$TIMX> { /// Set the PWM frequency. Actual frequency may differ from /// requested due to precision of input clock. To check actual @@ -108,15 +142,33 @@ macro_rules! pwm { let psc = (ratio - 1) / 0xffff; let arr = ratio / (psc + 1) - 1; + self.set_prescaler_register(psc as _); + self.set_period_register(arr as _); + + self.tim.cr1.write(|w| w.cen().set_bit()); + } + + /// Set only prescale register + pub fn set_prescaler_register(&mut self, prescaler: u16) { + unsafe { + self.tim.psc.write(|w| w.psc().bits(prescaler)); + } + } + + /// Set prescaler to be able to reach `freq` or higher + /// + /// NOTE: Actual lowest reachable frequency may be lower than requested + /// due to rounding errors + /// NOTE: This will not update the period register + pub fn set_min_frequency(&mut self, freq: Hertz) { + let ratio = self.clk / freq; + let psc = (ratio - 1) / 0xffff; + unsafe { self.tim.psc.write(|w| w.psc().bits(psc as u16)); - self.tim.arr.write(|w| w.$arr().bits(arr as u16)); - $( - self.tim.arr.modify(|_, w| w.$arr_h().bits((arr >> 16) as u16)); - )* - self.tim.cr1.write(|w| w.cen().set_bit()) } } + /// Starts listening pub fn listen(&mut self) { self.tim.dier.write(|w| w.uie().set_bit()); @@ -131,6 +183,14 @@ macro_rules! pwm { self.tim.sr.modify(|_, w| w.uif().clear_bit()); } + pub fn start_timer(&mut self) { + self.tim.cr1.modify(|_, w| w.cen().set_bit()) + } + + pub fn pause_timer(&mut self) { + self.tim.cr1.modify(|_, w| w.cen().clear_bit()) + } + /// Resets counter value pub fn reset(&mut self) { self.tim.cnt.reset(); @@ -140,11 +200,11 @@ macro_rules! pwm { pub fn freq(&self) -> Hertz { Hertz::from_raw(self.clk.raw() / (self.tim.psc.read().bits() + 1) - / (self.tim.arr.read().bits() + 1)) + / (self.get_period_register() as u32 + 1)) } } )+ - } + }; } #[allow(unused_macros)] @@ -160,14 +220,14 @@ macro_rules! pwm_q { } } -#[cfg(any(feature = "stm32g0x1", feature = "stm32g070"))] +#[cfg(any(feature = "stm32g030", feature = "stm32g0x1", feature = "stm32g070"))] macro_rules! pwm_hal { ($($TIMX:ident: - ($CH:ty, $ccxe:ident, $ccmrx_output:ident, $ocxpe:ident, $ocxm:ident, $ccrx:ident, $ccrx_l:ident, $ccrx_h:ident),)+ + ($CH:ty, $ccxe:ident, $ccmrx_output:ident, $ocxpe:ident, $ocxm:ident, $ccrx:ident, $ccrx_l:ident, $ccrx_h:ident, $duty_t:ty),)+ ) => { $( impl hal::PwmPin for PwmPin<$TIMX, $CH> { - type Duty = u32; + type Duty = $duty_t; fn disable(&mut self) { unsafe { @@ -183,16 +243,16 @@ macro_rules! pwm_hal { } } - fn get_duty(&self) -> u32 { - unsafe { (*$TIMX::ptr()).$ccrx.read().bits() } + fn get_duty(&self) -> Self::Duty { + unsafe { (*$TIMX::ptr()).$ccrx.read().bits() as _ } } - fn get_max_duty(&self) -> u32 { - unsafe { (*$TIMX::ptr()).arr.read().bits() } + fn get_max_duty(&self) -> Self::Duty { + unsafe { (*$TIMX::ptr()).arr.read().bits() as _ } } - fn set_duty(&mut self, duty: u32) { - unsafe { (*$TIMX::ptr()).$ccrx.write(|w| w.bits(duty)) } + fn set_duty(&mut self, duty: Self::Duty) { + unsafe { (*$TIMX::ptr()).$ccrx.write(|w| w.bits(duty as u32)) } } } )+ @@ -269,7 +329,7 @@ pwm_advanced_hal! { TIM17: (Channel1, cc1e: cc1ne, ccmr1_output, oc1pe, oc1m, ccr1, moe), } -#[cfg(any(feature = "stm32g070"))] +#[cfg(feature = "stm32g070")] pwm_advanced_hal! { TIM15: (Channel1, cc1e: cc1ne, ccmr1_output, oc1pe, oc1m1, ccr1, moe), } @@ -281,40 +341,40 @@ pwm_advanced_hal! { #[cfg(feature = "stm32g0x1")] pwm_hal! { - TIM2: (Channel1, cc1e, ccmr1_output, oc1pe, oc1m, ccr1, ccr1_l, ccr1_h), - TIM2: (Channel2, cc2e, ccmr1_output, oc2pe, oc2m, ccr2, ccr2_l, ccr2_h), - TIM2: (Channel3, cc3e, ccmr2_output, oc3pe, oc3m, ccr3, ccr3_l, ccr3_h), - TIM2: (Channel4, cc4e, ccmr2_output, oc4pe, oc4m, ccr4, ccr4_l, ccr4_h), - TIM3: (Channel1, cc1e, ccmr1_output, oc1pe, oc1m, ccr1, ccr1_l, ccr1_h), - TIM3: (Channel2, cc2e, ccmr1_output, oc2pe, oc2m, ccr2, ccr2_l, ccr2_h), - TIM3: (Channel3, cc3e, ccmr2_output, oc3pe, oc3m, ccr3, ccr3_l, ccr3_h), - TIM3: (Channel4, cc4e, ccmr2_output, oc4pe, oc4m, ccr4, ccr4_l, ccr4_h), + TIM2: (Channel1, cc1e, ccmr1_output, oc1pe, oc1m, ccr1, ccr1_l, ccr1_h, u32), + TIM2: (Channel2, cc2e, ccmr1_output, oc2pe, oc2m, ccr2, ccr2_l, ccr2_h, u32), + TIM2: (Channel3, cc3e, ccmr2_output, oc3pe, oc3m, ccr3, ccr3_l, ccr3_h, u32), + TIM2: (Channel4, cc4e, ccmr2_output, oc4pe, oc4m, ccr4, ccr4_l, ccr4_h, u32), + TIM3: (Channel1, cc1e, ccmr1_output, oc1pe, oc1m, ccr1, ccr1_l, ccr1_h, u32), + TIM3: (Channel2, cc2e, ccmr1_output, oc2pe, oc2m, ccr2, ccr2_l, ccr2_h, u32), + TIM3: (Channel3, cc3e, ccmr2_output, oc3pe, oc3m, ccr3, ccr3_l, ccr3_h, u32), + TIM3: (Channel4, cc4e, ccmr2_output, oc4pe, oc4m, ccr4, ccr4_l, ccr4_h, u32), } -#[cfg(feature = "stm32g070")] +#[cfg(any(feature = "stm32g030", feature = "stm32g070"))] pwm_hal! { - TIM3: (Channel1, cc1e, ccmr1_output, oc1pe, oc1m, ccr1, ccr1_l, ccr1_h), - TIM3: (Channel2, cc2e, ccmr1_output, oc2pe, oc2m, ccr2, ccr2_l, ccr2_h), - TIM3: (Channel3, cc3e, ccmr2_output, oc3pe, oc3m, ccr3, ccr3_l, ccr3_h), - TIM3: (Channel4, cc4e, ccmr2_output, oc4pe, oc4m, ccr4, ccr4_l, ccr4_h), + TIM3: (Channel1, cc1e, ccmr1_output, oc1pe, oc1m, ccr1, ccr1_l, ccr1_h, u16), + TIM3: (Channel2, cc2e, ccmr1_output, oc2pe, oc2m, ccr2, ccr2_l, ccr2_h, u16), + TIM3: (Channel3, cc3e, ccmr2_output, oc3pe, oc3m, ccr3, ccr3_l, ccr3_h, u16), + TIM3: (Channel4, cc4e, ccmr2_output, oc4pe, oc4m, ccr4, ccr4_l, ccr4_h, u16), } pwm! { - TIM1: (tim1, arr), - TIM3: (tim3, arr_l, arr_h), - TIM14: (tim14, arr), - TIM16: (tim16, arr), - TIM17: (tim17, arr), + b16, TIM1: (tim1, arr), + b16, TIM3: (tim3, arr_l), + b16, TIM14: (tim14, arr), + b16, TIM16: (tim16, arr), + b16, TIM17: (tim17, arr), } #[cfg(feature = "stm32g0x1")] pwm! { - TIM2: (tim2, arr_l, arr_h), + b32, TIM2: (tim2, arr_l, arr_h), } #[cfg(any(feature = "stm32g070", feature = "stm32g071", feature = "stm32g081"))] pwm! { - TIM15: (tim15, arr), + b16, TIM15: (tim15, arr), } #[cfg(feature = "stm32g0x1")]