Skip to content

Commit 35c6885

Browse files
committed
STM32: 16 bits ticker, fixes in set function and handler
This commit simplifies ticker interrupt set function and handler. There were issues around the 16 bits timer wrap-around timing as we were aligning interrupts with wrap-around limits (0xFFFF) and then reading TIM_MST->CNT again in timer_update_irq_handler which could lead to crossing case with the wrap-around (TIM_FLAG_UPDATE) case. Now we're using the 16 lower bits of the timestamp as the reference from using in set_compare and never changing it. There is also no need to set comparator again in timer_update_irq_handler. This is more robust and also more efficient.
1 parent b9b5f0b commit 35c6885

File tree

2 files changed

+27
-25
lines changed

2 files changed

+27
-25
lines changed

targets/TARGET_STM/hal_tick_16b.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,19 @@ extern TIM_HandleTypeDef TimMasterHandle;
2424

2525
extern volatile uint32_t SlaveCounter;
2626
extern volatile uint32_t oc_int_part;
27-
extern volatile uint16_t oc_rem_part;
2827

2928
volatile uint32_t PreviousVal = 0;
3029

3130
void us_ticker_irq_handler(void);
3231
void set_compare(uint16_t count);
3332

33+
3434
#if defined(TARGET_STM32F0)
3535
void timer_update_irq_handler(void) {
3636
#else
3737
void timer_irq_handler(void)
3838
{
3939
#endif
40-
uint16_t cnt_val = TIM_MST->CNT;
4140
TimMasterHandle.Instance = TIM_MST;
4241

4342
// Clear Update interrupt flag
@@ -53,31 +52,25 @@ void timer_irq_handler(void)
5352
// Used for mbed timeout (channel 1) and HAL tick (channel 2)
5453
void timer_oc_irq_handler(void)
5554
{
56-
uint16_t cnt_val = TIM_MST->CNT;
5755
TimMasterHandle.Instance = TIM_MST;
5856
#endif
5957

6058
// Channel 1 for mbed timeout
6159
if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_CC1) == SET) {
6260
if (__HAL_TIM_GET_IT_SOURCE(&TimMasterHandle, TIM_IT_CC1) == SET) {
6361
__HAL_TIM_CLEAR_IT(&TimMasterHandle, TIM_IT_CC1);
64-
if (oc_rem_part > 0) {
65-
set_compare(oc_rem_part); // Finish the remaining time left
66-
oc_rem_part = 0;
67-
} else {
62+
6863
if (oc_int_part > 0) {
69-
set_compare(0xFFFF);
70-
oc_rem_part = cnt_val; // To finish the counter loop the next time
7164
oc_int_part--;
7265
} else {
73-
us_ticker_irq_handler();
66+
us_ticker_irq_handler();
7467
}
75-
}
7668
}
7769
}
7870

7971
// Channel 2 for HAL tick
8072
if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_CC2) == SET) {
73+
8174
if (__HAL_TIM_GET_IT_SOURCE(&TimMasterHandle, TIM_IT_CC2) == SET) {
8275
__HAL_TIM_CLEAR_IT(&TimMasterHandle, TIM_IT_CC2);
8376
uint32_t val = __HAL_TIM_GET_COUNTER(&TimMasterHandle);
@@ -114,11 +107,16 @@ HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
114107
TimMasterHandle.Init.Prescaler = (uint32_t)(SystemCoreClock / 1000000) - 1; // 1 us tick
115108
TimMasterHandle.Init.ClockDivision = 0;
116109
TimMasterHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
117-
#ifdef TARGET_STM32F0
110+
#if !defined(TARGET_STM32L0)
111+
TimMasterHandle.Init.RepetitionCounter = 0;
112+
#endif
113+
#ifdef TIM_AUTORELOAD_PRELOAD_DISABLE
118114
TimMasterHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
119115
#endif
120116
HAL_TIM_Base_Init(&TimMasterHandle);
121117

118+
//LL_TIM_EnableUpdateEvent(TimMasterHandle.Instance);
119+
122120
// Configure output compare channel 1 for mbed timeout (enabled later when used)
123121
HAL_TIM_OC_Start(&TimMasterHandle, TIM_CHANNEL_1);
124122

@@ -127,6 +125,8 @@ HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
127125
PreviousVal = __HAL_TIM_GET_COUNTER(&TimMasterHandle);
128126
__HAL_TIM_SET_COMPARE(&TimMasterHandle, TIM_CHANNEL_2, PreviousVal + HAL_TICK_DELAY);
129127

128+
129+
130130
// Configure interrupts
131131
// Update interrupt used for 32-bit counter
132132
// Output compare channel 1 interrupt for mbed timeout

targets/TARGET_STM/us_ticker_16b.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ TIM_HandleTypeDef TimMasterHandle;
2525

2626
volatile uint32_t SlaveCounter = 0;
2727
volatile uint32_t oc_int_part = 0;
28-
volatile uint16_t oc_rem_part = 0;
2928

3029
static int us_ticker_inited = 0;
3130

@@ -91,22 +90,25 @@ uint32_t us_ticker_read()
9190

9291
void us_ticker_set_interrupt(timestamp_t timestamp)
9392
{
94-
int delta = (int)((uint32_t)timestamp - us_ticker_read());
95-
96-
uint16_t cval = TIM_MST->CNT;
93+
int current_time = us_ticker_read();
94+
int delta = (int)(timestamp - current_time);
9795

9896
if (delta <= 0) { // This event was in the past
99-
us_ticker_irq_handler();
97+
/* Force the event to be handled in next interrupt context
98+
* This prevents calling interrupt handlers in loops as
99+
* us_ticker_set_interrupt might called again from the
100+
* application handler
101+
*/
102+
oc_int_part = 0;
103+
TimMasterHandle.Instance = TIM_MST;
104+
HAL_TIM_GenerateEvent(&TimMasterHandle, TIM_EVENTSOURCE_CC1);
100105
} else {
106+
/* set the comparator at the timestamp lower 16 bits
107+
* and count the number of wrap-around loops to do with
108+
* the upper 16 bits
109+
*/
101110
oc_int_part = (uint32_t)(delta >> 16);
102-
oc_rem_part = (uint16_t)(delta & 0xFFFF);
103-
if (oc_rem_part <= (0xFFFF - cval)) {
104-
set_compare(cval + oc_rem_part);
105-
oc_rem_part = 0;
106-
} else {
107-
set_compare(0xFFFF);
108-
oc_rem_part = oc_rem_part - (0xFFFF - cval);
109-
}
111+
set_compare(timestamp & 0xFFFF);
110112
}
111113
}
112114

0 commit comments

Comments
 (0)