From 92b3c9477a84c484b66645c213f0e85ccf6a4a2e Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 3 Sep 2017 07:40:38 -0600 Subject: [PATCH] Port Boris Astardzhiev RTC change for STM32L4 to STM32F7 --- arch/arm/src/stm32f7/Kconfig | 26 ++--- arch/arm/src/stm32f7/stm32_alarm.h | 36 +++++-- arch/arm/src/stm32f7/stm32_rtc.c | 106 +++++++++++++++++++-- arch/arm/src/stm32f7/stm32_rtc_lowerhalf.c | 49 ++++++++++ arch/arm/src/stm32l4/stm32l4_rtc.h | 16 ++-- 5 files changed, 202 insertions(+), 31 deletions(-) diff --git a/arch/arm/src/stm32f7/Kconfig b/arch/arm/src/stm32f7/Kconfig index f08c216509..ce6fb3079c 100644 --- a/arch/arm/src/stm32f7/Kconfig +++ b/arch/arm/src/stm32f7/Kconfig @@ -1828,35 +1828,38 @@ config STM32F7_SAVE_CRASHDUMP endif # STM32F7_BKPSRAM -config STM32F7_HAVE_RTC_COUNTER - bool - default n - config STM32F7_HAVE_RTC_SUBSECONDS bool select ARCH_HAVE_RTC_SUBSECONDS default y +menu "RTC Configuration" + depends on RTC + config RTC_MAGIC_REG - int "The BKP register used to store/check the Magic value to determine if RTC is set already" + int "BKP register" default 0 range 0 31 - depends on RTC && !STM32F7_HAVE_RTC_COUNTER + ---help--- + The BKP register used to store/check the Magic value to determine if + RTC is already setup config RTC_MAGIC - hex "Value used as Magic to determine if RTC is already setup" + hex "RTC Magic 1" default 0xfacefeee - depends on RTC && !STM32F7_HAVE_RTC_COUNTER + ---help--- + Value used as Magic to determine if the RTC is already setup config RTC_MAGIC_TIME_SET - hex "Value used as Magic to determine if RTC is setup and have time set" + hex "RTC Magic 2" default 0xfacefeef - depends on RTC && !STM32F7_HAVE_RTC_COUNTER + ---help--- + Value used as Magic to determine if the RTC has been setup and has + time set choice prompt "RTC clock source" default STM32F7_RTC_LSECLOCK - depends on RTC config STM32F7_RTC_HSECLOCK bool "HSE clock" @@ -1874,6 +1877,7 @@ config STM32F7_RTC_LSICLOCK Drive the RTC with the LSI clock endchoice #"RTC clock source" +endmenu # RTC Configuration config STM32F7_CUSTOM_CLOCKCONFIG bool "Custom clock configuration" diff --git a/arch/arm/src/stm32f7/stm32_alarm.h b/arch/arm/src/stm32f7/stm32_alarm.h index ee0b8b8916..a898f07478 100644 --- a/arch/arm/src/stm32f7/stm32_alarm.h +++ b/arch/arm/src/stm32f7/stm32_alarm.h @@ -57,8 +57,8 @@ typedef CODE void (*alm_callback_t)(FAR void *arg, unsigned int alarmid); enum alm_id_e { - RTC_ALARMA = 0, /* RTC ALARM A */ - RTC_ALARMB, /* RTC ALARM B */ + RTC_ALARMA = 0, /* RTC ALARM A */ + RTC_ALARMB, /* RTC ALARM B */ RTC_ALARM_LAST }; @@ -66,10 +66,18 @@ enum alm_id_e struct alm_setalarm_s { - int as_id; /* enum alm_id_e */ - struct tm as_time; /* Alarm expiration time */ - alm_callback_t as_cb; /* Callback (if non-NULL) */ - FAR void *as_arg; /* Argument for callback */ + int as_id; /* enum alm_id_e */ + struct tm as_time; /* Alarm expiration time */ + alm_callback_t as_cb; /* Callback (if non-NULL) */ + 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 */ }; /**************************************************************************** @@ -92,6 +100,22 @@ struct alm_setalarm_s int stm32_rtc_setalarm(FAR struct alm_setalarm_s *alminfo); +/************************************************************************************ + * Name: stm32_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 + * + ************************************************************************************/ + +int stm32_rtc_rdalarm(FAR struct alm_rdalarm_s *alminfo); + /**************************************************************************** * Name: stm32_rtc_cancelalarm * diff --git a/arch/arm/src/stm32f7/stm32_rtc.c b/arch/arm/src/stm32f7/stm32_rtc.c index eb83c016ca..97762f4d5a 100644 --- a/arch/arm/src/stm32f7/stm32_rtc.c +++ b/arch/arm/src/stm32f7/stm32_rtc.c @@ -595,11 +595,11 @@ static void rtc_resume(void) ****************************************************************************/ #ifdef CONFIG_RTC_ALARM -static int stm32_rtc_alarm_handler(int irq, void *context) +static int stm32_rtc_alarm_handler(int irq, void *context, void *arg) { FAR struct alm_cbinfo_s *cbinfo; alm_callback_t cb; - FAR void *arg; + FAR void *cbarg; uint32_t isr; uint32_t cr; int ret = OK; @@ -619,12 +619,12 @@ static int stm32_rtc_alarm_handler(int irq, void *context) /* Alarm A callback */ cb = cbinfo->ac_cb; - arg = (FAR void *)cbinfo->ac_arg; + cbarg = (FAR void *)cbinfo->ac_arg; cbinfo->ac_cb = NULL; cbinfo->ac_arg = NULL; - cb(arg, RTC_ALARMA); + cb(cbarg, RTC_ALARMA); } isr = getreg32(STM32_RTC_ISR) & ~RTC_ISR_ALRAF; @@ -644,12 +644,12 @@ static int stm32_rtc_alarm_handler(int irq, void *context) /* Alarm B callback */ cb = cbinfo->ac_cb; - arg = (FAR void *)cbinfo->ac_arg; + cbarg = (FAR void *)cbinfo->ac_arg; cbinfo->ac_cb = NULL; cbinfo->ac_arg = NULL; - cb(arg, RTC_ALARMB); + cb(cbarg, RTC_ALARMB); } isr = getreg32(STM32_RTC_ISR) & ~RTC_ISR_ALRBF; @@ -1559,4 +1559,98 @@ errout_with_wprunlock: } #endif +#ifdef CONFIG_RTC_ALARM +/************************************************************************************ + * Name: stm32_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 stm32_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: stm32_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 stm32_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 = STM32_RTC_ALRMAR; + ret = stm32_rtc_getalarmdatetime(alarmreg, + (struct tm *)alminfo->as_time); + } + break; + + case RTC_ALARMB: + { + alarmreg = STM32_RTC_ALRMBR; + ret = stm32_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/arch/arm/src/stm32f7/stm32_rtc_lowerhalf.c b/arch/arm/src/stm32f7/stm32_rtc_lowerhalf.c index 25868c58b8..6812a0fdcb 100644 --- a/arch/arm/src/stm32f7/stm32_rtc_lowerhalf.c +++ b/arch/arm/src/stm32f7/stm32_rtc_lowerhalf.c @@ -117,6 +117,8 @@ static int stm32_setrelative(FAR struct rtc_lowerhalf_s *lower, FAR const struct lower_setrelative_s *alarminfo); static int stm32_cancelalarm(FAR struct rtc_lowerhalf_s *lower, int alarmid); +static int stm32_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 = stm32_setalarm, .setrelative = stm32_setrelative, .cancelalarm = stm32_cancelalarm, + .rdalarm = stm32_rdalarm, #endif #ifdef CONFIG_RTC_IOCTL .ioctl = NULL, @@ -519,6 +522,52 @@ static int stm32_cancelalarm(FAR struct rtc_lowerhalf_s *lower, int alarmid) } #endif +/**************************************************************************** + * Name: stm32_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 stm32_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 = stm32_rtc_rdalarm(&lowerinfo); + + sched_unlock(); + } + + return ret; +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ diff --git a/arch/arm/src/stm32l4/stm32l4_rtc.h b/arch/arm/src/stm32l4/stm32l4_rtc.h index 4618bf8101..f5d12629c0 100644 --- a/arch/arm/src/stm32l4/stm32l4_rtc.h +++ b/arch/arm/src/stm32l4/stm32l4_rtc.h @@ -71,8 +71,8 @@ typedef CODE void (*alm_callback_t)(FAR void *arg, unsigned int alarmid); enum alm_id_e { - RTC_ALARMA = 0, /* RTC ALARM A */ - RTC_ALARMB, /* RTC ALARM B */ + RTC_ALARMA = 0, /* RTC ALARM A */ + RTC_ALARMB, /* RTC ALARM B */ RTC_ALARM_LAST }; @@ -80,18 +80,18 @@ enum alm_id_e struct alm_setalarm_s { - int as_id; /* enum alm_id_e */ - struct tm as_time; /* Alarm expiration time */ - alm_callback_t as_cb; /* Callback (if non-NULL) */ - FAR void *as_arg; /* Argument for callback */ + int as_id; /* enum alm_id_e */ + struct tm as_time; /* Alarm expiration time */ + alm_callback_t as_cb; /* Callback (if non-NULL) */ + 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 */ + int as_id; /* enum alm_id_e */ + FAR struct rtc_time *as_time; /* Argument for storing ALARM RTC time */ }; #endif /* CONFIG_RTC_ALARM */