2023-07-18 12:03 PM
I am trying to configure the TIM5 to get timestamp in milliseconds for a long period (over 40 seconds).
Here is the current configuration of TIM5:
// This function inits and start the timers used
void timer_init(void) {
__HAL_RCC_TIM5_CLK_ENABLE();
TIM5->PSC = (HAL_RCC_GetPCLK1Freq() / 1000000) - 1;
TIM5->CR1 |= TIM_CR1_CEN;
}
We did observed an overflow problem after about 40 seconds, our timeout were taking for ever to expire after the first 40 seconds. So we did use this test code to gather data:
snprintf(printbuff, sizeof(printbuff), "Timer 5 ARR %X PSC %X CR1 %X CR2 %X EGR %X RCR %X\n",
TIM5->ARR, TIM5->PSC, TIM5->CR1, TIM5->CR2, TIM5->EGR, TIM5->RCR);
send_uart(printbuff, strlen(printbuff));
while (true)
{
uint32_t mltime = TIM5->CNT;
HAL_Delay(1000);
uint32_t mctime = TIM5->CNT;
uint32_t mstime = (int32_t)mctime - (int32_t)mltime;
snprintf(printbuff, sizeof(printbuff), "Time ml %u mc %u ms %u\n", mltime, mctime, mstime);
send_uart(printbuff, strlen(printbuff));
if (mctime < mltime)
{
snprintf(printbuff, sizeof(printbuff), "Timer 5 ARR %X PSC %X CR1 %X CR2 %X EGR %X RCR %X\n",
TIM5->ARR, TIM5->PSC, TIM5->CR1, TIM5->CR2, TIM5->EGR, TIM5->RCR);
send_uart(printbuff, strlen(printbuff));
}
}
Here are the results:
Timer 5 ARR FFFFFFFF PSC 31 CR1 1 CR2 0 EGR 0 RCR 0
Time ml 3904281 mc 103971757 ms 100067476
Time ml 104340567 mc 204371761 ms 100031194
Time ml 204757745 mc 304771761 ms 100014016
Time ml 305158453 mc 405171759 ms 100013306
Time ml 405558259 mc 505571763 ms 100013504
Time ml 505958093 mc 605971757 ms 100013664
Time ml 606357915 mc 706371767 ms 100013852
Time ml 706757741 mc 806771771 ms 100014030
Time ml 807158433 mc 907171765 ms 100013332
...
Time ml 3821875199 mc 3921971765 ms 100096566
Time ml 3922375709 mc 4022471767 ms 100096058
Time ml 4022875355 mc 4122971763 ms 100096408
Time ml 4123375861 mc 4223471771 ms 100095910
Time ml 4223875521 mc 580089 ms 71671864
Timer 5 ARR FFFFFFFF PSC 31 CR1 1 CR2 0 EGR 0 RCR 0
Time ml 596455 mc 2598089 ms 2001634
Time ml 2604590 mc 4606089 ms 2001499
Time ml 4612760 mc 6614089 ms 2001329
Time ml 6620809 mc 8622089 ms 2001280
Time ml 8628771 mc 10630089 ms 2001318
Time ml 10636941 mc 12638089 ms 2001148
...
Time ml 4289685807 mc 4291686089 ms 2000282
Time ml 4291693821 mc 4293694089 ms 2000268
Time ml 4293701817 mc 734793 ms 2000272
Timer 5 ARR FFFFFFFF PSC 31 CR1 1 CR2 0 EGR 0 RCR 0
Time ml 750989 mc 2752793 ms 2001804
Time ml 2759299 mc 4760793 ms 2001494
Time ml 4767468 mc 6768793 ms 2001325
Time ml 6775465 mc 8776793 ms 2001328
Time ml 8783479 mc 10784793 ms 2001314
So after the timer overflow, the value are not valid anymore 2001148 instead of 100096566 (aka ~1 second). Last period before first overflow is also too short 71671864. Second overflow is ok constant to ~2001148.
When setting TIM5->EGR:
// This function inits and start the timers used
void timer_init(void) {
__HAL_RCC_TIM5_CLK_ENABLE();
TIM5->PSC = (HAL_RCC_GetPCLK1Freq() / 1000000) - 1;
TIM5->EGR = TIM_EGR_UG;
TIM5->CR1 |= TIM_CR1_CEN;
}
We have the following results:
Timer 5 ARR FFFFFFFF PSC 31 CR1 1 CR2 0 EGR 0 RCR 0
Time ml 77998 mc 2079435 ms 2001437
Time ml 2085769 mc 4087435 ms 2001666
Time ml 4094113 mc 6095435 ms 2001322
Time ml 6102110 mc 8103435 ms 2001325
Time ml 8110123 mc 10111435 ms 2001312
Time ml 10118294 mc 12119435 ms 2001141
Time ml 12126463 mc 14127435 ms 2000972
...
Time ml 4287159163 mc 4289159435 ms 2000272
Time ml 4289167160 mc 4291167435 ms 2000275
Time ml 4291175156 mc 4293175435 ms 2000279
Time ml 4293183153 mc 216139 ms 2000282
Timer 5 ARR FFFFFFFF PSC 31 CR1 1 CR2 0 EGR 0 RCR 0
Time ml 232342 mc 2234139 ms 2001797
Time ml 2240651 mc 4242139 ms 2001488
Time ml 4248821 mc 6250139 ms 2001318
Time ml 6256818 mc 8258139 ms 2001321
Time ml 8264814 mc 10266139 ms 2001325
...
Time ml 4287313872 mc 4289314139 ms 2000267
Time ml 4289321868 mc 4291322139 ms 2000271
Time ml 4291329865 mc 4293330139 ms 2000274
Time ml 4293337861 mc 370843 ms 2000278
Timer 5 ARR FFFFFFFF PSC 31 CR1 1 CR2 0 EGR 0 RCR 0
Time ml 387033 mc 2388843 ms 2001810
Time ml 2395342 mc 4396843 ms 2001501
Time ml 4403530 mc 6404843 ms 2001313
Time ml 6411526 mc 8412843 ms 2001317
Time ml 8419523 mc 10420843 ms 2001320
Wrong value of ~2000000 instead of 1 seconds. But it does never changes always ~2000000 even just before or after the overflow.
So we are thinking we have a configuration issue, what should be the right configuration?
Solved! Go to Solution.
2023-07-20 08:30 AM
> I am new to STM32F412, how can we set APB divider to 1 or to the right value. I made a patch dividing the value by 2 but I would like to make a real fix to the problem.
The cpu clock rate is typically higher than the peripheral clock rates because they often can't run as fast as the cpu. But you can adjust your clock settings if that's what you want. Otherwise, the x2 factor isn't a bug and isn't something that needs a fix. It's how the chip works.
2023-07-20 09:40 AM
> I am new to STM32F412, how can we set APB divider to 1 or to the right value. I made a patch dividing the value by 2 but I would like to make a real fix to the problem.
As TDK said above, it's not a problem, simply take it into account and make the prescaler twice as big (more precisely, ((HAL_RCC_GetPCLK1Freq() / 1000000) * 2) - 1; ).
JW
2023-07-20 10:44 PM
@SylvainFluent wrote:Thanks for your reply,
send_uart() is outside the timer handling so it does not affect the timer execution time, the send_uart() will only create a gap between the last mctime and the new mltime, but as we do not care about mltime - mctime but rather mctime - mltime, the time spent in send_uart() does not affect the results.
OMG, it's getting more and more embarrassing for me... :speak_no_evil_monkey:
you're absolutely right, even if send_uart() would take a year it would not affect your calculations.
2023-08-10 12:34 PM
Thanks, sorry I was moved on an higher priority project.
I test the solution and it works great.