1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-07-24 07:28:34 +00:00

feat(core): add rtc_get_timestamp function to RTC module.

[no changelog]
This commit is contained in:
kopecdav 2025-06-27 12:22:25 +02:00 committed by kopecdav
parent 50481cb0b0
commit 847e5224ec
2 changed files with 94 additions and 0 deletions

View File

@ -29,6 +29,18 @@
*/
bool rtc_init(void);
/**
* @brief Get the current timestamp from the RTC
*
* Retrieves the current timestamp as a number of seconds since the device got
* powered up for the first time. The timestamp is calculated based on the
* current date and time stored in the RTC.
*
* @param timestamp Pointer to a variable where the timestamp will be stored.
* @return true if the timestamp was successfully retrieved, false otherwise
*/
bool rtc_get_timestamp(uint32_t* timestamp);
/**
* @brief Callback invoked when the RTC wakeup event occurs
*

View File

@ -40,6 +40,9 @@ static rtc_driver_t g_rtc_driver = {
.initialized = false,
};
static uint32_t rtc_calendar_to_timestamp(const RTC_DateTypeDef* date,
const RTC_TimeTypeDef* time);
bool rtc_init(void) {
rtc_driver_t* drv = &g_rtc_driver;
@ -72,6 +75,33 @@ bool rtc_init(void) {
return true;
}
bool rtc_get_timestamp(uint32_t* timestamp) {
rtc_driver_t* drv = &g_rtc_driver;
if (!drv->initialized || timestamp == NULL) {
return false;
}
RTC_DateTypeDef date;
RTC_TimeTypeDef time;
// Get current time and date,
// Important: GetTime has to be called before the GetDate in order to unlock
// the values in higher-order callendar.
if (HAL_OK != HAL_RTC_GetTime(&drv->hrtc, &time, RTC_FORMAT_BCD)) {
return false;
}
// Get the current date
if (HAL_OK != HAL_RTC_GetDate(&drv->hrtc, &date, RTC_FORMAT_BCD)) {
return false;
}
*timestamp = rtc_calendar_to_timestamp(&date, &time);
return true;
}
bool rtc_wakeup_timer_start(uint32_t seconds, rtc_wakeup_callback_t callback,
void* context) {
rtc_driver_t* drv = &g_rtc_driver;
@ -139,4 +169,56 @@ void RTC_IRQHandler(void) {
IRQ_LOG_EXIT();
}
static const uint8_t days_in_month[] = {
31, // January
28, // February (not considering leap years here)
31, // March
30, // April
31, // May
30, // June
31, // July
31, // August
30, // September
31, // October
30, // November
31 // December
};
static uint8_t bcd2bin(uint8_t val) { return (val & 0x0F) + ((val >> 4) * 10); }
// Check for leap year
static int is_leap_year(int year) {
return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0));
}
static uint32_t rtc_calendar_to_timestamp(const RTC_DateTypeDef* date,
const RTC_TimeTypeDef* time) {
uint8_t year = bcd2bin(date->Year); // 0..99
uint8_t month = bcd2bin(date->Month); // 1..12
uint8_t day = bcd2bin(date->Date); // 1..31
uint8_t hour = bcd2bin(time->Hours);
uint8_t min = bcd2bin(time->Minutes);
uint8_t sec = bcd2bin(time->Seconds);
// STM RTC starts at 2000, so we need to offset the year evey time we
// calculate the leap years.
uint32_t days = 0;
for (int y = 0; y < year; ++y) {
days += 365;
if (is_leap_year(y + 2000)) days += 1;
}
for (int m = 1; m < month; ++m) {
days += days_in_month[m - 1];
if (m == 2 && is_leap_year(year + 2000)) days += 1;
}
days += day - 1;
uint32_t seconds = days * 86400 + hour * 3600 + min * 60 + sec;
// Unix epoch starts at 1970, STM32 RTC at 2000
// 946684800 = seconds from 1970-01-01 to 2000-01-01
return seconds + 946684800;
}
#endif // KERNEL_MODE