Fix RTC synchronization after sleep, add many more tests

There were two issues with the tests

1. Incorrect print formats causing incorrect output.

2. The RTC driver was not waiting for the shadow registers to be
updated after sleeping, their reset values to be read.
This commit is contained in:
2020-04-22 09:09:31 -07:00
parent 2fa4a5e658
commit f455ce9113
20 changed files with 700 additions and 94 deletions

View File

@@ -82,8 +82,8 @@ void LptimPwm::init_lptim()
/*!< Produce a 60Hz, signal with minimal "high" time. The display
only needs 2us of "high" time on EXTCOMM, and it draws a fair
amount of power. */
LPTIM1->ARR = 0x4FF;
LPTIM1->CMP = 0x4FE;
LPTIM1->ARR = 0x27F;
LPTIM1->CMP = 0x27E;
while(!(LPTIM1->ISR & LPTIM_ISR_ARROK)) {}
while(!(LPTIM1->ISR & LPTIM_ISR_CMPOK)) {}

View File

@@ -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

View File

@@ -54,7 +54,6 @@ void UsartDriver::init()
#error "Unknown device family"
#endif
// Set TX (PA9) to output, push/pull
SET_TO(GPIOA->AFR[1], GPIO_AFRH_AFSEL9, 7u << GPIO_AFRH_AFSEL9_Pos); //AF7 (USART1_TX)
SET_TO(GPIOA->MODER, GPIO_MODER_MODE9, 2u << GPIO_MODER_MODE9_Pos); // Alternate Function

View File

@@ -96,6 +96,16 @@ public:
, m_seconds(seconds)
{}
inline bool operator ==(const WallClockTime &t2) const {
return m_hours == t2.m_hours
&& m_minutes == t2.m_minutes
&& m_seconds == t2.m_seconds;
}
inline bool operator !=(const WallClockTime &t2) const {
return !operator==(t2);
}
static inline uint8_t hour24_to_hour12(uint8_t hour24) {
if (hour24 == 0) {
return 12;
@@ -220,4 +230,5 @@ private:
uint8_t m_minutes;
uint8_t m_seconds;
};
}