Skip to content

Commit ee596cf

Browse files
LMESTM0xc0170
authored andcommitted
Update STM32 16 bits us_tickers in line with new mbed HAL
The new HAL allows to share the timer bit width and frequency, the actual handling of mapping 16 bits counter up to 32 bits or 64 bits is now managed by mbed common layer. This makes this ticker layer very similar to 32bits one and much easier than before.
1 parent 2153046 commit ee596cf

File tree

2 files changed

+19
-145
lines changed

2 files changed

+19
-145
lines changed

targets/TARGET_STM/hal_tick_16b.c

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@
2222

2323
extern TIM_HandleTypeDef TimMasterHandle;
2424

25-
extern volatile uint32_t SlaveCounter;
26-
extern volatile uint32_t oc_int_part;
27-
2825
volatile uint32_t PreviousVal = 0;
2926

3027
void us_ticker_irq_handler(void);
@@ -37,14 +34,6 @@ void timer_irq_handler(void)
3734
#endif
3835
TimMasterHandle.Instance = TIM_MST;
3936

40-
// Clear Update interrupt flag
41-
if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_UPDATE) == SET) {
42-
if (__HAL_TIM_GET_IT_SOURCE(&TimMasterHandle, TIM_IT_UPDATE) == SET) {
43-
__HAL_TIM_CLEAR_IT(&TimMasterHandle, TIM_IT_UPDATE);
44-
SlaveCounter++;
45-
}
46-
}
47-
4837
#if defined(TARGET_STM32F0)
4938
} // end timer_update_irq_handler function
5039
// Used for mbed timeout (channel 1) and HAL tick (channel 2)
@@ -57,12 +46,7 @@ void timer_oc_irq_handler(void)
5746
if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_CC1) == SET) {
5847
if (__HAL_TIM_GET_IT_SOURCE(&TimMasterHandle, TIM_IT_CC1) == SET) {
5948
__HAL_TIM_CLEAR_IT(&TimMasterHandle, TIM_IT_CC1);
60-
61-
if (oc_int_part > 0) {
62-
oc_int_part--;
63-
} else {
6449
us_ticker_irq_handler();
65-
}
6650
}
6751
}
6852

@@ -142,7 +126,6 @@ HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
142126
#endif
143127

144128
// Enable interrupts
145-
__HAL_TIM_ENABLE_IT(&TimMasterHandle, TIM_IT_UPDATE); // For 32-bit counter
146129
__HAL_TIM_ENABLE_IT(&TimMasterHandle, TIM_IT_CC2); // For HAL tick
147130

148131
// Enable timer

targets/TARGET_STM/us_ticker_16b.c

Lines changed: 19 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -23,157 +23,48 @@
2323

2424
TIM_HandleTypeDef TimMasterHandle;
2525

26-
volatile uint32_t SlaveCounter = 0;
27-
volatile uint32_t oc_int_part = 0;
26+
// Declare ticker as 16 bits - mbed layer takes care of mapping to 32 or 64
27+
// bits
28+
const ticker_info_t* us_ticker_get_info()
29+
{
30+
static const ticker_info_t info = {
31+
1000000,
32+
16
33+
};
34+
return &info;
35+
}
2836

2937
void us_ticker_init(void)
3038
{
31-
/* NOTE: assuming that HAL tick has already been initialized! */
39+
/* NOTE: assuming thaiHAL tick has already been initialized! */
40+
us_ticker_disable_interrupt();
3241
}
3342

3443
uint32_t us_ticker_read()
3544
{
36-
uint16_t cntH_old, cntH, cntL;
37-
do {
38-
cntH_old = SlaveCounter;
39-
/* SlaveCounter needs to be checked before AND after we read the
40-
* current counter TIM_MST->CNT, in case it wraps around.
41-
* there are 2 possible cases of wrap around
42-
* 1) in case this function is interrupted by timer_irq_handler and
43-
* the SlaveCounter is updated. In that case we will loop again.
44-
* 2) in case this function is called from interrupt context during
45-
* wrap-around condtion. That would prevent/delay the timer_irq_handler
46-
* from being called so we need to locally check the FLAG_UPDATE and
47-
* update the cntH accordingly. The SlaveCounter variable itself will
48-
* be updated in the interrupt handler just after ...
49-
*/
50-
if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_UPDATE) == SET) {
51-
cntH_old += 1;
52-
}
53-
cntL = TIM_MST->CNT;
54-
cntH = SlaveCounter;
55-
if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_UPDATE) == SET) {
56-
cntH += 1;
57-
}
58-
} while(cntH_old != cntH);
59-
// Glue the upper and lower part together to get a 32 bit timer
60-
return (uint32_t)(cntH << 16 | cntL);
45+
return TIM_MST->CNT;
6146
}
6247

6348
void us_ticker_set_interrupt(timestamp_t timestamp)
6449
{
6550
// NOTE: This function must be called with interrupts disabled to keep our
6651
// timer interrupt setup atomic
67-
6852
// Set new output compare value
6953
__HAL_TIM_SET_COMPARE(&TimMasterHandle, TIM_CHANNEL_1, timestamp & 0xFFFF);
7054
// Ensure the compare event starts clear
7155
__HAL_TIM_CLEAR_FLAG(&TimMasterHandle, TIM_FLAG_CC1);
7256
// Enable IT
7357
__HAL_TIM_ENABLE_IT(&TimMasterHandle, TIM_IT_CC1);
74-
75-
/* Set the number of timer wrap-around loops before the actual timestamp
76-
* is reached. If the calculated delta time is more than halfway to the
77-
* next compare event, check to see if a compare event has already been
78-
* set, and if so, add one to the wrap-around count. This is done to
79-
* ensure the correct wrap count is used in the corner cases where the
80-
* 16 bit counter passes the compare value during the process of
81-
* configuring this interrupt.
82-
*
83-
* Assumption: The time to execute this function is less than 32ms
84-
* (otherwise incorrect behaviour could result)
85-
*
86-
* Consider the following corner cases:
87-
* 1) timestamp is 1 us in the future:
88-
* oc_int_part = 0 initially
89-
* oc_int_part left at 0 because ((delta - 1) & 0xFFFF) < 0x8000
90-
* Compare event should happen in 1 us and us_ticker_irq_handler()
91-
* called
92-
* 2) timestamp is 0x8000 us in the future:
93-
* oc_int_part = 0 initially
94-
* oc_int_part left at 0 because ((delta - 1) & 0xFFFF) < 0x8000
95-
* There should be no possibility of the CC1 flag being set yet
96-
* (see assumption above). When the compare event does occur in
97-
* 32768 us, us_ticker_irq_handler() will be called
98-
* 3) timestamp is 0x8001 us in the future:
99-
* oc_int_part = 0 initially
100-
* ((delta - 1) & 0xFFFF) >= 0x8000 but there should be no
101-
* possibility of the CC1 flag being set yet (see assumption above),
102-
* so oc_int_part will be left at 0, and when the compare event
103-
* does occur in 32769 us, us_ticker_irq_handler() will be called
104-
* 4) timestamp is 0x10000 us in the future:
105-
* oc_int_part = 0 initially
106-
* ((delta - 1) & 0xFFFF) >= 0x8000
107-
* There are two subcases:
108-
* a) The timer counter has not incremented past the compare
109-
* value while setting up the interrupt. In this case, the
110-
* CC1 flag will not be set, so oc_int_part will be
111-
* left at 0, and when the compare event occurs in 65536 us,
112-
* us_ticker_irq_handler() will be called
113-
* b) The timer counter has JUST incremented past the compare
114-
* value. In this case, the CC1 flag will be set, so
115-
* oc_int_part will be incremented to 1, and the interrupt will
116-
* occur immediately after this function returns, where
117-
* oc_int_part will decrement to 0 without calling
118-
* us_ticker_irq_handler(). Then about 65536 us later, the
119-
* compare event will occur again, and us_ticker_irq_handler()
120-
* will be called
121-
* 5) timestamp is 0x10001 us in the future:
122-
* oc_int_part = 1 initially
123-
* oc_int_part left at 1 because ((delta - 1) & 0xFFFF) < 0x8000
124-
* CC1 flag will not be set (see assumption above). In 1 us the
125-
* compare event will cause an interrupt, where oc_int_part will be
126-
* decremented to 0 without calling us_ticker_irq_handler(). Then
127-
* about 65536 us later, the compare event will occur again, and
128-
* us_ticker_irq_handler() will be called
129-
* 6) timestamp is 0x18000 us in the future:
130-
* oc_int_part = 1 initially
131-
* oc_int_part left at 1 because ((delta - 1) & 0xFFFF) < 0x8000
132-
* There should be no possibility of the CC1 flag being set yet
133-
* (see assumption above). When the compare event does occur in
134-
* 32768 us, oc_int_part will be decremented to 0 without calling
135-
* us_ticker_irq_handler(). Then about 65536 us later, the
136-
* compare event will occur again, and us_ticker_irq_handler() will
137-
* be called
138-
* 7) timestamp is 0x18001 us in the future:
139-
* oc_int_part = 1 initially
140-
* ((delta - 1) & 0xFFFF) >= 0x8000 but there should be no
141-
* possibility of the CC1 flag being set yet (see assumption above),
142-
* so oc_int_part will be left at 1, and when the compare event
143-
* does occur in 32769 us, oc_int_part will be decremented to 0
144-
* without calling us_ticker_irq_handler(). Then about 65536 us
145-
* later, the compare event will occur again, and
146-
* us_ticker_irq_handler() will be called
147-
*
148-
* delta - 1 is used because the timer compare event happens on the
149-
* counter incrementing to match the compare value, and it won't occur
150-
* immediately when the compare value is set to the current counter
151-
* value.
152-
*/
153-
uint32_t current_time = us_ticker_read();
154-
uint32_t delta = timestamp - current_time;
155-
/* Note: The case of delta <= 0 is handled in MBED upper layer */
156-
oc_int_part = (delta - 1) >> 16;
157-
if ( ((delta - 1) & 0xFFFF) >= 0x8000 &&
158-
__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_CC1) == SET ) {
159-
++oc_int_part;
160-
/* NOTE: Instead of incrementing oc_int_part here, we could clear
161-
* the CC1 flag, but then you'd have to wait to ensure the
162-
* interrupt is knocked down before returning and reenabling
163-
* interrupts. Since this is a rare case, it's not worth it
164-
* to try and optimize it, and it keeps the code simpler and
165-
* safer to just do this increment instead.
166-
*/
167-
}
168-
16958
}
17059

17160
void us_ticker_fire_interrupt(void)
17261
{
173-
/* When firing the event, the number of 16 bits counter wrap-ups (oc_int)
174-
* must be re-initialized */
175-
oc_int_part = 0;
176-
HAL_TIM_GenerateEvent(&TimMasterHandle, TIM_EVENTSOURCE_CC1);
62+
// Ensure the compare event starts clear
63+
__HAL_TIM_CLEAR_FLAG(&TimMasterHandle, TIM_FLAG_CC1);
64+
LL_TIM_GenerateEvent_CC1(TimMasterHandle.Instance);
65+
// Enable IT
66+
__HAL_TIM_ENABLE_IT(&TimMasterHandle, TIM_IT_CC1);
67+
17768
}
17869

17970
/* NOTE: must be called with interrupts disabled! */

0 commit comments

Comments
 (0)