Changes to support fully write protecting the backup domain. N.B. stm32_pwr_enablebkp did not account for the delay from enable to the domain being writable. The KISS solution is a up_udelay. A more complex solution would be a negated write test with restore. From David Sidrane.

This commit is contained in:
Gregory Nutt 2015-02-21 14:53:33 -06:00
parent 2d91128111
commit 7d43cf2087
4 changed files with 132 additions and 25 deletions

View File

@ -2,7 +2,7 @@
* arch/arm/src/stm32/stm32_pwr.c * arch/arm/src/stm32/stm32_pwr.c
* *
* Copyright (C) 2011 Uros Platise. All rights reserved. * Copyright (C) 2011 Uros Platise. All rights reserved.
* Copyright (C) 2013 Gregory Nutt. All rights reserved. * Copyright (C) 2013, 2015 Gregory Nutt. All rights reserved.
* Authors: Uros Platise <uros.platise@isotel.eu> * Authors: Uros Platise <uros.platise@isotel.eu>
* Gregory Nutt <gnutt@nuttx.org> * Gregory Nutt <gnutt@nuttx.org>
* *
@ -43,6 +43,7 @@
#include <nuttx/arch.h> #include <nuttx/arch.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include <errno.h> #include <errno.h>
#include "up_arch.h" #include "up_arch.h"
@ -85,16 +86,64 @@ static inline void stm32_pwr_modifyreg(uint8_t offset, uint16_t clearbits, uint1
* and backup SRAM). * and backup SRAM).
* *
* Input Parameters: * Input Parameters:
* None * protect - sets the write protections
* *
* Returned Values: * Returned Values:
* None * None
* *
************************************************************************************/ ************************************************************************************/
void stm32_pwr_enablebkp(void) void stm32_pwr_enablebkp(bool writable)
{ {
stm32_pwr_modifyreg(STM32_PWR_CR_OFFSET, 0, PWR_CR_DBP); uint16_t regval;
/* Enable or disable the ability to write*/
regval = stm32_pwr_getreg(STM32_PWR_CR_OFFSET);
regval &= ~PWR_CR_DBP;
regval |= writable ? PWR_CR_DBP : 0;
stm32_pwr_putreg(STM32_PWR_CR_OFFSET, regval);
if (writable)
{
/* Enable does not happen right away */
up_udelay(4);
}
}
/************************************************************************************
* Name: stm32_pwr_enablebreg
*
* Description:
* Enables the Backup regulator, the Backup regulator (used to maintain backup
* SRAM content in Standby and VBAT modes) is enabled. If BRE is reset, the backup
* regulator is switched off. The backup SRAM can still be used but its content will
* be lost in the Standby and VBAT modes. Once set, the application must wait that
* the Backup Regulator Ready flag (BRR) is set to indicate that the data written
* into the RAM will be maintained in the Standby and VBAT modes.
*
* Input Parameters:
* regon - state to set it to
*
* Returned Values:
* None
*
************************************************************************************/
void stm32_pwr_enablebreg(bool regon)
{
uint16_t regval;
regval = stm32_pwr_getreg(STM32_PWR_CSR_OFFSET);
regval &= ~PWR_CSR_BRE;
regval |= regon ? PWR_CSR_BRE : 0;
stm32_pwr_putreg(STM32_PWR_CSR_OFFSET, regval);
if (regon)
{
while ((stm32_pwr_getreg(STM32_PWR_CSR_OFFSET) & PWR_CSR_BRR) == 0);
}
} }
/************************************************************************************ /************************************************************************************

View File

@ -1,7 +1,7 @@
/************************************************************************************ /************************************************************************************
* arch/arm/src/stm32/stm32_pwr.h * arch/arm/src/stm32/stm32_pwr.h
* *
* Copyright (C) 2009, 2013 Gregory Nutt. All rights reserved. * Copyright (C) 2009, 2013, 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -42,6 +42,8 @@
#include <nuttx/config.h> #include <nuttx/config.h>
#include <stdbool.h>
#include "chip.h" #include "chip.h"
#include "chip/stm32_pwr.h" #include "chip/stm32_pwr.h"
@ -54,7 +56,8 @@
#undef EXTERN #undef EXTERN
#if defined(__cplusplus) #if defined(__cplusplus)
#define EXTERN extern "C" #define EXTERN extern "C"
extern "C" { extern "C"
{
#else #else
#define EXTERN extern #define EXTERN extern
#endif #endif
@ -71,14 +74,35 @@ extern "C" {
* and backup SRAM). * and backup SRAM).
* *
* Input Parameters: * Input Parameters:
* None * writable - sets the write protections
* *
* Returned Values: * Returned Values:
* None * None
* *
************************************************************************************/ ************************************************************************************/
void stm32_pwr_enablebkp(void); void stm32_pwr_enablebkp(bool writable);
/************************************************************************************
* Name: stm32_pwr_enablebreg
*
* Description:
* Enables the Backup regulator, the Backup regulator (used to maintain backup
* SRAM content in Standby and VBAT modes) is enabled. If BRE is reset, the backup
* regulator is switched off. The backup SRAM can still be used but its content will
* be lost in the Standby and VBAT modes. Once set, the application must wait that
* the Backup Regulator Ready flag (BRR) is set to indicate that the data written
* into the RAM will be maintained in the Standby and VBAT modes.
*
* Input Parameters:
* regon - state to set it to
*
* Returned Values:
* None
*
************************************************************************************/
void stm32_pwr_enablebreg(bool regon);
/************************************************************************************ /************************************************************************************
* Name: stm32_pwr_setvos * Name: stm32_pwr_setvos

View File

@ -39,6 +39,7 @@
#include <nuttx/config.h> #include <nuttx/config.h>
#include <stdbool.h>
#include <time.h> #include <time.h>
#include <errno.h> #include <errno.h>
#include <debug.h> #include <debug.h>
@ -219,6 +220,12 @@ static void rtc_dumptime(FAR struct tm *tp, FAR const char *msg)
static void rtc_wprunlock(void) static void rtc_wprunlock(void)
{ {
/* Enable write access to the backup domain (RTC registers, RTC backup data
* registers and backup SRAM).
*/
stm32_pwr_enablebkp(true);
/* The following steps are required to unlock the write protection on all the /* The following steps are required to unlock the write protection on all the
* RTC registers (except for RTC_ISR[13:8], RTC_TAFCR, and RTC_BKPxR). * RTC registers (except for RTC_ISR[13:8], RTC_TAFCR, and RTC_BKPxR).
* *
@ -251,6 +258,12 @@ static inline void rtc_wprlock(void)
/* Writing any wrong key reactivates the write protection. */ /* Writing any wrong key reactivates the write protection. */
putreg32(0xff, STM32_RTC_WPR); putreg32(0xff, STM32_RTC_WPR);
/* Disable write access to the backup domain (RTC registers, RTC backup data registers
* and backup SRAM).
*/
stm32_pwr_enablebkp(false);
} }
/************************************************************************************ /************************************************************************************
@ -569,15 +582,15 @@ static int rtc_resume(void)
#endif #endif
int ret; int ret;
/* Wait for the RTC Time and Date registers to be syncrhonized with RTC APB /* Wait for the RTC Time and Date registers to be synchronized with RTC APB
* clock. * clock.
*/ */
ret = rtc_synchwait(); ret = rtc_synchwait();
#ifdef CONFIG_RTC_ALARM
/* Clear the RTC alarm flags */ /* Clear the RTC alarm flags */
#ifdef CONFIG_RTC_ALARM
regval = getreg32(STM32_RTC_ISR); regval = getreg32(STM32_RTC_ISR);
regval &= ~(RTC_ISR_ALRAF|RTC_ISR_ALRBF); regval &= ~(RTC_ISR_ALRAF|RTC_ISR_ALRBF);
putreg32(regval, STM32_RTC_ISR); putreg32(regval, STM32_RTC_ISR);
@ -645,11 +658,6 @@ int up_rtcinitialize(void)
* maximum performance. * maximum performance.
*/ */
/* Enable access to the backup domain (RTC registers, RTC backup data registers
* and backup SRAM).
*/
stm32_pwr_enablebkp();
rtc_dumpregs("On reset"); rtc_dumpregs("On reset");
/* Enable the External Low-Speed (LSE) Oscillator setup the LSE as the RTC clock /* Enable the External Low-Speed (LSE) Oscillator setup the LSE as the RTC clock
@ -677,6 +685,12 @@ int up_rtcinitialize(void)
ret = rtc_setup(); ret = rtc_setup();
/* Enable write access to the backup domain (RTC registers, RTC
* backup data registers and backup SRAM).
*/
stm32_pwr_enablebkp(true);
/* Remember that the RTC is initialized */ /* Remember that the RTC is initialized */
putreg32(RTC_MAGIC, STM32_RTC_BK0R); putreg32(RTC_MAGIC, STM32_RTC_BK0R);
@ -710,9 +724,16 @@ int up_rtcinitialize(void)
} }
while (ret != OK && ++nretry < maxretry); while (ret != OK && ++nretry < maxretry);
/* Disable write access to the backup domain (RTC registers, RTC backup
* data registers and backup SRAM).
*/
stm32_pwr_enablebkp(false);
if (ret != OK && nretry > 0) if (ret != OK && nretry > 0)
{ {
rtclldbg("setup/resume ran %d times and failed with %d\n", nretry, ret); rtclldbg("setup/resume ran %d times and failed with %d\n",
nretry, ret);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
@ -1030,4 +1051,3 @@ int stm32_rtc_setalarm(FAR const struct timespec *tp, alarmcb_t callback)
#endif #endif
#endif /* CONFIG_RTC */ #endif /* CONFIG_RTC */

View File

@ -6,7 +6,7 @@
* *
* With extensions, modifications by: * With extensions, modifications by:
* *
* Copyright (C) 2011-2013 Gregory Nutt. All rights reserved. * Copyright (C) 2011-2013, 2015 Gregory Nutt. All rights reserved.
* Author: Gregroy Nutt <gnutt@nuttx.org> * Author: Gregroy Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -164,7 +164,7 @@ static alarmcb_t g_alarmcb;
* Public Data * Public Data
************************************************************************************/ ************************************************************************************/
/* Variable determines the state of the LSE oscilator. /* Variable determines the state of the LSE oscillator.
* Possible errors: * Possible errors:
* - on start-up * - on start-up
* - during operation, reported by LSE interrupt * - during operation, reported by LSE interrupt
@ -358,12 +358,17 @@ static int stm32_rtc_interrupt(int irq, void *context)
int up_rtcinitialize(void) int up_rtcinitialize(void)
{ {
/* Set access to the peripheral, enable the backup domain (BKP) and the lower power /* Enable write access to the backup domain (RTC registers, RTC backup data
* extern 32,768Hz (Low-Speed External, LSE) oscillator. Configure the LSE to * registers and backup SRAM).
* drive the RTC. */
stm32_pwr_enablebkp(true);
/* Set access to the peripheral, enable the backup domain (BKP) and the lower
* power external 32,768Hz (Low-Speed External, LSE) oscillator. Configure the
* LSE to drive the RTC.
*/ */
stm32_pwr_enablebkp();
stm32_rcc_enablelse(); stm32_rcc_enablelse();
/* TODO: Get state from this function, if everything is /* TODO: Get state from this function, if everything is
@ -397,12 +402,19 @@ int up_rtcinitialize(void)
{ {
up_waste(); up_waste();
} }
modifyreg16(STM32_RTC_CRH, 0, RTC_CRH_OWIE); modifyreg16(STM32_RTC_CRH, 0, RTC_CRH_OWIE);
/* Alarm Int via EXTI Line */ /* Alarm Int via EXTI Line */
/* STM32_IRQ_RTCALRM 41: RTC alarm through EXTI line interrupt */ /* STM32_IRQ_RTCALRM 41: RTC alarm through EXTI line interrupt */
/* Disable write access to the backup domain (RTC registers, RTC backup data
* registers and backup SRAM).
*/
stm32_pwr_enablebkp(false);
return OK; return OK;
} }
@ -434,7 +446,7 @@ time_t up_rtc_time(void)
/* The RTC counter is read from two 16-bit registers to form one 32-bit /* The RTC counter is read from two 16-bit registers to form one 32-bit
* value. Because these are non-atomic operations, many things can happen * value. Because these are non-atomic operations, many things can happen
* between the two reads: This thread could get suspended or interrrupted * between the two reads: This thread could get suspended or interrupted
* or the lower 16-bit counter could rollover between reads. Disabling * or the lower 16-bit counter could rollover between reads. Disabling
* interrupts will prevent suspensions and interruptions: * interrupts will prevent suspensions and interruptions:
*/ */
@ -502,7 +514,7 @@ int up_rtc_gettime(FAR struct timespec *tp)
/* The RTC counter is read from two 16-bit registers to form one 32-bit /* The RTC counter is read from two 16-bit registers to form one 32-bit
* value. Because these are non-atomic operations, many things can happen * value. Because these are non-atomic operations, many things can happen
* between the two reads: This thread could get suspended or interrrupted * between the two reads: This thread could get suspended or interrupted
* or the lower 16-bit counter could rollover between reads. Disabling * or the lower 16-bit counter could rollover between reads. Disabling
* interrupts will prevent suspensions and interruptions: * interrupts will prevent suspensions and interruptions:
*/ */
@ -643,6 +655,7 @@ int stm32_rtc_setalarm(FAR const struct timespec *tp, alarmcb_t callback)
ret = OK; ret = OK;
} }
return ret; return ret;
} }
#endif #endif
@ -684,6 +697,7 @@ int stm32_rtc_cancelalarm(void)
ret = OK; ret = OK;
} }
return ret; return ret;
} }
#endif #endif