diff --git a/arch/arm/src/stm32f7/Kconfig b/arch/arm/src/stm32f7/Kconfig index ff7dfe80cfd..e727aef24aa 100644 --- a/arch/arm/src/stm32f7/Kconfig +++ b/arch/arm/src/stm32f7/Kconfig @@ -1823,7 +1823,7 @@ config STM32F7_HAVE_RTC_COUNTER config STM32F7_HAVE_RTC_SUBSECONDS bool - default n + default y config RTC_MAGIC_REG int "The BKP register used to store/check the Magic value to determine if RTC is set already" diff --git a/arch/arm/src/stm32f7/Make.defs b/arch/arm/src/stm32f7/Make.defs index 8baa4fbf135..06a190f463f 100644 --- a/arch/arm/src/stm32f7/Make.defs +++ b/arch/arm/src/stm32f7/Make.defs @@ -149,6 +149,10 @@ ifeq ($(filter y,$(CONFIG_STM32F7_IWDG) $(CONFIG_STM32F7_RTC_LSICLOCK)),y) CHIP_CSRCS += stm32_lsi.c endif +ifeq ($(CONFIG_STM32F7_RTC_LSECLOCK),y) +CHIP_CSRCS += stm32_lse.c +endif + ifeq ($(CONFIG_STM32F7_I2C),y) CHIP_CSRCS += stm32_i2c.c endif diff --git a/arch/arm/src/stm32f7/stm32_exti_pwr.c b/arch/arm/src/stm32f7/stm32_exti_pwr.c index 09d064e930e..3c4f2d07a3b 100644 --- a/arch/arm/src/stm32f7/stm32_exti_pwr.c +++ b/arch/arm/src/stm32f7/stm32_exti_pwr.c @@ -129,7 +129,7 @@ static int stm32_exti_pvd_isr(int irq, void *context, void *arg) ****************************************************************************/ int stm32_exti_pvd(bool risingedge, bool fallingedge, bool event, - xcpt_t func, void *arg); + xcpt_t func, void *arg) { /* Get the previous GPIO IRQ handler; Save the new IRQ handler. */ diff --git a/arch/arm/src/stm32f7/stm32_lse.c b/arch/arm/src/stm32f7/stm32_lse.c new file mode 100644 index 00000000000..162630060b9 --- /dev/null +++ b/arch/arm/src/stm32f7/stm32_lse.c @@ -0,0 +1,86 @@ +/**************************************************************************** + * arch/arm/src/stm32f7/stm32_lse.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * David Sidrane + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "up_arch.h" + +#include "stm32_rcc.h" +#include "stm32_pwr.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_rcc_enablelse + * + * Description: + * Enable the External Low-Speed (LSE) oscillator. + * + ****************************************************************************/ + +void stm32_rcc_enablelse(void) +{ + uint32_t regval; + + /* The LSE is in the RTC domain and write access is denied to this domain + * after reset, you have to enable write access using DBP bit in the PWR CR + * register before to configuring the LSE. + */ + + stm32_pwr_enablebkp(true); + + /* Enable the External Low-Speed (LSE) oscillator by setting the LSEON bit + * the RCC BDCR register. + */ + + regval = getreg32(STM32_RCC_BDCR); + regval |= RCC_BDCR_LSEON; + putreg32(regval,STM32_RCC_BDCR); + + /* Wait for the LSE clock to be ready */ + + while (((regval = getreg32(STM32_RCC_BDCR)) & RCC_BDCR_LSERDY) == 0); + + /* Disable backup domain access if it was disabled on entry */ + + stm32_pwr_enablebkp(false); +} diff --git a/arch/arm/src/stm32f7/stm32_lsi.c b/arch/arm/src/stm32f7/stm32_lsi.c index 46e96163727..636662721b5 100644 --- a/arch/arm/src/stm32f7/stm32_lsi.c +++ b/arch/arm/src/stm32f7/stm32_lsi.c @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/arm/src/stm32f/stm32_lsi.c + * arch/arm/src/stm32f7/stm32_lsi.c * * Copyright (C) 2012, 2015-2016 Gregory Nutt. All rights reserved. * Authors: Gregory Nutt diff --git a/arch/arm/src/stm32f7/stm32_rtc.c b/arch/arm/src/stm32f7/stm32_rtc.c index 8a21ec41fea..2840fac8a5d 100644 --- a/arch/arm/src/stm32f7/stm32_rtc.c +++ b/arch/arm/src/stm32f7/stm32_rtc.c @@ -196,7 +196,7 @@ static void rtc_dumpregs(FAR const char *msg) rtcinfo(" TSDR: %08x\n", getreg32(STM32_RTC_TSDR)); rtcinfo(" TSSSR: %08x\n", getreg32(STM32_RTC_TSSSR)); rtcinfo(" CALR: %08x\n", getreg32(STM32_RTC_CALR)); - rtcinfo(" TAFCR: %08x\n", getreg32(STM32_RTC_TAFCR)); + rtcinfo(" TAMPCR: %08x\n", getreg32(STM32_RTC_TAMPCR)); rtcinfo("ALRMASSR: %08x\n", getreg32(STM32_RTC_ALRMASSR)); rtcinfo("ALRMBSSR: %08x\n", getreg32(STM32_RTC_ALRMBSSR)); rtcinfo("MAGICREG: %08x\n", getreg32(RTC_MAGIC_REG)); @@ -227,7 +227,8 @@ static void rtc_dumpregs(FAR const char *msg) ****************************************************************************/ #ifdef CONFIG_DEBUG_RTC_INFO -static void rtc_dumptime(FAR const struct tm *tp, FAR const char *msg) +static void rtc_dumptime(FAR const struct tm *tp, FAR const uint32_t *usecs, + FAR const char *msg) { rtcinfo("%s:\n", msg); rtcinfo(" tm_sec: %08x\n", tp->tm_sec); @@ -236,9 +237,14 @@ static void rtc_dumptime(FAR const struct tm *tp, FAR const char *msg) rtcinfo(" tm_mday: %08x\n", tp->tm_mday); rtcinfo(" tm_mon: %08x\n", tp->tm_mon); rtcinfo(" tm_year: %08x\n", tp->tm_year); + + if (usecs != NULL) + { + rtcinfo(" usecs: %08x\n", (unsigned int)*usecs); + } } #else -# define rtc_dumptime(tp, msg) +# define rtc_dumptime(tp, usecs, msg) #endif /**************************************************************************** @@ -1069,34 +1075,48 @@ int up_rtc_initialize(void) * ****************************************************************************/ -#ifdef CONFIG_STM32_HAVE_RTC_SUBSECONDS +#ifdef CONFIG_STM32F7_HAVE_RTC_SUBSECONDS int stm32_rtc_getdatetime_with_subseconds(FAR struct tm *tp, FAR long *nsec) #else int up_rtc_getdatetime(FAR struct tm *tp) #endif { -#ifdef CONFIG_STM32_HAVE_RTC_SUBSECONDS - uint32_t ssr; -#endif uint32_t dr; uint32_t tr; uint32_t tmp; +#ifdef CONFIG_STM32F7_HAVE_RTC_SUBSECONDS + uint32_t ssr; + uint32_t prediv_s; + uint32_t usecs; +#endif /* Sample the data time registers. There is a race condition here... If * we sample the time just before midnight on December 31, the date could - * be wrong because the day rolled over while were sampling. + * be wrong because the day rolled over while were sampling. Thus loop for + * checking overflow here is needed. There is a race condition with + * subseconds too. If we sample TR register just before second rolling + * and subseconds are read at wrong second, we get wrong time. */ do { dr = getreg32(STM32_RTC_DR); tr = getreg32(STM32_RTC_TR); -#ifdef CONFIG_STM32_HAVE_RTC_SUBSECONDS +#ifdef CONFIG_STM32F7_HAVE_RTC_SUBSECONDS ssr = getreg32(STM32_RTC_SSR); + tmp = getreg32(STM32_RTC_TR); + if (tmp != tr) + { + continue; + } #endif tmp = getreg32(STM32_RTC_DR); + if (tmp == dr) + { + break; + } } - while (tmp != dr); + while (1); rtc_dumpregs("Reading Time"); @@ -1141,31 +1161,31 @@ int up_rtc_getdatetime(FAR struct tm *tp) tp->tm_isdst = 0 #endif -#ifdef CONFIG_STM32_HAVE_RTC_SUBSECONDS +#ifdef CONFIG_STM32F7_HAVE_RTC_SUBSECONDS /* Return RTC sub-seconds if no configured and if a non-NULL value * of nsec has been provided to receive the sub-second value. */ - if (nsec) + prediv_s = getreg32(STM32_RTC_PRER) & RTC_PRER_PREDIV_S_MASK; + prediv_s >>= RTC_PRER_PREDIV_S_SHIFT; + + ssr &= RTC_SSR_MASK; + + /* Maximum prediv_s is 0x7fff, thus we can multiply by 100000 and + * still fit 32-bit unsigned integer. + */ + + usecs = (((prediv_s - ssr) * 100000) / (prediv_s + 1)) * 10; + if (nsec != NULL) { - uint32_t prediv_s; - uint32_t usecs; - - prediv_s = getreg32(STM32_RTC_PRER) & RTC_PRER_PREDIV_S_MASK; - prediv_s >>= RTC_PRER_PREDIV_S_SHIFT; - - ssr &= RTC_SSR_MASK; - - /* Maximum prediv_s is 0x7fff, thus we can multiply by 100000 and - * still fit 32-bit unsigned integer. - */ - - usecs = (((prediv_s - ssr) * 100000) / (prediv_s + 1)) * 10; *nsec = usecs * 1000; } -#endif /* CONFIG_STM32_HAVE_RTC_SUBSECONDS */ - rtc_dumptime((FAR const struct tm *)tp, "Returning"); + rtc_dumptime((FAR const struct tm *)tp, &usecs, "Returning"); +#else /* CONFIG_STM32_HAVE_RTC_SUBSECONDS */ + rtc_dumptime((FAR const struct tm *)tp, NULL, "Returning"); +#endif + return OK; } @@ -1192,7 +1212,7 @@ int up_rtc_getdatetime(FAR struct tm *tp) * ****************************************************************************/ -#ifdef CONFIG_STM32_HAVE_RTC_SUBSECONDS +#ifdef CONFIG_STM32F7_HAVE_RTC_SUBSECONDS int up_rtc_getdatetime(FAR struct tm *tp) { return stm32_rtc_getdatetime_with_subseconds(tp, NULL); @@ -1221,7 +1241,7 @@ int stm32_rtc_setdatetime(FAR const struct tm *tp) uint32_t dr; int ret; - rtc_dumptime(tp, "Setting time"); + rtc_dumptime(tp, NULL, "Setting time"); /* Then write the broken out values to the RTC */ @@ -1337,7 +1357,7 @@ int stm32_rtc_setalarm(FAR struct alm_setalarm_s *alminfo) /* REVISIT: Should test that the time is in the future */ - rtc_dumptime(&alminfo->as_time, "New alarm time"); + rtc_dumptime(&alminfo->as_time, NULL, "New alarm time"); /* Break out the values to the HW alarm register format. The values in * all STM32 fields match the fields of struct tm in this case. Notice