Finally, a familiarity with the use of MCUXpresso IDE and SDK installation is assumed.
In essence, MCUs incorporating Arm Trustzone technology are able to provide system wide isolation between Secure (S) and Non Secure (NS) worlds. Within the Non Secure environment, access to certain operations, peripherals etc. are controlled from the Secure world. This behaviour is delivered by a single CPU with execution time being shared between these two worlds.
Developing for systems using Trustzone features presents a number of challenges in particular providing Secure World services for Non Secure application developers, debugging of both Secure and Non Secure code (projects) and delivering a usage model within the IDE that can be easily used and understood.
The examples supplied with the SDK contain both Secure and Non Secure linked projects and are configured within the IDE to demonstrate development from the point of view of both Secure and Non Secure development.
However, a more typical 'real world' situation may be for developers working on Non Secure project development and treating the Secure world as a 'Black Box' (or Bootloader) that provides a number of explicit secure operations. This use case will be discussed in a subsequent article.
Note: the LPC55S69 is a multicore MCU as in it contains two physical CPUs - numbered 0 and 1. In these examples all code is targeted at CPU 0, and the use of CPU 1 is outside the scope of this article.
Importing (Linked) Example Project
First, ensure you have installed version SDK version 2.6 for the LPCXpresso55S69 EVK board into MCUXpresso IDE. Once installed it will be visible within the Installed SDKs view and its version shown as below:
From the Quickstart view, launch the 'Import SDK example(s)' Wizard, then select the LPCXpresso55S69 board and click <next>
Expand the trustzone examples and click either of the Hello World projects. Since these projects are linked, both the Secure (_s) and Non Secure (_ns) examples will be selected. Click <finish> to start the import.
Note: Linked projects are coloured yellow within the wizard. This project linkage is set because the Non Secure project relies on Secure project for access to allowed Secure operations (calls). Where as the Secure project references the Non Secure project for debug operations (flash programming).
Once imported, you will see the Project Explorer view contains the projects as expected.
Project Settings Exploration
The memory allocation of each project can be seen in the Project Explorer view by opening the Project Settings Node and then the Memory Node. From here you can see the input memory ranges set for the managed linker script mechanism (for each project):
Apart from the veneer table, these projects can be considered as separate entities and must have non overlapping memory regions.
Secure: A feature of the address space security is that the setting of address bit 28 signifies a secure location (odd numbers in the most significant nibble).
The flash region PROGRAM_FLASH at 0x10000000 specifies the secure LinkServer flash driver LPC55xx_S.cfx.
The SG_veneer_table block at 0x1000FE00 is used for code to provide a gateway to (certain) secure functions and inherits the same flash driver. Note: the name SG_veneer_table is a 'magic' string recognised by the IDE as an option for veneer placement (see later)
Non Secure: For these addresses, bit 28 is not set signifying non secure locations (even numbers in the most significant nibble)
The flash region PROGRAM_FLASH at 0x10000 specifies the non secure LinkServer flash driver LPC55xx.cfx.
Trustzone capable MCUs have a number of dedicated Project Properties primarily addressing linkage and debug.
A project set to be Secure will have further options available, including a setting for the location of the Secure veneer table, and check box to cause the generation of the Import Library. An additional Secure Gateway Import Library can also be specified.
Secure: Below is shown the MCU Linker -> Trustzone properties dialogue.
Note the Secure Gateway Placement (Secure veneers to shared secure operations) is set to use the 'magic' flash memory region (mentioned in the previous section) for placement.
Also observe the MCU Debugger -> Trustzone option. If used (as in this example), this takes the name of the associated non secure project which will then automatically be (built and) programmed when the Secure project debug operation is performed. In addition the symbols for this associated project will be added to allow source level debugging of both projects.
When selected, it will look like below:
Non Secure: Below is shown the MCU Linker -> Trustzone properties dialogue: Note the Secure Gateway Import Library references the Secure projects generated library location.
Building the Example Projects
Building the examples is as simple selecting the project and clicking Build in the Quickstart panel. Be aware that building the Non Secure project will force the Secure project to build first to provide linkage to the Secure Gateway library.
Assuming neither project has been built before, building the Non Secure Hello World project will result in the generation of both Secure and Non Secure .axf(s) and generate the output as below:
Memory region Used Size Region Size %age Used PROGRAM_FLASH: 16872 B 65024 B 25.95% SG_veneer_table: 32 B 512 B 6.25% Ram0: 4388 B 32 KB 13.39% Finished building target: lpcxpresso55s69_hello_world_s.axf
Memory region Used Size Region Size %age Used PROGRAM_FLASH: 7372 B 456 KB 1.58% Ram0: 8448 B 172 KB 4.80% Finished building target: lpcxpresso55s69_hello_world_ns.axf
Note: building the Secure project does not force a build of the Non Secure since there are no build dependencies in this direction.
Debugging the Example Projects
As already mentioned, these examples demonstrate development from the point of view of both Secure and Non Secure projects. Hence the initial flow is intended to show startup within a the Secure world and then the migration to the Non Secure where a secure operation will be performed.
Therefore, begin by selecting the Secure Project in the Project Explorer view and clicking Debug in the Quickstart Panel. Since we have the option set to enable the pre-programming of the Non Secure binary there will be two stages to this debug operation.
Note: If this is the first time this project has been debugged, you will be presented with the option to select a debug probe. Then, since this is a MultiCore MCU, you must also select the core to use (be sure that this is set to Core 0).
First, the Non Secure binary will be programmed into flash memory - this automatic step will proceed like a normal binary programming operation and generate a log associated with Non Secure project, a fragment shown below:
Flash variant 'LPC55xx (608KB)' detected (608KB = 19*32K at 0x0) Writing 7372 bytes to address 0x00010000 in Flash 1 of 1 ( 0) Writing pages 2-2 at 0x00010000 with 7372 bytes ( 0) at 00010000: 0 bytes - 0/7372 (100) at 00010000: 8192 bytes - 8192/7372 Erased/Wrote sector 2-2 with 7372 bytes in 122msec Closing flash driver LPC55xx.cfx (100) Finished writing Flash successfully. Flash Write Done Loaded 0x1CCC bytes in 417ms (about 17kB/s)
Secondly, the Secure project will then be programmed in the normal way, this will generate a standard debug log associated with the Secure project, a fragment is shown below:
Note: again if this is the first time, the debug probe and MCU core must be selected. For subsequent debug operations, these options will be remembered.
Flash variant 'LPC55xx (608KB) (Secure)' detected (608KB = 19*32K at 0x10000000) Writing 32 bytes to address 0x1000FE00 in Flash 1000A000 done 25% (8192 out of 32288) 1000C000 done 50% (16384 out of 32288) 1000E000 done 76% (24576 out of 32288) 10010000 done 100% (32768 out of 32288) Erased/Wrote sector 1-1 with 32 bytes in 709msec Closing flash driver LPC55xx_S.cfx Flash Write Done Flash Program Summary: 16904 bytes in 1.00 seconds (16.59 KB/sec) Starting execution using system reset and halt target with a stall address Retask read watchpoint 1 at 0x50000040 for boot ROM stall Restore internally retasked watch #1 no type address 0x0 (unused) Note - system reset leaves VTOR at 0x13000000 (not 0x10000000 which a booted image might assume) Stopped (Was Reset) [Reset from Unknown] Stopped: Breakpoint #2
Once programming is complete, you should arrive at the default Breakpoint on main within the Secure world as below:
Click Run and this project will first perform some board/MCU initialisation, print a greeting (as below), then setup the environment for the Non Secure project to execute.
Note: this step is necessary because the non secure project is not run from reset, so cannot rely on the default hardware behaviour for initialisation of Stack, Interrupt handlers etc. This is essentially the same operation that a bootloader would perform.
Next, a jump will be made to the Non Secure world.
Note: since the non secure project is not debugged directly, it will have no default breakpoint on its main function. To explore the execution, it is recommended to open the Non Secure projects Source -> hello_world_ns.c and manually set a breakpoint as shown below:
Reminder, since we have the option set to enable the pre-programming of the Non Secure binary this also enabled the loading of Non Secure symbols (which can be observed in the Secure projects debug launch configuration (shown below). It is the loading of these symbols which enables source level debug of the Non Secure project while we are actually debugging the Secure project.
Finally, click Run to run this example to termination and observe the output.
Note: the significance of this example is that the String Compare operation was supplied to the Non Secure project by the Secure project and accessed securely via the Non Secure Entry (NSE).
This step concludes the expected use of this example.
Another mode of operation is to perform a Debug operation directly on the Non Secure project. This is a perfectly valid operation provided the Secure project has first been programmed into flash. If so the Non Secure project will behave like a standard project and arrive the breakpoint on main ()... However, if the Secure Project has not been pre-loaded, the debug operation will fail.
If Debug operations fail...
It is possible to program an image into flash that when run prevents further debug operations succeeding. Should this occur, please follow the steps below:
Click on the "Clean Up debug" button on the main IDE toolbar - this kills any stale low level debug operations
Disconnect the USB cable from your board to remove power
Place a jumper on the ISP header (J10) - this will prevent the board booting the image in flash by forcing the MCU to enter ISP mode
Now reconnect the USB cable to Debug Link connector (P6)
Now select a project in the Project Explorer view, and then click on the GUI Flash Tool on the main IDE toolbar - and use this to mass erase the flash. [More details on using the GUI Flash Tools can be found inside the supplied IDE v11.0 User Guide]
If this succeeds, then:
Disconnect the USB cable from your board
Remove the jumper on the ISP header (J10)
Now reconnect the USB cable to Debug Link connector (P6)
Now try starting a debug session for your project again using the Quickstart Panel's Debug button. If this problem occurs as part of application development, try programming a known working example to ensure there are no underlying problems.