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:
parent
4672745a5b
commit
995caca9c7
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,18 +100,40 @@ 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
|
||||
rtc_wakeup_timer_stop();
|
||||
|
||||
if (callback != NULL) {
|
||||
callback(callback_context);
|
||||
} else {
|
||||
wakeup_flags_set(WAKEUP_FLAG_RTC);
|
||||
}
|
||||
}
|
||||
|
||||
mpu_restore(mpu_mode);
|
||||
IRQ_LOG_EXIT();
|
||||
|
Loading…
Reference in New Issue
Block a user