diff --git a/arch/arm/src/stm32f7/stm32_rtc.c b/arch/arm/src/stm32f7/stm32_rtc.c index cfc5819daa..cea967769d 100644 --- a/arch/arm/src/stm32f7/stm32_rtc.c +++ b/arch/arm/src/stm32f7/stm32_rtc.c @@ -42,7 +42,6 @@ #include #include -#include #include #include @@ -67,7 +66,7 @@ /* Configuration ************************************************************/ /* This RTC implementation supports * - date/time RTC hardware - * - extended functions Alarm A and B for STM32F4xx and onwards + * - extended functions Alarm A and B * */ #ifndef CONFIG_RTC_DATETIME @@ -604,6 +603,12 @@ static int stm32_rtc_alarm_handler(int irq, void *context, void *arg) uint32_t cr; int ret = OK; + /* Enable write access to the backup domain (RTC registers, RTC + * backup data registers and backup SRAM). + */ + + (void)stm32_pwr_enablebkp(true); + isr = getreg32(STM32_RTC_ISR); /* Check for EXTI from Alarm A or B and handle according */ @@ -627,8 +632,9 @@ static int stm32_rtc_alarm_handler(int irq, void *context, void *arg) cb(cbarg, RTC_ALARMA); } - isr = getreg32(STM32_RTC_ISR) & ~RTC_ISR_ALRAF; - putreg32(isr, STM32_RTC_CR); + isr = getreg32(STM32_RTC_ISR); + isr &= ~RTC_ISR_ALRAF; + putreg32(isr, STM32_RTC_ISR); } } @@ -652,12 +658,19 @@ static int stm32_rtc_alarm_handler(int irq, void *context, void *arg) cb(cbarg, RTC_ALARMB); } - isr = getreg32(STM32_RTC_ISR) & ~RTC_ISR_ALRBF; - putreg32(isr, STM32_RTC_CR); + isr = getreg32(STM32_RTC_ISR); + isr &= ~RTC_ISR_ALRBF; + putreg32(isr, STM32_RTC_ISR); } } #endif + /* Disable write access to the backup domain (RTC registers, RTC backup + * data registers and backup SRAM). + */ + + (void)stm32_pwr_enablebkp(false); + return ret; } #endif @@ -746,31 +759,39 @@ static int rtchw_check_alrbwf(void) #ifdef CONFIG_RTC_ALARM static int rtchw_set_alrmar(rtc_alarmreg_t alarmreg) { + int isr; int ret = -EBUSY; - /* Need to follow RTC register wrote protection + /* Need to allow RTC register write * Disable the write protection for RTC registers */ rtc_wprunlock(); - /* Disable RTC alarm & Interrupt */ + /* Disable RTC alarm A & Interrupt A */ modifyreg32(STM32_RTC_CR, (RTC_CR_ALRAE | RTC_CR_ALRAIE), 0); + /* Ensure Alarm A flag reset; this is edge triggered */ + + isr = getreg32(STM32_RTC_ISR) & ~RTC_ISR_ALRAF; + putreg32(isr, STM32_RTC_ISR); + + /* Wait for Alarm A to be writable */ + ret = rtchw_check_alrawf(); if (ret != OK) { goto errout_with_wprunlock; } - /* Set the RTC Alarm register */ + /* Set the RTC Alarm A register */ putreg32(alarmreg, STM32_RTC_ALRMAR); - rtcinfo(" TR: %08x ALRMAR: %08x\n", - getreg32(STM32_RTC_TR), getreg32(STM32_RTC_ALRMAR)); + putreg32(0, STM32_RTC_ALRMASSR); + rtcinfo(" ALRMAR: %08x\n", getreg32(STM32_RTC_ALRMAR)); - /* Enable RTC alarm */ + /* Enable RTC alarm A */ modifyreg32(STM32_RTC_CR, 0, (RTC_CR_ALRAE | RTC_CR_ALRAIE)); @@ -783,9 +804,10 @@ errout_with_wprunlock: #if defined(CONFIG_RTC_ALARM) && CONFIG_RTC_NALARMS > 1 static int rtchw_set_alrmbr(rtc_alarmreg_t alarmreg) { + int isr; int ret = -EBUSY; - /* Need to follow RTC register wrote protection + /* Need to allow RTC register write * Disable the write protection for RTC registers */ @@ -795,17 +817,24 @@ static int rtchw_set_alrmbr(rtc_alarmreg_t alarmreg) modifyreg32(STM32_RTC_CR, (RTC_CR_ALRBE | RTC_CR_ALRBIE), 0); + /* Ensure Alarm B flag reset; this is edge triggered */ + + isr = getreg32(STM32_RTC_ISR) & ~RTC_ISR_ALRBF; + putreg32(isr, STM32_RTC_ISR); + + /* Wait for Alarm B to be writable */ + ret = rtchw_check_alrbwf(); if (ret != OK) { goto rtchw_set_alrmbr_exit; } - /* Set the RTC Alarm register */ + /* Set the RTC Alarm B register */ putreg32(alarmreg, STM32_RTC_ALRMBR); - rtcinfo(" TR: %08x ALRMBR: %08x\n", - getreg32(STM32_RTC_TR), getreg32(STM32_RTC_ALRMBR)); + putreg32(0, STM32_RTC_ALRMBSSR); + rtcinfo(" ALRMBR: %08x\n", getreg32(STM32_RTC_ALRMBR)); /* Enable RTC alarm B */ @@ -1078,7 +1107,7 @@ int up_rtc_initialize(void) * * 1. Configure and enable the EXTI Line 17 RTC ALARM in interrupt mode * and select the rising edge sensitivity. - * For STM32F4xx + * For STM32F7: * EXTI line 21 RTC Tamper & Timestamp * EXTI line 22 RTC Wakeup * 2. Configure and enable the RTC_Alarm IRQ channel in the NVIC. @@ -1086,12 +1115,10 @@ int up_rtc_initialize(void) */ (void)stm32_exti_alarm(true, false, true, stm32_rtc_alarm_handler, NULL); - rtc_dumpregs("After InitExtiAlarm"); -#else - rtc_dumpregs("After Initialization"); #endif g_rtc_enabled = true; + rtc_dumpregs("After Initialization"); return OK; } @@ -1162,9 +1189,8 @@ int up_rtc_getdatetime(FAR struct tm *tp) rtc_dumpregs("Reading Time"); - /* 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. + /* Convert the RTC time to fields in struct tm format. All of the STM32 + * ranges of values correspond between struct tm and the time register. */ tmp = (tr & (RTC_TR_SU_MASK | RTC_TR_ST_MASK)) >> RTC_TR_SU_SHIFT; @@ -1204,7 +1230,7 @@ int up_rtc_getdatetime(FAR struct tm *tp) #endif #ifdef CONFIG_STM32F7_HAVE_RTC_SUBSECONDS - /* Return RTC sub-seconds if no configured and if a non-NULL value + /* Return RTC sub-seconds if a non-NULL value * of nsec has been provided to receive the sub-second value. */ @@ -1261,7 +1287,7 @@ int up_rtc_getdatetime(FAR struct tm *tp) } #endif -/************************************************************************************ +/**************************************************************************** * Name: up_rtc_getdatetime_with_subseconds * * Description: @@ -1283,7 +1309,7 @@ int up_rtc_getdatetime(FAR struct tm *tp) * Returned Value: * Zero (OK) on success; a negated errno on failure * - ************************************************************************************/ + ****************************************************************************/ #ifdef CONFIG_ARCH_HAVE_RTC_SUBSECONDS # ifndef CONFIG_STM32F7_HAVE_RTC_SUBSECONDS @@ -1321,14 +1347,15 @@ int stm32_rtc_setdatetime(FAR const struct tm *tp) /* Then write the broken out values to the RTC */ - /* Convert the struct tm format to RTC time register fields. All of the - * STM32 All of the ranges of values correspond between struct tm and the + /* Convert the struct tm format to RTC time register fields. + * All of the ranges of values correspond between struct tm and the * time register. */ tr = (rtc_bin2bcd(tp->tm_sec) << RTC_TR_SU_SHIFT) | (rtc_bin2bcd(tp->tm_min) << RTC_TR_MNU_SHIFT) | (rtc_bin2bcd(tp->tm_hour) << RTC_TR_HU_SHIFT); + tr &= ~RTC_TR_RESERVED_BITS; /* Now convert the fields in struct tm format to the RTC date register * fields: @@ -1389,6 +1416,22 @@ int stm32_rtc_setdatetime(FAR const struct tm *tp) return ret; } +/**************************************************************************** + * Name: stm32_rtc_havesettime + * + * Description: + * Check if RTC time has been set. + * + * Returned Value: + * Returns true if RTC date-time have been previously set. + * + ****************************************************************************/ + +bool stm32_rtc_havesettime(void) +{ + return getreg32(RTC_MAGIC_REG) == RTC_MAGIC_TIME_SET; +} + /**************************************************************************** * Name: up_rtc_settime * @@ -1470,8 +1513,6 @@ int stm32_rtc_setalarm(FAR struct alm_setalarm_s *alminfo) cbinfo->ac_cb = NULL; cbinfo->ac_arg = NULL; } - - rtc_dumpregs("Set AlarmA"); } break; @@ -1488,8 +1529,6 @@ int stm32_rtc_setalarm(FAR struct alm_setalarm_s *alminfo) cbinfo->ac_cb = NULL; cbinfo->ac_arg = NULL; } - - rtc_dumpregs("Set AlarmB"); } break; #endif @@ -1499,6 +1538,8 @@ int stm32_rtc_setalarm(FAR struct alm_setalarm_s *alminfo) break; } + rtc_dumpregs("After alarm setting"); + return ret; } #endif @@ -1554,6 +1595,7 @@ int stm32_rtc_cancelalarm(enum alm_id_e alarmid) /* Unset the alarm */ putreg32(-1, STM32_RTC_ALRMAR); + modifyreg32(STM32_RTC_ISR, RTC_ISR_ALRAF, 0); rtc_wprlock(); ret = OK; } @@ -1586,6 +1628,7 @@ int stm32_rtc_cancelalarm(enum alm_id_e alarmid) /* Unset the alarm */ putreg32(-1, STM32_RTC_ALRMBR); + modifyreg32(STM32_RTC_ISR, RTC_ISR_ALRBF, 0); rtc_wprlock(); ret = OK; } @@ -1605,7 +1648,7 @@ errout_with_wprunlock: } #endif -/************************************************************************************ +/**************************************************************************** * Name: stm32_rtc_rdalarm * * Description: @@ -1617,7 +1660,7 @@ errout_with_wprunlock: * 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) diff --git a/arch/arm/src/stm32f7/stm32_rtc.h b/arch/arm/src/stm32f7/stm32_rtc.h index a46361a55d..0ec4a808f0 100644 --- a/arch/arm/src/stm32f7/stm32_rtc.h +++ b/arch/arm/src/stm32f7/stm32_rtc.h @@ -111,8 +111,7 @@ extern "C" * during initialization to set up the system time when CONFIG_RTC and * CONFIG_RTC_DATETIME are selected (and CONFIG_RTC_HIRES is not). * - * NOTE: Some date/time RTC hardware is capability of sub-second accuracy. - * Thatsub-second accuracy is returned through 'nsec'. + * NOTE: The sub-second accuracy is returned through 'nsec'. * * Input Parameters: * tp - The location to return the high resolution time value. @@ -148,6 +147,19 @@ struct tm; int stm32_rtc_setdatetime(FAR const struct tm *tp); #endif +/**************************************************************************** + * Name: stm32_rtc_havesettime + * + * Description: + * Check if RTC time has been set. + * + * Returned Value: + * Returns true if RTC date-time have been previously set. + * + ****************************************************************************/ + +bool stm32_rtc_havesettime(void); + /**************************************************************************** * Name: stm32_rtc_lowerhalf * diff --git a/arch/arm/src/stm32l4/stm32l4_rtc.h b/arch/arm/src/stm32l4/stm32l4_rtc.h index e7b06fcb31..6aa47d5f22 100644 --- a/arch/arm/src/stm32l4/stm32l4_rtc.h +++ b/arch/arm/src/stm32l4/stm32l4_rtc.h @@ -133,13 +133,13 @@ extern "C" * Public Functions ****************************************************************************/ -/************************************************************************************ +/**************************************************************************** * Name: stm32l4_rtc_is_initialized * * Description: * Returns 'true' if the RTC has been initialized - * Returns 'false' if the RTC has never been initialized since first time power - * up, and the counters are stopped until it is first initialized. + * Returns 'false' if the RTC has never been initialized since first time + * power up, and the counters are stopped until it is first initialized. * * Input Parameters: * None @@ -147,7 +147,7 @@ extern "C" * Returned Value: * Returns true if RTC has been initialized. * - ************************************************************************************/ + ****************************************************************************/ bool stm32l4_rtc_is_initialized(void); @@ -198,7 +198,7 @@ int stm32l4_rtc_setdatetime(FAR const struct tm *tp); #endif /**************************************************************************** - * Name: stm32l4_rtc_setdatetime + * Name: stm32l4_rtc_havesettime * * Description: * Check if RTC time has been set. @@ -227,7 +227,7 @@ bool stm32l4_rtc_havesettime(void); int stm32l4_rtc_setalarm(FAR struct alm_setalarm_s *alminfo); -/************************************************************************************ +/**************************************************************************** * Name: stm32l4_rtc_rdalarm * * Description: @@ -239,7 +239,7 @@ int stm32l4_rtc_setalarm(FAR struct alm_setalarm_s *alminfo); * Returned Value: * Zero (OK) on success; a negated errno on failure * - ************************************************************************************/ + ****************************************************************************/ int stm32l4_rtc_rdalarm(FAR struct alm_rdalarm_s *alminfo);