Skip to content

Commit a703cbe

Browse files
jdascenziocarlescufi
authored andcommitted
drivers: timer: stm32 lptim fix long time interrupt locking
The waiting of the flag ARROK could be quite long (100µs-200µs in my test). During this time, the interrupts are locked that is not recommended. To avoid this, we manage the update of the autoreload value in interruption Signed-off-by: Julien D'Ascenzio <[email protected]>
1 parent 7109632 commit a703cbe

File tree

1 file changed

+41
-12
lines changed

1 file changed

+41
-12
lines changed

drivers/timer/stm32_lptim_timer.c

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@
4343
* This is for example about of 65000 x 2000ms when clocked by LSI
4444
*/
4545
static uint32_t accumulated_lptim_cnt;
46+
/* Next autoreload value to set */
47+
static uint32_t autoreload_next;
48+
/* Indicate if the autoreload register is ready for a write */
49+
static bool autoreload_ready = true;
4650

4751
static struct k_spinlock lock;
4852

@@ -51,6 +55,20 @@ static void lptim_irq_handler(const struct device *unused)
5155

5256
ARG_UNUSED(unused);
5357

58+
uint32_t autoreload = LL_LPTIM_GetAutoReload(LPTIM1);
59+
60+
if ((LL_LPTIM_IsActiveFlag_ARROK(LPTIM1) != 0)
61+
&& LL_LPTIM_IsEnabledIT_ARROK(LPTIM1) != 0) {
62+
LL_LPTIM_ClearFlag_ARROK(LPTIM1);
63+
if ((autoreload_next > 0) && (autoreload_next != autoreload)) {
64+
/* the new autoreload value change, we set it */
65+
autoreload_ready = false;
66+
LL_LPTIM_SetAutoReload(LPTIM1, autoreload_next);
67+
} else {
68+
autoreload_ready = true;
69+
}
70+
}
71+
5472
if ((LL_LPTIM_IsActiveFlag_ARRM(LPTIM1) != 0)
5573
&& LL_LPTIM_IsEnabledIT_ARRM(LPTIM1) != 0) {
5674

@@ -61,9 +79,8 @@ static void lptim_irq_handler(const struct device *unused)
6179

6280
/* increase the total nb of autoreload count
6381
* used in the sys_clock_cycle_get_32() function.
64-
* Reading the CNT register gives a reliable value
6582
*/
66-
uint32_t autoreload = LL_LPTIM_GetAutoReload(LPTIM1) + 1;
83+
autoreload++;
6784

6885
accumulated_lptim_cnt += autoreload;
6986

@@ -79,6 +96,23 @@ static void lptim_irq_handler(const struct device *unused)
7996
}
8097
}
8198

99+
static void lptim_set_autoreload(uint32_t arr)
100+
{
101+
/* Update autoreload register */
102+
autoreload_next = arr;
103+
104+
if (!autoreload_ready)
105+
return;
106+
107+
/* The ARR register ready, we could set it directly */
108+
if ((arr > 0) && (arr != LL_LPTIM_GetAutoReload(LPTIM1))) {
109+
/* The new autoreload value change, we set it */
110+
autoreload_ready = false;
111+
LL_LPTIM_ClearFlag_ARROK(LPTIM1);
112+
LL_LPTIM_SetAutoReload(LPTIM1, arr);
113+
}
114+
}
115+
82116
static inline uint32_t z_clock_lptim_getcounter(void)
83117
{
84118
uint32_t lp_time;
@@ -175,13 +209,8 @@ void sys_clock_set_timeout(int32_t ticks, bool idle)
175209
next_arr = lp_time + LPTIM_GUARD_VALUE;
176210
}
177211

178-
/* ARROK bit validates previous write operation to ARR register */
179-
while (LL_LPTIM_IsActiveFlag_ARROK(LPTIM1) == 0) {
180-
}
181-
LL_LPTIM_ClearFlag_ARROK(LPTIM1);
182-
183-
/* run timer and wait for the reload match */
184-
LL_LPTIM_SetAutoReload(LPTIM1, next_arr);
212+
/* Update autoreload register */
213+
lptim_set_autoreload(next_arr);
185214

186215
k_spin_unlock(&lock, key);
187216
}
@@ -345,6 +374,7 @@ static int sys_clock_driver_init(const struct device *dev)
345374
#endif
346375
LL_LPTIM_ClearFLAG_ARRM(LPTIM1);
347376
/* ARROK bit validates the write operation to ARR register */
377+
LL_LPTIM_EnableIT_ARROK(LPTIM1);
348378
LL_LPTIM_ClearFlag_ARROK(LPTIM1);
349379

350380
accumulated_lptim_cnt = 0;
@@ -357,11 +387,10 @@ static int sys_clock_driver_init(const struct device *dev)
357387
/* Set the Autoreload value once the timer is enabled */
358388
if (IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
359389
/* LPTIM1 is triggered on a LPTIM_TIMEBASE period */
360-
LL_LPTIM_SetAutoReload(LPTIM1, LPTIM_TIMEBASE);
361-
390+
lptim_set_autoreload(LPTIM_TIMEBASE);
362391
} else {
363392
/* LPTIM1 is triggered on a Tick period */
364-
LL_LPTIM_SetAutoReload(LPTIM1, COUNT_PER_TICK - 1);
393+
lptim_set_autoreload(COUNT_PER_TICK - 1);
365394
}
366395

367396
/* Start the LPTIM counter in continuous mode */

0 commit comments

Comments
 (0)