diff --git a/arch/arm/src/max326xx/common/max326_rtc_lowerhalf.c b/arch/arm/src/max326xx/common/max326_rtc_lowerhalf.c index 348a129e721..dccc9c20b61 100644 --- a/arch/arm/src/max326xx/common/max326_rtc_lowerhalf.c +++ b/arch/arm/src/max326xx/common/max326_rtc_lowerhalf.c @@ -106,6 +106,7 @@ struct max326_lowerhalf_s /**************************************************************************** * Private Function Prototypes ****************************************************************************/ + /* Prototypes for static methods in struct rtc_ops_s */ static int max326_rdtime(FAR struct rtc_lowerhalf_s *lower, @@ -374,7 +375,7 @@ static bool max326_havesettime(FAR struct rtc_lowerhalf_s *lower) #ifdef CONFIG_RTC_ALARM static int max326_setalarm(FAR struct rtc_lowerhalf_s *lower, - FAR const struct lower_setalarm_s *alarminfo) + FAR const struct lower_setalarm_s *alarminfo) { FAR struct max326_lowerhalf_s *priv; FAR struct max326_cbinfo_s *cbinfo; @@ -579,22 +580,35 @@ static int max326_cancelalarm(FAR struct rtc_lowerhalf_s *lower, int alarmid) static int max326_rdalarm(FAR struct rtc_lowerhalf_s *lower, FAR struct lower_rdalarm_s *alarminfo) { - struct alm_rdalarm_s lowerinfo; int ret = -EINVAL; - DEBUGASSERT(lower != NULL && alarminfo != NULL && alarminfo->time != NULL); - DEBUGASSERT(alarminfo->id < RTC_NALARMS); + DEBUGASSERT(lower != NULL && alarminfo != NULL); + DEBUGASSERT(alarminfo->id == 0 && alarminfo->time != NULL); - if (alarminfo->id < RTC_NALARMS) + if (alarminfo->id == 0) { + b32_t ftime; + /* Disable pre-emption while we do this so that we don't have to worry * about being suspended and working on an old time. */ - sched_lock(); - lowerinfo.ar_time = alarminfo->time; - ret = max326_rtc_rdalarm(&lowerinfo); - sched_unlock(); + ret = max326_rtc_rdalarm(&ftime); + if (ret >= 0) + { + /* Extract integer seconds from the b32_t value */ + + time_t sec = (time_t)(b32toi(ftime)); + + /* Convert to struct rtc_time (aka struct tm) */ + +#ifdef CONFIG_LIBC_LOCALTIME + (void)localtime_r(&sec, (FAR struct tm *)alarminfo->time); +#else + (void)gmtime_r(&sec, (FAR struct tm *)alarminfo->time); +#endif + ret = OK; + } } return ret; diff --git a/arch/arm/src/max326xx/max32660/max32660_rtc.c b/arch/arm/src/max326xx/max32660/max32660_rtc.c index 0048c0a26e4..9d32beeab9c 100644 --- a/arch/arm/src/max326xx/max32660/max32660_rtc.c +++ b/arch/arm/src/max326xx/max32660/max32660_rtc.c @@ -96,7 +96,7 @@ static FAR void *g_alarmarg; * Public Data ****************************************************************************/ -/* Indicates that the RTC has be initialized */ +/* Indicates that the RTC has been initialized */ volatile bool g_rtc_enabled = false; @@ -519,10 +519,8 @@ int max326_rtc_setalarm(FAR struct timespec *ts, alm_callback_t cb, FAR void *ar { irqstate_t flags; b32_t ftime; + uint64_t rssa; uint32_t regval; - uint32_t sec; - uint32_t ssec; - uint32_t verify; int ret = -EBUSY; DEBUGASSERT(alminfo != NULL && alminfo->as_cb != NULL); @@ -538,16 +536,45 @@ int max326_rtc_setalarm(FAR struct timespec *ts, alm_callback_t cb, FAR void *ar g_alarmcb = cb; g_alarmarg = arg; - /* Get the time as a fixed precision number. */ + /* Get the time as a fixed precision number. + * Form: ssssssss ssssssss ffffffff ffffff + * | `- 32-bits of fraction + * `- 32-bits of integer seconds + */ ftime = max326_rtc_tm2b32(ts); - sec = b32toi(ftime); - ssec = (uint32_t)(b32frac(ftime) >> (32 - 8)); - /* We need to disable ALARMs in order to write to the RAS and RSSA - * registers. + /* Convert to RSSA value. + * + * Writing RSSA sets the starting value for the sub-second alarm + * counter. Writing the SSEN enables the sub-second alarm. Once + * enabled, the sub-second alarm begins up-counting from the RSSA + * value. When the counter rolls over from 0xffffffff to 0x00000000. + * A 256Hz clock drives the sub-second alarm allowing a maximum + * interval of 16,777,216 seconds with a resolution of approximately + * 3.9 msec. + * + * The delay is ssss ssff Where ssssss is the ls 24 bits of seconds + * and ff is the 8bit fractional value. To get the RSSA, that value + * has to be subtracted from 1 << 32. */ + if (b32toi(ftime) >16777216) + { + rssa = 0; + } + else + { + rssa = 0x0000000100000000 - + ((ftime >> (32 - 8)) & 0x00000000ffffffff); + if (rssa > UINT32_MAX) + { + rssa = UINT32_MAX; + } + } + + /* We need to disable ALARMs in order to write to the RSSA registers. */ + flags = spin_lock_irqsave(); regval = getreg32(MAX326_RTC_CTRL); @@ -555,15 +582,9 @@ int max326_rtc_setalarm(FAR struct timespec *ts, alm_callback_t cb, FAR void *ar putreg32(regval, MAX326_RTC_CTRL); max326_rtc_waitbusy(); - /* Then write the time values to the RAS and RSSA registers. */ + /* Then write the RSSA values. */ - do - { - putreg32(sec, MAX326_RTC_RAS); - putreg32(ssec, MAX326_RTC_RSSA); - verify = getreg32(MAX326_RTC_RAS); - } - while (verify != sec); + putreg32(rssa, MAX326_RTC_RSSA); /* Enable sub-second alarm */ @@ -582,6 +603,70 @@ int max326_rtc_setalarm(FAR struct timespec *ts, alm_callback_t cb, FAR void *ar } #endif +/**************************************************************************** + * Name: max326_rtc_rdalarm + * + * Description: + * Query an alarm configured in hardware. + * + * Input Parameters: + * ftime - Location to return the current alarm setting. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +int max326_rtc_rdalarm(FAR b32_t *ftime) +{ + uint64_t b32val; + uint64_t b32rssa; + uint32_t sec; + uint32_t rssa; + uint32_t verify; + uint32_t regval; + + DEBUGASSERT(ftime != NULL); + + /* Read the SEC and the RSSA registers */ + + do + { + rssa = getreg32(MAX326_RTC_RSSA); + sec = getreg32(MAX326_RTC_SEC); + verify = getreg32(MAX326_RTC_RSSA); + } + while (verify != rssa); + + /* Check if the alarm is enabled */ + + regval = getreg32(MAX326_RTC_CTRL); + if ((regval & RTC_CTRL_ALARM_SSEN) == 0) + { + return -EINVAL; + } + + /* Convert the RSA value to b32_t time + * + * Form: SSssssssff00000 + * + * Where SS is the MS 8-bits of seconds from the SEC register + * ssssss is the LS 24 bits of seconds from the RRSA register. + * ff is the MS 8-bit of the fractional value. + * + * Where the sssssff value is (1 << 32) - RRSA, that is, the time + * remaining until the rollover. + */ + + b32val = (uint64_t)(sec & 0xff000000) << 32; + b32rssa = 0x0000000100000000 - (uint64_t)rssa; + b32rssa = (b32rssa & 0x00000000ffffffff) << (32 - 8); + *ftime = (b32_t)(b32val | b32rssa); + return OK; +} +#endif + /**************************************************************************** * Name: max326_rtc_cancelalarm * diff --git a/arch/arm/src/max326xx/max326_rtc.h b/arch/arm/src/max326xx/max326_rtc.h index 4a650d06de3..7736e6a17d8 100644 --- a/arch/arm/src/max326xx/max326_rtc.h +++ b/arch/arm/src/max326xx/max326_rtc.h @@ -41,6 +41,7 @@ ****************************************************************************/ #include +#include /**************************************************************************** * Public Types @@ -52,13 +53,6 @@ typedef CODE void (*alm_callback_t)(FAR void *arg, unsigned int alarmid); -/* Structure used to pass parameters to query an alarm */ - -struct alm_rdalarm_s -{ - FAR struct rtc_time *ar_time; /* Argument for storing ALARM RTC time */ -}; - /**************************************************************************** * Public Data ****************************************************************************/ @@ -84,6 +78,7 @@ extern "C" * * Input Parameters: * ts - Alarm time + * id - A * cb - Callback invoked when alarm expires * arg - Argument passed with the alarm * @@ -104,7 +99,7 @@ int max326_rtc_setalarm(FAR struct timespec *ts, alm_callback_t cb, * Query an alarm configured in hardware. * * Input Parameters: - * alminfo - Information about the alarm configuration. + * ftime - Location to return the current alarm setting. * * Returned Value: * Zero (OK) on success; a negated errno on failure @@ -112,7 +107,7 @@ int max326_rtc_setalarm(FAR struct timespec *ts, alm_callback_t cb, ****************************************************************************/ #ifdef CONFIG_RTC_ALARM -int max326_rtc_rdalarm(FAR struct alm_rdalarm_s *alminfo); +int max326_rtc_rdalarm(FAR b32_t *ftime); #endif /****************************************************************************