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:
parent
50481cb0b0
commit
847e5224ec
@ -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
|
||||
*
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user