Skip to content

Nuvoton: Adhere to reworked RTC spec to release with Mbed OS 5.9 #7031

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 31, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion targets/TARGET_NUVOTON/TARGET_M451/rtc_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ void rtc_init(void)

void rtc_free(void)
{
// N/A
CLK_DisableModuleClock(rtc_modinit.clkidx);
}

int rtc_isenabled(void)
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down
17 changes: 16 additions & 1 deletion targets/TARGET_NUVOTON/TARGET_M480/rtc_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ void rtc_init(void)

void rtc_free(void)
{
// N/A
CLK_DisableModuleClock(rtc_modinit.clkidx);
}

int rtc_isenabled(void)
Expand All @@ -114,6 +114,7 @@ int rtc_isenabled(void)
// NOTE: Check RTC Init Active flag to support crossing reset cycle.
return !! (RTC->INIT & RTC_INIT_ACTIVE_Msk);
}

time_t rtc_read(void)
{
/* NOTE: After boot, RTC time registers are not synced immediately, about 1 sec latency.
Expand All @@ -137,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);
Expand All @@ -162,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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,13 +210,34 @@ 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);
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);
Expand Down
16 changes: 15 additions & 1 deletion targets/TARGET_NUVOTON/TARGET_NANO100/rtc_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ void rtc_init(void)

void rtc_free(void)
{
// N/A
CLK_DisableModuleClock(rtc_modinit.clkidx);
}

int rtc_isenabled(void)
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down
16 changes: 16 additions & 0 deletions targets/TARGET_NUVOTON/TARGET_NUC472/device/StdDriver/nuc472_rtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
20 changes: 19 additions & 1 deletion targets/TARGET_NUVOTON/TARGET_NUC472/rtc_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ void rtc_init(void)

void rtc_free(void)
{
// N/A
CLK_DisableModuleClock(rtc_modinit.clkidx);
}

int rtc_isenabled(void)
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down
8 changes: 4 additions & 4 deletions targets/targets.json
Original file line number Diff line number Diff line change
Expand Up @@ -3796,7 +3796,7 @@
},
"inherits": ["Target"],
"macros_add": ["MBEDTLS_CONFIG_HW_SUPPORT"],
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "TRNG", "CAN", "FLASH", "EMAC"],
"device_has": ["RTC", "ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "TRNG", "CAN", "FLASH", "EMAC"],
"features": ["LWIP"],
"release_versions": ["5"],
"device_name": "NUC472HI8AE",
Expand Down Expand Up @@ -3868,7 +3868,7 @@
},
"inherits": ["Target"],
"progen": {"target": "numaker-pfm-m453"},
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "CAN", "FLASH"],
"device_has": ["RTC", "ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "CAN", "FLASH"],
"release_versions": ["2", "5"],
"device_name": "M453VG6AE",
"bootloader_supported": true
Expand Down Expand Up @@ -3899,7 +3899,7 @@
},
"inherits": ["Target"],
"macros": ["CMSIS_VECTAB_VIRTUAL", "CMSIS_VECTAB_VIRTUAL_HEADER_FILE=\"cmsis_nvic.h\"","MBED_FAULT_HANDLER_DISABLED"],
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH"],
"device_has": ["RTC", "ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH"],
"release_versions": ["5"],
"device_name": "NANO130KE3BN"
},
Expand Down Expand Up @@ -4067,7 +4067,7 @@
},
"inherits": ["Target"],
"macros_add": ["MBEDTLS_CONFIG_HW_SUPPORT"],
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "TRNG", "FLASH", "CAN", "EMAC"],
"device_has": ["RTC", "ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "TRNG", "FLASH", "CAN", "EMAC"],
"features": ["LWIP"],
"release_versions": ["5"],
"device_name": "M487JIDAE",
Expand Down