TrustZone Application Development and Debugging

TrustZone is a security hardware extension that has been included with the Arm Cortex-M33 processor in the RSL15 device. This extension provides hardware isolation between secure and non-secure components, and can separate safe applications from unsafe ones, protecting underlying system components from being accessed or changed by untrusted code. For more information on the hardware support for TrustZone, see TrustZone.

When using TrustZone, the application is typically divided into two components, containing the secure and the non-secure application code respectively. System execution starts in the secure application component, which executes the non-secure application when necessary.

NOTE: The main loop for the application can exist in either the secure or the non-secure application component.

  • If the loop is in the non-secure application, no additional support is required.
  • If the loop is in the secure application, the secure application must re-initialize and start execution of the non-secure application component from the reset handler each time the non-secure application component is expected to be executed.

Secure Application Components

Secure application components must include:

  • All standard application items (stack pointer, vector table, standard interrupt and exception handlers, and system startup code)
  • System configuration, including configuration of the execution environment for the non-secure application. This configuration includes:
    • The secure environment as defined by the Secure Attribution Unit (SAU) using the SAU_* registers, and the Implementation Defined Attribution Unit (IDAU) using the SYSCTRL_NS_ACCESS_* registers
    • The available peripherals, including the NVIC and other private peripherals
  • A secure fault handler for catching faults that occur due to illegal accesses in the non-secure application
  • Initialization and execution of the non-secure application component, including:
    • Configuration of the non-secure component's main stack pointer (MSP_NS)
    • Execution of the non-secure application component starting from its reset handler

The secure application component can provide an API for the non-secure application component. This API can provide access to secure hardware and firmware components that would otherwise be inaccessible to non-secure applications. All secure API functions that can be called from non-secure code must be declared as non-secure entry points, using the cmse_nonsecure_entry attribute.

The following provides an example API definition that supports toggling a GPIO that would not otherwise be accessible to non-secure code:

void __attribute__ ((cmse_nonsecure_entry)) NSC_GPIO_Toggle(void)

Non-Secure Application Components

Non-secure application components must include:

  • A non-secure specific stack pointer
  • A non-secure specific vector table, including a reset handler and any other interrupt handlers that are needed in the non-secure application

IMPORTANT: The secure and non-secure application components must target different memory areas for code, data, and stack memory.

The non-secure application components must not include:

  • Accesses to secure hardware components (including system configuration)
  • Access to any peripherals that are not made accessible through the IDAU
  • Calls into the secure application, except through function calls to API functions declared as non-secure entry points

IMPORTANT: If an illegal access is included in the non-secure application, the secure application's secure fault handler is triggered and is used to handle the violation.

Debugging TrustZone Applications

When using TrustZone, extra steps beyond what is described in Debugging the Sample Code are required. To debug the application components:

  1. Load the non-secure application component to memory.
    • Loading this component can be implemented by setting up a debug or run launch configuration that loads the non-secure application component. It is best practice to clear the Debug Configuration > Startup > Continue setting when loading this component.

      An example debug configuration supporting loading a non-secure application is shown in "Loading non-secure application components" figure.

      Figure: Loading non-secure application components

  2. Load symbols from both application components and execute the secure application component.
    • The secure application component's symbols are loaded using Debug Configuration > Startup > Load Symbols and Executable > Load symbols > Use project binary: <secure component elf file>.
    • To support debugging both application components, the following line must be added to the Debug ConfigurationStartup > Run/Restart Commands box:

      add-symbol-file <non-secure component elf file> <non-secure component address>

      Where <non-secure component address> is the address of the non-secure component's vector table.

    An example debug configuration, supporting the loading of a secure application and symbols for both the secure and non-secure application components, is shown in "Loading Secure Components and Debugging a Complete TrustZone Application" figure.

    Figure: Loading Secure Components and Debugging a Complete TrustZone Application

  3. Load the secure application component to memory.