arch/arm/src/max326xx: Add missing function to get the alarm time.

This commit is contained in:
Gregory Nutt 2018-11-21 15:06:02 -06:00
parent bd5d079c02
commit c7cb4fa594
3 changed files with 129 additions and 35 deletions

View File

@ -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;

View File

@ -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
*

View File

@ -41,6 +41,7 @@
****************************************************************************/
#include <nuttx/config.h>
#include <fixedmath.h>
/****************************************************************************
* 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
/****************************************************************************