From 7d43cf2087eed585eac1406177d4d3e992168fe6 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 21 Feb 2015 14:53:33 -0600 Subject: [PATCH] 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. --- arch/arm/src/stm32/stm32_pwr.c | 57 ++++++++++++++++++++++++++-- arch/arm/src/stm32/stm32_pwr.h | 32 ++++++++++++++-- arch/arm/src/stm32/stm32_rtcc.c | 38 ++++++++++++++----- arch/arm/src/stm32/stm32_rtcounter.c | 30 +++++++++++---- 4 files changed, 132 insertions(+), 25 deletions(-) diff --git a/arch/arm/src/stm32/stm32_pwr.c b/arch/arm/src/stm32/stm32_pwr.c index 21a3975992..73febc5180 100644 --- a/arch/arm/src/stm32/stm32_pwr.c +++ b/arch/arm/src/stm32/stm32_pwr.c @@ -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 * Gregory Nutt * @@ -43,6 +43,7 @@ #include #include +#include #include #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); + } } /************************************************************************************ diff --git a/arch/arm/src/stm32/stm32_pwr.h b/arch/arm/src/stm32/stm32_pwr.h index 2ec3de6dc3..7559531a0e 100644 --- a/arch/arm/src/stm32/stm32_pwr.h +++ b/arch/arm/src/stm32/stm32_pwr.h @@ -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 * * Redistribution and use in source and binary forms, with or without @@ -42,6 +42,8 @@ #include +#include + #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 diff --git a/arch/arm/src/stm32/stm32_rtcc.c b/arch/arm/src/stm32/stm32_rtcc.c index a1fc5c1a9d..884ac8cacb 100644 --- a/arch/arm/src/stm32/stm32_rtcc.c +++ b/arch/arm/src/stm32/stm32_rtcc.c @@ -39,6 +39,7 @@ #include +#include #include #include #include @@ -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 */ - diff --git a/arch/arm/src/stm32/stm32_rtcounter.c b/arch/arm/src/stm32/stm32_rtcounter.c index 5613b05aa4..7f030cbc33 100644 --- a/arch/arm/src/stm32/stm32_rtcounter.c +++ b/arch/arm/src/stm32/stm32_rtcounter.c @@ -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 * * 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