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
*
* 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>
* Gregory Nutt <gnutt@nuttx.org>
*
@ -43,6 +43,7 @@
#include <nuttx/arch.h>
#include <stdint.h>
#include <stdbool.h>
#include <errno.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).
*
* Input Parameters:
* None
* protect - sets the write protections
*
* Returned Values:
* 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
*
* 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>
*
* Redistribution and use in source and binary forms, with or without
@ -42,6 +42,8 @@
#include <nuttx/config.h>
#include <stdbool.h>
#include "chip.h"
#include "chip/stm32_pwr.h"
@ -54,7 +56,8 @@
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C" {
extern "C"
{
#else
#define EXTERN extern
#endif
@ -71,14 +74,35 @@ extern "C" {
* and backup SRAM).
*
* Input Parameters:
* None
* writable - sets the write protections
*
* Returned Values:
* 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

View File

@ -39,6 +39,7 @@
#include <nuttx/config.h>
#include <stdbool.h>
#include <time.h>
#include <errno.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)
{
/* 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
* 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. */
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
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.
*/
ret = rtc_synchwait();
#ifdef CONFIG_RTC_ALARM
/* Clear the RTC alarm flags */
#ifdef CONFIG_RTC_ALARM
regval = getreg32(STM32_RTC_ISR);
regval &= ~(RTC_ISR_ALRAF|RTC_ISR_ALRBF);
putreg32(regval, STM32_RTC_ISR);
@ -645,11 +658,6 @@ int up_rtcinitialize(void)
* maximum performance.
*/
/* Enable access to the backup domain (RTC registers, RTC backup data registers
* and backup SRAM).
*/
stm32_pwr_enablebkp();
rtc_dumpregs("On reset");
/* 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();
/* 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 */
putreg32(RTC_MAGIC, STM32_RTC_BK0R);
@ -710,9 +724,16 @@ int up_rtcinitialize(void)
}
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)
{
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;
}
@ -1030,4 +1051,3 @@ int stm32_rtc_setalarm(FAR const struct timespec *tp, alarmcb_t callback)
#endif
#endif /* CONFIG_RTC */

View File

@ -6,7 +6,7 @@
*
* 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>
*
* Redistribution and use in source and binary forms, with or without
@ -164,7 +164,7 @@ static alarmcb_t g_alarmcb;
* Public Data
************************************************************************************/
/* Variable determines the state of the LSE oscilator.
/* Variable determines the state of the LSE oscillator.
* Possible errors:
* - on start-up
* - during operation, reported by LSE interrupt
@ -358,12 +358,17 @@ static int stm32_rtc_interrupt(int irq, void *context)
int up_rtcinitialize(void)
{
/* Set access to the peripheral, enable the backup domain (BKP) and the lower power
* extern 32,768Hz (Low-Speed External, LSE) oscillator. Configure the LSE to
* drive the RTC.
/* Enable write access to the backup domain (RTC registers, RTC backup data
* registers and backup SRAM).
*/
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();
/* TODO: Get state from this function, if everything is
@ -397,12 +402,19 @@ int up_rtcinitialize(void)
{
up_waste();
}
modifyreg16(STM32_RTC_CRH, 0, RTC_CRH_OWIE);
/* Alarm Int via EXTI Line */
/* 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;
}
@ -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
* 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
* 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
* 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
* interrupts will prevent suspensions and interruptions:
*/
@ -643,6 +655,7 @@ int stm32_rtc_setalarm(FAR const struct timespec *tp, alarmcb_t callback)
ret = OK;
}
return ret;
}
#endif
@ -684,6 +697,7 @@ int stm32_rtc_cancelalarm(void)
ret = OK;
}
return ret;
}
#endif