cancel
Showing results for 
Search instead for 
Did you mean: 

Continuous reset loop with SBSFU on STM32L4R9. Reset always happens right at the moment the secure engine is called.

NAhme.2
Associate II

When the Secure Engine Call (inside SE_Init() function) is called in this line:

e_ret_status = (*SE_CallGatePtr)(SE_INIT_ID, peSE_Status, primask_bit, uSystemCoreClock);

(which is between a SE_EnterSecureMode and SE_ExitSecureMode).

The MCU resets at this point, the reset happens continuously (reset loop) always at this line. The code executed until after SE_EnterSecureMode(&primask_bit); is called. I have added TRACE calls to check this.

Here is the problem area:

/* Enter Secure Mode */
  TRACE("\r\n= [SE_Init] SE_EnterSecureMode...");
  SE_EnterSecureMode(&primask_bit);
 
  /* Secure Engine Call */
  TRACE("\r\n= [SE_Init] (*SE_CallGatePtr)..."); //RESET HAPPENS BELOW:
  e_ret_status = (*SE_CallGatePtr)(SE_INIT_ID, peSE_Status, primask_bit, uSystemCoreClock);
  TRACE("\r\n= [SE_Init] (*SE_CallGatePtr) done");
 
  /* Exit Secure Mode */
  TRACE("\r\n= [SE_Init] SE_ExitSecureMode...");
  SE_ExitSecureMode(primask_bit);

I have setup all other paramters correctly for STM32L4R9 following AN5056 section 3 (Porting X-CUBE-SBSFU to another board) and have made appropriate memory mapping changes for Secure Engine, SBSFU, Download Area, Active Image defined flash sections. Also the SE RAM1 sections. As per errata, I have defined SE firewall protected RAM1 to be under maximum 128KB (instead of 192KB) - actually just 4KB.

I have also seen this issue and applied the recommendation, to no success:

https://community.st.com/s/question/0D50X0000ADEGfr/firewall-reset-when-accessing-unprotected-sram1-memory-stm32l4r9

I have no idea what is happening. I'm not even sure it's the firewall spurious reset. I disabled SFU_FWALL_PROTECT_ENABLE define and the same issue persists. Also if it was an actual firewall (or other reset) I would get the TRACE printout telling me that. This is just a inexplicable reset.

0693W00000AP7mlQAD.png

Any help is appreciated. It's a complete showstopper with SBSFU.

21 REPLIES 21
firmwareguru
Associate II

Hi, I have spent much time working with the X-CUBE-SBSFU system.

To start, I would ensure that *all* protections are off. That means the SBSFU should not be allowed to set any option bytes during its initialization.

I routinely use the debugger (STM32CubeIDE + STLINK) to trace through SBSFU and SECoreBin. This can be accomplished by ensuring the protections are off (RDP level 0 is set and remains set) and by loading the symbols from both SECoreBin and SBSFU elf files into the debugger, while only downloading the SBSFU binary to the target (since the SBSFU binary includes the SECoreBin binary).

The reset could be that SE_CallGatePtr is NULL (hard fault).

The best way to find out is really to fire up the debugger and step through the function calls. You do not need to build the applications any differently.

Let us know how that goes.

Hi!

Thanks for your response!

So I've tried with disabling all the protections RDP, WRP, PCROP, FWALL, TAMPER, DAP, DMA, IWDG, MPU, but the same issue persists. Which leads me to believe it's not any of these protections that are causing reset, but there is another issue.

Not sure why SE_CallGatePtr would be NULL as the macro SET_CALLGATE(); is called inside SE_Init(..). That should be setting up the Callgate function pointer.

I have not modified much in the code other than changing the UART port, and modifying the memory mapping for download/active area and teh SE RAM Region addresses (in mapping_fwimg.ld, and mapping_sbsfu.ld files). These are very straightforward and I've checked 10x to make sure everything correct here.

When I debug, if I put breakpoint at

e_ret_status = (*SE_CallGatePtr)(SE_INIT_ID, peSE_Status, primask_bit, uSystemCoreClock);

then the program runs to that line and stops. If I put breakpoint on next line of code "SE_ExitSecureMode(primask_bit);", the debugger is "lost" and if I pause it goes to 0x1fff355c "break at 0x1fff355c with no debug information available, or outside of program code." If I press the "reset" button to restart debug from main function start, It does not work as debugger is lost. I have to exit and re-enter debugging and same thing repeats. What do I look for now? any ideas?

firmwareguru
Associate II

Well it certainly appears that the Program Counter is going off into the weeds.

Can you provide the value, as reported by the debugger, of SE_CallGatePtr before that line is executed? I would expect it to be somewhere in system flash starting at 0x08000000.

On the protections, have you verified that they are not actually enabled in the option bytes on your target? Use STM32CubeProgrammer to go through the option bytes like firewall etc. to ensure they are off or disabled. I am not sure if the latest X-CUBE-SBSFU has a regression script (regression.sh) like the TF-M offering in the project directory, but if it does that could be run to reset the option bytes.

So the value of SE_CallGatePtr is <optimized out> when I stop program before that line is executed (by breakpoint).

0693W00000AQ6Z4QAL.png 

As for protections, I can see from Option Bytes read through STM32CubeProgrammer that Read Out Protection is AA: Level 0. Also PCROP and Write Protection in Bank 1 are also disabled. These have to be disabled anyway to reprogram/flash device and debug. For firewall specifically I don't see anything in Option Bytes > User Configuration or anywhere else.

For the SE_CallGatePtr being optimized out - could that be an issue? however why does the example project work for the STM32L476G-DISCO board without any issues? As I said I only modified few things and am testing on the STM32L4R9I-DISCO.

Would it help if I sent you a .zip of the SBSFU+SECoreBin projects?

firmwareguru
Associate II

The SE_CallGatePtr is set with this function:

#define SET_CALLGATE() \
  SE_ErrorStatus(*SE_CallGatePtr)(SE_FunctionIDTypeDef ID, SE_StatusTypeDef *peSE_Status, \
                                           ...);  /*!< Secure Engine CALLGATE  pointer function*/ \
  SE_CallGatePtr = (SE_ErrorStatus(*)(SE_FunctionIDTypeDef, SE_StatusTypeDef *, \
                                        ...))((uint32_t) SE_CALLGATE_REGION_ROM_START + 1U);

It is fixed to SE_CALLGATE_REGION_ROM_START + 1U. What is the value of SE_CALLGATE_REGION_ROM_START from your linker configuration? Better yet, go into the project .map file and search for it to find the actual value the linker placed it at.

The arguments could also be a problem and source of faulting. peSE_Status is a pointer to 0x2009ffe0. This a region located at the very end of the 384 KB SRAM3 area (0x5FFE0 into 0x60000 total available) of the L4R9 device. It must be pointing to a stack location 32 bytes down from the top. This has to be where SBSFU is operating out of right now.

So in mapping_export.h:

extern uint32_t __ICFEDIT_SE_CallGate_region_ROM_start__; 
#define SE_CALLGATE_REGION_ROM_START ((uint32_t)& __ICFEDIT_SE_CallGate_region_ROM_start__)

and then in mapping_sbsfu.ld:

VECTOR_SIZE = 0x200;
__ICFEDIT_SE_Code_region_ROM_start__       = 0x08000000 + VECTOR_SIZE;
__ICFEDIT_SE_CallGate_region_ROM_start__   = __ICFEDIT_SE_Code_region_ROM_start__ + 0x4;

So therefore __ICFEDIT_SE_CallGate_region_ROM_start__  should be 0x08000000 + VECTOR_SIZE(0x200) + 0x4 = 0x8000204

in the .map file created by linker this value is confirmed:

0x0000000008000204                __ICFEDIT_SE_CallGate_region_ROM_start__ = (__ICFEDIT_SE_Code_region_ROM_start__ + 0x4)

As for SBSFU SE under firewall I have:

(this is not modified by me, neither is the above).

/* RAM section */
/* SE RAM1 region protected by firewall */
/* SE stack is placed 1st in RAM, stack overflow does not write on other RAM area */
__ICFEDIT_SE_region_RAM_start__     = 0x20000000;
__ICFEDIT_SE_region_RAM_stack_top__ = 0x20000400;
__ICFEDIT_SE_region_RAM_end__       = 0x20000FFF;

But as for SBUSFU RAM Region I am using RAM3:

/* SBSFU RAM region */
__ICFEDIT_SB_region_RAM_start__     = 0x20081000; /*OLD: __ICFEDIT_SE_region_RAM_end__ + 1;*/
__ICFEDIT_SB_region_RAM_end__       = 0x2009FFFF;

So that is because, as per errata, we don't have overlap of the low 18-bits with SE Firewall in RAM1 region. This issue is explained here:

https://community.st.com/s/question/0D50X0000ADEGfr/firewall-reset-when-accessing-unprotected-sram1-memory-stm32l4r9

So what do you recommend here? Is this the issue? SB_region_RAM has a good 128KB as per region defined above.

Jocelyn RICARD
ST Employee

Hello,

looking at your description it seems that your board is setup to boot on system bootloader.

Reason I'm telling this is that you get 0x1fff355c address.

So, if this is the case, the remap at address 0 is the system bootloader and not the user flash.

On first interrupt you jump to the VTOR address which I think is not set to user flash but left at 0.

So, you you please look at you boot option bytes?

Also, what happens if you don't use the debugger, is your STM32 booting on SBSFU ?

Best regards

Jocelyn

Hi Jocelyn,

Yes whether or not using debugger, the STM32 boots SBSFU, as SBSFU (incl. SECoreBin) are programmed to device, no user application. So it's expected the system boots SBSFU. But the problem is described in my first post that it's constantly resetting at the line Secure Engine Call with SECallGate pointer.

This SBSFU code works well for STM32L476 DISCO board, to modify it to run on STM32L4R9 DISCO board, I changed flash mapping, UART for printf, and some project files to change the STM32 defined as STM32L476xx to STM32L4R9xx. No functional code changes were made. I'm not sure what is missing in ST SBSFU documentation that I'm not doing which is causing this issue.

Jocelyn RICARD
ST Employee

Hello,

OK, then the issue is very probably related to a test made in the secure engine to check that calling address or data provided is located at the right place.

To figure this out one way is to add the symbols of the secure engine in your SBSFU debug session and go step by step in assembly mode.

This will allow you to find the location of the test that leads to the system reset.

You can also review the content of the se_callgate.c and look for the calls to NVIC_SystemReset.

Best regards

Jocelyn