diff --git a/arch/arm/src/stm32l4/stm32l4_rtc.h b/arch/arm/src/stm32l4/stm32l4_rtc.h index 3e0a5a21307..4618bf8101b 100644 --- a/arch/arm/src/stm32l4/stm32l4_rtc.h +++ b/arch/arm/src/stm32l4/stm32l4_rtc.h @@ -86,6 +86,14 @@ struct alm_setalarm_s FAR void *as_arg; /* Argument for callback */ }; +/* Structure used to pass parameters to query an alarm */ + +struct alm_rdalarm_s +{ + int as_id; /* enum alm_id_e */ + FAR struct rtc_time *as_time;/* Argument for storing ALARM RTC time */ +}; + #endif /* CONFIG_RTC_ALARM */ /**************************************************************************** diff --git a/arch/arm/src/stm32l4/stm32l4_rtc_lowerhalf.c b/arch/arm/src/stm32l4/stm32l4_rtc_lowerhalf.c index f3415af305d..9f499eb6f8b 100644 --- a/arch/arm/src/stm32l4/stm32l4_rtc_lowerhalf.c +++ b/arch/arm/src/stm32l4/stm32l4_rtc_lowerhalf.c @@ -116,6 +116,8 @@ static int stm32l4_setrelative(FAR struct rtc_lowerhalf_s *lower, FAR const struct lower_setrelative_s *alarminfo); static int stm32l4_cancelalarm(FAR struct rtc_lowerhalf_s *lower, int alarmid); +static int stm32l4_rdalarm(FAR struct rtc_lowerhalf_s *lower, + FAR struct lower_rdalarm_s *alarminfo); #endif /**************************************************************************** @@ -133,6 +135,7 @@ static const struct rtc_ops_s g_rtc_ops = .setalarm = stm32l4_setalarm, .setrelative = stm32l4_setrelative, .cancelalarm = stm32l4_cancelalarm, + .rdalarm = stm32l4_rdalarm, #endif #ifdef CONFIG_RTC_IOCTL .ioctl = NULL, @@ -496,6 +499,52 @@ static int stm32l4_cancelalarm(FAR struct rtc_lowerhalf_s *lower, int alarmid) } #endif +/**************************************************************************** + * Name: stm32l4_rdalarm + * + * Description: + * Query the RTC alarm. + * + * Input Parameters: + * lower - A reference to RTC lower half driver state structure + * alarminfo - Provided information needed to query the alarm + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +static int stm32l4_rdalarm(FAR struct rtc_lowerhalf_s *lower, + FAR struct lower_rdalarm_s *alarminfo) +{ + struct alm_rdalarm_s lowerinfo; + int ret = -EINVAL; + + ASSERT(lower != NULL && alarminfo != NULL && alarminfo->time != NULL); + DEBUGASSERT(alarminfo->id == RTC_ALARMA || alarminfo->id == RTC_ALARMB); + + if (alarminfo->id == RTC_ALARMA || alarminfo->id == RTC_ALARMB) + { + /* 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.as_id = alarminfo->id; + lowerinfo.as_time = alarminfo->time; + + ret = stm32l4_rtc_rdalarm(&lowerinfo); + + sched_unlock(); + } + + return ret; +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ diff --git a/arch/arm/src/stm32l4/stm32l4_rtcc.c b/arch/arm/src/stm32l4/stm32l4_rtcc.c index 05f4ff5ae25..5fbab089611 100644 --- a/arch/arm/src/stm32l4/stm32l4_rtcc.c +++ b/arch/arm/src/stm32l4/stm32l4_rtcc.c @@ -1479,4 +1479,98 @@ errout_with_wprunlock: } #endif +#ifdef CONFIG_RTC_ALARM +/************************************************************************************ + * Name: stm32l4_rtc_getalarmdatetime + * + * Description: + * Get the current date and time for a RTC alarm. + * + * Input Parameters: + * reg - RTC alarm register + * tp - The location to return the high resolution time value. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +int stm32l4_rtc_getalarmdatetime(rtc_alarmreg_t reg, FAR struct tm *tp) +{ + uint32_t data, tmp; + + ASSERT(tp != NULL); + + /* Sample the data time register. */ + + data = getreg32(reg); + + /* Convert the RTC time to fields in struct tm format. All of the STM32 + * All of the ranges of values correspond between struct tm and the time + * register. + */ + + tmp = (data & (RTC_ALRMR_SU_MASK | RTC_ALRMR_ST_MASK)) >> RTC_ALRMR_SU_SHIFT; + tp->tm_sec = rtc_bcd2bin(tmp); + + tmp = (data & (RTC_ALRMR_MNU_MASK | RTC_ALRMR_MNT_MASK)) >> RTC_ALRMR_MNU_SHIFT; + tp->tm_min = rtc_bcd2bin(tmp); + + tmp = (data & (RTC_ALRMR_HU_MASK | RTC_ALRMR_HT_MASK)) >> RTC_ALRMR_HU_SHIFT; + tp->tm_hour = rtc_bcd2bin(tmp); + + return OK; +} +#endif + +/************************************************************************************ + * Name: stm32l4_rtc_rdalarm + * + * Description: + * Query an alarm configured in hardware. + * + * Input Parameters: + * alminfo - Information about the alarm configuration. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +int stm32l4_rtc_rdalarm(FAR struct alm_rdalarm_s *alminfo) +{ + rtc_alarmreg_t alarmreg; + int ret = -EINVAL; + + ASSERT(alminfo != NULL); + DEBUGASSERT(RTC_ALARM_LAST > alminfo->as_id); + + switch (alminfo->as_id) + { + case RTC_ALARMA: + { + alarmreg = STM32L4_RTC_ALRMAR; + ret = stm32l4_rtc_getalarmdatetime(alarmreg, + (struct tm *)alminfo->as_time); + } + break; + + case RTC_ALARMB: + { + alarmreg = STM32L4_RTC_ALRMBR; + ret = stm32l4_rtc_getalarmdatetime(alarmreg, + (struct tm *)alminfo->as_time); + } + break; + + default: + rtcerr("ERROR: Invalid ALARM%d\n", alminfo->as_id); + break; + } + + return ret; +} +#endif + #endif /* CONFIG_RTC */ diff --git a/drivers/timers/rtc.c b/drivers/timers/rtc.c index 990cec845fa..e712be0c1cc 100644 --- a/drivers/timers/rtc.c +++ b/drivers/timers/rtc.c @@ -529,6 +529,40 @@ static int rtc_ioctl(FAR struct file *filep, int cmd, unsigned long arg) } } break; + + /* RTC_RD_ALARM query the alarm. + * + * Argument: A writable reference to the queried alarm. + * + */ + + case RTC_RD_ALARM: + { + FAR struct rtc_rdalarm_s *alarmquery = + (FAR struct rtc_rdalarm_s *)((uintptr_t)arg); + FAR struct rtc_alarminfo_s *upperinfo; + struct lower_rdalarm_s lowerinfo; + int alarmid; + + DEBUGASSERT(alarmquery != NULL); + alarmid = alarmquery->id; + DEBUGASSERT(alarmid >= 0 && alarmid < CONFIG_RTC_NALARMS); + + /* Is the alarm active? */ + + upperinfo = &upper->alarminfo[alarmid]; + alarmquery->active = upperinfo->active; + + lowerinfo.id = alarmid; + lowerinfo.priv = (FAR void *)upper; + lowerinfo.time = (FAR struct rtc_time *)&alarmquery->time; + + if (ops->rdalarm) + { + ret = ops->rdalarm(upper->lower, &lowerinfo); + } + } + break; #endif /* CONFIG_RTC_ALARM */ /* Forward any unrecognized IOCTLs to the lower half driver... they diff --git a/include/nuttx/timers/rtc.h b/include/nuttx/timers/rtc.h index 33b761ed0e4..c0b6e7ff32b 100644 --- a/include/nuttx/timers/rtc.h +++ b/include/nuttx/timers/rtc.h @@ -177,6 +177,13 @@ #define RTC_CANCEL_ALARM _RTCIOC(0x0006) +/* RTC_RD_ALARM query the alarm. + * + * Argument: An ALARM ID value that indicates which alarm should be queried. + */ + +#define RTC_RD_ALARM _RTCIOC(0x0007) + /* Architecture-specific RTC IOCTLS should begin at RTC_USER_IOCBASE. For * example: * @@ -185,7 +192,8 @@ * etc. */ -#define RTC_USER_IOCBASE 0x0007 +#define RTC_USER_IOCBASE 0x0008 + /**************************************************************************** * Public Types @@ -273,6 +281,15 @@ struct lower_setrelative_s FAR void *priv; /* Private argurment to accompany callback */ time_t reltime; /* Relative time in seconds */ }; + +/* Structure used with the rdalarm method */ + +struct lower_rdalarm_s +{ + uint8_t id; /* Indicates the alarm to be set */ + FAR void *priv; /* Private argurment to accompany callback */ + FAR struct rtc_time *time;/* Queried RTC time pointer */ +}; #endif /* The RTC driver is implemented as a common, upper-half character driver @@ -318,6 +335,11 @@ struct rtc_ops_s /* cancelalarm cancels the current alarm. */ CODE int (*cancelalarm)(FAR struct rtc_lowerhalf_s *lower, int alarmid); + + /* rdalarm query the current alarm. */ + + CODE int (*rdalarm)(FAR struct rtc_lowerhalf_s *lower, + FAR struct lower_rdalarm_s *alarminfo); #endif #ifdef CONFIG_RTC_IOCTL