Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more methods to Pwm<T> #140

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/crc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
)
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/dma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion src/exti.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
}
Expand Down
18 changes: 9 additions & 9 deletions src/rtc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,10 @@ impl Rtc {

pub fn set_alarm_a(&mut self, alarm: impl Into<Alarm>) {
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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
}

Expand Down
7 changes: 4 additions & 3 deletions src/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
136 changes: 98 additions & 38 deletions src/timer/pwm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,39 @@ impl<TIM> Pwm<TIM> {
}

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<Self> {
Expand Down Expand Up @@ -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
Expand All @@ -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());
Expand All @@ -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();
Expand All @@ -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)]
Expand All @@ -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 {
Expand All @@ -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)) }
}
}
)+
Expand Down Expand Up @@ -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),
}
Expand All @@ -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")]
Expand Down