1. Article purpose[edit source]
This article explains how the TAMP backup registers are used by STM32MPU Embedded Software on STM32MP15.
2. Overview[edit source]
The STM32MP15 embeds 32 backup registers of 32 bits. A programmable border allows these backup registers to be split into a secure and a non-secure groupa.
3. Backup register usage[edit source]
This paragraph explains the default usage of of backup registers by the ROM code and STM32MPU Embedded Software distribution. The subsequent chapter then shows the backup register mapping used to fulfill those needs.
![]() |
Backup register(s) might be used for another purpose by the application when the feature(s) listed below is/are not used by the said application |
3.1. Boot counter feature[edit source]
The BOOT_COUNTER is used by U-Boot to detect boot failures between its execution and before the complete Linux application initialization:
- It is incremented by U-Boot
- It is reset by the application
Hence if U-Boot reads a non-null value after a reset, this means that something went wrong at boot time. This information can be used to initiate entry into a fail safe mode.
3.2. Boot mode selection feature[edit source]
The BOOT_MODE register is used to propagate boot mode information from one component to the next boot stage, on cold boot or after a reset:
- The ROM code executes a serial boot if BOOT_MODE[7:0] is equal to 0xFF, as stated in the ROM code boot device selection strategy. In this case, the backup register is reset by the ROM code before proceeding with the serial boot mode. Other values are ignored by the ROM code.
- TF-A gets the selected boot device from the ROM code context in SYSRAM and writes it into BOOT_MODE[15:8] for U-Boot[1].
- U-Boot uses the BOOT_MODE register to get TF-A and Linux kernel (as explained in the next bullet) information[2] in order to select the desired boot mode (among "NORMAL", "STM32PROG", ...[1]) and build the appropriate "chosen" node in the device tree. This device tree is given to the Linux kernel for its start up, as explained in the "Runtime configuration" paragraph in Documentation/devicetree/usage-model.rst .
- The Linux kernel can force a reboot mode by writing to the BOOT_MODE register. This writing is done via the "reboot" Linux command, which is configured via the compatible "syscon-reboot-mode" in the device tree [2].
3.3. Firmware update info feature[edit source]
The FWU_INFO is used by TF-A BL2 to detect boot failures between its execution and before the complete Linux application initialization during a Secure Firmware Update.
3.4. DDR and CPU wake up management feature[edit source]
The MAGIC_NUMBER and BRANCH_ADDRESS registers allow control of the DDR initialization and the Arm® Cortex®-A7 CPU core's behavior on system transitions:
- On cold boot, the ROM code sets the MAGIC_NUMBER register to 0x0. When the FSBL TF-A BL2 reads a value different from 0xCA7FACE0 (for example 0x0) in MAGIC_NUMBER, it performs a complete DDR initialization before jumping to the SSBL (U-Boot).
- Before entering Standby with DDR in self-refresh low power mode, the PSCI framework writes the return address to which the Arm® Cortex®-A7 core 0 should branch to on wake up into the BRANCH_ADDRESS register, and sets the MAGIC_NUMBER register to 0xCA7FACE0.
- On wakeup from Standby, when the FSBL reads the value 0xCA7FACE0 from the MAGIC_NUMBER register, it has to perform a partial DDR initialization to exit Self-Refresh, before branching the Arm® Cortex®-A7 core 0 non-secure execution back to the address given by the BRANCH_ADDRESS register.
- On startup, the Linux® kernel starts to run on the Arm® Cortex®-A7 core 0, and uses the PSCI framework to write the address where the core 1 has to jump in BRANCH_ADDRESS register and to set MAGIC_NUMBER register to 0xCA7FACE1. These values are then interpreted by the ROM code, as explained in secondary core boot paragraph.
3.5. Cortex-M4 wake up feature[edit source]
The ROM code can autonomously start the Arm Cortex®-M4 with a firmware kept in RETRAM after a Standby low power mode period:
- On wake up from Standby low power mode, the M4_WAKEUP_AREA_HASH, M4_WAKEUP_AREA_LENGTH and M4_WAKEUP_AREA_START registers are used by the ROM code to perform an integrity check on the Arm Cortex®-M4 firmware stored in RETRAM. If successful, the ROM code starts the Cortex-M4 execution.
- Before entering Standby mode, it is the application's responsibility to set the above registers; the application has to compute and store the SHA-256 hash to be used by the ROM code on wake up. The hash is computed starting from the address stored in M4_WAKEUP_AREA_START, for the length defined in M4_WAKEUP_AREA_LENGTH and is stored in M4_WAKEUP_AREA_HASH.
- In addition to this branching mechanism, the Cortex-M4 coprocessor may need to access to some system resources that are secured (and so not accessible) by default. To achieve this, the RCC registers RCC_TZCR, EXTI_TZENR1, EXTI_TZENR2 and EXTI_TZENR3 respectively are saved into the WAKEUP_SEC, M4_SECURITY_PERIMETER_EXTI1, M4_SECURITY_PERIMETER_EXTI2, and M4_SECURITY_PERIMETER_EXTI3 registers by the application before entering Standby mode, and are restored by the ROM code on wake up.
3.6. Cortex-M4 management feature[edit source]
Two registers are used to control the Arm Cortex®-M4 coprocessor from the Arm Cortex®-A7:
- The COPRO_RSC_TBL_ADDRESS register owns the Coprocessor resource table base address. This is read by the Linux Kernel to retrieve the resource table when the Cortex-M4 firmware is loaded by U-Boot or OP-TEE.
- The CORTEX_M_STATE register reflects the Cortex-M4 state. This is written by U-Boot or OP-TEE when loading the firmware; it can be updated by the Cortex-M4 firmware at runtime and is read by the Linux Kernel to know the coprocessor state.
4. Memory mapping[edit source]
The table below shows the backup register mapping used by STM32MPU Embedded Software.
The TAMP backup register base address is 0x5C00A100, corresponding to TAMP_BKP0R.
TAMP register | Securitya | ROM / software register name | Comment |
---|---|---|---|
TAMP_BKP31R | Non-secure | M4_WAKEUP_AREA_HASH | SHA-256 value, see Cortex-M4 wake up feature |
TAMP_BKP30R | Non-secure | ||
TAMP_BKP29R | Non-secure | ||
TAMP_BKP28R | Non-secure | ||
TAMP_BKP27R | Non-secure | ||
TAMP_BKP26R | Non-secure | ||
TAMP_BKP25R | Non-secure | ||
TAMP_BKP24R | Non-secure | ||
TAMP_BKP23R | Non-secure | M4_WAKEUP_AREA_LENGTH | See Cortex-M4 wake up feature |
TAMP_BKP22R | Non-secure | M4_WAKEUP_AREA_START | See Cortex-M4 wake up feature |
TAMP_BKP21R | Non-secure | BOOT_COUNTER | See Boot counter feature |
TAMP_BKP20R | Non-secure | BOOT_MODE | See Boot mode selection feature |
TAMP_BKP19R | Non-secure | (Reserved for future use) | |
TAMP_BKP18R | Non-secure | CORTEX_M_STATE | See Cortex-M4 management feature |
TAMP_BKP17R | Non-secure | COPRO_RSC_TBL_ADDRESS | See Cortex-M4 management feature |
TAMP_BKP16R | Non-secure | (Reserved for future use) | |
TAMP_BKP15R | Non-secure | (Reserved for future use) | |
TAMP_BKP14R | Secure Write/ Non-secure Read | (Reserved for future use) | |
TAMP_BKP13R | Secure Write/ Non-secure Read | (Reserved for future use) | |
TAMP_BKP12R | Secure Write/ Non-secure Read | (Reserved for future use) | |
TAMP_BKP11R | Secure Write/ Non-secure Read | (Reserved for future use) | |
TAMP_BKP10R | Secure Write/ Non-secure Read | FWU_INFO | See Firmware update info feature |
TAMP_BKP9R | Secure | (Reserved for future use) | |
TAMP_BKP8R | Secure | (Reserved for future use) | |
TAMP_BKP7R | Secure | (Reserved for future use) | |
TAMP_BKP6R | Secure | (Reserved for future use) | |
TAMP_BKP5R | Secure | BRANCH_ADDRESS | See DDR and CPU wake up management feature |
TAMP_BKP4R | Secure | MAGIC_NUMBER | See DDR and CPU wake up management feature |
TAMP_BKP3R | Secure | M4_SECURITY_PERIMETER_EXTI3 | See Cortex-M4 wake up feature |
TAMP_BKP2R | Secure | M4_SECURITY_PERIMETER_EXTI2 | See Cortex-M4 wake up feature |
TAMP_BKP1R | Secure | M4_SECURITY_PERIMETER_EXTI1 | See Cortex-M4 wake up feature |
TAMP_BKP0R | Secure | WAKEUP_SEC | See Cortex-M4 wake up feature |
a: the security borders are configured by the Secure OS (look for "zone" in plat/st/stm32mp1/sp_min/sp_min_setup.c for TF-A SP-MIN or in core/arch/arm/plat-stm32mp1/main.c for OP-TEE), so the source code has to be modified if a different border is needed.
5. References[edit source]