Skip to content

Commit 2b8e05e

Browse files
author
Bogdan Marinescu
committed
[NUCLEO_F103RB] Timer fixes
- the timer data structures were not properly initialized - changed slave timer mode to external clock 1 (section 15.3.15 of the manual) - avoid a possible race condition when concatenating the values of the two 16-bit timers
1 parent 1dbb6d9 commit 2b8e05e

File tree

1 file changed

+17
-4
lines changed
  • libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB

1 file changed

+17
-4
lines changed

libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/us_ticker.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ void us_ticker_init(void) {
3333

3434
// Time base configuration
3535
// TIM1 is used as "master", "TIM4" as "slave". TIM4 is clocked by TIM1.
36+
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
3637
TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
3738
TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)(SystemCoreClock / 1000000) - 1; // 1 µs tick
3839
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
@@ -42,6 +43,7 @@ void us_ticker_init(void) {
4243
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
4344

4445
// Master timer configuration
46+
TIM_OCStructInit(&TIM_OCInitStructure);
4547
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
4648
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
4749
TIM_OCInitStructure.TIM_Pulse = 0;
@@ -51,7 +53,7 @@ void us_ticker_init(void) {
5153
TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update);
5254

5355
// Slave timer configuration
54-
TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Gated);
56+
TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_External1);
5557
TIM_SelectInputTrigger(TIM4, TIM_TS_ITR0);
5658

5759
// Enable timers
@@ -60,10 +62,21 @@ void us_ticker_init(void) {
6062
}
6163

6264
uint32_t us_ticker_read() {
63-
uint32_t counter;
65+
uint32_t counter, counter2;
6466
if (!us_ticker_inited) us_ticker_init();
65-
counter = (uint32_t)((uint32_t)TIM_GetCounter(TIM4) << 16) + (uint32_t)TIM_GetCounter(TIM1);
66-
return counter;
67+
// A situation might appear when TIM1 overflows right after TIM4 is read and before the
68+
// new (overflowed) value of TIM1 is read, which would make the code below consider the
69+
// previous (incorrect) value of TIM4 and the new value of TIM1, which would return a
70+
// value in the past. Avoid this by computing consecutive values of the timer until they
71+
// are properly ordered.
72+
counter = counter2 = (uint32_t)((uint32_t)TIM_GetCounter(TIM4) << 16) + (uint32_t)TIM_GetCounter(TIM1);
73+
while (1) {
74+
counter2 = (uint32_t)((uint32_t)TIM_GetCounter(TIM4) << 16) + (uint32_t)TIM_GetCounter(TIM1);
75+
if (counter2 > counter)
76+
break;
77+
counter = counter2;
78+
}
79+
return counter2;
6780
}
6881

6982
void us_ticker_set_interrupt(unsigned int timestamp) {

0 commit comments

Comments
 (0)