Merged in juniskane/nuttx_stm32l4/stm32l4_rtc_fixes_pr (pull request #509)

STM32L4 small fixes to RTC

* STM32L4 RTC: init mode was never exited because nested locking in rtc_synchwait() disabled backup domain access

* STM32L4 RTC: use backup register magic value instead of INITS bit

    The INITS (bit 4) of RTC_ISR register cannot be used to reliably
    detect backup domain reset. This is because we can operate our
    device without ever initializing the year field in the RTC calendar
    if our application does not care about correct date being set.

    Hardware also clears the bit when RTC date is set back to year 2000:

    nsh> date -s "Jan 01 00:00:00 2001"
    rtc_dumptime: Setting time:
    rtc_dumptime:   tm: 2001-01-01 00:00:00
    rtc_dumpregs: New time setting:
    rtc_dumpregs:       TR: 00000000
    rtc_dumpregs:       DR: 00012101
    rtc_dumpregs:       CR: 00000000
    rtc_dumpregs:      ISR: 00000037
    ...
    nsh> date -s "Jan 01 00:00:00 2000"
    rtc_dumptime: Setting time:
    rtc_dumptime:   tm: 2000-01-01 00:00:00
    rtc_dumpregs: New time setting:
    rtc_dumpregs:       TR: 00000000
    rtc_dumpregs:       DR: 0000c101
    rtc_dumpregs:       CR: 00000000
    rtc_dumpregs:      ISR: 00000027      <--- Bit 4 went missing!
    ...

    This patch allows us to do:

      stm32l4_pmstop(true);

      /* Stop mode disables HSE/HSI/PLL and wake happens with default system
       * clock. So reconfigure clocks early on Stop mode return.
       */

      stm32l4_clockconfig();

    without stm32l4_clockconfig() doing spurious and harmful backup domain
    reset in rcc_resetbkp().

* STM32L4 RTC: put back the SSR race condition workaround

    ST has confirmed that the issue has not been fixed, and that it applies
    to STM32L4 too (was not in errata sheets due to documentation bug)
    See discussion:

    https://community.st.com/thread/43710-issue-with-rtc-maximum-time-resolution

* STM32F4, STM32L4, STM32F7 RTC: add more CONFIG_RTC_NALARMS > 1 to reduce code size

* STM32L4: rename stm32l4_rtcc.c to stm32l4_rtc.c to better match STM32F7

    Cosmetic changes to comments

* STM32, STM32L4, STM32F7 RTC: stray comment and typos in chip/stm32_rtcc.h

* STM32L4 RTC: change maximum alarm time from 24h to one month

Approved-by: Gregory Nutt <gnutt@nuttx.org>
This commit is contained in:
Juha Niskanen 2017-10-13 12:32:33 +00:00 committed by Gregory Nutt
parent e013eb68de
commit 7c815e555c
11 changed files with 170 additions and 185 deletions

View File

@ -241,7 +241,7 @@
#define RTC_CR_ADD1H (1 << 16) /* Bit 16: Add 1 hour (summer time change) */
#define RTC_CR_SUB1H (1 << 17) /* Bit 17: Subtract 1 hour (winter time change) */
#define RTC_CR_BKP (1 << 18) /* Bit 18: Backup */
#define RTC_CR_COSEL (1 << 19) /* Bit 19 : Calibration output selection */
#define RTC_CR_COSEL (1 << 19) /* Bit 19: Calibration output selection */
#define RTC_CR_POL (1 << 20) /* Bit 20: Output polarity */
#define RTC_CR_OSEL_SHIFT (21) /* Bits 21-22: Output selection */
#define RTC_CR_OSEL_MASK (3 << RTC_CR_OSEL_SHIFT)
@ -271,7 +271,7 @@
#ifdef CONFIG_STM32_STM32L15XX
# define RTC_ISR_TAMP3F (1 << 15) /* Bit 15: TAMPER3 detection flag */
#endif
#define RTC_ISR_RECALPF (1 << 16) /* Bit 16: Recalibration pending Flag */
#define RTC_ISR_RECALPF (1 << 16) /* Bit 16: Recalibration pending flag */
#define RTC_ISR_ALLFLAGS (0x00017fff)
/* RTC prescaler register */
@ -352,11 +352,11 @@
/* RTC time stamp date register */
#define RTC_TSDR_DU_SHIFT (0) /* Bit 0-3: Date units in BCD format */
#define RTC_TSDR_DU_MASK (15 << RTC_TSDR_DU_SHIFT) */
#define RTC_TSDR_DU_MASK (15 << RTC_TSDR_DU_SHIFT)
#define RTC_TSDR_DT_SHIFT (4) /* Bits 4-5: Date tens in BCD format */
#define RTC_TSDR_DT_MASK (3 << RTC_TSDR_DT_SHIFT)
#define RTC_TSDR_MU_SHIFT (8) /* Bits 8-11: Month units in BCD format */
#define RTC_TSDR_MU_MASK (xx << RTC_TSDR_MU_SHIFT)
#define RTC_TSDR_MU_MASK (15 << RTC_TSDR_MU_SHIFT)
#define RTC_TSDR_MT (1 << 12) /* Bit 12: Month tens in BCD format */
#define RTC_TSDR_WDU_SHIFT (13) /* Bits 13-15: Week day units */
#define RTC_TSDR_WDU_MASK (7 << RTC_TSDR_WDU_SHIFT)

View File

@ -103,7 +103,7 @@ static int stm32_exti_alarm_isr(int irq, void *context, FAR void *arg)
* Sets/clears EXTI alarm interrupt.
*
* Parameters:
* - rising/falling edge: enables interrupt on rising/falling edget
* - rising/falling edge: enables interrupt on rising/falling edge
* - event: generate event when set
* - func: when non-NULL, generate interrupt
* - arg: Argument passed to the interrupt callback
@ -117,8 +117,6 @@ static int stm32_exti_alarm_isr(int irq, void *context, FAR void *arg)
int stm32_exti_alarm(bool risingedge, bool fallingedge, bool event,
xcpt_t func, void *arg)
{
/* Get the previous GPIO IRQ handler; Save the new IRQ handler. */
g_alarm_callback = func;
g_callback_arg = arg;
@ -152,7 +150,5 @@ int stm32_exti_alarm(bool risingedge, bool fallingedge, bool event,
func ? 0 : EXTI_RTC_ALARM,
func ? EXTI_RTC_ALARM : 0);
/* Return the old IRQ handler */
return OK;
}

View File

@ -858,7 +858,7 @@ static inline void rtc_enable_alarm(void)
}
#endif
/************************************************************************************
/****************************************************************************
* Name: stm32_rtc_getalarmdatetime
*
* Description:
@ -871,7 +871,7 @@ static inline void rtc_enable_alarm(void)
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
************************************************************************************/
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
static int stm32_rtc_getalarmdatetime(rtc_alarmreg_t reg, FAR struct tm *tp)
@ -1638,6 +1638,7 @@ int stm32_rtc_rdalarm(FAR struct alm_rdalarm_s *alminfo)
}
break;
#if CONFIG_RTC_NALARMS > 1
case RTC_ALARMB:
{
alarmreg = STM32_RTC_ALRMBR;
@ -1645,6 +1646,7 @@ int stm32_rtc_rdalarm(FAR struct alm_rdalarm_s *alminfo)
(struct tm *)alminfo->ar_time);
}
break;
#endif
default:
rtcerr("ERROR: Invalid ALARM%d\n", alminfo->ar_id);

View File

@ -222,7 +222,7 @@
#define RTC_CR_ADD1H (1 << 16) /* Bit 16: Add 1 hour (summer time change) */
#define RTC_CR_SUB1H (1 << 17) /* Bit 17: Subtract 1 hour (winter time change) */
#define RTC_CR_BKP (1 << 18) /* Bit 18: Backup */
#define RTC_CR_COSEL (1 << 19) /* Bit 19 : Calibration output selection */
#define RTC_CR_COSEL (1 << 19) /* Bit 19: Calibration output selection */
#define RTC_CR_POL (1 << 20) /* Bit 20: Output polarity */
#define RTC_CR_OSEL_SHIFT (21) /* Bits 21-22: Output selection */
#define RTC_CR_OSEL_MASK (3 << RTC_CR_OSEL_SHIFT)
@ -251,8 +251,8 @@
#define RTC_ISR_TAMP1F (1 << 13) /* Bit 13: Tamper detection flag */
#define RTC_ISR_TAMP2F (1 << 14) /* Bit 14: TAMPER2 detection flag */
#define RTC_ISR_TAMP3F (1 << 15) /* Bit 15: TAMPER3 detection flag */
#define RTC_ISR_RECALPF (1 << 16) /* Bit 16: Recalibration pending Flag */
#define RTC_ISR_ITSF (1 << 17) /* Bit 17:Internal tTime-stamp flagg */
#define RTC_ISR_RECALPF (1 << 16) /* Bit 16: Recalibration pending flag */
#define RTC_ISR_ITSF (1 << 17) /* Bit 17: Internal time-stamp flag */
#define RTC_ISR_ALLFLAGS (0x0003ffff)
/* RTC prescaler register */
@ -324,11 +324,11 @@
/* RTC time stamp date register */
#define RTC_TSDR_DU_SHIFT (0) /* Bit 0-3: Date units in BCD format */
#define RTC_TSDR_DU_MASK (15 << RTC_TSDR_DU_SHIFT) */
#define RTC_TSDR_DU_MASK (15 << RTC_TSDR_DU_SHIFT)
#define RTC_TSDR_DT_SHIFT (4) /* Bits 4-5: Date tens in BCD format */
#define RTC_TSDR_DT_MASK (3 << RTC_TSDR_DT_SHIFT)
#define RTC_TSDR_MU_SHIFT (8) /* Bits 8-11: Month units in BCD format */
#define RTC_TSDR_MU_MASK (xx << RTC_TSDR_MU_SHIFT)
#define RTC_TSDR_MU_MASK (15 << RTC_TSDR_MU_SHIFT)
#define RTC_TSDR_MT (1 << 12) /* Bit 12: Month tens in BCD format */
#define RTC_TSDR_WDU_SHIFT (13) /* Bits 13-15: Week day units */
#define RTC_TSDR_WDU_MASK (7 << RTC_TSDR_WDU_SHIFT)

View File

@ -125,8 +125,6 @@ static int stm32_exti_alarm_isr(int irq, void *context, FAR void *arg)
int stm32_exti_alarm(bool risingedge, bool fallingedge, bool event,
xcpt_t func, void *arg)
{
/* Get the previous GPIO IRQ handler; Save the new IRQ handler. */
g_alarm_callback = func;
g_callback_arg = arg;
@ -160,7 +158,5 @@ int stm32_exti_alarm(bool risingedge, bool fallingedge, bool event,
func ? 0 : EXTI_RTC_ALARM,
func ? EXTI_RTC_ALARM : 0);
/* Return the old IRQ handler */
return OK;
}

View File

@ -817,7 +817,7 @@ rtchw_set_alrmbr_exit:
}
#endif
/************************************************************************************
/****************************************************************************
* Name: stm32_rtc_getalarmdatetime
*
* Description:
@ -830,7 +830,7 @@ rtchw_set_alrmbr_exit:
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
************************************************************************************/
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
static int stm32_rtc_getalarmdatetime(rtc_alarmreg_t reg, FAR struct tm *tp)
@ -1418,7 +1418,7 @@ int up_rtc_settime(FAR const struct timespec *tp)
* Name: stm32_rtc_setalarm
*
* Description:
* Set an alarm to an asbolute time using associated hardware.
* Set an alarm to an absolute time using associated hardware.
*
* Input Parameters:
* alminfo - Information about the alarm configuration.
@ -1505,7 +1505,7 @@ int stm32_rtc_setalarm(FAR struct alm_setalarm_s *alminfo)
* Name: stm32_rtc_cancelalarm
*
* Description:
* Cancel an alaram.
* Cancel an alarm.
*
* Input Parameters:
* alarmid - Identifies the alarm to be cancelled
@ -1636,6 +1636,7 @@ int stm32_rtc_rdalarm(FAR struct alm_rdalarm_s *alminfo)
}
break;
#if CONFIG_RTC_NALARMS > 1
case RTC_ALARMB:
{
alarmreg = STM32_RTC_ALRMBR;
@ -1643,6 +1644,7 @@ int stm32_rtc_rdalarm(FAR struct alm_rdalarm_s *alminfo)
(struct tm *)alminfo->ar_time);
}
break;
#endif
default:
rtcerr("ERROR: Invalid ALARM%d\n", alminfo->ar_id);

View File

@ -184,7 +184,7 @@ CHIP_CSRCS += stm32l4_exti_alarm.c
endif
ifeq ($(CONFIG_RTC_DRIVER),y)
CHIP_CSRCS += stm32l4_rtc_lowerhalf.c
CHIP_CSRCS += stm32l4_rtcc.c
CHIP_CSRCS += stm32l4_rtc.c
endif
endif

View File

@ -252,8 +252,8 @@
#define RTC_ISR_TAMP1F (1 << 13) /* Bit 13: Tamper detection flag */
#define RTC_ISR_TAMP2F (1 << 14) /* Bit 14: TAMPER2 detection flag */
#define RTC_ISR_TAMP3F (1 << 15) /* Bit 15: TAMPER3 detection flag */
#define RTC_ISR_RECALPF (1 << 16) /* Bit 16: Recalibration pending Flag */
#define RTC_ISR_ITSF (1 << 17) /* Bit 17: Recalibration pending Flag */
#define RTC_ISR_RECALPF (1 << 16) /* Bit 16: Recalibration pending flag */
#define RTC_ISR_ITSF (1 << 17) /* Bit 17: Internal time-stamp flag */
#define RTC_ISR_ALLFLAGS (0x0003ffff)
/* RTC prescaler register */
@ -325,11 +325,11 @@
/* RTC time stamp date register */
#define RTC_TSDR_DU_SHIFT (0) /* Bit 0-3: Date units in BCD format */
#define RTC_TSDR_DU_MASK (15 << RTC_TSDR_DU_SHIFT) */
#define RTC_TSDR_DU_MASK (15 << RTC_TSDR_DU_SHIFT)
#define RTC_TSDR_DT_SHIFT (4) /* Bits 4-5: Date tens in BCD format */
#define RTC_TSDR_DT_MASK (3 << RTC_TSDR_DT_SHIFT)
#define RTC_TSDR_MU_SHIFT (8) /* Bits 8-11: Month units in BCD format */
#define RTC_TSDR_MU_MASK (xx << RTC_TSDR_MU_SHIFT)
#define RTC_TSDR_MU_MASK (15 << RTC_TSDR_MU_SHIFT)
#define RTC_TSDR_MT (1 << 12) /* Bit 12: Month tens in BCD format */
#define RTC_TSDR_WDU_SHIFT (13) /* Bits 13-15: Week day units */
#define RTC_TSDR_WDU_MASK (7 << RTC_TSDR_WDU_SHIFT)

View File

@ -117,8 +117,6 @@ static int stm32l4_exti_alarm_isr(int irq, void *context, FAR void *arg)
int stm32l4_exti_alarm(bool risingedge, bool fallingedge, bool event,
xcpt_t func, void *arg)
{
/* Get the previous GPIO IRQ handler; Save the new IRQ handler. */
g_alarm_callback = func;
g_callback_arg = arg;
@ -152,7 +150,5 @@ int stm32l4_exti_alarm(bool risingedge, bool fallingedge, bool event,
func ? 0 : EXTI1_RTC_ALARM,
func ? EXTI1_RTC_ALARM : 0);
/* Return the old IRQ handler */
return OK;
}

View File

@ -1,5 +1,5 @@
/************************************************************************************
* arch/arm/src/stm32l4/stm32l4_rtcc.c
/****************************************************************************
* arch/arm/src/stm32l4/stm32l4_rtc.c
*
* Copyright (C) 2012-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
@ -32,11 +32,11 @@
* 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 "chip.h"
@ -61,11 +61,11 @@
#ifdef CONFIG_RTC
/************************************************************************************
/****************************************************************************
* Pre-processor Definitions
************************************************************************************/
****************************************************************************/
/* Configuration ********************************************************************/
/* Configuration ************************************************************/
/* This RTC implementation supports
* - date/time RTC hardware
* - extended functions Alarm A and B
@ -99,30 +99,16 @@
#define RTC_MAGIC_TIME_SET CONFIG_RTC_MAGIC_TIME_SET
#define RTC_MAGIC_REG STM32L4_RTC_BKR(CONFIG_RTC_MAGIC_REG)
/* Constants ************************************************************************/
/* Constants ****************************************************************/
#define SYNCHRO_TIMEOUT (0x00020000)
#define INITMODE_TIMEOUT (0x00010000)
/* BCD conversions */
#define RTC_ALRMR_ENABLE (0x00000000)
#define rtc_reg_tr_bin2bcd(tp) \
((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))
#define rtc_reg_alrmr_bin2bcd(tm) \
((rtc_bin2bcd((tm)->tm_sec) << RTC_ALRMR_SU_SHIFT) | \
(rtc_bin2bcd((tm)->tm_min) << RTC_ALRMR_MNU_SHIFT) | \
(rtc_bin2bcd((tm)->tm_hour) << RTC_ALRMR_HU_SHIFT))
/* Need to ignore DATE/DOW part of alarm; rtc_reg_alrmr_bin2bcd only encodes hms */
#define RTC_ALRMR_ENABLE (0x80000000)
/************************************************************************************
/****************************************************************************
* Private Types
************************************************************************************/
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
typedef unsigned int rtc_alarmreg_t;
@ -134,9 +120,9 @@ struct alm_cbinfo_s
};
#endif
/************************************************************************************
/****************************************************************************
* Private Data
************************************************************************************/
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
/* Callback to use when an EXTI is activated */
@ -145,31 +131,33 @@ static struct alm_cbinfo_s g_alarmcb[RTC_ALARM_LAST];
static bool g_alarm_enabled; /* True: Alarm interrupts are enabled */
#endif
/************************************************************************************
/****************************************************************************
* Public Data
************************************************************************************/
****************************************************************************/
/* g_rtc_enabled is set true after the RTC has successfully initialized */
volatile bool g_rtc_enabled = false;
/************************************************************************************
/****************************************************************************
* Private Function Prototypes
************************************************************************************/
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
static int rtchw_check_alrawf(void);
static int rtchw_check_alrbwf(void);
static int rtchw_set_alrmar(rtc_alarmreg_t alarmreg);
#if CONFIG_RTC_NALARMS > 1
static int rtchw_check_alrbwf(void);
static int rtchw_set_alrmbr(rtc_alarmreg_t alarmreg);
#endif
static inline void rtc_enable_alarm(void);
#endif
/************************************************************************************
/****************************************************************************
* Private Functions
************************************************************************************/
****************************************************************************/
/************************************************************************************
/****************************************************************************
* Name: rtc_dumpregs
*
* Description:
@ -181,7 +169,7 @@ static inline void rtc_enable_alarm(void);
* Returned Value:
* None
*
************************************************************************************/
****************************************************************************/
#ifdef CONFIG_DEBUG_RTC_INFO
static void rtc_dumpregs(FAR const char *msg)
@ -204,12 +192,13 @@ static void rtc_dumpregs(FAR const char *msg)
rtcinfo(" TAMPCR: %08x\n", getreg32(STM32L4_RTC_TAMPCR));
rtcinfo("ALRMASSR: %08x\n", getreg32(STM32L4_RTC_ALRMASSR));
rtcinfo("ALRMBSSR: %08x\n", getreg32(STM32L4_RTC_ALRMBSSR));
rtcinfo("MAGICREG: %08x\n", getreg32(RTC_MAGIC_REG));
}
#else
# define rtc_dumpregs(msg)
#endif
/************************************************************************************
/****************************************************************************
* Name: rtc_dumptime
*
* Description:
@ -221,7 +210,7 @@ static void rtc_dumpregs(FAR const char *msg)
* Returned Value:
* None
*
************************************************************************************/
****************************************************************************/
#ifdef CONFIG_DEBUG_RTC_INFO
static void rtc_dumptime(FAR const struct tm *tp, FAR const char *msg)
@ -244,7 +233,7 @@ static void rtc_dumptime(FAR const struct tm *tp, FAR const char *msg)
# define rtc_dumptime(tp, msg)
#endif
/************************************************************************************
/****************************************************************************
* Name: rtc_wprunlock
*
* Description:
@ -256,7 +245,7 @@ static void rtc_dumptime(FAR const struct tm *tp, FAR const char *msg)
* Returned Value:
* None
*
************************************************************************************/
****************************************************************************/
static void rtc_wprunlock(void)
{
@ -277,7 +266,7 @@ static void rtc_wprunlock(void)
putreg32(0x53, STM32L4_RTC_WPR);
}
/************************************************************************************
/****************************************************************************
* Name: rtc_wprlock
*
* Description:
@ -289,7 +278,7 @@ static void rtc_wprunlock(void)
* Returned Value:
* None
*
************************************************************************************/
****************************************************************************/
static inline void rtc_wprlock(void)
{
@ -302,7 +291,7 @@ static inline void rtc_wprlock(void)
(void)stm32l4_pwr_enablebkp(false);
}
/************************************************************************************
/****************************************************************************
* Name: rtc_synchwait
*
* Description:
@ -315,7 +304,7 @@ static inline void rtc_wprlock(void)
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
************************************************************************************/
****************************************************************************/
static int rtc_synchwait(void)
{
@ -323,10 +312,6 @@ static int rtc_synchwait(void)
uint32_t regval;
int ret;
/* Disable the write protection for RTC registers */
rtc_wprunlock();
/* Clear Registers synchronization flag (RSF) */
regval = getreg32(STM32L4_RTC_ISR);
@ -348,13 +333,10 @@ static int rtc_synchwait(void)
}
}
/* Re-enable the write protection for RTC registers */
rtc_wprlock();
return ret;
}
/************************************************************************************
/****************************************************************************
* Name: rtc_enterinit
*
* Description:
@ -366,7 +348,7 @@ static int rtc_synchwait(void)
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
************************************************************************************/
****************************************************************************/
static int rtc_enterinit(void)
{
@ -402,7 +384,7 @@ static int rtc_enterinit(void)
return ret;
}
/************************************************************************************
/****************************************************************************
* Name: rtc_exitinit
*
* Description:
@ -414,7 +396,7 @@ static int rtc_enterinit(void)
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
************************************************************************************/
****************************************************************************/
static void rtc_exitinit(void)
{
@ -425,7 +407,7 @@ static void rtc_exitinit(void)
putreg32(regval, STM32L4_RTC_ISR);
}
/************************************************************************************
/****************************************************************************
* Name: rtc_bin2bcd
*
* Description:
@ -437,7 +419,7 @@ static void rtc_exitinit(void)
* Returned Value:
* The value in BCD representation
*
************************************************************************************/
****************************************************************************/
static uint32_t rtc_bin2bcd(int value)
{
@ -452,7 +434,7 @@ static uint32_t rtc_bin2bcd(int value)
return (msbcd << 4) | value;
}
/************************************************************************************
/****************************************************************************
* Name: rtc_bin2bcd
*
* Description:
@ -464,7 +446,7 @@ static uint32_t rtc_bin2bcd(int value)
* Returned Value:
* The value in binary representation
*
************************************************************************************/
****************************************************************************/
static int rtc_bcd2bin(uint32_t value)
{
@ -472,12 +454,12 @@ static int rtc_bcd2bin(uint32_t value)
return (int)(tens + (value & 0x0f));
}
/************************************************************************************
/****************************************************************************
* Name: rtc_resume
*
* Description:
* Called when the RTC was already initialized on a previous power cycle. This
* just brings the RTC back into full operation.
* Called when the RTC was already initialized on a previous power cycle.
* This just brings the RTC back into full operation.
*
* Input Parameters:
* None
@ -485,7 +467,7 @@ static int rtc_bcd2bin(uint32_t value)
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
************************************************************************************/
****************************************************************************/
static void rtc_resume(void)
{
@ -504,7 +486,7 @@ static void rtc_resume(void)
#endif
}
/************************************************************************************
/****************************************************************************
* Name: stm32l4_rtc_alarm_handler
*
* Description:
@ -517,7 +499,7 @@ static void rtc_resume(void)
* Returned Value:
* Zero (OK) on success; A negated errno value on failure.
*
************************************************************************************/
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
static int stm32l4_rtc_alarm_handler(int irq, FAR void *context, FAR void *rtc_handler_arg)
@ -565,6 +547,7 @@ static int stm32l4_rtc_alarm_handler(int irq, FAR void *context, FAR void *rtc_h
}
}
#if CONFIG_RTC_NALARMS > 1
cr = getreg32(STM32L4_RTC_CR);
if ((cr & RTC_CR_ALRBIE) != 0)
{
@ -592,6 +575,7 @@ static int stm32l4_rtc_alarm_handler(int irq, FAR void *context, FAR void *rtc_h
putreg32(isr, STM32L4_RTC_ISR);
}
}
#endif
/* Disable write access to the backup domain (RTC registers, RTC backup
* data registers and backup SRAM).
@ -603,7 +587,7 @@ static int stm32l4_rtc_alarm_handler(int irq, FAR void *context, FAR void *rtc_h
}
#endif
/************************************************************************************
/****************************************************************************
* Name: rtchw_check_alrXwf X= a or B
*
* Description:
@ -615,7 +599,7 @@ static int stm32l4_rtc_alarm_handler(int irq, FAR void *context, FAR void *rtc_h
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
************************************************************************************/
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
static int rtchw_check_alrawf(void)
@ -643,7 +627,7 @@ static int rtchw_check_alrawf(void)
}
#endif
#ifdef CONFIG_RTC_ALARM
#if defined(CONFIG_RTC_ALARM) && CONFIG_RTC_NALARMS > 1
static int rtchw_check_alrbwf(void)
{
volatile uint32_t timeout;
@ -669,12 +653,12 @@ static int rtchw_check_alrbwf(void)
}
#endif
/************************************************************************************
/****************************************************************************
* Name: stm32l4_rtchw_set_alrmXr X is a or b
*
* Description:
* Set the alarm (A or B) hardware registers, using the required hardware access
* protocol
* Set the alarm (A or B) hardware registers, using the required hardware
* access protocol
*
* Input Parameters:
* alarmreg - the register
@ -682,7 +666,7 @@ static int rtchw_check_alrbwf(void)
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
************************************************************************************/
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
static int rtchw_set_alrmar(rtc_alarmreg_t alarmreg)
@ -729,7 +713,7 @@ errout_with_wprunlock:
}
#endif
#ifdef CONFIG_RTC_ALARM
#if defined(CONFIG_RTC_ALARM) && CONFIG_RTC_NALARMS > 1
static int rtchw_set_alrmbr(rtc_alarmreg_t alarmreg)
{
int isr;
@ -813,7 +797,7 @@ static inline void rtc_enable_alarm(void)
}
#endif
/************************************************************************************
/****************************************************************************
* Name: stm32l4_rtc_getalarmdatetime
*
* Description:
@ -826,7 +810,7 @@ static inline void rtc_enable_alarm(void)
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
************************************************************************************/
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
static int stm32l4_rtc_getalarmdatetime(rtc_alarmreg_t reg, FAR struct tm *tp)
@ -857,36 +841,36 @@ static int stm32l4_rtc_getalarmdatetime(rtc_alarmreg_t reg, FAR struct tm *tp)
}
#endif
/************************************************************************************
/****************************************************************************
* Public Functions
************************************************************************************/
****************************************************************************/
/************************************************************************************
/****************************************************************************
* Name: stm32l4_rtc_is_initialized
*
* Description:
* Returns 'true' if the RTC has been initialized (according to the RTC itself).
* It will be 'false' if the RTC has never been initialized since first time power
* 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.
*
* Input Parameters:
* None
*
* Returned Value:
* bool -- true if the INITS flag is set in the ISR.
* Returns true if RTC has been initialized.
*
************************************************************************************/
****************************************************************************/
bool stm32l4_rtc_is_initialized(void)
{
uint32_t regval;
regval = getreg32(STM32L4_RTC_ISR);
regval = getreg32(RTC_MAGIC_REG);
return (regval & RTC_ISR_INITS) ? true : false;
return regval == RTC_MAGIC || regval == RTC_MAGIC_TIME_SET;
}
/************************************************************************************
/****************************************************************************
* Name: up_rtc_initialize
*
* Description:
@ -899,13 +883,12 @@ bool stm32l4_rtc_is_initialized(void)
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
************************************************************************************/
****************************************************************************/
int up_rtc_initialize(void)
{
bool init_stat;
uint32_t regval;
int ret;
rtc_dumpregs("Before Initialization");
@ -928,6 +911,8 @@ int up_rtc_initialize(void)
modifyreg32(STM32L4_RCC_BDCR, RCC_BDCR_RTCSEL_MASK, RCC_BDCR_RTCSEL_LSI);
#elif defined(CONFIG_STM32L4_RTC_LSECLOCK)
modifyreg32(STM32L4_RCC_BDCR, RCC_BDCR_RTCSEL_MASK, RCC_BDCR_RTCSEL_LSE);
#else
# error "No clock for RTC!"
#endif
/* Enable the RTC Clock by setting the RTCEN bit in the RCC register */
@ -954,7 +939,7 @@ int up_rtc_initialize(void)
rtc_dumpregs("After Failed Initialization");
return -1;
return ERROR;
}
else
{
@ -962,6 +947,7 @@ int up_rtc_initialize(void)
regval = getreg32(STM32L4_RTC_CR);
regval &= ~(RTC_CR_FMT | RTC_CR_OSEL_MASK | RTC_CR_POL);
putreg32(regval, STM32L4_RTC_CR);
/* Configure RTC pre-scaler with the required values */
@ -992,16 +978,19 @@ int up_rtc_initialize(void)
STM32L4_RTC_PRER);
#endif
/* Exit Initialization mode */
rtc_exitinit();
/* Wait for the RTC Time and Date registers to be synchronized with RTC APB
* clock.
*/
ret = rtc_synchwait();
(void)ret;
rtc_synchwait();
/* Exit Initialization mode */
/* Keep the fact that the RTC is initialized */
rtc_exitinit();
putreg32(RTC_MAGIC, RTC_MAGIC_REG);
/* Enable the write protection for RTC registers */
@ -1022,16 +1011,10 @@ int up_rtc_initialize(void)
(void)stm32l4_pwr_enablebkp(true);
/* Disable the write protection for RTC registers */
//rtc_wprunlock();
/* Write protection for RTC registers does not need to be disabled. */
rtc_resume();
/* Enable the write protection for RTC registers */
//rtc_wprlock();
/* Disable write access to the backup domain (RTC registers, RTC backup
* data registers and backup SRAM).
*/
@ -1045,29 +1028,7 @@ int up_rtc_initialize(void)
return OK;
}
/************************************************************************************
* Name: stm32_rtc_irqinitialize
*
* Description:
* Initialize IRQs for RTC, not possible during up_rtc_initialize because
* up_irqinitialize is called later.
*
* Input Parameters:
* None
*
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
************************************************************************************/
int stm32_rtc_irqinitialize(void)
{
/* Nothing to do */
return OK;
}
/************************************************************************************
/****************************************************************************
* Name: stm32l4_rtc_getdatetime_with_subseconds
*
* Description:
@ -1086,7 +1047,7 @@ int stm32_rtc_irqinitialize(void)
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
************************************************************************************/
****************************************************************************/
int stm32l4_rtc_getdatetime_with_subseconds(FAR struct tm *tp, FAR long *nsec)
{
@ -1097,13 +1058,33 @@ int stm32l4_rtc_getdatetime_with_subseconds(FAR struct tm *tp, FAR long *nsec)
uint32_t tr;
uint32_t tmp;
/* Sample the date time registers. Must read in this order. */
/* 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. 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(STM32L4_RTC_DR);
tr = getreg32(STM32L4_RTC_TR);
#ifdef CONFIG_STM32L4_HAVE_RTC_SUBSECONDS
ssr = getreg32(STM32L4_RTC_SSR);
ssr = getreg32(STM32L4_RTC_SSR);
tmp = getreg32(STM32L4_RTC_TR);
if (tmp != tr)
{
continue;
}
#endif
tr = getreg32(STM32L4_RTC_TR);
dr = getreg32(STM32L4_RTC_DR);
tmp = getreg32(STM32L4_RTC_DR);
if (tmp == dr)
{
break;
}
}
while (1);
rtc_dumpregs("Reading Time");
@ -1176,7 +1157,7 @@ int stm32l4_rtc_getdatetime_with_subseconds(FAR struct tm *tp, FAR long *nsec)
return OK;
}
/************************************************************************************
/****************************************************************************
* Name: up_rtc_getdatetime
*
* Description:
@ -1197,14 +1178,14 @@ int stm32l4_rtc_getdatetime_with_subseconds(FAR struct tm *tp, FAR long *nsec)
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
************************************************************************************/
****************************************************************************/
int up_rtc_getdatetime(FAR struct tm *tp)
{
return stm32l4_rtc_getdatetime_with_subseconds(tp, NULL);
}
/************************************************************************************
/****************************************************************************
* Name: up_rtc_getdatetime_with_subseconds
*
* Description:
@ -1226,7 +1207,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_STM32L4_HAVE_RTC_SUBSECONDS
@ -1238,7 +1219,7 @@ int up_rtc_getdatetime_with_subseconds(FAR struct tm *tp, FAR long *nsec)
}
#endif
/************************************************************************************
/****************************************************************************
* Name: stm32l4_rtc_setdatetime
*
* Description:
@ -1252,7 +1233,7 @@ int up_rtc_getdatetime_with_subseconds(FAR struct tm *tp, FAR long *nsec)
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
************************************************************************************/
****************************************************************************/
int stm32l4_rtc_setdatetime(FAR const struct tm *tp)
{
@ -1330,7 +1311,7 @@ int stm32l4_rtc_setdatetime(FAR const struct tm *tp)
return ret;
}
/************************************************************************************
/****************************************************************************
* Name: stm32l4_rtc_havesettime
*
* Description:
@ -1339,19 +1320,19 @@ int stm32l4_rtc_setdatetime(FAR const struct tm *tp)
* Returned Value:
* Returns true if RTC date-time have been previously set.
*
************************************************************************************/
****************************************************************************/
bool stm32l4_rtc_havesettime(void)
{
return getreg32(RTC_MAGIC_REG) == RTC_MAGIC_TIME_SET;
}
/************************************************************************************
/****************************************************************************
* Name: up_rtc_settime
*
* Description:
* Set the RTC to the provided time. All RTC implementations must be able to
* set their time based on a standard timespec.
* Set the RTC to the provided time. All RTC implementations must be able
* to set their time based on a standard timespec.
*
* Input Parameters:
* tp - the time to use
@ -1359,19 +1340,21 @@ bool stm32l4_rtc_havesettime(void)
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
************************************************************************************/
****************************************************************************/
int up_rtc_settime(FAR const struct timespec *tp)
{
FAR struct tm newtime;
/* Break out the time values (not that the time is set only to units of seconds) */
/* Break out the time values (not that the time is set only to units of
* seconds)
*/
(void)gmtime_r(&tp->tv_sec, &newtime);
return stm32l4_rtc_setdatetime(&newtime);
}
/************************************************************************************
/****************************************************************************
* Name: stm32l4_rtc_setalarm
*
* Description:
@ -1383,7 +1366,7 @@ int up_rtc_settime(FAR const struct timespec *tp)
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
************************************************************************************/
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
int stm32l4_rtc_setalarm(FAR struct alm_setalarm_s *alminfo)
@ -1403,9 +1386,15 @@ int stm32l4_rtc_setalarm(FAR struct alm_setalarm_s *alminfo)
rtc_dumptime(&alminfo->as_time, "New alarm time");
/* Break out the values to the HW alarm register format */
/* Break out the values to the HW alarm register format. The values in
* all STM32L4 fields match the fields of struct tm in this case. Notice
* that the alarm is limited to one month.
*/
alarmreg = rtc_reg_alrmr_bin2bcd(&alminfo->as_time);
alarmreg = (rtc_bin2bcd(alminfo->as_time.tm_sec) << RTC_ALRMR_SU_SHIFT) |
(rtc_bin2bcd(alminfo->as_time.tm_min) << RTC_ALRMR_MNU_SHIFT) |
(rtc_bin2bcd(alminfo->as_time.tm_hour) << RTC_ALRMR_HU_SHIFT) |
(rtc_bin2bcd(alminfo->as_time.tm_mday) << RTC_ALRMR_DU_SHIFT);
/* Set the alarm in hardware and enable interrupts from the RTC */
@ -1426,6 +1415,7 @@ int stm32l4_rtc_setalarm(FAR struct alm_setalarm_s *alminfo)
}
break;
#if CONFIG_RTC_NALARMS > 1
case RTC_ALARMB:
{
cbinfo = &g_alarmcb[RTC_ALARMB];
@ -1440,6 +1430,7 @@ int stm32l4_rtc_setalarm(FAR struct alm_setalarm_s *alminfo)
}
}
break;
#endif
default:
rtcerr("ERROR: Invalid ALARM%d\n", alminfo->as_id);
@ -1509,6 +1500,7 @@ int stm32l4_rtc_cancelalarm(enum alm_id_e alarmid)
}
break;
#if CONFIG_RTC_NALARMS > 1
case RTC_ALARMB:
{
/* Cancel the global callback function */
@ -1540,6 +1532,7 @@ int stm32l4_rtc_cancelalarm(enum alm_id_e alarmid)
ret = OK;
}
break;
#endif
default:
rtcerr("ERROR: Invalid ALARM%d\n", alarmid);
@ -1554,7 +1547,7 @@ errout_with_wprunlock:
}
#endif
/************************************************************************************
/****************************************************************************
* Name: stm32l4_rtc_rdalarm
*
* Description:
@ -1566,7 +1559,7 @@ errout_with_wprunlock:
* 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)
@ -1587,6 +1580,7 @@ int stm32l4_rtc_rdalarm(FAR struct alm_rdalarm_s *alminfo)
}
break;
#if CONFIG_RTC_NALARMS > 1
case RTC_ALARMB:
{
alarmreg = STM32L4_RTC_ALRMBR;
@ -1594,6 +1588,7 @@ int stm32l4_rtc_rdalarm(FAR struct alm_rdalarm_s *alminfo)
(struct tm *)alminfo->ar_time);
}
break;
#endif
default:
rtcerr("ERROR: Invalid ALARM%d\n", alminfo->ar_id);

View File

@ -117,21 +117,19 @@ extern "C"
* Name: stm32l4_rtc_is_initialized
*
* Description:
* Returns 'true' if the RTC has been initialized (according to the RTC itself).
* It will be 'false' if the RTC has never been initialized since first time power
* 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.
*
* Input Parameters:
* None
*
* Returned Value:
* bool -- true if the INITS flag is set in the ISR.
* Returns true if RTC has been initialized.
*
************************************************************************************/
#ifdef CONFIG_RTC_DRIVER
bool stm32l4_rtc_is_initialized(void);
#endif
/****************************************************************************
* Name: stm32l4_rtc_getdatetime_with_subseconds