Skip to content

Commit 14b1ba1

Browse files
mmahadevan108danieldegrasse
authored andcommitted
drivers: timer: Fix the logic to compensate the clock when turned off
The original logic relied on the tick passed in. This method is inaccurate as the tick value passed in was the exit latency. Update the code to calculate the remaining time left and set a counter using this value. Signed-off-by: Mahesh Mahadevan <[email protected]>
1 parent d0f9ccc commit 14b1ba1

File tree

2 files changed

+25
-9
lines changed

2 files changed

+25
-9
lines changed

drivers/timer/mcux_os_timer.c

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ static uint64_t cyc_sys_compensated;
4444
*/
4545
static const struct device *counter_dev;
4646
/* Indicates if the counter is running. */
47-
bool counter_running;
47+
static bool counter_running;
4848
#endif
4949

5050
static uint64_t mcux_lpc_ostick_get_compensated_timer_value(void)
@@ -90,12 +90,10 @@ static uint32_t mcux_lpc_ostick_set_counter_timeout(int32_t curr_timeout)
9090
uint32_t ret = 0;
9191

9292
if (counter_dev) {
93-
uint32_t timeout;
94-
int32_t ticks;
93+
uint32_t ticks;
9594
struct counter_top_cfg top_cfg = { 0 };
96-
timeout = k_ticks_to_us_near32(curr_timeout);
9795

98-
ticks = counter_us_to_ticks(counter_dev, timeout);
96+
ticks = counter_us_to_ticks(counter_dev, curr_timeout);
9997
ticks = CLAMP(ticks, 1, counter_get_max_top_value(counter_dev));
10098

10199
top_cfg.ticks = ticks;
@@ -181,28 +179,42 @@ static uint32_t mcux_lpc_ostick_compensate_system_timer(void)
181179

182180
void sys_clock_set_timeout(int32_t ticks, bool idle)
183181
{
184-
ARG_UNUSED(idle);
185-
186182
if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
187183
/* Only for tickless kernel system */
188184
return;
189185
}
190186

191187
#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(standby)) && CONFIG_PM
192-
if (idle) {
188+
/* We intercept calls from idle with a 0 tick count */
189+
if (idle && ticks == 0) {
193190
/* OS Timer may not be able to wakeup in certain low power modes.
194191
* For these cases, we start a counter that can wakeup
195192
* from low power modes.
196193
*/
197194
if (pm_state_next_get(0)->state == PM_STATE_STANDBY) {
198-
if (mcux_lpc_ostick_set_counter_timeout(ticks) == 0) {
195+
uint64_t timeout;
196+
197+
/* Check the amount of time left and switch to a counter
198+
* that is active in this power mode.
199+
*/
200+
timeout = base->MATCH_L;
201+
timeout |= (uint64_t)(base->MATCH_H) << 32;
202+
timeout = OSTIMER_GrayToDecimal(timeout);
203+
timeout -= OSTIMER_GetCurrentTimerValue(base);
204+
/* Round up to the next tick boundary */
205+
timeout += (CYC_PER_TICK - 1);
206+
/* Convert to microseconds and round up to the next value */
207+
timeout = (((timeout / CYC_PER_TICK) * CYC_PER_TICK) * CYC_PER_US);
208+
if (mcux_lpc_ostick_set_counter_timeout(timeout) == 0) {
199209
/* A low power counter has been started. No need to
200210
* go further, simply return
201211
*/
202212
return;
203213
}
204214
}
205215
}
216+
#else
217+
ARG_UNUSED(idle);
206218
#endif
207219

208220
ticks = ticks == K_TICKS_FOREVER ? MAX_TICKS : ticks;

soc/nxp/rw/power.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(pin1)))
1313
#include <zephyr/drivers/gpio/gpio_mcux_lpc.h>
1414
#endif
15+
#include <zephyr/drivers/timer/system_timer.h>
1516

1617
#include "fsl_power.h"
1718

@@ -197,6 +198,9 @@ __weak void pm_state_set(enum pm_state state, uint8_t substate_id)
197198
#endif /* CONFIG_MPU */
198199

199200
POWER_EnableWakeup(DT_IRQN(DT_NODELABEL(rtc)));
201+
202+
sys_clock_set_timeout(0, true);
203+
200204
if (POWER_EnterPowerMode(POWER_MODE3, &slp_cfg)) {
201205
#ifdef CONFIG_MPU
202206
/* Restore MPU as is lost after PM3 exit*/

0 commit comments

Comments
 (0)