From e1d6b393cf3ad049d8b65ba3c5750ff282a9e653 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 19 Apr 2023 11:45:36 +0200 Subject: [PATCH 1/8] Add more methods to Pwm --- src/timer/pwm.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/src/timer/pwm.rs b/src/timer/pwm.rs index fe5ecfa..20b2057 100644 --- a/src/timer/pwm.rs +++ b/src/timer/pwm.rs @@ -108,15 +108,50 @@ macro_rules! pwm { let psc = (ratio - 1) / 0xffff; let arr = ratio / (psc + 1) - 1; + self.set_prescaler_register(psc as u16); + self.set_period_register(arr as u16); + 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.cr1.write(|w| w.cen().set_bit()); + } + } + + /// 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)); $( - self.tim.arr.modify(|_, w| w.$arr_h().bits((arr >> 16) as u16)); + self.tim.arr.modify(|_, w| w.$arr_h().bits((period >> 16) as u16)); )* - self.tim.cr1.write(|w| w.cen().set_bit()) } } + + /// Get value of period register, this is often times the same as max duty cycle + pub fn get_period_register(&mut self) -> u16 { + self.tim.arr.read().bits() as u16 + } + + /// 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)); + } + } + /// Starts listening pub fn listen(&mut self) { self.tim.dier.write(|w| w.uie().set_bit()); @@ -131,6 +166,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() { + self.tim.cr1.modify(|w| w.cen().clear_bit()) + } + /// Resets counter value pub fn reset(&mut self) { self.tim.cnt.reset(); From 3d7b44e588a929ea1187bc6db5fcb8693cfd5a1f Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 19 Apr 2023 15:44:06 +0200 Subject: [PATCH 2/8] TIM3 is only 16bit, read all 32bits for 32bit timers --- src/timer/pwm.rs | 73 ++++++++++++++++++++++++++++++------------------ 1 file changed, 46 insertions(+), 27 deletions(-) diff --git a/src/timer/pwm.rs b/src/timer/pwm.rs index 20b2057..ab35057 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: u16) { + 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 @@ -116,21 +150,6 @@ macro_rules! pwm { } } - /// 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)); - $( - self.tim.arr.modify(|_, w| w.$arr_h().bits((period >> 16) as u16)); - )* - } - } - - /// Get value of period register, this is often times the same as max duty cycle - pub fn get_period_register(&mut self) -> u16 { - self.tim.arr.read().bits() as u16 - } - /// Set only prescale register pub fn set_prescaler_register(&mut self, prescaler: u16) { unsafe { @@ -167,11 +186,11 @@ macro_rules! pwm { } pub fn start_timer(&mut self) { - self.tim.cr1.modify(|w| w.cen().set_bit()) + self.tim.cr1.modify(|_, w| w.cen().set_bit()) } - pub fn pause_timer() { - self.tim.cr1.modify(|w| w.cen().clear_bit()) + pub fn pause_timer(&mut self) { + self.tim.cr1.modify(|_, w| w.cen().clear_bit()) } /// Resets counter value @@ -183,11 +202,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)] @@ -343,16 +362,16 @@ pwm_hal! { } 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"))] From c4a71b4d41d2c075d935ed45875790b627928ed5 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 19 Apr 2023 16:04:53 +0200 Subject: [PATCH 3/8] Fix errors --- src/timer/pwm.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/timer/pwm.rs b/src/timer/pwm.rs index ab35057..b3f3335 100644 --- a/src/timer/pwm.rs +++ b/src/timer/pwm.rs @@ -87,7 +87,7 @@ macro_rules! pwm { (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: u16) { + pub fn set_period_register(&mut self, period: u32) { unsafe { self.tim.arr.write(|w| w.bits(period)); } @@ -142,12 +142,10 @@ macro_rules! pwm { let psc = (ratio - 1) / 0xffff; let arr = ratio / (psc + 1) - 1; - self.set_prescaler_register(psc as u16); - self.set_period_register(arr as u16); + self.set_prescaler_register(psc as _); + self.set_period_register(arr as _); - unsafe { - self.tim.cr1.write(|w| w.cen().set_bit()); - } + self.tim.cr1.write(|w| w.cen().set_bit()); } /// Set only prescale register @@ -376,7 +374,7 @@ pwm! { #[cfg(any(feature = "stm32g070", feature = "stm32g071", feature = "stm32g081"))] pwm! { - TIM15: (tim15, arr), + b16, TIM15: (tim15, arr), } #[cfg(feature = "stm32g0x1")] From 097624dd1745a4eea6d63741a1f46e50e80cb19b Mon Sep 17 00:00:00 2001 From: Justin Latimer Date: Tue, 15 Aug 2023 14:35:07 +1200 Subject: [PATCH 4/8] Add a function to get DMA transfer words remaining (#142) --- src/dma.rs | 5 +++++ 1 file changed, 5 insertions(+) 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 { From 43b3bf45701b97278583eea091891e09653b9db9 Mon Sep 17 00:00:00 2001 From: Vitaly Domnikov Date: Wed, 22 Nov 2023 15:52:01 -0800 Subject: [PATCH 5/8] update rustc version --- src/crc.rs | 8 ++------ src/gpio.rs | 8 ++++---- src/spi.rs | 4 ++-- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/crc.rs b/src/crc.rs index 1943205..ff1a9f9 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 { @@ -174,11 +173,8 @@ impl Crc { pub fn feed(&mut self, data: &[u8]) { 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); - } + let ptr = &crc.dr as *const _; + unsafe { core::ptr::write_volatile(ptr as *mut u8, *byte) }; } } 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/spi.rs b/src/spi.rs index bab5130..69290c7 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -264,8 +264,8 @@ 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) } + let ptr = &self.spi.dr as *const _; + unsafe { core::ptr::write_volatile(ptr as *mut u8, byte) }; return Ok(()); } else { nb::Error::WouldBlock From 2e21350dcea034f308be506fa33bf132c2f1dd4b Mon Sep 17 00:00:00 2001 From: Vitaly Domnikov Date: Sun, 17 Mar 2024 11:08:16 -0700 Subject: [PATCH 6/8] make clippy happy --- src/crc.rs | 8 ++++++-- src/rtc.rs | 18 +++++++++--------- src/spi.rs | 7 ++++--- src/timer/pwm.rs | 2 +- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/crc.rs b/src/crc.rs index ff1a9f9..fa1bd68 100644 --- a/src/crc.rs +++ b/src/crc.rs @@ -173,8 +173,12 @@ impl Crc { pub fn feed(&mut self, data: &[u8]) { let crc = unsafe { &(*CRC::ptr()) }; for byte in data { - let ptr = &crc.dr as *const _; - unsafe { core::ptr::write_volatile(ptr as *mut u8, *byte) }; + unsafe { + core::ptr::write_volatile( + core::cell::UnsafeCell::raw_get(&crc.dr as *const _ as _), + byte, + ) + } } } 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 69290c7..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() { - let ptr = &self.spi.dr as *const _; - unsafe { core::ptr::write_volatile(ptr 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 b3f3335..8618c7b 100644 --- a/src/timer/pwm.rs +++ b/src/timer/pwm.rs @@ -329,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), } From efe771757e6ef33e5831ab94f3804a39e6d6b2fa Mon Sep 17 00:00:00 2001 From: AdinAck Date: Sun, 17 Mar 2024 11:12:08 -0700 Subject: [PATCH 7/8] fix `is_pending` logical error (#144) --- src/exti.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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) } } } From 5864a8d5b5c32adf7f784a5904510c50d0382230 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 19 Jun 2024 15:08:43 +0200 Subject: [PATCH 8/8] PWM - Use correct type for duty --- src/timer/pwm.rs | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/timer/pwm.rs b/src/timer/pwm.rs index 8618c7b..ea6c497 100644 --- a/src/timer/pwm.rs +++ b/src/timer/pwm.rs @@ -220,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 { @@ -243,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)) } } } )+ @@ -341,22 +341,22 @@ 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! {