2024-04-10 7:53 AM - edited 2024-04-10 7:55 AM
Hello,
I have two applications: one at 0x08000000 and one at 0x08080000. Both run fine individually (when setting the boot config bytes to the fitting offset). Now I want to use the one at 0x08000000 as secure area and escape it by using exitSecureArea. In the debugger, I can observe that the code runs fine until the very call to exitSecureArea. Now my questions are:
1. Is there something else I need to to? This seems to suggest that I need to set the VTOR register. I currently (try to) do it before the call to exitSecureArea.
2. If I need to setup the VTOR register, is my code below correct? Or do I need to do it differently/at a different place?
3. Does exitSecureArea also work when the secure area is not set? I only tried without setting it as not to brick the device.
4. Is there a way to debug this nicely?
typedef struct
{
uint32_t sizeInBytes; /*!< pass 0 for an empty secure area */
uint32_t startAddress; /*!< pass NULL for an empty secure area */
uint32_t removeDuringBankErase; /*!< if 0, keep area during bank/mass erase. else area will be removed */
} RSS_SecureArea_t;
typedef struct
{
/**
* This service is used to exit from secure user software and jump to user main application.
* There is no system reset triggered by this service
*/
// vectors is the base of the other app
// build the other app, but for a different starting address
void (*exitSecureArea)(uint32_t vectors, uint32_t jtagState);
/**
* This service sets Secure user area boundaries.
* This service can be used only when a secure area is set for the first time.
* A system reset is triggered after service completion.
*/
void (*resetAndInitializeSecureAreas)(uint32_t nbAreas, RSS_SecureArea_t *areas); /*!< nbAreas=1 or 2;
1 per bank */
} RSS_API_Table_t;
#define RSS_API ((RSS_API_Table_t*)0x1FF09514)
void main(){
[...]
__disable_irq();
SCB->VTOR = 0x08080000;
__enable_irq();
RSS_API->exitSecureArea(0x08080000, 1);
}
Thanks for your help!
2024-04-10 2:07 PM - edited 2024-04-11 2:47 AM
> In the debugger, I can observe that the code runs fine until the very call to exitSecureArea
Really? Debugger does not work while the program runs in the secure area.
Setting the VTOR to the non-secure program before jump is not needed, IIRC. The non-secure program can set it later. Make sure you call exitSecureArea correctly.
@Jocelyn RICARD could you look at this, please?
2024-04-11 12:26 AM
Let me be more precise: I want to use the application at 0x08000000 as secure area. To that end, I follow this application note, which suggests to run the setup before to ensure it works fine. As I have not completed this step, I did not set the secure area bytes yet and as such can still use the debugger. Your point raises a great question though: does exitSecureArea work if the secure configuration is not setup (question 3 in the original post)?
The code that sets the VTOR and calls exitSecureArea is hidden under the spoiler above. I hope it is correct.
When is the non-secure program later supposed to set it? Some time in the starting process? Or is main good enough?
Thanks for your help!
2024-04-11 2:49 AM - edited 2024-04-11 2:51 AM
> does exitSecureArea work if the secure configuration is not setup
Yes it should work. At least it worked on H753, and even on H743 without secure area function at all.
> When is the non-secure program later supposed to set it?
Both variants are good, just make sure that systick or other interrupts don't occur before VTOR is set.
2024-04-12 2:40 AM
I tried both versions and neither worked for me. Again, I can run both apps fine alone. I modified the second app (located at 0x08080000) in two ways, as follows:
1. I added SCB->VTOR = 0x08080000; in the very first line in main. App still runs fine, exitSecureArea still does not work.
2. I added the following assembly to the start of the reset vector:
mov r3, 0x0808
lsl r3, 0x10
mov r2, 0xe
lsl r2, 0x1c
orr r2, 0xed00
orr r2, 0x8
str r3, [r2]
Again, app runs fine alone but exitSecureArea still does not run the app.
Are these two options implemented correctly? Otherwise, what do I need to change?
2024-04-15 2:47 AM
Any new ideas? @Pavel A. @Jocelyn RICARD
2024-04-18 10:21 AM
Hello @smnhff ,
I'm sorry, I'm very busy and don't have time to check what could go wrong with your setup.
Now, I made some time ago an example for using secure mem.
I share it here so you can have a look and test it on your board.
Best regards
Jocelyn
2025-09-30 2:55 AM
Hello @Jocelyn RICARD,
I am working on configuring secure memory with RDP on STM32, and I am facing an issue during regression. My goal is to preserve the secure memory area (bootloader) while performing regression from RDP Level 1 to Level 0. Below is the approach I followed:
Enabled RDP Level 1 and the Security Bit.
Initialized the secure area on the first flash sector using the following function:
void enableRSSonBootloaderArea (void) {
uint8_t userInput = 0;
printf("Check CM4 is disabled before enabling secure memory...\r\n");
if (FLASH->OPTSR_CUR & FLASH_OPTSR_BCM4)
{
printf("CM4 BOOT should be disabled before enabling secure memory\r\n");
return;
}
printf("!!!!!!!!!!! Setting Root Secure Services !!!!!!!!!!!\r\n");
printf("Permission to Initialize RSS on Bootloader Area y/n \r\n");
userInput = ReadUserInput();
switch (userInput) {
case 'y':
printf("Set secure memory on first flash sector calling RSS\r\ndo you want to keep rss area? [y/n]\r\n");
RSS_SecureArea_t aSecureAreas[2];
userInput = ReadUserInput();
if (userInput =='y') {
aSecureAreas[0].removeDuringBankErase = 0; //this will make secure area region not erase during regression of RDP 1 to 0
aSecureAreas[1].removeDuringBankErase = 0;
} else {
aSecureAreas[0].removeDuringBankErase = 1; //this will make secure area region erase during regression of RDP 1 to 0
aSecureAreas[1].removeDuringBankErase = 1;
}
aSecureAreas[0].sizeInBytes = 128 * 1024;
aSecureAreas[0].startAddress = 0x08000000;
/* Only 1 secure area is used */
aSecureAreas[1].sizeInBytes = 0;
aSecureAreas[1].startAddress = (uint32_t) NULL;
printf("Setting secure area : SecArea.size: %ld SecArea.addr:0x%8.8lx", aSecureAreas[0].sizeInBytes, aSecureAreas[0].startAddress);
/* no need to set pbIsProtectionToBeApplied and e_ret_status because the next function triggers a RESET */
RSS_API->resetAndInitializeSecureAreas(1, aSecureAreas);
break;
case 'n':
printf("RSS Initialization Aborted!\r\n");
default:
printf("Invalid Entry Try Again from beggining!\r\n");
break;
}
}
After initialization, I verified FLASH->SCAR_CUR and confirmed DMES1 = 0.
For regression, I modified the function as follows to preserve the secure area:
void Dmes0RegressionKeepRss (void) {
HAL_StatusTypeDef error;
uint8_t userInput = 0;
printf("DMES0 Regression Launched only Application is getting erased keeping rss ....please wait 10s\r\n");
__HAL_FLASH_CLEAR_FLAG_BANK1(FLASH_FLAG_ALL_ERRORS_BANK1);
__HAL_FLASH_CLEAR_FLAG_BANK1(FLASH_FLAG_ALL_ERRORS_BANK2);
/* checking conditions for doing dmes0 regression
* as we want to keep our rss area i.e. bootloader
* and to do so we must have initialized the rss with dmes as 0
* and we rss area is defined
* and it has rss exit function and download application feature activated.
**/
/* checking dmes status */
if (((FLASH->SCAR_CUR1 & FLASH_SCAR_DMES) == 0) && /* checking secure area is defined or not? */
(((FLASH->SCAR_CUR1 & FLASH_SCAR_SEC_AREA_END) >> FLASH_SCAR_SEC_AREA_END_Pos) >
((FLASH->SCAR_CUR1 & FLASH_SCAR_SEC_AREA_START) >> FLASH_SCAR_SEC_AREA_START_Pos))
){
printf("conditions for dmes0 regression checked!\r\nflash->scar_cur1:%lx\r\n", FLASH->SCAR_CUR1);
printf("want to proceed with dmes0 regression? [y/n]\r\n");
userInput = ReadUserInput();
if (userInput != 'y') {
return;
}
HAL_FLASH_OB_Unlock();
FLASH->OPTSR_PRG = 0x13BEAAF0; /* RDP level 0 */
// FLASH->PRAR_PRG1 = 0x80000FFF; /* No PCROP */
FLASH->SCAR_PRG1 = FLASH->SCAR_CUR1; /* No secure area */
// FLASH->WPSN_PRG1 = 0x000000FF; /* No WRP */
if ((error=HAL_FLASH_OB_Launch()) != HAL_OK)
{
printf("HAL_FLASH_OB_Launch failed. HAL_ERROR: %d Error code : %8.8lx ...\r\n", error, pFlash.ErrorCode);
printf("Flash->SR1: 0x%8.8lx\r\n", FLASH->SR1);
}
// Shouldn't go past this point
if (HAL_FLASH_OB_Lock()!= HAL_OK)
{
printf("Error HAL_FLASH_OB_Lock\r\n");
}
printf("RDP1 regression fai!ed");
} else {
printf("dmes0 regression failed conditions not ok\r\n");
}
}
Even though:
I kept the security bit enabled,
FLASH->SCAR_CUR and FLASH->SCAR_PRG were set properly,
DMES1 = 0, and
the secure memory area was correctly defined (start < end address),
after regression my bootloader code was erased.
Could you please clarify what I might be missing here? Specifically:
Should the secure area be re-initialized after regression?
Is there an additional configuration required to ensure that the bootloader region is preserved during RDP regression?
Does removeDuringBankErase = 0 guarantee retention of the secure area across regression?
Any guidance on how to properly configure regression while keeping the secure area intact would be greatly appreciated.
Thank you in advance.