mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-07-29 18:08:19 +00:00
feat(core/prodtest): add functions for setting and getting RTC datetime
[no changelog]
This commit is contained in:
parent
64c22a8e65
commit
f97ead8bb5
@ -1066,7 +1066,30 @@ rtc-timestamp
|
|||||||
OK 1886533
|
OK 1886533
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### rtc-set
|
||||||
|
Sets the current RTC date and time.
|
||||||
|
|
||||||
|
`rtc-set <year> <month> <day> <hour> <minute> <second>`
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```
|
||||||
|
rtc-set 2025 07 03 14 23 00
|
||||||
|
OK
|
||||||
|
```
|
||||||
|
|
||||||
|
### rtc-get
|
||||||
|
Reads the current RTC date and time.
|
||||||
|
|
||||||
|
Response format:
|
||||||
|
`OK <year> <month> <day> <hour> <minute> <second> <day-of-week>`, where `day-of-week` is a number from 1 (Monday) to 7 (Sunday).
|
||||||
|
|
||||||
|
Where:
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```
|
||||||
|
rtc-get
|
||||||
|
OK 2025 07 03 14 23 00 4
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,6 +38,47 @@ static void prodtest_rtc_timestamp(cli_t* cli) {
|
|||||||
cli_ok(cli, "%u", timestamp);
|
cli_ok(cli, "%u", timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void prodtest_rtc_set(cli_t* cli) {
|
||||||
|
if (cli_arg_count(cli) != 6) {
|
||||||
|
cli_error_arg_count(cli);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t year, month, day, hour, minute, second;
|
||||||
|
if (!cli_arg_uint32(cli, "year", &year) ||
|
||||||
|
!cli_arg_uint32(cli, "month", &month) ||
|
||||||
|
!cli_arg_uint32(cli, "day", &day) ||
|
||||||
|
!cli_arg_uint32(cli, "hour", &hour) ||
|
||||||
|
!cli_arg_uint32(cli, "minute", &minute) ||
|
||||||
|
!cli_arg_uint32(cli, "second", &second)) {
|
||||||
|
cli_error_arg(cli, "Invalid date/time values");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rtc_set(year, month, day, hour, minute, second)) {
|
||||||
|
cli_error(cli, CLI_ERROR, "Failed to set RTC time");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cli_ok(cli, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void prodtest_rtc_get(cli_t* cli) {
|
||||||
|
if (cli_arg_count(cli) > 0) {
|
||||||
|
cli_error_arg_count(cli);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc_datetime_t datetime;
|
||||||
|
if (!rtc_get(&datetime)) {
|
||||||
|
cli_error(cli, CLI_ERROR, "Failed to get RTC time");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cli_ok(cli, "%04u %02u %02u %02u %02u %02u %02u", datetime.year,
|
||||||
|
datetime.month, datetime.day, datetime.hour, datetime.minute,
|
||||||
|
datetime.second, datetime.weekday);
|
||||||
|
}
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
PRODTEST_CLI_CMD(
|
PRODTEST_CLI_CMD(
|
||||||
.name = "rtc-timestamp",
|
.name = "rtc-timestamp",
|
||||||
@ -46,4 +87,20 @@ PRODTEST_CLI_CMD(
|
|||||||
.args = ""
|
.args = ""
|
||||||
);
|
);
|
||||||
|
|
||||||
|
PRODTEST_CLI_CMD(
|
||||||
|
.name = "rtc-set",
|
||||||
|
.func = prodtest_rtc_set,
|
||||||
|
.info = "Set RTC date/time",
|
||||||
|
.args = "<year> <month> <day> <hour> <minute> <second>",
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
PRODTEST_CLI_CMD(
|
||||||
|
.name = "rtc-get",
|
||||||
|
.func = prodtest_rtc_get,
|
||||||
|
.info = "Get RTC date/time",
|
||||||
|
.args = "",
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -19,6 +19,18 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <trezor_types.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t year; /**< Full year (e.g., 2025) */
|
||||||
|
uint8_t month; /**< Month (1–12) */
|
||||||
|
uint8_t day; /**< Day of the month (1–31) */
|
||||||
|
uint8_t hour; /**< Hour (0–23) */
|
||||||
|
uint8_t minute; /**< Minute (0–59) */
|
||||||
|
uint8_t second; /**< Second (0–59) */
|
||||||
|
uint8_t weekday; /**< Weekday (1=Monday to 7=Sunday) */
|
||||||
|
} rtc_datetime_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialize the RTC driver
|
* @brief Initialize the RTC driver
|
||||||
*
|
*
|
||||||
@ -67,3 +79,32 @@ bool rtc_wakeup_timer_start(uint32_t seconds, rtc_wakeup_callback_t callback,
|
|||||||
* @brief Stop the RTC wakeup timer
|
* @brief Stop the RTC wakeup timer
|
||||||
*/
|
*/
|
||||||
void rtc_wakeup_timer_stop(void);
|
void rtc_wakeup_timer_stop(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the RTC using discrete time values
|
||||||
|
*
|
||||||
|
* Sets the RTC date and time using individual components: year, month, day,
|
||||||
|
* hour, minute, and second. The weekday is automatically calculated based on
|
||||||
|
* the given date.
|
||||||
|
*
|
||||||
|
* @param year Full year (e.g., 2025). Must be between 2000 and 2099.
|
||||||
|
* @param month Month (1–12).
|
||||||
|
* @param day Day of the month (1–31).
|
||||||
|
* @param hour Hour (0–23).
|
||||||
|
* @param minute Minute (0–59).
|
||||||
|
* @param second Second (0–59).
|
||||||
|
* @return true if the time was successfully set, false otherwise
|
||||||
|
*/
|
||||||
|
bool rtc_set(uint16_t year, uint8_t month, uint8_t day, uint8_t hour,
|
||||||
|
uint8_t minute, uint8_t second);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the current RTC time as a structured date and time
|
||||||
|
*
|
||||||
|
* Reads the RTC date and time registers and returns the result in a
|
||||||
|
* structured format.
|
||||||
|
*
|
||||||
|
* @param datetime Pointer to an rtc_datetime_t struct to hold the result.
|
||||||
|
* @return true if the time was successfully retrieved, false otherwise
|
||||||
|
*/
|
||||||
|
bool rtc_get(rtc_datetime_t* datetime);
|
||||||
|
@ -87,7 +87,7 @@ bool rtc_get_timestamp(uint32_t* timestamp) {
|
|||||||
|
|
||||||
// Get current time and date,
|
// Get current time and date,
|
||||||
// Important: GetTime has to be called before the GetDate in order to unlock
|
// Important: GetTime has to be called before the GetDate in order to unlock
|
||||||
// the values in higher-order callendar.
|
// the values in higher-order calendar.
|
||||||
if (HAL_OK != HAL_RTC_GetTime(&drv->hrtc, &time, RTC_FORMAT_BCD)) {
|
if (HAL_OK != HAL_RTC_GetTime(&drv->hrtc, &time, RTC_FORMAT_BCD)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -221,4 +221,82 @@ static uint32_t rtc_calendar_to_timestamp(const RTC_DateTypeDef* date,
|
|||||||
return seconds + 946684800;
|
return seconds + 946684800;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool rtc_set(uint16_t year, uint8_t month, uint8_t day, uint8_t hour,
|
||||||
|
uint8_t minute, uint8_t second) {
|
||||||
|
rtc_driver_t* drv = &g_rtc_driver;
|
||||||
|
if (!drv->initialized) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate inputs
|
||||||
|
if (year < 2000 || year > 2099 || month < 1 || month > 12 || day < 1 ||
|
||||||
|
day > 31 || hour > 23 || minute > 59 || second > 59) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Weekday calculation using Zeller's Congruence ---
|
||||||
|
// Adjust month/year for Zeller's algorithm
|
||||||
|
int y = (month <= 2) ? year - 1 : year;
|
||||||
|
int m = (month <= 2) ? month + 12 : month;
|
||||||
|
int d = day;
|
||||||
|
|
||||||
|
int K = y % 100;
|
||||||
|
int J = y / 100;
|
||||||
|
int h = (d + 13 * (m + 1) / 5 + K + K / 4 + J / 4 + 5 * J) % 7;
|
||||||
|
|
||||||
|
// Convert Zeller's output to RTC weekday (1 = Monday, ..., 7 = Sunday)
|
||||||
|
// Zeller: 0 = Saturday, 1 = Sunday, 2 = Monday, ..., 6 = Friday
|
||||||
|
uint8_t weekday = ((h + 5) % 7) + 1;
|
||||||
|
|
||||||
|
RTC_TimeTypeDef time = {.Hours = hour,
|
||||||
|
.Minutes = minute,
|
||||||
|
.Seconds = second,
|
||||||
|
.TimeFormat = RTC_HOURFORMAT_24,
|
||||||
|
.DayLightSaving = RTC_DAYLIGHTSAVING_NONE,
|
||||||
|
.StoreOperation = RTC_STOREOPERATION_RESET};
|
||||||
|
|
||||||
|
if (HAL_OK != HAL_RTC_SetTime(&drv->hrtc, &time, RTC_FORMAT_BIN)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTC_DateTypeDef date = {
|
||||||
|
.Year = year - 2000, .Month = month, .Date = day, .WeekDay = weekday};
|
||||||
|
|
||||||
|
if (HAL_OK != HAL_RTC_SetDate(&drv->hrtc, &date, RTC_FORMAT_BIN)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rtc_get(rtc_datetime_t* datetime) {
|
||||||
|
rtc_driver_t* drv = &g_rtc_driver;
|
||||||
|
|
||||||
|
if (!drv->initialized || datetime == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTC_DateTypeDef date;
|
||||||
|
RTC_TimeTypeDef time;
|
||||||
|
|
||||||
|
// Get current time before date (important for consistency)
|
||||||
|
if (HAL_OK != HAL_RTC_GetTime(&drv->hrtc, &time, RTC_FORMAT_BIN)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HAL_OK != HAL_RTC_GetDate(&drv->hrtc, &date, RTC_FORMAT_BIN)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
datetime->year = 2000 + date.Year;
|
||||||
|
datetime->month = date.Month;
|
||||||
|
datetime->day = date.Date;
|
||||||
|
datetime->hour = time.Hours;
|
||||||
|
datetime->minute = time.Minutes;
|
||||||
|
datetime->second = time.Seconds;
|
||||||
|
datetime->weekday = date.WeekDay;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // KERNEL_MODE
|
#endif // KERNEL_MODE
|
||||||
|
Loading…
Reference in New Issue
Block a user