This is an example to demonstrate non-PSA secure/non-secure code running on Nuvoton TrustZone targets.
In the following, we take NuMaker-PFM-M2351/NuMaker-M2354 as examples for explanation.
In the following, we compile our program with ARMCLANG toolchain.
On TrustZone targets, it is necessary to partition the hardware first for secure/non-secure code to run on secure/non-secure worlds respectively.
On Nuvoton's TrustZone chips, it is necessary to Mass Erase the chip first by external tool e.g. ICP Tool before we can partition the hardware (only once). Fortunately, if we flash secure code through drag-n-drop, Nu-Link/Nu-Link2 would issue Mass Erase in its erase/program flow. With that, secure code can get one chance to re-partition the hardware without resorting to other tools.
In the following example, we would partition the flash into secure/non-secure worlds,
where flash addresses start at 0x00000000
/(0x10000000
+ Secure Flash Size) respectively:
0x00000000-0x0003FFFF
)0x10040000-0x1007FFFF
)0x00000000-0x0007FFFF
)0x10080000-0x100FFFFF
)In the following example, we would partition the SRAM into secure/non-secure worlds,
where SRAM addresses start at 0x20000000
/(0x30000000
+ Secure SRAM Size) respectively:
0x20000000-0x20007FFF
)0x30008000-0x30017FFF
)0x20000000-0x2001FFFF
)0x30020000-0x3003FFFF
)TODO
Follow the steps below to compile TrustZone non-PSA secure code.
Clone NuMaker-mbed-TZ-secure-example
mbed import https://github.com/OpenNuvoton/NuMaker-mbed-TZ-secure-example
cd NuMaker-mbed-TZ-secure-example
Tell Mbed of secure flash/SRAM partition for secure world
To compile TrustZone non-PSA secure code, we need to tell Mbed build system of secure flash/SRAM partition for secure world. The step is required.
{
"target_overrides": {
......
"NU_PFM_M2351_NPSA_S": {
......
"target.mbed_rom_start" : "0x0",
"target.mbed_rom_size" : "0x40000",
"target.mbed_ram_start" : "0x20000000",
"target.mbed_ram_size" : "0x8000",
......
}
}
}
{
"target_overrides": {
......
"NU_M2354_NPSA_S": {
......
"target.mbed_rom_start" : "0x0",
"target.mbed_rom_size" : "0x80000",
"target.mbed_ram_start" : "0x20000000",
"target.mbed_ram_size" : "0x20000"
......
}
}
}
Don't enable RTOS
The secure code runs with RTOS disabled. Secure code with RTOS is not supported yet.
{
"requires": ["bare-metal", "rtos-api"],
......
}
Adjust TZ process max stack slots/stack size
"macros": [
"MBED_CONF_TZ_PROCESS_STACK_SLOTS=8",
"MBED_CONF_TZ_PROCESS_STACK_SIZE=2048",
......
],
NOTE1: TZ max stack slots MBED_CONF_TZ_PROCESS_STACK_SLOTS
limits max NS threads which enable TZ access MBED_TZ_DEFAULT_ACCESS
.
NOTE2: TZ stack size MBED_CONF_TZ_PROCESS_STACK_SIZE
is for secure library (NSC function). Its value is enlarged for custom NSC function.
NOTE3: Avoid printf
-like call in NSC function because it needs large stack and runs the risk of stack overflow.
Tell Mbed of boot stack size when RTOS is absent for secure world (optional, preferred)
The default boot stack size when RTOS is absent may not meet your requirement. Change it explicitly.
{
"target_overrides": {
......
"NU_PFM_M2351_NPSA_S": {
......
"target.boot-stack-size" : "0x1000",
......
}
}
}
Enable serial and so printf (optional, not preferred)
To run with serial enabled, add "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", and "STDIO_MESSAGES" in the configuration option target.device_has_add
.
{
"target_overrides": {
......
"NU_PFM_M2351_NPSA_S": {
......
"target.device_has_add": ["SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES"],
......
}
}
}
Besides, disable STDIO buffered serial explicitly as well. STDIO buffered serial needs USB UART INT. By default, both USB UART and its INT are configured as non-secure. Even though secure code can control this UART via non-secure data access, there's no USB UART INT in secure side. So disable this function explicitly for safe.
{
"target_overrides": {
"*": {
......
"platform.stdio-buffered-serial" : false,
......
},
......
}
}
To run with serial disabled, add "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", and "STDIO_MESSAGES" in the configuration option target.device_has_remove
.
{
"target_overrides": {
......
"NU_PFM_M2351_NPSA_S": {
......
"target.device_has_remove": ["SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES"],
......
}
}
}
{
"target_overrides": {
......
"NU_M2354_NPSA_S": {
......
"target.device_has_remove": ["SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES"],
......
}
}
}
Enable fault handler dump message (optional)
{
"target_overrides": {
......
"NU_PFM_M2351_NPSA_S": {
......
"target.macros_remove": ["MBED_FAULT_HANDLER_DISABLED"],
......
},
"NU_M2354_NPSA_S": {
......
"target.macros_remove": ["MBED_FAULT_HANDLER_DISABLED"],
......
}
}
}
NOTE: This gets unnecessary when fault handler dump message gets to enabled by default in future Mbed OS version.
Change non-secure jump address (optional)
This is done by configuring tz-start-ns
in mbed_app.json
or custom one.
If not specified, it defaults to start of non-secure flash.
To jump to non-default non-secure address like:
0x10044000
0x10084000
mbed_app.json
or custom one would have:
{
"target_overrides": {
......
"NU_PFM_M2351_NPSA_S": {
......
"tz-start-ns": "0x10044000",
......
}
}
}
{
"target_overrides": {
......
"NU_M2354_NPSA_S": {
......
"tz-start-ns": "0x10084000",
......
}
}
}
Compile by running command:
mbed compile -m NU_PFM_M2351_NPSA_S -t ARM --app-config mbed_app_custom.json
mbed compile -m NU_M2354_NPSA_S -t ARM --app-config mbed_app_custom.json
Keep compiled secure code for non-secure code build process later
M2351:
BUILD/NU_PFM_M2351_NPSA_S/ARM/NuMaker-mbed-TZ-secure-example.hex
BUILD/NU_PFM_M2351_NPSA_S/ARM/cmse-lib.o
M2354:
BUILD/NU_M2354_NPSA_S/ARM/NuMaker-mbed-TZ-secure-example.hex
BUILD/NU_M2354_NPSA_S/ARM/cmse-lib.o
Follow the steps below to compile TrustZone non-PSA non-secure code.
Clone NuMaker-mbed-TZ-nonsecure-example
mbed import https://github.com/OpenNuvoton/NuMaker-mbed-TZ-nonsecure-example
cd NuMaker-mbed-TZ-nonsecure-example`
Tell Mbed of non-secure flash/SRAM partition for non-secure world
To compile TrustZone non-secure code, we need to tell Mbed build system of non-secure flash/SRAM partition for non-secure world. If we skip the step, default non-secure partition would be applied. Usually, the step is required if we compile our own secure code as above which would change the default partition.
"target_overrides": {
......
"NU_PFM_M2351_NPSA_NS": {
......
"target.mbed_rom_start" : "0x10040000",
"target.mbed_rom_size" : "0x40000",
"target.mbed_ram_start" : "0x30008000",
"target.mbed_ram_size" : "0x10000",
.......
}
}
"target_overrides": {
......
"NU_M2354_NPSA_NS": {
......
"target.mbed_rom_start" : "0x10080000",
"target.mbed_rom_size" : "0x80000",
"target.mbed_ram_start" : "0x30020000",
"target.mbed_ram_size" : "0x20000",
......
}
}
Exclude pre-built secure image/gateway library
There has been a pre-built secure code in mbed-os directory tree. To link with our own one as above, we must exclude the pre-built one.
"target_overrides": {
......
"NU_PFM_M2351_NPSA_NS": {
"target.extra_labels_remove" : ["NU_PREBUILD_SECURE"],
......
}
}
"target_overrides": {
......
"NU_M2354_NPSA_NS": {
"target.extra_labels_remove" : ["NU_PREBUILD_SECURE"],
......
}
}
Add compiled secure code above into non-secure code build process
Create one directory named below in the root of the example, and copy NuMaker-mbed-TZ-secure-example.hex
/cmse_lib.o
(just built above) there:
TARGET_NU_PFM_M2351_NPSA_NS
TARGET_NU_M2354_NPSA_NS
Compile by running command:
M2351:
mbed compile -m NU_PFM_M2351_NPSA_NS -t ARM --app-config mbed_app_custom.json
M2354:
mbed compile -m NU_M2354_NPSA_NS -t ARM --app-config mbed_app_custom.json
Flash compiled secure/non-secure code together
Drag-n-drop below to flash compiled secure/non-secure code together:
BUILD/NU_PFM_M2351_NPSA_NS/ARM/NuMaker-mbed-TZ-nonsecure-example.hex
onto NuMaker-PFM-M2351 board
BUILD/NU_M2354_NPSA_NS/ARM/NuMaker-mbed-TZ-nonsecure-example.hex
onto NuMaker-M2354 board
If everything goes well, you would see console log emitted by non-secure code like:
+---------------------------------------------+
| Non-secure code is running ... |
+---------------------------------------------+
Non-secure main thread: 0
Non-secure main thread: 1
Non-secure main thread: 2
Non-secure main thread: 3
Non-secure main thread: 4
You would also see console log emitted by secure code in the front if serial is enabled in it.
NOTE: Configure your terminal program to 115200/8-N-1.