RTC: add interface for check if RTC time has been set

New interface allows checking if RTC time has been set.  This allows to application to detect if RTC has valid time (after
reset) or should application attempt to get real time by other means (for example, by launching ntpclient or GPS).
This commit is contained in:
Jussi Kivilinna 2017-04-06 09:53:11 -06:00 committed by Gregory Nutt
parent ac8ddf4eb1
commit e3b3e57e56
16 changed files with 220 additions and 36 deletions

View File

@ -121,6 +121,7 @@ static const struct rtc_ops_s g_rtc_ops =
{
.rdtime = kinetis_rdtime,
.settime = kinetis_settime,
.havesettime = NULL,
#ifdef CONFIG_RTC_ALARM
.setalarm = kinetis_setalarm,
.setrelative = kinetis_setrelative,

View File

@ -6334,10 +6334,15 @@ config RTC_MAGIC_REG
depends on RTC && !STM32_HAVE_RTC_COUNTER
config RTC_MAGIC
hex "Value used as Magic to determine if RTC is set already"
hex "Value used as Magic to determine if RTC is already setup"
default 0xfacefeee
depends on RTC && !STM32_HAVE_RTC_COUNTER
config RTC_MAGIC_TIME_SET
hex "Value used as Magic to determine if RTC is setup and have time set"
default 0xfacefeef
depends on RTC && !STM32_HAVE_RTC_COUNTER
choice
prompt "RTC clock source"
default RTC_LSECLOCK

View File

@ -131,7 +131,7 @@ static inline void rcc_resetbkp(void)
stm32_pwr_initbkp(false);
regval = getreg32(RTC_MAGIC_REG);
if (regval != RTC_MAGIC)
if (regval != RTC_MAGIC && regval != RTC_MAGIC_TIME_SET)
{
stm32_pwr_enablebkp(true);

View File

@ -83,11 +83,16 @@
# define CONFIG_RTC_MAGIC (0xfacefeee)
#endif
#if !defined(CONFIG_RTC_MAGIC_TIME_SET)
# define CONFIG_RTC_MAGIC_TIME_SET (CONFIG_RTC_MAGIC + 1)
#endif
#if !defined(CONFIG_RTC_MAGIC_REG)
# define CONFIG_RTC_MAGIC_REG (0)
#endif
#define RTC_MAGIC CONFIG_RTC_MAGIC
#define RTC_MAGIC_TIME_SET CONFIG_RTC_MAGIC_TIME_SET
#define RTC_MAGIC_REG STM32_RTC_BKR(CONFIG_RTC_MAGIC_REG)
/****************************************************************************

View File

@ -49,6 +49,8 @@
#include <nuttx/arch.h>
#include <nuttx/timers/rtc.h>
#include "up_arch.h"
#include "chip.h"
#include "stm32_rtc.h"
@ -111,6 +113,7 @@ static int stm32_rdtime(FAR struct rtc_lowerhalf_s *lower,
FAR struct rtc_time *rtctime);
static int stm32_settime(FAR struct rtc_lowerhalf_s *lower,
FAR const struct rtc_time *rtctime);
static bool stm32_havesettime(FAR struct rtc_lowerhalf_s *lower);
#ifdef CONFIG_RTC_ALARM
static int stm32_setalarm(FAR struct rtc_lowerhalf_s *lower,
@ -130,6 +133,7 @@ static const struct rtc_ops_s g_rtc_ops =
{
.rdtime = stm32_rdtime,
.settime = stm32_settime,
.havesettime = stm32_havesettime,
#ifdef CONFIG_RTC_ALARM
.setalarm = stm32_setalarm,
.setrelative = stm32_setrelative,
@ -345,6 +349,25 @@ static int stm32_settime(FAR struct rtc_lowerhalf_s *lower,
#endif
}
/****************************************************************************
* Name: stm32_havesettime
*
* Description:
* Implements the havesettime() method of the RTC driver interface
*
* Input Parameters:
* lower - A reference to RTC lower half driver state structure
*
* Returned Value:
* Returns true if RTC date-time have been previously set.
*
****************************************************************************/
static bool stm32_havesettime(FAR struct rtc_lowerhalf_s *lower)
{
return getreg32(RTC_MAGIC_REG) == RTC_MAGIC_TIME_SET;
}
/****************************************************************************
* Name: stm32_setalarm
*

View File

@ -600,7 +600,7 @@ int up_rtc_initialize(void)
stm32_pwr_enablebkp(true);
if (regval != RTC_MAGIC)
if (regval != RTC_MAGIC && regval != RTC_MAGIC_TIME_SET)
{
/* Some boards do not have the external 32khz oscillator installed, for those
* boards we must fallback to the crummy internal RC clock or the external high
@ -712,7 +712,7 @@ int up_rtc_initialize(void)
* has been writing to to back-up date register DR0.
*/
if (regval != RTC_MAGIC)
if (regval != RTC_MAGIC && regval != RTC_MAGIC_TIME_SET)
{
rtcinfo("Do setup\n");
@ -1004,6 +1004,15 @@ int stm32_rtc_setdatetime(FAR const struct tm *tp)
ret = rtc_synchwait();
}
/* Remember that the RTC is initialized and had its time set. */
if (getreg32(RTC_MAGIC_REG) != RTC_MAGIC_TIME_SET)
{
stm32_pwr_enablebkp(true);
putreg32(RTC_MAGIC_TIME_SET, RTC_MAGIC_REG);
stm32_pwr_enablebkp(false);
}
/* Re-enable the write protection for RTC registers */
rtc_wprlock();

View File

@ -894,7 +894,7 @@ int up_rtc_initialize(void)
stm32_pwr_enablebkp(true);
if (regval != RTC_MAGIC)
if (regval != RTC_MAGIC && regval != RTC_MAGIC_TIME_SET)
{
/* Some boards do not have the external 32khz oscillator installed,
* for those boards we must fallback to the crummy internal RC clock
@ -1011,7 +1011,7 @@ int up_rtc_initialize(void)
* has been writing to to back-up date register DR0.
*/
if (regval != RTC_MAGIC)
if (regval != RTC_MAGIC && regval != RTC_MAGIC_TIME_SET)
{
rtcinfo("Do setup\n");
@ -1287,6 +1287,15 @@ int stm32_rtc_setdatetime(FAR const struct tm *tp)
ret = rtc_synchwait();
}
/* Remember that the RTC is initialized and had its time set. */
if (getreg32(RTC_MAGIC_REG) != RTC_MAGIC_TIME_SET)
{
stm32_pwr_enablebkp(true);
putreg32(RTC_MAGIC_TIME_SET, RTC_MAGIC_REG);
stm32_pwr_enablebkp(false);
}
/* Re-enable the write protection for RTC registers */
rtc_wprlock();
@ -1362,7 +1371,7 @@ int stm32_rtc_setalarm(FAR struct alm_setalarm_s *alminfo)
(rtc_bin2bcd(alminfo->as_time.tm_min) << RTC_ALRMR_MNU_SHIFT) |
(rtc_bin2bcd(alminfo->as_time.tm_hour) << RTC_ALRMR_HU_SHIFT) |
(rtc_bin2bcd(alminfo->as_time.tm_mday) << RTC_ALRMR_DU_SHIFT);
/* Set the alarm in hardware and enable interrupts from the RTC */
switch (alminfo->as_id)

View File

@ -1832,10 +1832,15 @@ config RTC_MAGIC_REG
depends on RTC && !STM32F7_HAVE_RTC_COUNTER
config RTC_MAGIC
hex "Value used as Magic to determine if RTC is set already"
hex "Value used as Magic to determine if RTC is already setup"
default 0xfacefeee
depends on RTC && !STM32F7_HAVE_RTC_COUNTER
config RTC_MAGIC_TIME_SET
hex "Value used as Magic to determine if RTC is setup and have time set"
default 0xfacefeef
depends on RTC && !STM32F7_HAVE_RTC_COUNTER
choice
prompt "RTC clock source"
default STM32F7_RTC_LSECLOCK

View File

@ -856,9 +856,13 @@ int up_rtc_initialize(void)
regval = getreg32(RTC_MAGIC_REG);
/* Enable write access to the backup domain (RTC registers, RTC
* backup data registers and backup SRAM).
*/
stm32_pwr_enablebkp(true);
if (regval != RTC_MAGIC)
if (regval != RTC_MAGIC && regval != RTC_MAGIC_TIME_SET)
{
/* Issue the Backup domain Reset Per Section 5.3.20 DocID028270 Rev 2
* The LSEON, LSEBYP, RTCSEL and RTCEN bits in the RCC backup domain
@ -949,8 +953,6 @@ int up_rtc_initialize(void)
}
}
stm32_pwr_enablebkp(false);
/* Loop, attempting to initialize/resume the RTC. This loop is necessary
* because it seems that occasionally it takes longer to initialize the
* RTC (the actual failure is in rtc_synchwait()).
@ -988,7 +990,7 @@ int up_rtc_initialize(void)
* has been writing to to back-up date register DR0.
*/
if (regval != RTC_MAGIC)
if (regval != RTC_MAGIC && regval != RTC_MAGIC_TIME_SET)
{
rtcinfo("Do setup\n");
@ -996,12 +998,6 @@ int up_rtc_initialize(void)
ret = rtc_setup();
/* Enable write access to the backup domain (RTC registers, RTC
* backup data registers and backup SRAM).
*/
stm32_pwr_enablebkp(true);
/* Remember that the RTC is initialized */
putreg32(RTC_MAGIC, RTC_MAGIC_REG);
@ -1297,6 +1293,15 @@ int stm32_rtc_setdatetime(FAR const struct tm *tp)
ret = rtc_synchwait();
}
/* Remember that the RTC is initialized and had its time set. */
if (getreg32(RTC_MAGIC_REG) != RTC_MAGIC_TIME_SET)
{
stm32_pwr_enablebkp(true);
putreg32(RTC_MAGIC_TIME_SET, RTC_MAGIC_REG);
stm32_pwr_enablebkp(false);
}
/* Re-enable the write protection for RTC registers */
rtc_wprlock();

View File

@ -66,11 +66,16 @@
# define CONFIG_RTC_MAGIC (0xfacefeee)
#endif
#if !defined(CONFIG_RTC_MAGIC_TIME_SET)
# define CONFIG_RTC_MAGIC_TIME_SET (CONFIG_RTC_MAGIC + 1)
#endif
#if !defined(CONFIG_RTC_MAGIC_REG)
# define CONFIG_RTC_MAGIC_REG (0)
#endif
#define RTC_MAGIC CONFIG_RTC_MAGIC
#define RTC_MAGIC_TIME_SET CONFIG_RTC_MAGIC_TIME_SET
#define RTC_MAGIC_REG STM32_RTC_BKR(CONFIG_RTC_MAGIC_REG)
/****************************************************************************

View File

@ -50,6 +50,8 @@
#include <nuttx/arch.h>
#include <nuttx/timers/rtc.h>
#include "up_arch.h"
#include "chip.h"
#include "stm32_rtc.h"
@ -106,6 +108,7 @@ static int stm32_rdtime(FAR struct rtc_lowerhalf_s *lower,
FAR struct rtc_time *rtctime);
static int stm32_settime(FAR struct rtc_lowerhalf_s *lower,
FAR const struct rtc_time *rtctime);
static bool stm32_havesettime(FAR struct rtc_lowerhalf_s *lower);
#ifdef CONFIG_RTC_ALARM
static int stm32_setalarm(FAR struct rtc_lowerhalf_s *lower,
@ -125,6 +128,7 @@ static const struct rtc_ops_s g_rtc_ops =
{
.rdtime = stm32_rdtime,
.settime = stm32_settime,
.havesettime = stm32_havesettime,
#ifdef CONFIG_RTC_ALARM
.setalarm = stm32_setalarm,
.setrelative = stm32_setrelative,
@ -314,6 +318,25 @@ static int stm32_settime(FAR struct rtc_lowerhalf_s *lower,
#endif
}
/****************************************************************************
* Name: stm32_havesettime
*
* Description:
* Implements the havesettime() method of the RTC driver interface
*
* Input Parameters:
* lower - A reference to RTC lower half driver state structure
*
* Returned Value:
* Returns true if RTC date-time have been previously set.
*
****************************************************************************/
static bool stm32_havesettime(FAR struct rtc_lowerhalf_s *lower)
{
return getreg32(RTC_MAGIC_REG) == RTC_MAGIC_TIME_SET;
}
/****************************************************************************
* Name: stm32_setalarm
*

View File

@ -171,6 +171,19 @@ struct tm;
int stm32l4_rtc_setdatetime(FAR const struct tm *tp);
#endif
/****************************************************************************
* Name: stm32l4_rtc_setdatetime
*
* Description:
* Check if RTC time has been set.
*
* Returned Value:
* Returns true if RTC date-time have been previously set.
*
****************************************************************************/
bool stm32l4_rtc_havesettime(void);
#ifdef CONFIG_RTC_ALARM
/****************************************************************************
* Name: stm32l4_rtc_setalarm

View File

@ -107,6 +107,7 @@ static int stm32l4_rdtime(FAR struct rtc_lowerhalf_s *lower,
FAR struct rtc_time *rtctime);
static int stm32l4_settime(FAR struct rtc_lowerhalf_s *lower,
FAR const struct rtc_time *rtctime);
static bool stm32l4_havesettime(FAR struct rtc_lowerhalf_s *lower);
#ifdef CONFIG_RTC_ALARM
static int stm32l4_setalarm(FAR struct rtc_lowerhalf_s *lower,
@ -127,6 +128,7 @@ static const struct rtc_ops_s g_rtc_ops =
{
.rdtime = stm32l4_rdtime,
.settime = stm32l4_settime,
.havesettime = stm32l4_havesettime,
#ifdef CONFIG_RTC_ALARM
.setalarm = stm32l4_setalarm,
.setrelative = stm32l4_setrelative,
@ -235,7 +237,7 @@ static int stm32l4_rdtime(FAR struct rtc_lowerhalf_s *lower,
ret = up_rtc_getdatetime((FAR struct tm *)rtctime);
sem_post(&priv->devsem);
return ret;
}
@ -273,12 +275,31 @@ static int stm32l4_settime(FAR struct rtc_lowerhalf_s *lower,
*/
ret = stm32l4_rtc_setdatetime((FAR const struct tm *)rtctime);
sem_post(&priv->devsem);
return ret;
}
/****************************************************************************
* Name: stm32l4_havesettime
*
* Description:
* Implements the havesettime() method of the RTC driver interface
*
* Input Parameters:
* lower - A reference to RTC lower half driver state structure
*
* Returned Value:
* Returns true if RTC date-time have been previously set.
*
****************************************************************************/
static bool stm32l4_havesettime(FAR struct rtc_lowerhalf_s *lower)
{
return stm32l4_rtc_havesettime();
}
/****************************************************************************
* Name: stm32l4_setalarm
*

View File

@ -87,6 +87,10 @@
# define CONFIG_RTC_MAGIC (0xfacefeee)
#endif
#if !defined(CONFIG_RTC_MAGIC_TIME_SET)
# define CONFIG_RTC_MAGIC_TIME_SET (CONFIG_RTC_MAGIC + 1)
#endif
#if !defined(CONFIG_RTC_MAGIC_REG)
# define CONFIG_RTC_MAGIC_REG (0)
#endif
@ -185,7 +189,7 @@ static void rtc_dumpregs(FAR const char *msg)
rtcinfo(" ISR: %08x\n", getreg32(STM32L4_RTC_ISR));
rtcinfo(" PRER: %08x\n", getreg32(STM32L4_RTC_PRER));
rtcinfo(" WUTR: %08x\n", getreg32(STM32L4_RTC_WUTR));
rtcinfo(" ALRMAR: %08x\n", getreg32(STM32L4_RTC_ALRMAR));
rtcinfo(" ALRMBR: %08x\n", getreg32(STM32L4_RTC_ALRMBR));
rtcinfo(" SHIFTR: %08x\n", getreg32(STM32L4_RTC_SHIFTR));
@ -693,12 +697,12 @@ static int rtchw_set_alrmar(rtc_alarmreg_t alarmreg)
modifyreg32(STM32L4_RTC_CR, (RTC_CR_ALRAE | RTC_CR_ALRAIE), 0);
/* Ensure Alarm A flag reset; this is edge triggered */
isr = getreg32(STM32L4_RTC_ISR) & ~RTC_ISR_ALRAF;
putreg32(isr, STM32L4_RTC_ISR);
/* Wait for Alarm A to be writable */
ret = rtchw_check_alrawf();
if (ret != OK)
{
@ -739,12 +743,12 @@ static int rtchw_set_alrmbr(rtc_alarmreg_t alarmreg)
modifyreg32(STM32L4_RTC_CR, (RTC_CR_ALRBE | RTC_CR_ALRBIE), 0);
/* Ensure Alarm B flag reset; this is edge triggered */
isr = getreg32(STM32L4_RTC_ISR) & ~RTC_ISR_ALRBF;
putreg32(isr, STM32L4_RTC_ISR);
/* Wait for Alarm B to be writable */
ret = rtchw_check_alrbwf();
if (ret != OK)
{
@ -865,7 +869,7 @@ int up_rtc_initialize(void)
init_stat = rtc_is_inits();
if(!init_stat)
if (!init_stat)
{
/* Enable write access to the backup domain (RTC registers, RTC
* backup data registers and backup SRAM).
@ -951,11 +955,11 @@ int up_rtc_initialize(void)
(void)ret;
/* Exit Initialization mode */
rtc_exitinit();
/* Enable the write protection for RTC registers */
rtc_wprlock();
/* Disable write access to the backup domain (RTC registers, RTC backup
@ -978,11 +982,11 @@ int up_rtc_initialize(void)
//rtc_wprunlock();
rtc_resume();
/* Enable the write protection for RTC registers */
//rtc_wprlock();
/* Disable write access to the backup domain (RTC registers, RTC backup
* data registers and backup SRAM).
*/
@ -1210,6 +1214,15 @@ int stm32l4_rtc_setdatetime(FAR const struct tm *tp)
ret = rtc_synchwait();
}
/* Remember that the RTC is initialized and had its time set. */
if (getreg32(CONFIG_RTC_MAGIC_REG) != CONFIG_RTC_MAGIC_TIME_SET)
{
stm32l4_pwr_enablebkp(true);
putreg32(CONFIG_RTC_MAGIC_TIME_SET, CONFIG_RTC_MAGIC_REG);
stm32l4_pwr_enablebkp(false);
}
/* Re-enable the write protection for RTC registers */
rtc_wprlock();
@ -1217,6 +1230,22 @@ int stm32l4_rtc_setdatetime(FAR const struct tm *tp)
return ret;
}
/************************************************************************************
* Name: stm32l4_rtc_setdatetime
*
* Description:
* Check if RTC time has been set.
*
* Returned Value:
* Returns true if RTC date-time have been previously set.
*
************************************************************************************/
bool stm32l4_rtc_havesettime(void)
{
return getreg32(CONFIG_RTC_MAGIC_REG) == CONFIG_RTC_MAGIC_TIME_SET;
}
/************************************************************************************
* Name: up_rtc_settime
*

View File

@ -332,7 +332,7 @@ static int rtc_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
/* RTC_SET_TIME sets the RTC's time
*
* Argument: A read-only reference to a struct rtc_time containing the
* Argument: A read-only reference to a struct rtc_time containing
* the new time to be set.
*/
@ -348,6 +348,24 @@ static int rtc_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
break;
/* RTC_HAVE_SET_TIME checks if RTC's time had been set
*
* Argument: A writable reference to a bool to receive true/false return
* value of the check.
*/
case RTC_HAVE_SET_TIME:
{
FAR bool *have_set_time = (FAR bool *)((uintptr_t)arg);
if (ops->havesettime)
{
*have_set_time = ops->havesettime(upper->lower);
ret = OK;
}
}
break;
#ifdef CONFIG_RTC_ALARM
/* RTC_SET_ALARM sets the alarm time.
*

View File

@ -145,13 +145,22 @@
#define RTC_SET_TIME _RTCIOC(0x0002)
/* RTC_HAVE_SET_TIME checks if RTC's time had been set
*
* Argument: A writable reference to a bool to receive true/false return value
* of the check.
*/
#define RTC_HAVE_SET_TIME _RTCIOC(0x0003)
/* RTC_SET_ALARM sets the alarm time (for RTCs that support alarms).
*
* Argument: A read-only reference to a struct rtc_setalarm_s containing the
* new alarm time to be set.
*/
#define RTC_SET_ALARM _RTCIOC(0x0003)
#define RTC_SET_ALARM _RTCIOC(0x0004)
/* RTC_SET_RELATIVE sets the alarm time relative to the current time.
*
@ -159,14 +168,14 @@
* new relative alarm time to be set.
*/
#define RTC_SET_RELATIVE _RTCIOC(0x0004)
#define RTC_SET_RELATIVE _RTCIOC(0x0005)
/* RTC_SET_RELATIVE cancel the alarm.
*
* Argument: An ALARM ID value that indicates which alarm should be canceled.
*/
#define RTC_CANCEL_ALARM _RTCIOC(0x0005)
#define RTC_CANCEL_ALARM _RTCIOC(0x0006)
/* Architecture-specific RTC IOCTLS should begin at RTC_USER_IOCBASE. For
* example:
@ -176,7 +185,7 @@
* etc.
*/
#define RTC_USER_IOCBASE 0x0006
#define RTC_USER_IOCBASE 0x0007
/****************************************************************************
* Public Types
@ -291,6 +300,10 @@ struct rtc_ops_s
CODE int (*settime)(FAR struct rtc_lowerhalf_s *lower,
FAR const struct rtc_time *rtctime);
/* havesettime checks if RTC time have been set */
CODE bool (*havesettime)(FAR struct rtc_lowerhalf_s *lower);
#ifdef CONFIG_RTC_ALARM
/* setalarm sets up a new alarm. */