cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L071 LPTIM Instant ARRM

Tom Monkhouse
Associate
Posted on March 02, 2017 at 14:52

I've recently set about to use the Low Power Timer on an STM32L071. The idea is to set it to count up to a particular value then stop, the code for which follows:

void hal_Timers_LowPower_Once(uint32_t period)

{

    LPTIM1->CR |= LPTIM_CR_ENABLE;

    LPTIM1->ARR = period;

    while( 0u == (LPTIM1->ISR & LPTIM_ISR_ARROK) );

    LPTIM1->ICR = LPTIM_ICR_ARROKCF;

    LPTIM1->CR |= LPTIM_CR_SNGSTRT;

    while( 0u == (LPTIM1->ISR & LPTIM_ISR_ARRM) );

}

Before calling this function, the ISR, IER, CFGR, CR, CMP and CNT registers are all 0x00000000 (reset values).

The ARRM flag seems to be set immediately after SNGSTRT is programmed, regardless of the ARR value or clock source. This has happened with 2 MHz, 16 MHz and 32 MHz APB clocks.

If I include this line after setting SNGSTRT:

LPTIM1->ICR = LPTIM_ICR_ARRMCF;

Clearing the ARRM flag *after* it starts, it will operate properly most of the time, but this surely runs the risk of clearing the actual ARR Match event. An interrupt could easily delay that clear.

So what's the deal? ARRM (and CMPM) get set as soon as SNGSTRT is set. Is there a way to prevent this?

#stm32l071 #stm32 #lptim
3 REPLIES 3
Posted on March 02, 2017 at 23:04

Isn't ARRM set already *before* you set SNGSTRT? In other words, if you do clear ARRM before you set SNGSTRT, will it be set again immediately after SNGSTRT being set?

As ARR==CNT==0 just after LPTIM enable, a match occurs there...?

JW

Posted on March 03, 2017 at 10:29

Alas, no. The only flag that changes is ARROK, which I wait for and clear before starting.

I thought perhaps it was one of those issues that only crop up while debugging, but toggling a line either side of the function confirms that it takes the same amount of time regardless of the value of ARR.

Posted on March 07, 2017 at 00:11

I tried your code on a L053 DISCO with default-after-reset clock setting. I added a read of the status register into a global variable just before and after setting SNGSTRT, and both instances stored zero. CNT at the moment of readout was 5.

 LPTIM1->CR |= LPTIM_CR_ENABLE;
 LPTIM1->ARR = 0x123;
 while( 0u == (LPTIM1->ISR & LPTIM_ISR_ARROK) );
 LPTIM1->ICR = LPTIM_ICR_ARROKCF;
 lptim_isr[0] = LPTIM1->ISR;
 LPTIM1->CR |= LPTIM_CR_SNGSTRT;
 lptim_isr[1] = LPTIM1->ISR;
 lptim_isr[2] = LPTIM1->CNT;
 while( 0u == (LPTIM1->ISR & LPTIM_ISR_ARRM) );�?�?�?�?�?�?�?�?�?

How did you test the status register? Are you aware of the fact that the timers don't stop with the processor upon hitting a breakpoint, unless the respective bits in DBG_APBx_FZ are set?

JW