[Nuvoton] Fix RTC cannot cross reset cycle

pull/7031/head
ccli8 2018-05-29 15:33:34 +08:00
parent ee7efb556d
commit 6065e3a943
6 changed files with 101 additions and 0 deletions

View File

@ -136,9 +136,18 @@ time_t rtc_read(void)
if (! _rtc_maketime(&datetime_tm, &t_hwrtc_origin, RTC_FULL_LEAP_YEAR_SUPPORT)) {
return 0;
}
/* Load t_write from RTC spare register to cross reset cycle */
RTC_WaitAccessEnable();
RTC_EnableSpareAccess();
RTC_WaitAccessEnable();
t_write = RTC_READ_SPARE_REGISTER(0);
RTC_WaitAccessEnable();
while (! (RTC->SPRCTL & RTC_SPRCTL_SPRRWRDY_Msk));
}
S_RTC_TIME_DATA_T hwrtc_datetime_2K_present;
RTC_WaitAccessEnable();
RTC_GetDateAndTime(&hwrtc_datetime_2K_present);
/* Convert date time from H/W RTC to struct TM */
rtc_convert_datetime_hwrtc_to_tm(&datetime_tm, &hwrtc_datetime_2K_present);
@ -161,6 +170,15 @@ void rtc_write(time_t t)
t_write = t;
/* Store t_write to RTC spare register to cross reset cycle */
RTC_WaitAccessEnable();
RTC_EnableSpareAccess();
RTC_WaitAccessEnable();
RTC_WRITE_SPARE_REGISTER(0, t_write);
RTC_WaitAccessEnable();
while (! (RTC->SPRCTL & RTC_SPRCTL_SPRRWRDY_Msk));
RTC_WaitAccessEnable();
RTC_SetDateAndTime((S_RTC_TIME_DATA_T *) &DATETIME_HWRTC_ORIGIN);
/* NOTE: When engine is clocked by low power clock source (LXT/LIRC), we need to wait for 3 engine clocks. */
wait_us((NU_US_PER_SEC / NU_RTCCLK_PER_SEC) * 3);

View File

@ -138,9 +138,16 @@ time_t rtc_read(void)
if (! _rtc_maketime(&datetime_tm, &t_hwrtc_origin, RTC_FULL_LEAP_YEAR_SUPPORT)) {
return 0;
}
/* Load t_write from RTC spare register to cross reset cycle */
RTC_WaitAccessEnable();
RTC_EnableSpareAccess();
RTC_WaitAccessEnable();
t_write = RTC_READ_SPARE_REGISTER(0);
}
S_RTC_TIME_DATA_T hwrtc_datetime_2K_present;
RTC_WaitAccessEnable();
RTC_GetDateAndTime(&hwrtc_datetime_2K_present);
/* Convert date time from H/W RTC to struct TM */
rtc_convert_datetime_hwrtc_to_tm(&datetime_tm, &hwrtc_datetime_2K_present);
@ -163,6 +170,13 @@ void rtc_write(time_t t)
t_write = t;
/* Store t_write to RTC spare register to cross reset cycle */
RTC_WaitAccessEnable();
RTC_EnableSpareAccess();
RTC_WaitAccessEnable();
RTC_WRITE_SPARE_REGISTER(0, t_write);
RTC_WaitAccessEnable();
RTC_SetDateAndTime((S_RTC_TIME_DATA_T *) &DATETIME_HWRTC_ORIGIN);
/* NOTE: When engine is clocked by low power clock source (LXT/LIRC), we need to wait for 3 engine clocks. */
wait_us((NU_US_PER_SEC / NU_RTCCLK_PER_SEC) * 3);

View File

@ -210,6 +210,26 @@ typedef struct {
*/
#define RTC_DISABLE_TICK_WAKEUP() (RTC->TTR &= ~RTC_TTR_TWKE_Msk);
/* Declare these inline functions here to avoid MISRA C 2004 rule 8.1 error */
static __INLINE void RTC_WaitAccessEnable(void);
/**
* @brief Wait RTC Access Enable
*
* @param None
*
* @return None
*
* @details This function is used to enable the maximum RTC read/write accessible time.
*/
static __INLINE void RTC_WaitAccessEnable(void)
{
/* NOTE: When RTC->AER is written with RTC_WRITE_KEY frequently, we may lock in the loop here.
* A workaround is to re-initialize RTC->INIR without checking RTC->INIR[ACTIVE] flag. */
RTC->INIR = RTC_INIT_KEY;
RTC->AER = RTC_WRITE_KEY;
while(!(RTC->AER & RTC_AER_ENF_Msk)) RTC->AER = RTC_WRITE_KEY;
}
void RTC_Open(S_RTC_TIME_DATA_T *sPt);
void RTC_Close(void);
@ -217,6 +237,7 @@ void RTC_32KCalibration(int32_t i32FrequencyX100);
void RTC_SetTickPeriod(uint32_t u32TickSelection);
void RTC_EnableInt(uint32_t u32IntFlagMask);
void RTC_DisableInt(uint32_t u32IntFlagMask);
void RTC_EnableSpareAccess(void);
uint32_t RTC_GetDayOfWeek(void);
void RTC_DisableTamperDetection(void);
void RTC_EnableTamperDetection(uint32_t u32PinCondition);

View File

@ -136,9 +136,16 @@ time_t rtc_read(void)
if (! _rtc_maketime(&datetime_tm, &t_hwrtc_origin, RTC_FULL_LEAP_YEAR_SUPPORT)) {
return 0;
}
/* Load t_write from RTC spare register to cross reset cycle */
RTC_WaitAccessEnable();
t_write = RTC_READ_SPARE_REGISTER(0);
RTC_WaitAccessEnable();
while (! (RTC->SPRCTL & RTC_SPRCTL_SPRRDY_Msk));
}
S_RTC_TIME_DATA_T hwrtc_datetime_2K_present;
RTC_WaitAccessEnable();
RTC_GetDateAndTime(&hwrtc_datetime_2K_present);
/* Convert date time from H/W RTC to struct TM */
rtc_convert_datetime_hwrtc_to_tm(&datetime_tm, &hwrtc_datetime_2K_present);
@ -161,6 +168,13 @@ void rtc_write(time_t t)
t_write = t;
/* Store t_write to RTC spare register to cross reset cycle */
RTC_WaitAccessEnable();
RTC_WRITE_SPARE_REGISTER(0, t_write);
RTC_WaitAccessEnable();
while (! (RTC->SPRCTL & RTC_SPRCTL_SPRRDY_Msk));
RTC_WaitAccessEnable();
RTC_SetDateAndTime((S_RTC_TIME_DATA_T *) &DATETIME_HWRTC_ORIGIN);
/* NOTE: When engine is clocked by low power clock source (LXT/LIRC), we need to wait for 3 engine clocks. */
wait_us((NU_US_PER_SEC / NU_RTCCLK_PER_SEC) * 3);

View File

@ -191,7 +191,23 @@ typedef struct {
*/
#define RTC_GET_TAMPER_FLAG(u32PinNum) ( (RTC->TAMPSTS & (1 << u32PinNum)) >> u32PinNum)
/* Declare these inline functions here to avoid MISRA C 2004 rule 8.1 error */
static __INLINE void RTC_WaitAccessEnable(void);
/**
* @brief Wait RTC Access Enable
*
* @param None
*
* @return None
*
* @details This function is used to enable the maximum RTC read/write accessible time.
*/
static __INLINE void RTC_WaitAccessEnable(void)
{
RTC->RWEN = RTC_WRITE_KEY;
while(!(RTC->RWEN & RTC_RWEN_RWENF_Msk));
}
void RTC_Open(S_RTC_TIME_DATA_T *sPt);
void RTC_Close(void);

View File

@ -136,9 +136,18 @@ time_t rtc_read(void)
if (! _rtc_maketime(&datetime_tm, &t_hwrtc_origin, RTC_FULL_LEAP_YEAR_SUPPORT)) {
return 0;
}
/* Load t_write from RTC spare register to cross reset cycle */
RTC_WaitAccessEnable();
RTC_EnableSpareAccess();
RTC_WaitAccessEnable();
t_write = RTC_READ_SPARE_REGISTER(0);
RTC_WaitAccessEnable();
while (! (RTC->SPRCTL & RTC_SPRCTL_SPRRWRDY_Msk));
}
S_RTC_TIME_DATA_T hwrtc_datetime_2K_present;
RTC_WaitAccessEnable();
RTC_GetDateAndTime(&hwrtc_datetime_2K_present);
/* Convert date time from H/W RTC to struct TM */
rtc_convert_datetime_hwrtc_to_tm(&datetime_tm, &hwrtc_datetime_2K_present);
@ -161,6 +170,15 @@ void rtc_write(time_t t)
t_write = t;
/* Store t_write to RTC spare register to cross reset cycle */
RTC_WaitAccessEnable();
RTC_EnableSpareAccess();
RTC_WaitAccessEnable();
RTC_WRITE_SPARE_REGISTER(0, t_write);
RTC_WaitAccessEnable();
while (! (RTC->SPRCTL & RTC_SPRCTL_SPRRWRDY_Msk));
RTC_WaitAccessEnable();
RTC_SetDateAndTime((S_RTC_TIME_DATA_T *) &DATETIME_HWRTC_ORIGIN);
/* NOTE: When engine is clocked by low power clock source (LXT/LIRC), we need to wait for 3 engine clocks. */
wait_us((NU_US_PER_SEC / NU_RTCCLK_PER_SEC) * 3);