Trait stm32wlxx_hal::lptim::LpTim
source · pub trait LpTim: LpTim {
type TrgSel: Into<u32>;
Show 14 methods
// Required methods
fn new(tim: Self::Pac, clk: Clk, pre: Prescaler, rcc: &mut RCC) -> Self;
fn free(self) -> Self::Pac;
unsafe fn pulse_reset(rcc: &mut RCC);
fn enable_clock(rcc: &mut RCC);
unsafe fn disable_clock(rcc: &mut RCC);
fn clk(rcc: &RCC) -> Clk;
// Provided methods
fn hz(&self) -> &Ratio<u32> { ... }
fn cnt() -> u16 { ... }
fn isr() -> u32 { ... }
fn set_ier(&mut self, ier: u32) { ... }
unsafe fn set_icr(&mut self, icr: u32) { ... }
fn is_enabled(&self) -> bool { ... }
fn setup_trigger(&mut self, filter: Filter, pol: TrgPol, sel: Self::TrgSel) { ... }
fn set_max_duty(&mut self, duty: u16) { ... }
}
Expand description
Low-power timer trait.
Required Associated Types§
Required Methods§
sourcefn new(tim: Self::Pac, clk: Clk, pre: Prescaler, rcc: &mut RCC) -> Self
fn new(tim: Self::Pac, clk: Clk, pre: Prescaler, rcc: &mut RCC) -> Self
Create a new LPTIM driver.
This will enable the ADC clock and reset the ADC peripheral.
Note: This will select the clock source, but you are responsible for enabling that clock source.
Example
use stm32wlxx_hal::{
lptim::{self, LpTim, LpTim1, Prescaler::Div1},
pac,
};
let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
// enable the HSI16 source clock
dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
while dp.RCC.cr.read().hsirdy().is_not_ready() {}
let lptim1: LpTim1 = LpTim1::new(dp.LPTIM1, lptim::Clk::Hsi16, Div1, &mut dp.RCC);
sourcefn free(self) -> Self::Pac
fn free(self) -> Self::Pac
Free the LPTIM registers from the driver.
Example
use stm32wlxx_hal::{
lptim::{self, LpTim, LpTim1, Prescaler::Div1},
pac,
};
let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
// enable the HSI16 source clock
dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
while dp.RCC.cr.read().hsirdy().is_not_ready() {}
let lptim1: LpTim1 = LpTim1::new(dp.LPTIM1, lptim::Clk::Hsi16, Div1, &mut dp.RCC);
// ... use lptim
let lptim1: pac::LPTIM1 = lptim1.free();
sourceunsafe fn pulse_reset(rcc: &mut RCC)
unsafe fn pulse_reset(rcc: &mut RCC)
sourcefn enable_clock(rcc: &mut RCC)
fn enable_clock(rcc: &mut RCC)
Enable clocks for the LPTIM peripheral.
new
will enable clocks for you.
sourceunsafe fn disable_clock(rcc: &mut RCC)
unsafe fn disable_clock(rcc: &mut RCC)
Disable the LPTIM peripheral clock.
Safety
- Ensure nothing is using the timer before disabling the clock.
- You are responsible for re-enabling the clock before using the timer.
Provided Methods§
sourcefn hz(&self) -> &Ratio<u32>
fn hz(&self) -> &Ratio<u32>
Get the clock speed in hertz.
Example
use stm32wlxx_hal::{
lptim::{self, LpTim, LpTim1, Prescaler::Div1},
pac,
};
let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
// enable the HSI16 source clock
dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
while dp.RCC.cr.read().hsirdy().is_not_ready() {}
let lptim1: LpTim1 = LpTim1::new(dp.LPTIM1, lptim::Clk::Hsi16, Div1, &mut dp.RCC);
assert_eq!(lptim1.hz().to_integer(), 16_000_000);
sourcefn set_ier(&mut self, ier: u32)
fn set_ier(&mut self, ier: u32)
Enable and disable interrupts.
Panics
- (debug) timer is enabled.
Example
Enable all IRQs.
use stm32wlxx_hal::{
lptim::{self, LpTim, LpTim1, Prescaler::Div1},
pac,
};
let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
// enable the HSI16 source clock
dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
while dp.RCC.cr.read().hsirdy().is_not_ready() {}
let mut lptim1: LpTim1 = LpTim1::new(dp.LPTIM1, lptim::Clk::Hsi16, Div1, &mut dp.RCC);
lptim1.set_ier(lptim::irq::ALL);
sourceunsafe fn set_icr(&mut self, icr: u32)
unsafe fn set_icr(&mut self, icr: u32)
Clear interrupts.
Safety
There is a big erratum entry for interrupts getting stuck, and the interrupts should only be cleared under certain circumstances (see workaround).
Device may remain stuck in LPTIM interrupt when clearing event flag
Description
This limitation occurs when the LPTIM is configured in interrupt mode (at least one interrupt is enabled) and the software clears any flag in LPTIM_ISR register by writing its corresponding bit in LPTIM_ICR register. If the interrupt status flag corresponding to a disabled interrupt is cleared simultaneously with a new event detection, the set and clear commands might reach the APB domain at the same time, leading to an asynchronous interrupt signal permanently stuck high. This issue can occur either during an interrupt subroutine execution (where the flag clearing is usually done), or outside an interrupt subroutine. Consequently, the firmware remains stuck in the LPTIM interrupt routine, and the device cannot enter Stop mode.
Workaround
To avoid this issue, it is strongly advised to follow the recommendations listed below:
- Clear the flag only when its corresponding interrupt is enabled in the interrupt enable register.
- If for specific reasons, it is required to clear some flags that have corresponding interrupt lines disabled in the interrupt enable register, it is recommended to clear them during the current subroutine prior to those which have corresponding interrupt line enabled in the interrupt enable register.
- Flags must not be cleared outside the interrupt subroutine.
sourcefn is_enabled(&self) -> bool
fn is_enabled(&self) -> bool
Returns true
if the timer is enabled.
sourcefn setup_trigger(&mut self, filter: Filter, pol: TrgPol, sel: Self::TrgSel)
fn setup_trigger(&mut self, filter: Filter, pol: TrgPol, sel: Self::TrgSel)
sourcefn set_max_duty(&mut self, duty: u16)
fn set_max_duty(&mut self, duty: u16)
Set the maximum duty cycle (autoreload value).
This is used to control the frequency of the PWM output.
This function does not poll for completion, use isr
and ARROK
to determine when the value has been updated.
Example
Set the frequency to 50Hz (20ms period) for servo motor control.
use stm32wlxx_hal::{
gpio,
lptim::{self, LpTim, LpTim1},
pac,
};
let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
// enable the HSI16 source clock
dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
while dp.RCC.cr.read().hsirdy().is_not_ready() {}
let pc: gpio::PortC = gpio::PortC::split(dp.GPIOC, &mut dp.RCC);
let mut lptim1: LpTim1 = LpTim1::new(
dp.LPTIM1,
lptim::Clk::Hsi16,
lptim::Prescaler::Div8,
&mut dp.RCC,
);
cortex_m::interrupt::free(|cs| lptim1.new_output_pin(pc.c1, cs));
// 20ms period to control PWM servo motors
const SERVO_FREQ_HZ: u32 = 50;
// source_freq / prescaler = 16_000_000 MHz / 8 = 2 Mhz
let lptim1_freq_hz = lptim1.hz().to_integer();
// 2MHz / 50Hz = 40_000
let max_duty: u32 = lptim1_freq_hz / SERVO_FREQ_HZ;
lptim1.set_max_duty(max_duty.try_into().unwrap());