cancel
Showing results for 
Search instead for 
Did you mean: 

HardFault when changing from Secure to NonSecure mode on STM32L552/562 and STM32U5A5

980nm
Associate II

Hi,

When trying to run a simple TrustZone+UART project generated by STM32CubeMX, the chip raises a HardFault when switching to NonSecure mode. In the HardFault handler, the Cortex-M33 CFSR registrer is set to 0x400, indicating an instruction bus error, and lr set to 0xffff_ffa9 (i.e. raised from non-secure code).

The NonSecure code area's access flags (using the TT instruction etc.) is 0x02be0100 (i.e. should allow NS access) and the MPU is disabled, so that doesn't seem to be the issue. This thread details a similar problem, where the GTZC is protecting some regions of RAM from NS access. However, I've set all entries of MPCBB_SecConfig_array to zero (in the autogenerated MX_GTZC_S_Init() function), and that doesn't solve the issue.

Does anyone know what could cause this, and how to fix it?

Thanks.

1 ACCEPTED SOLUTION

Accepted Solutions
980nm
Associate II

After more digging:

  • It's actually technically a BusFault, I just didn't have the handler enabled in SCB_SHCSR. Doesn't change much about the origin.
  • the GTZC reports an illegal access on SRAM 5 (which is where the NS stack lives). This is weird, as it is marked as NS and non-privileged in MX_GTZC_S_Init(). (And NS code is running as privileged anyway.)
  • .... turns out the generated-by-STM32CubeMX code doesn't actually call MX_GTZC_S_Init(). Sigh.

View solution in original post

4 REPLIES 4
980nm
Associate II

After some more mucking around, I'm also getting the issue on a fresh STM32U5A5 Nucleo-144 devboard. I've made care to disable Secure Area 2 in STM32CubeProgrammer (SECWM2_PSTRT=0xff, SECWM2_PEND=0) yet that also doesn't resolve the issue. SAU_SFSR is zero, and SCB_ICSR indicates only a HardFault is active (0x803). SCB_SHCSR (0x4) and SCB_HFSR (0x4000_0000) also don't have any relevant bits set.

980nm
Associate II

After more digging:

  • It's actually technically a BusFault, I just didn't have the handler enabled in SCB_SHCSR. Doesn't change much about the origin.
  • the GTZC reports an illegal access on SRAM 5 (which is where the NS stack lives). This is weird, as it is marked as NS and non-privileged in MX_GTZC_S_Init(). (And NS code is running as privileged anyway.)
  • .... turns out the generated-by-STM32CubeMX code doesn't actually call MX_GTZC_S_Init(). Sigh.
STea
ST Employee

Hello @980nm ,

Thank you for the detailed explanation and the time investigated in this issue, could you please share your version of MX and the .IOC file used to generate this as well as the version of tools used to try and reproduce the issue from my side as the projects provided in the CubeU5Firmware package doesn't show such behavior.
Regards

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
980nm
Associate II

Sorry for the delay. I'm running STM32CubeMX version 6.12.0, with device package version 1.5.1 for L5, and 1.6.0 for U5. (I did hand-edit the L5 IOC file, as I have an the Nucleo-144 but with a STM32L562 swapped in with some hand-soldering. So I edited the file to make it use the default Nucleo-144 board stuff, but enable the extra features in the L562.)

If you want to know about some other bugs in STM32CubeMX I've come across for this project (these happen in both GNU Makefile and CMake projects):

  • The generated build scripts emit broken source code paths: the startup code is in ./Core/startup/startup_stm32*.s , but the build scripts emit ./Startup/startup_stm32*.s instead
  • For the STM32U5, the linker scripts are not written to the file system. I had to generate a project for one of the different build systems, copy the linker scripts to somewhere, regenerate as make/CMake (which I wanted to use), and then copy the linker scripts back into the right location.
  • Similarly, the linker script filenames were left out of the build files themselves. This caused the build system to invoke the linker with a -T flag without subsequent file name, thus interpreting the *next* flag as a file name, making the entire command parsing system go out of sync, leading to cryptic errors.