2023-01-10 01:48 PM
// Code to start the one shot timer
void set_delta_alarm(Long t) {
LL_LPTIM_Enable(LPTIM2);
while (0 == LL_LPTIM_IsEnabled(LPTIM2)) ;
LL_LPTIM_SetAutoReload(LPTIM2, t); // * TE_SECOND / ONE_SECOND);
LL_LPTIM_ClearFLAG_ARRM(LPTIM2);
LL_LPTIM_StartCounter(LPTIM2, LL_LPTIM_OPERATING_MODE_ONESHOT);
LL_LPTIM_EnableIT_ARRM(LPTIM2);
}
// generated code to initialize the timer
/* LPTIM2 init function */
void MX_LPTIM2_Init(void)
{
/* USER CODE BEGIN LPTIM2_Init 0 */
/* USER CODE END LPTIM2_Init 0 */
LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM2_CLKSOURCE_LSE);
/* Peripheral clock enable */
LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_LPTIM2);
/* LPTIM2 interrupt Init */
NVIC_SetPriority(LPTIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_EnableIRQ(LPTIM2_IRQn);
/* USER CODE BEGIN LPTIM2_Init 1 */
/* USER CODE END LPTIM2_Init 1 */
LL_LPTIM_SetClockSource(LPTIM2, LL_LPTIM_CLK_SOURCE_INTERNAL);
LL_LPTIM_SetPrescaler(LPTIM2, LL_LPTIM_PRESCALER_DIV1);
LL_LPTIM_SetPolarity(LPTIM2, LL_LPTIM_OUTPUT_POLARITY_REGULAR);
LL_LPTIM_SetUpdateMode(LPTIM2, LL_LPTIM_UPDATE_MODE_IMMEDIATE);
LL_LPTIM_SetCounterMode(LPTIM2, LL_LPTIM_COUNTER_MODE_INTERNAL);
LL_LPTIM_TrigSw(LPTIM2);
LL_LPTIM_SetInput1Src(LPTIM2, LL_LPTIM_INPUT1_SRC_GPIO);
/* USER CODE BEGIN LPTIM2_Init 2 */
/* USER CODE END LPTIM2_Init 2 */
}
Here are the functions that initialize the timer and then start the one shot. I've also included an image of the timer from the debugger stalled out with the one-shot bit set. Hardware is supposed to notice the bit is set and then clear it, starting the timer. Obviously this hasn't happened. To get the timer going, I use the following sequence:
set the control register to zero. then write 3 to the control register twice. then the timer starts going again. You can see in the debug image that the CNT register is zero and the ARR is 3 and even tho the counter is enabled, it isn't counting!
I wonder if there is a race condition? Perhaps when the interrupt triggers when CNT == ARR, it gets serviced before the CNT can be reset to zero from the HW using the LSE clock. The hw state machine might be reacting slower to the event than the instructions to restart the timer and the timer is not ready to be reset?
Update. This takes a long time to run tests!
First workaround I tried to start the LPTIM2 twice by repeating the code to start it twice. Nope. Timer stopped after half a day. My next strategy seems to be working so far, but the overhead for running a simple little timer is getting ridiculous. In the re-arming function, just before the timer is enabled, I put in code to disable the timer and a while loop to "sync" up with the slower state machine waiting for the timer to be disabled. This way I know that the timer is off so the rest of the code should work.
LL_LPTIM_Disable(LPTIM2);
while (LL_LPTIM_IsEnabled(LPTIM2)) ;
This leads me to think that if the timer ran off a slower clock, or if the processor speed was higher, things would get worse. This is based on the assertion that the timer causes an interrupt which starts code running to rearm the timer before the timer has had a chance to fully stop. By adding in the stopping code, at the start of the delta function, I get the timer to a known condition, and then it functions as expected.
LPTIM2 is using LSE @ 32khz, tthe core clock is HSI @ 16Mhz.