Skip to content

Commit 6065e3a

Browse files
committed
[Nuvoton] Fix RTC cannot cross reset cycle
1 parent ee7efb5 commit 6065e3a

File tree

6 files changed

+101
-0
lines changed

6 files changed

+101
-0
lines changed

targets/TARGET_NUVOTON/TARGET_M451/rtc_api.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,18 @@ time_t rtc_read(void)
136136
if (! _rtc_maketime(&datetime_tm, &t_hwrtc_origin, RTC_FULL_LEAP_YEAR_SUPPORT)) {
137137
return 0;
138138
}
139+
140+
/* Load t_write from RTC spare register to cross reset cycle */
141+
RTC_WaitAccessEnable();
142+
RTC_EnableSpareAccess();
143+
RTC_WaitAccessEnable();
144+
t_write = RTC_READ_SPARE_REGISTER(0);
145+
RTC_WaitAccessEnable();
146+
while (! (RTC->SPRCTL & RTC_SPRCTL_SPRRWRDY_Msk));
139147
}
140148

141149
S_RTC_TIME_DATA_T hwrtc_datetime_2K_present;
150+
RTC_WaitAccessEnable();
142151
RTC_GetDateAndTime(&hwrtc_datetime_2K_present);
143152
/* Convert date time from H/W RTC to struct TM */
144153
rtc_convert_datetime_hwrtc_to_tm(&datetime_tm, &hwrtc_datetime_2K_present);
@@ -161,6 +170,15 @@ void rtc_write(time_t t)
161170

162171
t_write = t;
163172

173+
/* Store t_write to RTC spare register to cross reset cycle */
174+
RTC_WaitAccessEnable();
175+
RTC_EnableSpareAccess();
176+
RTC_WaitAccessEnable();
177+
RTC_WRITE_SPARE_REGISTER(0, t_write);
178+
RTC_WaitAccessEnable();
179+
while (! (RTC->SPRCTL & RTC_SPRCTL_SPRRWRDY_Msk));
180+
181+
RTC_WaitAccessEnable();
164182
RTC_SetDateAndTime((S_RTC_TIME_DATA_T *) &DATETIME_HWRTC_ORIGIN);
165183
/* NOTE: When engine is clocked by low power clock source (LXT/LIRC), we need to wait for 3 engine clocks. */
166184
wait_us((NU_US_PER_SEC / NU_RTCCLK_PER_SEC) * 3);

targets/TARGET_NUVOTON/TARGET_M480/rtc_api.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,16 @@ time_t rtc_read(void)
138138
if (! _rtc_maketime(&datetime_tm, &t_hwrtc_origin, RTC_FULL_LEAP_YEAR_SUPPORT)) {
139139
return 0;
140140
}
141+
142+
/* Load t_write from RTC spare register to cross reset cycle */
143+
RTC_WaitAccessEnable();
144+
RTC_EnableSpareAccess();
145+
RTC_WaitAccessEnable();
146+
t_write = RTC_READ_SPARE_REGISTER(0);
141147
}
142148

143149
S_RTC_TIME_DATA_T hwrtc_datetime_2K_present;
150+
RTC_WaitAccessEnable();
144151
RTC_GetDateAndTime(&hwrtc_datetime_2K_present);
145152
/* Convert date time from H/W RTC to struct TM */
146153
rtc_convert_datetime_hwrtc_to_tm(&datetime_tm, &hwrtc_datetime_2K_present);
@@ -163,6 +170,13 @@ void rtc_write(time_t t)
163170

164171
t_write = t;
165172

173+
/* Store t_write to RTC spare register to cross reset cycle */
174+
RTC_WaitAccessEnable();
175+
RTC_EnableSpareAccess();
176+
RTC_WaitAccessEnable();
177+
RTC_WRITE_SPARE_REGISTER(0, t_write);
178+
179+
RTC_WaitAccessEnable();
166180
RTC_SetDateAndTime((S_RTC_TIME_DATA_T *) &DATETIME_HWRTC_ORIGIN);
167181
/* NOTE: When engine is clocked by low power clock source (LXT/LIRC), we need to wait for 3 engine clocks. */
168182
wait_us((NU_US_PER_SEC / NU_RTCCLK_PER_SEC) * 3);

targets/TARGET_NUVOTON/TARGET_NANO100/device/StdDriver/nano100_rtc.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,13 +210,34 @@ typedef struct {
210210
*/
211211
#define RTC_DISABLE_TICK_WAKEUP() (RTC->TTR &= ~RTC_TTR_TWKE_Msk);
212212

213+
/* Declare these inline functions here to avoid MISRA C 2004 rule 8.1 error */
214+
static __INLINE void RTC_WaitAccessEnable(void);
215+
216+
/**
217+
* @brief Wait RTC Access Enable
218+
*
219+
* @param None
220+
*
221+
* @return None
222+
*
223+
* @details This function is used to enable the maximum RTC read/write accessible time.
224+
*/
225+
static __INLINE void RTC_WaitAccessEnable(void)
226+
{
227+
/* NOTE: When RTC->AER is written with RTC_WRITE_KEY frequently, we may lock in the loop here.
228+
* A workaround is to re-initialize RTC->INIR without checking RTC->INIR[ACTIVE] flag. */
229+
RTC->INIR = RTC_INIT_KEY;
230+
RTC->AER = RTC_WRITE_KEY;
231+
while(!(RTC->AER & RTC_AER_ENF_Msk)) RTC->AER = RTC_WRITE_KEY;
232+
}
213233

214234
void RTC_Open(S_RTC_TIME_DATA_T *sPt);
215235
void RTC_Close(void);
216236
void RTC_32KCalibration(int32_t i32FrequencyX100);
217237
void RTC_SetTickPeriod(uint32_t u32TickSelection);
218238
void RTC_EnableInt(uint32_t u32IntFlagMask);
219239
void RTC_DisableInt(uint32_t u32IntFlagMask);
240+
void RTC_EnableSpareAccess(void);
220241
uint32_t RTC_GetDayOfWeek(void);
221242
void RTC_DisableTamperDetection(void);
222243
void RTC_EnableTamperDetection(uint32_t u32PinCondition);

targets/TARGET_NUVOTON/TARGET_NANO100/rtc_api.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,16 @@ time_t rtc_read(void)
136136
if (! _rtc_maketime(&datetime_tm, &t_hwrtc_origin, RTC_FULL_LEAP_YEAR_SUPPORT)) {
137137
return 0;
138138
}
139+
140+
/* Load t_write from RTC spare register to cross reset cycle */
141+
RTC_WaitAccessEnable();
142+
t_write = RTC_READ_SPARE_REGISTER(0);
143+
RTC_WaitAccessEnable();
144+
while (! (RTC->SPRCTL & RTC_SPRCTL_SPRRDY_Msk));
139145
}
140146

141147
S_RTC_TIME_DATA_T hwrtc_datetime_2K_present;
148+
RTC_WaitAccessEnable();
142149
RTC_GetDateAndTime(&hwrtc_datetime_2K_present);
143150
/* Convert date time from H/W RTC to struct TM */
144151
rtc_convert_datetime_hwrtc_to_tm(&datetime_tm, &hwrtc_datetime_2K_present);
@@ -161,6 +168,13 @@ void rtc_write(time_t t)
161168

162169
t_write = t;
163170

171+
/* Store t_write to RTC spare register to cross reset cycle */
172+
RTC_WaitAccessEnable();
173+
RTC_WRITE_SPARE_REGISTER(0, t_write);
174+
RTC_WaitAccessEnable();
175+
while (! (RTC->SPRCTL & RTC_SPRCTL_SPRRDY_Msk));
176+
177+
RTC_WaitAccessEnable();
164178
RTC_SetDateAndTime((S_RTC_TIME_DATA_T *) &DATETIME_HWRTC_ORIGIN);
165179
/* NOTE: When engine is clocked by low power clock source (LXT/LIRC), we need to wait for 3 engine clocks. */
166180
wait_us((NU_US_PER_SEC / NU_RTCCLK_PER_SEC) * 3);

targets/TARGET_NUVOTON/TARGET_NUC472/device/StdDriver/nuc472_rtc.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,23 @@ typedef struct {
191191
*/
192192
#define RTC_GET_TAMPER_FLAG(u32PinNum) ( (RTC->TAMPSTS & (1 << u32PinNum)) >> u32PinNum)
193193

194+
/* Declare these inline functions here to avoid MISRA C 2004 rule 8.1 error */
195+
static __INLINE void RTC_WaitAccessEnable(void);
194196

197+
/**
198+
* @brief Wait RTC Access Enable
199+
*
200+
* @param None
201+
*
202+
* @return None
203+
*
204+
* @details This function is used to enable the maximum RTC read/write accessible time.
205+
*/
206+
static __INLINE void RTC_WaitAccessEnable(void)
207+
{
208+
RTC->RWEN = RTC_WRITE_KEY;
209+
while(!(RTC->RWEN & RTC_RWEN_RWENF_Msk));
210+
}
195211

196212
void RTC_Open(S_RTC_TIME_DATA_T *sPt);
197213
void RTC_Close(void);

targets/TARGET_NUVOTON/TARGET_NUC472/rtc_api.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,18 @@ time_t rtc_read(void)
136136
if (! _rtc_maketime(&datetime_tm, &t_hwrtc_origin, RTC_FULL_LEAP_YEAR_SUPPORT)) {
137137
return 0;
138138
}
139+
140+
/* Load t_write from RTC spare register to cross reset cycle */
141+
RTC_WaitAccessEnable();
142+
RTC_EnableSpareAccess();
143+
RTC_WaitAccessEnable();
144+
t_write = RTC_READ_SPARE_REGISTER(0);
145+
RTC_WaitAccessEnable();
146+
while (! (RTC->SPRCTL & RTC_SPRCTL_SPRRWRDY_Msk));
139147
}
140148

141149
S_RTC_TIME_DATA_T hwrtc_datetime_2K_present;
150+
RTC_WaitAccessEnable();
142151
RTC_GetDateAndTime(&hwrtc_datetime_2K_present);
143152
/* Convert date time from H/W RTC to struct TM */
144153
rtc_convert_datetime_hwrtc_to_tm(&datetime_tm, &hwrtc_datetime_2K_present);
@@ -161,6 +170,15 @@ void rtc_write(time_t t)
161170

162171
t_write = t;
163172

173+
/* Store t_write to RTC spare register to cross reset cycle */
174+
RTC_WaitAccessEnable();
175+
RTC_EnableSpareAccess();
176+
RTC_WaitAccessEnable();
177+
RTC_WRITE_SPARE_REGISTER(0, t_write);
178+
RTC_WaitAccessEnable();
179+
while (! (RTC->SPRCTL & RTC_SPRCTL_SPRRWRDY_Msk));
180+
181+
RTC_WaitAccessEnable();
164182
RTC_SetDateAndTime((S_RTC_TIME_DATA_T *) &DATETIME_HWRTC_ORIGIN);
165183
/* NOTE: When engine is clocked by low power clock source (LXT/LIRC), we need to wait for 3 engine clocks. */
166184
wait_us((NU_US_PER_SEC / NU_RTCCLK_PER_SEC) * 3);

0 commit comments

Comments
 (0)