driver: timer: stm32_lptim control the timer duration

This change makes the lptimer running with lower tick periods
and small tick values

Signed-off-by: Francois Ramu <francois.ramu@st.com>
This commit is contained in:
Francois Ramu 2020-05-11 15:53:19 +02:00 committed by Carles Cufí
commit 29ea09ee52

View file

@ -36,6 +36,7 @@
static u32_t accumulated_lptim_cnt; static u32_t accumulated_lptim_cnt;
static struct k_spinlock lock; static struct k_spinlock lock;
volatile u8_t lptim_fired;
static void lptim_irq_handler(struct device *unused) static void lptim_irq_handler(struct device *unused)
{ {
@ -50,6 +51,13 @@ static void lptim_irq_handler(struct device *unused)
/* do not change ARR yet, z_clock_announce will do */ /* do not change ARR yet, z_clock_announce will do */
LL_LPTIM_ClearFLAG_ARRM(LPTIM1); LL_LPTIM_ClearFLAG_ARRM(LPTIM1);
if (lptim_fired) {
lptim_fired = 0;
#if defined(LPTIM_CR_COUNTRST)
LL_LPTIM_ResetCounter(LPTIM1);
#endif
}
/* increase the total nb of autoreload count /* increase the total nb of autoreload count
* used in the z_timer_cycle_get_32() function. * used in the z_timer_cycle_get_32() function.
* Reading the CNT register gives a reliable value * Reading the CNT register gives a reliable value
@ -141,6 +149,7 @@ int z_clock_driver_init(struct device *device)
LL_LPTIM_ClearFlag_ARROK(LPTIM1); LL_LPTIM_ClearFlag_ARROK(LPTIM1);
accumulated_lptim_cnt = 0; accumulated_lptim_cnt = 0;
lptim_fired = 0;
/* Enable the LPTIM1 counter */ /* Enable the LPTIM1 counter */
LL_LPTIM_Enable(LPTIM1); LL_LPTIM_Enable(LPTIM1);
@ -225,6 +234,16 @@ void z_clock_set_timeout(s32_t ticks, bool idle)
if (next_arr > LPTIM_TIMEBASE) { if (next_arr > LPTIM_TIMEBASE) {
next_arr = LPTIM_TIMEBASE; next_arr = LPTIM_TIMEBASE;
} }
/* If we are close to the roll over of the ticker counter
* change current tick so it can be compared with buffer.
* If this event got outdated fire interrupt right now,
* else schedule it normally.
*/
if (next_arr <= ((lp_time + 1) & LPTIM_TIMEBASE)) {
NVIC_SetPendingIRQ(LPTIM1_IRQn);
lptim_fired = 1;
}
/* run timer and wait for the reload match */ /* run timer and wait for the reload match */
LL_LPTIM_SetAutoReload(LPTIM1, next_arr); LL_LPTIM_SetAutoReload(LPTIM1, next_arr);
@ -250,15 +269,22 @@ u32_t z_clock_elapsed(void)
lp_time = LL_LPTIM_GetCounter(LPTIM1); lp_time = LL_LPTIM_GetCounter(LPTIM1);
} }
/* In case of counter roll-over, add this value,
* even if the irq has not yet been handled
*/
if ((LL_LPTIM_IsActiveFlag_ARRM(LPTIM1) != 0)
&& LL_LPTIM_IsEnabledIT_ARRM(LPTIM1) != 0) {
lp_time += LL_LPTIM_GetAutoReload(LPTIM1) + 1;
}
k_spin_unlock(&lock, key); k_spin_unlock(&lock, key);
/* gives the value of LPTIM1 counter (ms) /* gives the value of LPTIM1 counter (ms)
* since the previous 'announce' * since the previous 'announce'
*/ */
u32_t ret = ((lp_time + 1) * 1000) / LPTIM_CLOCK; u64_t ret = (lp_time * CONFIG_SYS_CLOCK_TICKS_PER_SEC) / LPTIM_CLOCK;
/* convert to ticks */ return (u32_t)(ret);
return z_ms_to_ticks(ret);
} }
u32_t z_timer_cycle_get_32(void) u32_t z_timer_cycle_get_32(void)
@ -273,15 +299,25 @@ u32_t z_timer_cycle_get_32(void)
* of the LPTIM_CNT register, two successive read accesses * of the LPTIM_CNT register, two successive read accesses
* must be performed and compared * must be performed and compared
*/ */
while (lp_time != LL_LPTIM_GetCounter(LPTIM1)) { while (lp_time != LL_LPTIM_GetCounter(LPTIM1)) {
lp_time = LL_LPTIM_GetCounter(LPTIM1); lp_time = LL_LPTIM_GetCounter(LPTIM1);
} }
/* In case of counter roll-over, add this value,
* even if the irq has not yet been handled
*/
if ((LL_LPTIM_IsActiveFlag_ARRM(LPTIM1) != 0)
&& LL_LPTIM_IsEnabledIT_ARRM(LPTIM1) != 0) {
lp_time += LL_LPTIM_GetAutoReload(LPTIM1) + 1;
}
lp_time += accumulated_lptim_cnt; lp_time += accumulated_lptim_cnt;
/* convert lptim count in a nb of hw cycles with precision */
u64_t ret = lp_time * (sys_clock_hw_cycles_per_sec() / LPTIM_CLOCK);
k_spin_unlock(&lock, key); k_spin_unlock(&lock, key);
/* convert in hw cycles (keeping 32bit value) */ /* convert in hw cycles (keeping 32bit value) */
return ((lp_time / (LPTIM_CLOCK / 1000)) return (u32_t)(ret);
* (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000));
} }