Merged in leif_jakob/nuttx/stm32f1_rtc_fix (pull request #393)

multiple fixes for stm32f1xx RTC clock

Approved-by: Gregory Nutt <gnutt@nuttx.org>
This commit is contained in:
Leif Jakob 2017-06-14 21:07:55 +00:00 committed by Gregory Nutt
commit 06246cc283
7 changed files with 177 additions and 29 deletions

View File

@ -387,6 +387,11 @@ void up_irqinitialize(void)
up_enable_irq(STM32_IRQ_MEMFAULT);
#endif
#ifdef CONFIG_RTC
/* RTC was initialized earlier but IRQs weren't ready at that time */
stm32_rtc_irqinitialize();
#endif
/* Attach all other processor exceptions (except reset and sys tick) */
#ifdef CONFIG_DEBUG_FEATURES

View File

@ -79,21 +79,35 @@
#define STM32_RTC_PRESCALER_SECOND 32767 /* Default prescaler to get a second base */
#define STM32_RTC_PRESCALER_MIN 1 /* Maximum speed of 16384 Hz */
#if defined(CONFIG_STM32_STM32F10XX)
/* RTC is only a counter, store RTC data in backup domain register DR1 (if CONFIG_RTC_HIRES) and DR2 (state) */
#if !defined(CONFIG_RTC_MAGIC)
# define CONFIG_RTC_MAGIC (0xfacefeee)
# define CONFIG_RTC_MAGIC (0xface) /* only 16 bit */
#endif
#if !defined(CONFIG_RTC_MAGIC_TIME_SET)
# define CONFIG_RTC_MAGIC_TIME_SET (CONFIG_RTC_MAGIC + 1)
#define RTC_MAGIC_REG STM32_BKP_DR2
#else /* !CONFIG_STM32_STM32F10XX */
#if !defined(CONFIG_RTC_MAGIC)
# define CONFIG_RTC_MAGIC (0xfacefeee)
#endif
#if !defined(CONFIG_RTC_MAGIC_REG)
# define CONFIG_RTC_MAGIC_REG (0)
#endif
#define RTC_MAGIC_REG STM32_RTC_BKR(CONFIG_RTC_MAGIC_REG)
#endif /* CONFIG_STM32_STM32F10XX */
#define RTC_MAGIC CONFIG_RTC_MAGIC
#define RTC_MAGIC_TIME_SET CONFIG_RTC_MAGIC_TIME_SET
#define RTC_MAGIC_REG STM32_RTC_BKR(CONFIG_RTC_MAGIC_REG)
#if !defined(CONFIG_RTC_MAGIC_TIME_SET)
# define CONFIG_RTC_MAGIC_TIME_SET (CONFIG_RTC_MAGIC + 1)
#endif
/****************************************************************************
* Public Types
@ -118,6 +132,23 @@ extern "C"
* Public Functions
****************************************************************************/
/************************************************************************************
* 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);
/****************************************************************************
* Name: stm32_rtc_getdatetime_with_subseconds
*

View File

@ -365,7 +365,11 @@ static int stm32_settime(FAR struct rtc_lowerhalf_s *lower,
static bool stm32_havesettime(FAR struct rtc_lowerhalf_s *lower)
{
#if defined(CONFIG_STM32_STM32F10XX)
return getreg16(RTC_MAGIC_REG) == RTC_MAGIC_TIME_SET;
#else
return getreg32(RTC_MAGIC_REG) == RTC_MAGIC_TIME_SET;
#endif
}
/****************************************************************************

View File

@ -763,17 +763,37 @@ int up_rtc_initialize(void)
* 3. Configure the RTC to generate RTC alarms (Alarm A or Alarm B).
*/
g_rtc_enabled = true;
rtc_dumpregs("After Initialization");
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)
{
#ifdef CONFIG_RTC_ALARM
# warning "Missing EXTI setup logic"
/* Then attach the ALARM interrupt handler */
/* then attach the ALARM interrupt handler */
irq_attach(STM32_IRQ_RTC_WKUP, rtc_interrupt, NULL);
up_enable_irq(STM32_IRQ_RTC_WKUP);
#endif
g_rtc_enabled = true;
rtc_dumpregs("After Initialization");
return OK;
}

View File

@ -331,7 +331,9 @@ static int stm32_rtc_interrupt(int irq, void *context, FAR void *arg)
#ifdef CONFIG_RTC_HIRES
if ((source & RTC_CRL_OWF) != 0)
{
stm32_pwr_enablebkp(true);
putreg16(getreg16(RTC_TIMEMSB_REG) + 1, RTC_TIMEMSB_REG);
stm32_pwr_enablebkp(false);
}
#endif
@ -373,25 +375,33 @@ static int stm32_rtc_interrupt(int irq, void *context, FAR void *arg)
int up_rtc_initialize(void)
{
uint32_t regval;
/* Enable write access to the backup domain (RTC registers, RTC backup data
* registers and backup SRAM).
*/
stm32_pwr_enablebkp(true);
regval = getreg32(RTC_MAGIC_REG);
if (regval != RTC_MAGIC && regval != RTC_MAGIC_TIME_SET)
{
/* reset backup domain if bad magic */
modifyreg32(STM32_RCC_BDCR, 0, RCC_BDCR_BDRST);
modifyreg32(STM32_RCC_BDCR, RCC_BDCR_BDRST, 0);
putreg16(RTC_MAGIC, RTC_MAGIC_REG);
}
/* Select the lower power external 32,768Hz (Low-Speed External, LSE) oscillator
* as RTC Clock Source and enable the Clock */
modifyreg16(STM32_RCC_BDCR, RCC_BDCR_RTCSEL_MASK, RCC_BDCR_RTCSEL_LSE);
/* enable RTC and wait for RSF */
modifyreg16(STM32_RCC_BDCR, 0, RCC_BDCR_RTCEN);
/* TODO: Get state from this function, if everything is
* okay and whether it is already enabled (if it was disabled
* reset upper time register)
*/
g_rtc_enabled = true;
/* TODO: Possible stall? should we set the timeout period? and return with -1 */
stm32_rtc_wait4rsf();
@ -403,21 +413,19 @@ int up_rtc_initialize(void)
putreg16(STM32_RTC_PRESCALAR_VALUE & 0xffff, STM32_RTC_PRLL);
stm32_rtc_endwr();
/* Configure RTC interrupt to catch overflow and alarm interrupts. */
stm32_rtc_wait4rsf();
#if defined(CONFIG_RTC_HIRES) || defined(CONFIG_RTC_ALARM)
irq_attach(STM32_IRQ_RTC, stm32_rtc_interrupt, NULL);
up_enable_irq(STM32_IRQ_RTC);
#ifdef CONFIG_RTC_HIRES
/* enable overflow interrupt - alarm interrupt is enabled in stm32_rtc_setalarm */
modifyreg16(STM32_RTC_CRH, 0, RTC_CRH_OWIE);
#endif
/* Previous write is done? This is required prior writing into CRH */
/* TODO: Get state from this function, if everything is
* okay and whether it is already enabled (if it was disabled
* reset upper time register)
*/
while ((getreg16(STM32_RTC_CRL) & RTC_CRL_RTOFF) == 0)
{
up_waste();
}
modifyreg16(STM32_RTC_CRH, 0, RTC_CRH_OWIE);
g_rtc_enabled = true;
/* Alarm Int via EXTI Line */
@ -432,6 +440,33 @@ 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)
{
/* Configure RTC interrupt to catch overflow and alarm interrupts. */
#if defined(CONFIG_RTC_HIRES) || defined(CONFIG_RTC_ALARM)
irq_attach(STM32_IRQ_RTC, stm32_rtc_interrupt, NULL);
up_enable_irq(STM32_IRQ_RTC);
#endif
return OK;
}
/************************************************************************************
* Name: up_rtc_time
*
@ -613,6 +648,7 @@ int up_rtc_settime(FAR const struct timespec *tp)
do
{
stm32_rtc_beginwr();
putreg16(RTC_MAGIC, RTC_MAGIC_TIME_SET);
putreg16(regvals.cnth, STM32_RTC_CNTH);
putreg16(regvals.cntl, STM32_RTC_CNTL);
cntl = getreg16(STM32_RTC_CNTL);
@ -652,6 +688,8 @@ int stm32_rtc_setalarm(FAR const struct timespec *tp, alarmcb_t callback)
uint16_t cr;
int ret = -EBUSY;
flags = enter_critical_section();
/* Is there already something waiting on the ALARM? */
if (g_alarmcb == NULL)
@ -664,6 +702,8 @@ int stm32_rtc_setalarm(FAR const struct timespec *tp, alarmcb_t callback)
stm32_rtc_breakout(tp, &regvals);
stm32_pwr_enablebkp(true);
/* Enable RTC alarm */
cr = getreg16(STM32_RTC_CRH);
@ -672,16 +712,18 @@ int stm32_rtc_setalarm(FAR const struct timespec *tp, alarmcb_t callback)
/* The set the alarm */
flags = enter_critical_section();
stm32_rtc_beginwr();
putreg16(regvals.cnth, STM32_RTC_ALRH);
putreg16(regvals.cntl, STM32_RTC_ALRL);
stm32_rtc_endwr();
leave_critical_section(flags);
stm32_pwr_enablebkp(false);
ret = OK;
}
leave_critical_section(flags);
return ret;
}
#endif
@ -706,6 +748,8 @@ int stm32_rtc_cancelalarm(void)
irqstate_t flags;
int ret = -ENODATA;
flags = enter_critical_section();
if (g_alarmcb != NULL)
{
/* Cancel the global callback function */
@ -714,16 +758,18 @@ int stm32_rtc_cancelalarm(void)
/* Unset the alarm */
flags = enter_critical_section();
stm32_pwr_enablebkp(true);
stm32_rtc_beginwr();
putreg16(0xffff, STM32_RTC_ALRH);
putreg16(0xffff, STM32_RTC_ALRL);
stm32_rtc_endwr();
leave_critical_section(flags);
stm32_pwr_enablebkp(false);
ret = OK;
}
leave_critical_section(flags);
return ret;
}
#endif

View File

@ -1058,6 +1058,27 @@ 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: stm32_rtc_getdatetime_with_subseconds
*

View File

@ -1003,6 +1003,27 @@ 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
*