2024-03-18 02:52 AM
Hi everyone,
It seems that I have a problem with my Timer 22 configuration, on my Microcontroller, STM32L031 I would like to stop it then restart them with a lower speed to go into sleep mode, except that my interrupt is never triggered.
Do you have an idea ?
//-----------------------------------------------------------------------------
void SLEEP_LP(uint16_t time)
//-----------------------------------------------------------------------------
{
HAL_NVIC_DisableIRQ(TIM21_IRQn); //---- Disable other timer IRQ for debug
HAL_NVIC_DisableIRQ(TIM2_IRQn);
RCC->APB2ENR &= ~RCC_APB2ENR_TIM22EN; //--- Disable Clock to reconf tim 22
TIM22->CR1 &= ~TIM_CR1_CEN; //--- Disable count
TIM22->SR = 0x00;
//--- Re Configuration Timer22 ---
RCC->APB2ENR |= RCC_APB2ENR_TIM22EN; //--- Enable Clock Tim22
TIM22->PSC = 65; //--- Prescaler : clock timer = 65536Hz/(prescaler+1) => ~1kHz
TIM22->ARR = time; //--- Auto reload Register
TIM22->DIER |= TIM_DIER_UIE; //--- Enable interrupt
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
RCC->ICSCR &= (~RCC_ICSCR_MSIRANGE); //--- MSI to 65,536kHz
// volatile uint64_t ii = HAL_RCC_GetSysClockFreq();
TIM22->CR1 |= TIM_CR1_CEN; //--- Enable count
PWR->CR |= PWR_CR_LPSDSR; //--- voltage regulator in low-power mode during sleep
SCB->SCR &= ~( SCB_SCR_SLEEPDEEP_Msk ); //--- low-power mode = sleep mode
FLASH->ACR |= FLASH_ACR_SLEEP_PD; //-- Flash OFF
while (end_sleep_flag == FALSE) __WFI(); //--- enter low-power mode
}
//-----------------------------------------------------------------------------
void TIM22_IRQHandler(void)
//-----------------------------------------------------------------------------
{
TIM22->SR = 0; //--- Clear Flag
end_sleep_flag = TRUE;
}
Thanks,
2024-03-18 03:09 AM
> RCC->APB2ENR &= ~RCC_APB2ENR_TIM22EN; //--- Disable Clock to reconf tim 22
No. You cannot write to TIM registers, if TIM has no clock. It means, the timer is running when you do this, and CNT is nonzero.
So, if you don't have ARR preload set, and you set it to value lower than CNT, it will count up until the "natural overflow" i.e. 65535. New prescaler won't get active until the next Update, so if prescaler was previously big enough, this may take too long time (minutes, hours).
Also, note, that setting ARR to 0 stops the timer.
JW
2024-03-18 05:59 AM
Yes, I have change my code according to your remarks, but 2 questions ?
First Did i need to stop the timer count before reconfigure them ?
Second : according to your remark i have added these line to have to take imediately my ARR value, is this correct ?
TIM22->CR1 |= TIM_CR1_CEN; //--- Enable count
TIM22->CNT = 0xFFFFFFFF - 1; // unint_32
while (end_sleep_flag == FALSE) __WFI(); //--- enter low-power mode
Thanks for your help,
2024-03-18 07:03 AM
The exact steps depend on exactly what do you want to achieve, but generally I'd recommend this sequence:
//--- Re Configuration Timer22 --- timer is already running
TIM22->CR1 &= ~TIM_CR1_CEN; //--- Disable count
TIM22->DIER = 0; //--- Disable interrupt
TIM22->PSC = 65; //--- Prescaler : clock timer = 65536Hz/(prescaler+1) => ~1kHz
TIM22->ARR = time; //--- Auto reload Register
TIM22->EGR = TIM_EGR_UG; // generate Update event to force loading of prescaler (and ARR if ARPE=1)
TIM22->CNT = 0; // this is here to generate delay, see comment
TIM22->SR = 0; // clear flags
TIM22->DIER |= TIM_DIER_UIE; //--- Enable interrupt
Writing 0 to CNT may not be needed, as that is cleared as side effect of setting TIM_EGR.UG, see description of that bit in RM. However, that step is there to insert a delay because it takes an few cycles until writes to TIMx_EGR take effect. This is not documented by ST, and as I wrote in that post, I am not sure about the timing, I am not ST insider; so test this and if you find the Update interrupt firing immediately after being enabled, this may be the area for changes.
JW
2024-03-18 07:31 AM
I havent use this register before i have added it
TIM_EGR_UG
Unfortunately my interrupt is still not called, but I think it's a problem of definition, because i have try many configuration, like interrupt with copare mode but I don't know yet, because in my opinion I respect the name of the call back function.
//-----------------------------------------------------------------------------
void TIM22_IRQHandler()
//-----------------------------------------------------------------------------
{
TIM22->SR = 0; //--- Clear Flag
timer22.flagFinVeille = TRUE;
GPIO_VERTE_ON;
}
And above all the SR register generates an event, but the function is never called...
Thanks
2024-03-18 09:31 AM
> SR register generates an event, but the function is never called
So, you have read out TIM22 registers, SR has UIF set, DIER has UIE set, correct?
And the interrupt does not fire, even if you don't enter sleep?
Is this interrupt enabled in NVIC?
Here is a generic checklist for "interrupt does not fire" cases.
JW