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§

source

type TrgSel: Into<u32>

Trigger selection options.

Required Methods§

source

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);
source

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();
source

unsafe fn pulse_reset(rcc: &mut RCC)

Reset the LPTIM peripheral.

new will pulse reset for you.

Safety
  1. Ensure nothing is using the timer before calling this function.
  2. You are responsible for setting up the timer after a reset.
source

fn enable_clock(rcc: &mut RCC)

Enable clocks for the LPTIM peripheral.

new will enable clocks for you.

source

unsafe fn disable_clock(rcc: &mut RCC)

Disable the LPTIM peripheral clock.

Safety
  1. Ensure nothing is using the timer before disabling the clock.
  2. You are responsible for re-enabling the clock before using the timer.
source

fn clk(rcc: &RCC) -> Clk

Get the clock source.

Example
use stm32wlxx_hal::{
    lptim::{self, LpTim, LpTim1},
    pac,
};

let dp: pac::Peripherals = pac::Peripherals::take().unwrap();
// PCLK is the power-on-reset value
assert_eq!(LpTim1::clk(&dp.RCC), lptim::Clk::Pclk);

Provided Methods§

source

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);
source

fn cnt() -> u16

Get the timer count.

source

fn isr() -> u32

Get the interrupt status.

source

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);
source

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.
source

fn is_enabled(&self) -> bool

Returns true if the timer is enabled.

source

fn setup_trigger(&mut self, filter: Filter, pol: TrgPol, sel: Self::TrgSel)

Setup a non-pin trigger.

Panics
  • (debug) timer is enabled.
source

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());

Object Safety§

This trait is not object safe.

Implementors§