cancel
Showing results for 
Search instead for 
Did you mean: 

STM32U575 TrustZone Proect Interrupt Confusion

Nicholas Parker
Associate III

Hello,

I'm looking for advice / help with Trust-Zone enabled project.  I'm just getting started with Trust-Zone so there is a bit of a learning curve I guess, and a lot I dont know.  I'm debugging in VSCode.  Debug config shown at bottom of message.  To start, I programmed TZEN for my STM32U575 to 1, but no read out protection is enabled.    The secure part of the project, which runs first (its ISR table is at 0xc000000 ) only does a handful of things currently, including running this - it is stock standard STM code I think.

static void NonSecure_Init(void)
{
  funcptr_NS NonSecure_ResetHandler;
  SCB_NS->VTOR = VTOR_TABLE_NS_START_ADDR;
  /* Set non-secure main stack (MSP_NS) */
  __TZ_set_MSP_NS((*(uint32_t *)VTOR_TABLE_NS_START_ADDR));
  /* Get non-secure reset handler */
  NonSecure_ResetHandler = (funcptr_NS)(*((uint32_t *)((VTOR_TABLE_NS_START_ADDR) + 4U)));
  /* Start non-secure state software application */
  NonSecure_ResetHandler();
}

 

When I start a debugging session, I assume that this code should have already run, right?  And the debugger is waiting for me to start debugging from non-secure main();

The non-secure project initalises UART4, then does a hello world (debug printf) but when UART4 tx empty interrupt occurs I  get hard faults.  I found that the UART4 ISRs are non running in the non secure project.  I added UART4 ISR handlers into the secure project, and found the PC was going there!   I added the following to the secure project, in an attempt to make the interrupt non secure. (but i dont think this would fix it, as where we are vectoring is wrong).

NVIC_SetTargetState(UART4_IRQn);
HAL_GTZC_TZSC_ConfigPeriphAttributes(GTZC_PERIPH_UART4,  GTZC_TZSC_PERIPH_NSEC);

 

This hasnt changed anything I can see -- the same vector table (the secure one) is being used.
If I look at SCB->VTOR, in the non-secure project, it is still 0xc0000000, which is the aliased secure vector table address.   I'm not sure which VTOR this is ? The secure or non-secure ? How can I tell?

However, in the non secure project during debug, if I change the this to 0x08080000, the address of my non secure table, I just end up getting hard faults running other peripheral init code.
 

I'm not making easy headway debugging this as the debugger behaviour is inconsistent will lock up and refuse to show me various registers that might be helpful.

Looking for any tips from anyone whos been here.

Thanks, Nick.

 

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch Debug Build",
            "type": "stlinkgdbtarget",
            "request": "launch",
            "svdPath": "C:/tools/svd/stm32u575.svd",
            "cwd": "${workspaceFolder}",
            //"preBuild": "${command:st-stm32-ide-debug-launch.build}",
            "runEntry": "main",
            "imagesAndSymbols": [
                {
                    "imageFileName": "${workspaceFolder}/Secure/build/fw_S.elf"
                },
                {
                    "imageFileName": "${workspaceFolder}/NonSecure/build/fw_NS.elf"
                }
            ],
            "verbose": false
        },
    ]
}

 

3 REPLIES 3
Saket_Om
ST Employee

Hello @Nicholas Parker 

On STM32U5 with TrustZone, the secure firmware (vector table at 0xC0000000) always starts first. The secure code must then call NonSecure_Init(), which configures the non-secure VTOR (SCB_NS->VTOR) to the base of the non-secure vector table (e.g. 0x08080000), sets the non-secure main stack pointer from that table, and finally jumps to the non-secure Reset_Handler. Once this is done, execution proceeds in the non-secure world (Reset_Handler → main()), and at that point SCB_NS->VTOR is expected to hold the non-secure vector table address, not 0xC0000000

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.
Saket_Om

Hello @Saket_Om ,

Thanks for reiterating the boot process. The major problem I created for myself in the end was that the secure areas / watermarks were not aligned correctly with the linker scripts - so when jumping to non-secure flash (in secure startup code), the flash being jumped to was secure...so things fell over.   Additionally, when I wasnt sure of the cause of issues, i possibly attributed them to the wrong source and confounding things was inconsistent and temporarmental seeming debuggin issue -- additionally knowing what the process is to make a peripheral and its interrupts (and sometime individual GPIOs) non-secure helped.

Too late for me, however I think ST could (unless one exists already that I missed) produce an excellent article and not just a code project perhaps titled 'TrustZone for Dummies', with mininal prior knowledge assumed, explaining in english a complete list of all the reasonable things to know about a basic trust zone app, with explanations about both apps, option bytes (critical!), programming, flash organisation, how debugging works with multiple .elfs, what is visible in each security context, comments on each line of code etc -- explainging how the communication works between them (NSC API etc) - i.e. a one stop shop.

Cheers, Nick

Nicholas Parker
Associate III
Finally for anyone else who needs its -- here it all you need in a launch.json configuration object to debug the trustzone enabled app (when you have VSCode STM32CubeDebugCore extension installed) :-
        {
            "name": "Debug Trustzone",
            "type": "stlinkgdbtarget",
            "svdPath" : "path:/stm32u575.svd",
            "request": "launch",
            "cwd": "${workspaceFolder}",
            "imagesAndSymbols": [{"imageFileName": "${workspaceFolder}/NonSecure/build/fw_NONSECURE.elf"},
                                 {"imageFileName": "${workspaceFolder}/Secure/build/fw_SECURE.elf"},
                                 ],
            "initCommands": ["tbreak main"],
            "verbose": false
        },