|
|
|
|
@@ -33,6 +33,9 @@ RtcDriver::RtcSystemTimer RtcDriver::m_sys_timer;
|
|
|
|
|
|
|
|
|
|
ReturnCode RtcDriver::init()
|
|
|
|
|
{
|
|
|
|
|
m_alarm_count = 0;
|
|
|
|
|
m_wakeup_count = 0;
|
|
|
|
|
|
|
|
|
|
init_hw();
|
|
|
|
|
|
|
|
|
|
return ReturnCode::OK;
|
|
|
|
|
@@ -110,14 +113,16 @@ ReturnCode RtcDriver::init_hw()
|
|
|
|
|
#elif defined(STM32L4XX)
|
|
|
|
|
uint32_t temp = RCC->CSR;
|
|
|
|
|
|
|
|
|
|
//SET(RCC->CSR, RCC_CSR_RTCRST);
|
|
|
|
|
// Reset the backup domain (includes the RTC)
|
|
|
|
|
SET(RCC->BDCR, RCC_BDCR_BDRST);
|
|
|
|
|
CLR(RCC->BDCR, RCC_BDCR_BDRST);
|
|
|
|
|
|
|
|
|
|
SET(RCC->APB1ENR1, RCC_APB1ENR1_PWREN);
|
|
|
|
|
SET(PWR->CR1, PWR_CR1_DBP);
|
|
|
|
|
|
|
|
|
|
SET(temp, RCC_BDCR_LSEON);
|
|
|
|
|
|
|
|
|
|
while (!(RCC->BDCR & RCC_BDCR_LSERDY)) {}
|
|
|
|
|
// while (!(RCC->BDCR & RCC_BDCR_LSERDY)) {}
|
|
|
|
|
|
|
|
|
|
SET_TO(temp, RCC_BDCR_RTCSEL, RCC_BDCR_RTCSEL_0);
|
|
|
|
|
SET(temp, RCC_BDCR_RTCEN);
|
|
|
|
|
@@ -141,8 +146,8 @@ ReturnCode RtcDriver::init_hw()
|
|
|
|
|
|
|
|
|
|
/*<! Load initial date and time */
|
|
|
|
|
|
|
|
|
|
// 12-Hour format
|
|
|
|
|
SET(RTC->CR, RTC_CR_FMT);
|
|
|
|
|
// 24-Hour format
|
|
|
|
|
CLR(RTC->CR, RTC_CR_FMT);
|
|
|
|
|
|
|
|
|
|
uint32_t time = 0;
|
|
|
|
|
SET(time, RTC_TR_PM);
|
|
|
|
|
@@ -163,7 +168,7 @@ ReturnCode RtcDriver::init_hw()
|
|
|
|
|
// Enable Wakeup irq, we may/will use them later
|
|
|
|
|
SET(RTC->CR, RTC_CR_WUTIE);
|
|
|
|
|
NVIC_EnableIRQ(RTC_IRQn);
|
|
|
|
|
NVIC_SetPriority(RTC_IRQn, 0);
|
|
|
|
|
NVIC_SetPriority(RTC_IRQn, 1);
|
|
|
|
|
#elif defined(STM32L4XX)
|
|
|
|
|
CLR(RTC->ICSR, RTC_ICSR_INIT);
|
|
|
|
|
|
|
|
|
|
@@ -173,15 +178,22 @@ ReturnCode RtcDriver::init_hw()
|
|
|
|
|
// Enable Wakeup irq, we may/will use them later
|
|
|
|
|
SET(RTC->CR, RTC_CR_WUTIE);
|
|
|
|
|
NVIC_EnableIRQ(RTC_WKUP_IRQn);
|
|
|
|
|
NVIC_SetPriority(RTC_WKUP_IRQn, 1);
|
|
|
|
|
NVIC_SetPriority(RTC_WKUP_IRQn, 0);
|
|
|
|
|
#else
|
|
|
|
|
#error "Unsupported device type"
|
|
|
|
|
#endif
|
|
|
|
|
enable_periodic_alarm();
|
|
|
|
|
|
|
|
|
|
disable_rtc_write();
|
|
|
|
|
// Disable the wakeup timer. This can be leftover from an old firmware/reset
|
|
|
|
|
|
|
|
|
|
//SET(EXTI->SWIER1, EXTI_SWIER1_SWI18);
|
|
|
|
|
// Clear the interrupt in the RTC
|
|
|
|
|
SET(RTC->SCR, RTC_SCR_CWUTF);
|
|
|
|
|
// Disable the Wakeup timer (its periodic, but we use it as a
|
|
|
|
|
// one-shot timer
|
|
|
|
|
CLR(RTC->CR, RTC_CR_WUTE);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
disable_rtc_write();
|
|
|
|
|
|
|
|
|
|
return ReturnCode::OK;
|
|
|
|
|
}
|
|
|
|
|
@@ -206,10 +218,6 @@ ReturnCode RtcDriver::get_time(BSP::WallClockTime &wall_time)
|
|
|
|
|
seconds += 10 * STM32_GET_FIELD(time, RTC_TR_ST);
|
|
|
|
|
seconds += STM32_GET_FIELD(time, RTC_TR_SU);
|
|
|
|
|
|
|
|
|
|
if (STM32_GET_FIELD(time, RTC_TR_PM)) {
|
|
|
|
|
hours += 12;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
new (&wall_time) BSP::WallClockTime(hours, minutes, seconds);
|
|
|
|
|
|
|
|
|
|
return ReturnCode::OK;
|
|
|
|
|
@@ -231,14 +239,9 @@ ReturnCode RtcDriver::set_time(const BSP::WallClockTime &wall_time)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*<! Load initial date and time */
|
|
|
|
|
|
|
|
|
|
// 12-Hour format
|
|
|
|
|
SET(RTC->CR, RTC_CR_FMT);
|
|
|
|
|
|
|
|
|
|
uint32_t time = 0;
|
|
|
|
|
SET_TO(time, RTC_TR_PM, wall_time.get_is_pm() << RTC_TR_PM_Pos);
|
|
|
|
|
SET_TO(time, RTC_TR_HT, wall_time.get_hours_12_tens() << RTC_TR_HT_Pos);
|
|
|
|
|
SET_TO(time, RTC_TR_HU, wall_time.get_hours_12_ones() << RTC_TR_HU_Pos);
|
|
|
|
|
SET_TO(time, RTC_TR_HT, wall_time.get_hours_24_tens() << RTC_TR_HT_Pos);
|
|
|
|
|
SET_TO(time, RTC_TR_HU, wall_time.get_hours_24_ones() << RTC_TR_HU_Pos);
|
|
|
|
|
SET_TO(time, RTC_TR_MNT, wall_time.get_minutes_tens() << RTC_TR_MNT_Pos);
|
|
|
|
|
SET_TO(time, RTC_TR_MNU, wall_time.get_minutes_ones() << RTC_TR_MNU_Pos);
|
|
|
|
|
SET_TO(time, RTC_TR_ST, wall_time.get_seconds_tens() << RTC_TR_ST_Pos);
|
|
|
|
|
@@ -247,11 +250,11 @@ ReturnCode RtcDriver::set_time(const BSP::WallClockTime &wall_time)
|
|
|
|
|
|
|
|
|
|
#if defined(STM32L0XX)
|
|
|
|
|
CLR(RTC->ISR, RTC_ISR_INIT);
|
|
|
|
|
while (!(RTC->ISR & RTC_ISR_INITF)) {}
|
|
|
|
|
while (!(RTC->ISR & RTC_ISR_INITF)) {} // FIXME: this is probably inverted
|
|
|
|
|
while (!(RTC->ISR & RTC_ISR_RSF)) {}
|
|
|
|
|
#elif defined(STM32L4XX)
|
|
|
|
|
CLR(RTC->ICSR, RTC_ICSR_INIT);
|
|
|
|
|
while (!(RTC->ICSR & RTC_ICSR_INITF)) {}
|
|
|
|
|
while ((RTC->ICSR & RTC_ICSR_INITF)) {}
|
|
|
|
|
while (!(RTC->ICSR & RTC_ICSR_RSF)) {}
|
|
|
|
|
#else
|
|
|
|
|
#error "Unsupported device type"
|
|
|
|
|
@@ -310,6 +313,7 @@ ReturnCode RtcDriver::set_wakeup_in(BSP::time_t wakeup_delay)
|
|
|
|
|
SET_TO(RTC->WUTR, RTC_WUTR_WUT, delay_cycles - 1);
|
|
|
|
|
SET_TO(RTC->CR, RTC_CR_WUCKSEL, wucksel << RTC_CR_WUCKSEL_Pos);
|
|
|
|
|
|
|
|
|
|
SET(RTC->SCR, RTC_SCR_CWUTF);
|
|
|
|
|
SET(RTC->CR, RTC_CR_WUTE);
|
|
|
|
|
|
|
|
|
|
disable_rtc_write();
|
|
|
|
|
@@ -322,7 +326,10 @@ BSP::time_t RtcDriver::RtcSystemTimer::get_time()
|
|
|
|
|
uint32_t new_secs, old_secs, ssr;
|
|
|
|
|
uint64_t new_timer_ticks, new_millis;
|
|
|
|
|
|
|
|
|
|
while (!(RTC->ICSR & RTC_ICSR_WUTWF)) {}
|
|
|
|
|
enable_rtc_write();
|
|
|
|
|
RTC->ICSR = ~(RTC_ICSR_INIT | RTC_ICSR_RSF);
|
|
|
|
|
disable_rtc_write();
|
|
|
|
|
while (!(RTC->ICSR & RTC_ICSR_RSF)) {}
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
__disable_irq();
|
|
|
|
|
@@ -395,9 +402,9 @@ extern "C" void RTC_IRQHandler()
|
|
|
|
|
|
|
|
|
|
static void irq_handler() {
|
|
|
|
|
|
|
|
|
|
SET(EXTI->PR1, EXTI_PR1_PIF20);
|
|
|
|
|
if (RTC->SR & RTC_ICSR_WUTWF) {
|
|
|
|
|
SET(EXTI->PR1, EXTI_PR1_PIF20);
|
|
|
|
|
|
|
|
|
|
if (RTC->SR & RTC_SR_WUTF) {
|
|
|
|
|
RtcDriver::increment_wakeup_count();
|
|
|
|
|
// Clear the interrupt in the RTC
|
|
|
|
|
SET(RTC->SCR, RTC_SCR_CWUTF);
|
|
|
|
|
@@ -423,6 +430,7 @@ extern "C" void RTC_ALARM_IRQHandler()
|
|
|
|
|
{
|
|
|
|
|
irq_handler();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
#error "Unsupported device type"
|
|
|
|
|
#endif
|
|
|
|
|
|