Skip to content

Arm TrustZone project

Felipe Torrezan edited this page Aug 21, 2026 · 9 revisions

The Arm TrustZone ®️ technology is a system-wide approach to security for Arm Cortex-A CPUs. Similar capabilities or, namely, the Cortex-M Security Extensions (CMSE), also became available as an optional feature for microcontrollers based on the ARMv8-M (or later) architecture.

Such extensions add memory protection, instructions for validating memory access, and controlled transition between two modes of execution: secure and non-secure.

CMSE standardizes an interface which requires tool support. The IAR build tools support CMSE via preprocessor symbols, extended keywords, intrinsic functions, compiler options, linker options, and the section Veneer$$CMSE. More information can be found within the <arm_cmse.h> header file installed with the product as well as in the associated IAR C/C++ Development Guide.

Helpful Resources

Interactive Example

A minimalistic project example is provided at examples/trustzone:

Project files
CMakeLists.txt
non-secure/CMakeLists.txt
non-secure/non-secure-hello.c
non-secure/v2m-mps2_ns.icf
secure/CMakeLists.txt
secure/secure-hello.c
secure/secure-hello.h
secure/v2m-mps2_s.icf

The focus of this interactive example is on how the CMakeLists can be configured in this particular scenario. This CMake project builds two executable targets: secure and non-secure. The secure target exports function entries that are used in the non-secure target via the custom target secure-import-lib, which is used as an intermediate step to mark the generated import library as GENERATED required by Ninja Generators for proper functioning.

There are two functions in the secure executable, callable from the non-secure executable via a secure gateway interface:

  • secure_hello(): Prints a greeting message, inspired in the classic "hello world" style.
  • register_secure_goodbye(): A callback function that returns a string which is printed when exiting from the secure executable.

Note

The code needed for the secure gateway interface is automatically generated by the IAR ILINK Linker, and will be placed in the Veneer$$CMSE section.

Tasks

  • Perform the following tasks in secure/CMakeLists.txt (click to show/hide answers):
TODO 1: Enable the CMSE in the compiler flags
target_compile_options(secure PRIVATE
  --cpu=$<TARGET_PROPERTY:CPU> 
  # TODO 1: Enable the CMSE in the compiler flags
  --cmse
)
TODO 2: Set the linker to produce an import library object file
target_link_options(secure PRIVATE
  --semihosting
  --cpu=$<TARGET_PROPERTY:CPU>
  --config ${CMAKE_CURRENT_SOURCE_DIR}/v2m-mps2_s.icf
  # TODO 2: Set the linker to produce an import library object file
  --import_cmse_lib_out $<TARGET_FILE_DIR:secure>
)
TODO 3: Add a custom target for explicitly marking the secure import library as `GENERATED`
# TODO 3: Add a custom target for explicitly marking the secure import library as `GENERATED`
#         (required for Ninja Generators)
add_custom_target(secure-import-lib
  DEPENDS secure
  COMMAND ${CMAKE_COMMAND} -E touch_nocreate $<TARGET_FILE_DIR:secure>/secure_import_lib.o
  BYPRODUCTS secure_import_lib.o
)
TODO 4: Include the secure import library in the generator's clean target
# TODO 4: Include the secure import library in the generator's clean target
#         (clean with: cmake --build build --target clean)
set_target_properties(secure PROPERTIES
  ADDITIONAL_CLEAN_FILES $<TARGET_FILE_DIR:secure>/secure_import_lib.o
)
  • Perform the following tasks in non-secure/CMakeLists.txt (click to show/hide answers):
TODO 5: Add secure-import-lib as a dependency for non-secure
add_dependencies(non-secure secure-import-lib)
TODO 6: Add secure to the non-secure include directories
target_include_directories(non-secure PRIVATE
  # TODO 6: Make use of the `secure` include directories
  $<TARGET_PROPERTY:secure,INTERFACE_INCLUDE_DIRECTORIES>
)
TODO 7: Add the generated import library to the non-secure target
target_link_options(non-secure PRIVATE
  --cpu=$<TARGET_PROPERTY:secure,CPU>
  --config ${CMAKE_CURRENT_SOURCE_DIR}/v2m-mps2_ns.icf
  --semihosting
  # TODO 7a: Add the generated import library to the `non-secure` target  
  $<TARGET_FILE_DIR:secure>/secure_import_lib.o
  # TODO 7b: Specify "no entry point" for the `non-secure` target
  --no_entry
) 
  • Finally build and test the project. Refer to the tutorial for more information.

Clone this wiki locally