STM: monotonic time even when RTC is changed
This commit is contained in:
parent
c75a768b59
commit
0b2f857542
@ -47,6 +47,11 @@ volatile uint32_t cached_date = 0;
|
||||
volatile uint32_t seconds_to_minute = 0;
|
||||
volatile uint32_t cached_hours_minutes = 0;
|
||||
|
||||
// The RTC starts at 2000-01-01 when it comes up.
|
||||
// If the RTC is set to a later time, the ticks the RTC returns will be offset by the new time.
|
||||
// Remember that offset so it can be removed when returning a monotonic tick count.
|
||||
static int64_t rtc_ticks_offset;
|
||||
|
||||
volatile bool alarmed_already[2];
|
||||
|
||||
bool peripherals_wkup_on = false;
|
||||
@ -59,6 +64,8 @@ uint32_t stm32_peripherals_get_rtc_freq(void) {
|
||||
}
|
||||
|
||||
void stm32_peripherals_rtc_init(void) {
|
||||
rtc_ticks_offset = 0;
|
||||
|
||||
// RTC oscillator selection is handled in peripherals/<family>/<line>/clocks.c
|
||||
__HAL_RCC_RTC_ENABLE();
|
||||
hrtc.Instance = RTC;
|
||||
@ -74,49 +81,9 @@ void stm32_peripherals_rtc_init(void) {
|
||||
HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
|
||||
}
|
||||
|
||||
#if CIRCUITPY_RTC
|
||||
void stm32_peripherals_rtc_get_time(timeutils_struct_time_t *tm) {
|
||||
RTC_DateTypeDef date = {0};
|
||||
RTC_TimeTypeDef time = {0};
|
||||
|
||||
int code;
|
||||
if ((code = HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN)) == HAL_OK &&
|
||||
(code = HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN)) == HAL_OK) {
|
||||
tm->tm_hour = time.Hours;
|
||||
tm->tm_min = time.Minutes;
|
||||
tm->tm_sec = time.Seconds;
|
||||
tm->tm_wday = date.WeekDay - 1;
|
||||
tm->tm_mday = date.Date;
|
||||
tm->tm_mon = date.Month;
|
||||
tm->tm_year = date.Year + 2000;
|
||||
tm->tm_yday = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void stm32_peripherals_rtc_set_time(timeutils_struct_time_t *tm) {
|
||||
RTC_DateTypeDef date = {0};
|
||||
RTC_TimeTypeDef time = {0};
|
||||
|
||||
time.Hours = tm->tm_hour;
|
||||
time.Minutes = tm->tm_min;
|
||||
time.Seconds = tm->tm_sec;
|
||||
date.WeekDay = tm->tm_wday + 1;
|
||||
date.Date = tm->tm_mday;
|
||||
date.Month = tm->tm_mon;
|
||||
date.Year = tm->tm_year - 2000;
|
||||
time.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
|
||||
time.StoreOperation = RTC_STOREOPERATION_RESET;
|
||||
|
||||
if (HAL_RTC_SetTime(&hrtc, &time, RTC_FORMAT_BIN) != HAL_OK ||
|
||||
HAL_RTC_SetDate(&hrtc, &date, RTC_FORMAT_BIN) != HAL_OK) {
|
||||
// todo - throw an exception
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// This function is called often for timing so we cache the seconds elapsed computation based on the
|
||||
// register value. The STM HAL always does shifts and conversion if we use it directly.
|
||||
uint64_t stm32_peripherals_rtc_raw_ticks(uint8_t *subticks) {
|
||||
STATIC uint64_t stm32_peripherals_rtc_raw_ticks(uint8_t *subticks) {
|
||||
// Disable IRQs to ensure we read all of the RTC registers as close in time as possible. Read
|
||||
// SSR twice to make sure we didn't read across a tick.
|
||||
__disable_irq();
|
||||
@ -164,6 +131,57 @@ uint64_t stm32_peripherals_rtc_raw_ticks(uint8_t *subticks) {
|
||||
return raw_ticks;
|
||||
}
|
||||
|
||||
// This function returns monotonically increasing ticks by adjusting away the RTC tick offset
|
||||
// from the last time the date was set.
|
||||
uint64_t stm32_peripherals_rtc_monotonic_ticks(uint8_t *subticks) {
|
||||
return stm32_peripherals_rtc_raw_ticks(subticks) - rtc_ticks_offset;
|
||||
}
|
||||
|
||||
#if CIRCUITPY_RTC
|
||||
void stm32_peripherals_rtc_get_time(timeutils_struct_time_t *tm) {
|
||||
RTC_DateTypeDef date = {0};
|
||||
RTC_TimeTypeDef time = {0};
|
||||
|
||||
int code;
|
||||
if ((code = HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN)) == HAL_OK &&
|
||||
(code = HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN)) == HAL_OK) {
|
||||
tm->tm_hour = time.Hours;
|
||||
tm->tm_min = time.Minutes;
|
||||
tm->tm_sec = time.Seconds;
|
||||
tm->tm_wday = date.WeekDay - 1;
|
||||
tm->tm_mday = date.Date;
|
||||
tm->tm_mon = date.Month;
|
||||
tm->tm_year = date.Year + 2000;
|
||||
tm->tm_yday = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void stm32_peripherals_rtc_set_time(timeutils_struct_time_t *tm) {
|
||||
RTC_DateTypeDef date = {0};
|
||||
RTC_TimeTypeDef time = {0};
|
||||
|
||||
uint64_t current_monotonic_ticks = stm32_peripherals_rtc_monotonic_ticks(NULL);
|
||||
|
||||
time.Hours = tm->tm_hour;
|
||||
time.Minutes = tm->tm_min;
|
||||
time.Seconds = tm->tm_sec;
|
||||
date.WeekDay = tm->tm_wday + 1;
|
||||
date.Date = tm->tm_mday;
|
||||
date.Month = tm->tm_mon;
|
||||
date.Year = tm->tm_year - 2000;
|
||||
time.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
|
||||
time.StoreOperation = RTC_STOREOPERATION_RESET;
|
||||
|
||||
if (HAL_RTC_SetTime(&hrtc, &time, RTC_FORMAT_BIN) != HAL_OK ||
|
||||
HAL_RTC_SetDate(&hrtc, &date, RTC_FORMAT_BIN) != HAL_OK) {
|
||||
// todo - throw an exception
|
||||
}
|
||||
|
||||
rtc_ticks_offset = stm32_peripherals_rtc_raw_ticks(NULL) - current_monotonic_ticks;
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
void stm32_peripherals_rtc_assign_wkup_callback(void (*callback)(void)) {
|
||||
wkup_callback = callback;
|
||||
}
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
uint32_t stm32_peripherals_get_rtc_freq(void);
|
||||
void stm32_peripherals_rtc_init(void);
|
||||
uint64_t stm32_peripherals_rtc_raw_ticks(uint8_t *subticks);
|
||||
uint64_t stm32_peripherals_rtc_monotonic_ticks(uint8_t *subticks);
|
||||
|
||||
void stm32_peripherals_rtc_assign_wkup_callback(void (*callback)(void));
|
||||
void stm32_peripherals_rtc_set_wakeup_mode_seconds(uint32_t seconds);
|
||||
|
@ -385,7 +385,7 @@ __attribute__((used)) void HardFault_Handler(void) {
|
||||
}
|
||||
|
||||
uint64_t port_get_raw_ticks(uint8_t *subticks) {
|
||||
return stm32_peripherals_rtc_raw_ticks(subticks);
|
||||
return stm32_peripherals_rtc_monotonic_ticks(subticks);
|
||||
}
|
||||
|
||||
// Enable 1/1024 second tick.
|
||||
|
Loading…
x
Reference in New Issue
Block a user