1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-07-15 11:08:08 +00:00

feat(core): add rtc wake-up callback

[no changelog]
This commit is contained in:
cepetr 2025-06-20 14:04:11 +02:00 committed by cepetr
parent 4672745a5b
commit 995caca9c7
3 changed files with 72 additions and 9 deletions

View File

@ -209,6 +209,22 @@ pm_status_t pm_get_state(pm_state_t* state) {
return PM_OK;
}
// This callback is called from inside the system_suspend() function
// when the rtc wake-up timer expires. The callback can perform
// measurements and update the fuel gauge state.
// - The callback can schedule the next wake-up by calling
// rtc_wakeup_timer_start().
// - If the callback return with wakeup_flags set, system_suspend() returns.
void pm_rtc_wakeup_callback(void* context) {
// TODO: update fuel gauge state
if (true) {
rtc_wakeup_timer_start(0, pm_rtc_wakeup_callback, NULL);
} else {
wakeup_flags_set(WAKEUP_FLAG_RTC);
}
}
pm_status_t pm_suspend(wakeup_flags_t* wakeup_reason) {
pm_driver_t* drv = &g_pm;
@ -234,13 +250,14 @@ pm_status_t pm_suspend(wakeup_flags_t* wakeup_reason) {
irq_unlock(irq_key);
#ifdef USE_RTC
// TODO: Uncomment to wake up by RTC timer
// Automatically wakes up after 10 seconds with PM_WAKEUP_FLAG_RTC set
// rtc_wakeup_timer_start(10);
// Automatically wakes up after specified time and call pm_rtc_wakeup_callback
rtc_wakeup_timer_start(10, pm_rtc_wakeup_callback, NULL);
#endif
wakeup_flags_t wakeup_flags = system_suspend();
rtc_wakeup_timer_stop();
// TODO: Handle wake-up flags
// UNUSED(wakeup_flags);

View File

@ -29,13 +29,29 @@
*/
bool rtc_init(void);
/**
* @brief Callback invoked when the RTC wakeup event occurs
*
* @param context Context pointer passed to rtc_wakeup_timer_start
*/
typedef void (*rtc_wakeup_callback_t)(void* context);
/**
* @brief Schedule a wakeup event after a specified number of seconds
*
* Configures the RTC to wake up the system from STOP mode after the specified
* number of seconds. After waking up, the PM_WAKEUP_FLAG_RTC flag is set.
* number of seconds. After waking up, callback is called if not NULL otherwise
* the WAKEUP_FLAG_RTC flag is set.
*
* @param seconds Number of seconds (1 to 65536) to wait before waking up.
* @param callback Callback function to be called when the wakeup event occurs.
* @param context Context pointer to be passed to the callback function.
* @return true if the wakeup was successfully scheduled, false otherwise
*/
bool rtc_wakeup_timer_start(uint32_t seconds);
bool rtc_wakeup_timer_start(uint32_t seconds, rtc_wakeup_callback_t callback,
void* context);
/**
* @brief Stop the RTC wakeup timer
*/
void rtc_wakeup_timer_stop(void);

View File

@ -31,6 +31,8 @@
typedef struct {
bool initialized;
RTC_HandleTypeDef hrtc;
rtc_wakeup_callback_t callback;
void* callback_context;
} rtc_driver_t;
// RTC driver instance
@ -70,7 +72,8 @@ bool rtc_init(void) {
return true;
}
bool rtc_wakeup_timer_start(uint32_t seconds) {
bool rtc_wakeup_timer_start(uint32_t seconds, rtc_wakeup_callback_t callback,
void* context) {
rtc_driver_t* drv = &g_rtc_driver;
if (!drv->initialized) {
@ -81,6 +84,11 @@ bool rtc_wakeup_timer_start(uint32_t seconds) {
return false;
}
irq_key_t irq_key = irq_lock();
drv->callback = callback;
drv->callback_context = context;
irq_unlock(irq_key);
HAL_StatusTypeDef status;
status = HAL_RTCEx_SetWakeUpTimer_IT(&drv->hrtc, seconds - 1,
@ -92,17 +100,39 @@ bool rtc_wakeup_timer_start(uint32_t seconds) {
return true;
}
void rtc_wakeup_timer_stop(void) {
rtc_driver_t* drv = &g_rtc_driver;
if (!drv->initialized) {
return;
}
HAL_RTCEx_DeactivateWakeUpTimer(&drv->hrtc);
drv->callback = NULL;
drv->callback_context = NULL;
}
void RTC_IRQHandler(void) {
rtc_driver_t* drv = &g_rtc_driver;
IRQ_LOG_ENTER();
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT);
if (READ_BIT(RTC->MISR, RTC_MISR_WUTMF) != 0U) {
// Clear the wakeup timer interrupt flag
WRITE_REG(RTC->SCR, RTC_SCR_CWUTF);
rtc_wakeup_callback_t callback = drv->callback;
void* callback_context = drv->callback_context;
// Deactivate the wakeup timer to prevent re-triggering
HAL_RTCEx_DeactivateWakeUpTimer(&g_rtc_driver.hrtc);
// Signal the wakeup event to the power manager
wakeup_flags_set(WAKEUP_FLAG_RTC);
rtc_wakeup_timer_stop();
if (callback != NULL) {
callback(callback_context);
} else {
wakeup_flags_set(WAKEUP_FLAG_RTC);
}
}
mpu_restore(mpu_mode);