|
|
# STM32 Backup SRAM
|
|
|
|
|
|
## Overview
|
|
|
The STM32F2/F4 microcontrollers provide a backup domain that includes 4 Kbytes of backup SRAM. This region can be considered as an internal EEPROM when VBAT is present: its content is preserved upon reset if VBAT is connected. This means that it can be used as a safe-guard memory (SGM).
|
|
|
|
... | ... | @@ -15,16 +13,33 @@ First of all you have to enable the backup SRAM: the backup domain is not readab |
|
|
Moreover, after a reset, the backup domain is protected against possible unwanted write accesses, so you have to disable write protection before being able to write again to the backup region.
|
|
|
|
|
|
The Miosix SGM driver constructor prepares the backup domain for you: it enables the backup clock and disables the write protection. It also retrieves the last board reset reason.
|
|
|
Please remember that the backup domain content is wiped by the driver if, after the reset, the `RCC_CSR_SFTRSTF` (i.e. software reset) flag is not set in the `RCC->CSR` register.
|
|
|
Please remember that the backup domain content is wiped by the driver if, after the reset, the `RCC_CSR_SFTRSTF` (i.e. software reset) flag is not set in the `RCC_CSR` register.
|
|
|
|
|
|
> :warning: **WARNING: Notice that more than one flag could be set at the same time in the `RCC_CSR` register!**
|
|
|
> **(e.g. software reset and reset pin flags)**
|
|
|
|
|
|
After enabling it, in order to read/write from/to the backup domain, you can simply use pointers or standard C/C++ functions, such as `memcpy` (better performance), starting from the backup region base address, which is `BKPSRAM_BASE`.
|
|
|
|
|
|
> :warning: **WARNING: Notice that more than one flag could be set at the same time in the `RCC->CSR` register!**
|
|
|
Otherwise, by specifing a dedicated section in the linker script (see below), you can use the `__attribute__(section(<section-name>))` in order to automatically store a global variable in the backup region. Then, in case of reboot, the variable's content is preserved.
|
|
|
The Miosix SGM driver defines the following macro:
|
|
|
```cpp
|
|
|
#define PRESERVE __attribute__((section(".preserve")))
|
|
|
```
|
|
|
where `.preserve` is the name of the section defined in the linker script.
|
|
|
|
|
|
After enabling it, in order to read/write from/to the backup domain, you can simply use pointers or standard C/C++ functions, such as `memcpy` (better performance), starting from the backup region base address, which is `BKPSRAM_BASE`.
|
|
|
In this way we can define a global variable that is stored in the backup domain as:
|
|
|
```cpp
|
|
|
uint8_t myvar PRESERVE;
|
|
|
|
|
|
// same as
|
|
|
uint8_t myvar __attribute__((section(".preserve")));
|
|
|
```
|
|
|
|
|
|
## Example
|
|
|
This basic example shows how you can write to the backup SRAM using the Miosix SGM driver.
|
|
|
These basic examples show how you can write to the backup SRAM using the Miosix SGM driver.
|
|
|
In a very similar way you can also read the data you stored.
|
|
|
|
|
|
#### 1. Pointers
|
|
|
```cpp
|
|
|
#include <miosix.h>
|
|
|
#include <arch/common/drivers/stm32_sgm.h>
|
... | ... | @@ -48,6 +63,32 @@ int main() { |
|
|
return 0;
|
|
|
}
|
|
|
```
|
|
|
#### 2. Section Attribute
|
|
|
If we declare `myvar` using the `PRESERVE` directive, its content will be preserved in the backup SRAM.
|
|
|
```cpp
|
|
|
#include <Common.h>
|
|
|
#include <arch/common/drivers/stm32_sgm.h>
|
|
|
|
|
|
using namespace miosix;
|
|
|
|
|
|
uint32_t myvar PRESERVE;
|
|
|
uint8_t myvar2 __attribute__((section(".preserve")));
|
|
|
|
|
|
int main() {
|
|
|
|
|
|
SGM &sgm = SGM::instance();
|
|
|
|
|
|
// the TRACE will print "myvar = 5"
|
|
|
// after the reboot
|
|
|
TRACE("myvar = %u", myvar);
|
|
|
|
|
|
myvar = 5;
|
|
|
|
|
|
reboot();
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
```
|
|
|
|
|
|
## Linker Script
|
|
|
In the board's linker script, a backup memory region has to be defined:
|
... | ... | @@ -60,7 +101,7 @@ MEMORY |
|
|
}
|
|
|
```
|
|
|
Where in this case `0x40024000` is the backup SRAM base address and `4K` (4 Kbytes) is its size.
|
|
|
|
|
|
|
|
|
A section in which `_preserve_start` and `_preserve_end` are defined is also needed, since these two addresses are used by the Miosix SGM driver.
|
|
|
```
|
|
|
.preserve(NOLOAD) : ALIGN(4)
|
... | ... | @@ -73,23 +114,25 @@ A section in which `_preserve_start` and `_preserve_end` are defined is also nee |
|
|
_preserve_end = .;
|
|
|
} > backupram
|
|
|
```
|
|
|
The `(NOLOAD)` directive will mark a section to not be loaded at run time. The linker will process the section normally, but will mark it so that a program loader will not load it into memory.
|
|
|
The `NOLOAD` directive will mark a section to not be loaded at run time. The linker will process the section normally, but will mark it so that a program loader will not load it into memory.
|
|
|
|
|
|
⚠️ WARNING ⚠️ *Remember to comment out the assignement to `_end` before adding the `preserve` section.*
|
|
|
<!---
|
|
|
> :warning: **WARNING: Remember to comment out the assignement to `_end` before adding the `preserve` section.**
|
|
|
```
|
|
|
_end = .;
|
|
|
PROVIDE(end = .);
|
|
|
```
|
|
|
--->
|
|
|
|
|
|
Refer to the [Skyward STM32F429ZI Anakin board](https://git.skywarder.eu/scs/miosix-kernel/-/blob/master/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_anakin/stm32_2m+256k_rom.ld) linker script as an example.
|
|
|
|
|
|
## Pros and Cons
|
|
|
Pros:
|
|
|
**Pros**:
|
|
|
* Useful to store relevant information that has to be persisted after a reset
|
|
|
* Included in STM32F2/F4 microcontrollers
|
|
|
* Simple to use
|
|
|
|
|
|
Cons:
|
|
|
**Cons**:
|
|
|
* Limited storage region
|
|
|
* Not actually a persistent storage
|
|
|
* VBAT requires an additional power supply or backup battery for better reliability
|
... | ... | |