Skip to content

Commit 37e50a6

Browse files
jdascenziocarlescufi
authored andcommitted
driver: timer: stm32_lptim: fix excess ticks
Some ticks are counted additionally when the autoreload interrupts were too close together. This patch improve the counts of the clock cycle. lptim_fired worked badly in particular because the flag ARRM was not raised when the interrupt was forced. Signed-off-by: Julien D'Ascenzio <[email protected]>
1 parent 01ff7ba commit 37e50a6

File tree

1 file changed

+19
-17
lines changed

1 file changed

+19
-17
lines changed

drivers/timer/stm32_lptim_timer.c

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,15 @@
3030
/* nb of LPTIM counter unit per kernel tick */
3131
#define COUNT_PER_TICK (LPTIM_CLOCK / CONFIG_SYS_CLOCK_TICKS_PER_SEC)
3232

33+
/* minimum nb of clock cycles to have to set autoreload register correctly */
34+
#define LPTIM_GUARD_VALUE 2
35+
3336
/* A 32bit value cannot exceed 0xFFFFFFFF/LPTIM_TIMEBASE counting cycles.
3437
* This is for example about of 65000 x 2000ms when clocked by LSI
3538
*/
3639
static u32_t accumulated_lptim_cnt;
3740

3841
static struct k_spinlock lock;
39-
volatile u8_t lptim_fired;
4042

4143
static void lptim_irq_handler(struct device *unused)
4244
{
@@ -51,13 +53,6 @@ static void lptim_irq_handler(struct device *unused)
5153
/* do not change ARR yet, z_clock_announce will do */
5254
LL_LPTIM_ClearFLAG_ARRM(LPTIM1);
5355

54-
if (lptim_fired) {
55-
lptim_fired = 0;
56-
#if defined(LPTIM_CR_COUNTRST)
57-
LL_LPTIM_ResetCounter(LPTIM1);
58-
#endif
59-
}
60-
6156
/* increase the total nb of autoreload count
6257
* used in the z_timer_cycle_get_32() function.
6358
* Reading the CNT register gives a reliable value
@@ -147,7 +142,6 @@ int z_clock_driver_init(struct device *device)
147142
LL_LPTIM_ClearFlag_ARROK(LPTIM1);
148143

149144
accumulated_lptim_cnt = 0;
150-
lptim_fired = 0;
151145

152146
/* Enable the LPTIM1 counter */
153147
LL_LPTIM_Enable(LPTIM1);
@@ -212,6 +206,17 @@ void z_clock_set_timeout(s32_t ticks, bool idle)
212206
lp_time = LL_LPTIM_GetCounter(LPTIM1);
213207
}
214208

209+
u32_t autoreload = LL_LPTIM_GetAutoReload(LPTIM1);
210+
211+
if (LL_LPTIM_IsActiveFlag_ARRM(LPTIM1)
212+
|| ((autoreload - lp_time) < LPTIM_GUARD_VALUE)) {
213+
/* interrupt happens or happens soon.
214+
* It's impossible to set autoreload value.
215+
*/
216+
k_spin_unlock(&lock, key);
217+
return;
218+
}
219+
215220
/* calculate the next arr value (cannot exceed 16bit)
216221
* adjust the next ARR match value to align on Ticks
217222
* from the current counter value to first next Tick
@@ -227,15 +232,12 @@ void z_clock_set_timeout(s32_t ticks, bool idle)
227232
if (next_arr > LPTIM_TIMEBASE) {
228233
next_arr = LPTIM_TIMEBASE;
229234
}
230-
231-
/* If we are close to the roll over of the ticker counter
232-
* change current tick so it can be compared with buffer.
233-
* If this event got outdated fire interrupt right now,
234-
* else schedule it normally.
235+
/* The new autoreload value must be LPTIM_GUARD_VALUE clock cycles
236+
* after current lptim to make sure we don't miss
237+
* an autoreload interrupt
235238
*/
236-
if (next_arr <= ((lp_time + 1) & LPTIM_TIMEBASE)) {
237-
NVIC_SetPendingIRQ(LPTIM1_IRQn);
238-
lptim_fired = 1;
239+
else if (next_arr < (lp_time + LPTIM_GUARD_VALUE)) {
240+
next_arr = lp_time + LPTIM_GUARD_VALUE;
239241
}
240242

241243
/* ARROK bit validates previous write operation to ARR register */

0 commit comments

Comments
 (0)