STM32F7: add support for LSE RTC and enable RTC subseconds
This commit is contained in:
parent
44f1326046
commit
41912ed98c
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
||||
|
86
arch/arm/src/stm32f7/stm32_lse.c
Normal file
86
arch/arm/src/stm32f7/stm32_lse.c
Normal file
@ -0,0 +1,86 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/stm32f7/stm32_lse.c
|
||||
*
|
||||
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
|
||||
* Authors: Gregory Nutt <gnutt@nuttx.org>
|
||||
* David Sidrane <david_s5@nscdg.com>
|
||||
*
|
||||
* 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 <nuttx/config.h>
|
||||
|
||||
#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);
|
||||
}
|
@ -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 <gnutt@nuttx.org>
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user