diff --git a/kernel/timeout.c b/kernel/timeout.c index 1c5ad0ff5b810..4653c1f0368bd 100644 --- a/kernel/timeout.c +++ b/kernel/timeout.c @@ -336,6 +336,7 @@ void z_vrfy_sys_clock_tick_set(uint64_t tick) #ifdef CONFIG_SOC_FAMILY_REALTEK_BEE /* To support RTK PM */ extern void sys_clock_only_add_cycle_count(int32_t ticks); +extern void CPU_DLPS_Exit(void); struct _timeout *get_first_timeout(void) { return first(); @@ -366,6 +367,7 @@ void sys_clock_restore_tick_and_cycle(void) void sys_clock_announce_process_timeout(void) { + /* Update the timeout list: only handle pended ticks. */ k_spinlock_key_t key = k_spin_lock(&timeout_lock); struct _timeout *t; @@ -383,11 +385,24 @@ void sys_clock_announce_process_timeout(void) pended_ticks = 0; - /* Separate the handling of pending tick counts and timeout - * callback functions to avoid errors when a timer is started + k_spin_unlock(&timeout_lock, key); + + /* Resume NVIC to trigger interrupts that occurred during DLPS. + * ISR might update the timout list, so ensure this is done after updating + * the timeout list. + */ + __disable_irq(); + CPU_DLPS_Exit(); + __enable_irq(); + + /* Manually trigger processing of the timeout callback. + * Separating updating pended ticks and timeout + * callback processing to avoid errors if timer behaivor happens * during the timer callback. */ + key = k_spin_lock(&timeout_lock); + for (t = first(); (t != NULL) && (t->dticks == 0); t = first()) { remove_timeout(t); diff --git a/soc/realtek/bee/rtl87x2g/power.c b/soc/realtek/bee/rtl87x2g/power.c index d1889af738d3e..e01eca4bc9a28 100644 --- a/soc/realtek/bee/rtl87x2g/power.c +++ b/soc/realtek/bee/rtl87x2g/power.c @@ -161,8 +161,6 @@ void pm_resume_devices_rtk(void) PM_DEVICE_ACTION_RESUME); } - CPU_DLPS_Exit(); - num_susp_rtk = 0; } @@ -183,7 +181,8 @@ void pm_reusme_systick_and_process_timeout(void) sys_clock_restore_tick_and_cycle(); __enable_irq(); - /* Subtract the pended tick from the timeout list and manually trigger a timeout process. */ + /* Subtract the pended tick from the timeout list, resume NVIC and manually trigger the + * timeout callback process. */ sys_clock_announce_process_timeout(); } diff --git a/tests/boards/rtl87x2g_evb/pm/timeout_wakeup/src/main.c b/tests/boards/rtl87x2g_evb/pm/timeout_wakeup/src/main.c index 86f6242691572..0dd52fc74841e 100644 --- a/tests/boards/rtl87x2g_evb/pm/timeout_wakeup/src/main.c +++ b/tests/boards/rtl87x2g_evb/pm/timeout_wakeup/src/main.c @@ -98,7 +98,7 @@ ZTEST(timeout_wakeup, test_k_thread_wakeup) uint32_t wakeup_count_thread; power_get_statistics(&wakeup_count_before_test, &last_wakeup_clk, &last_sleep_clk); - while (test_thread_sleep_num <= THREAD_SLEEP_NUMBERS) { + while (test_thread_sleep_num < THREAD_SLEEP_NUMBERS) { k_msleep(100); test_thread_sleep_num++; }