Creating Secure and Non-Secure projects
The LPC55S69 MCU series contains Arm TrustZone® and Trusted Execution Environment extension from NXP. It allows users to assign cores, memories, and peripherals to the Secure or the Non-Secure World and restrict access between them. Manufacturers can use it to secure critical functionality of a device. For example, the Secure code is provided on the device by the manufacturer and could not be modified by users. However, a user can create a Non-Secure application and download it to the device. A secure code can communicate over a channel which security cannot be exposed to the Non-Secure World. This example is shown in the tutorial.
This tutorial demonstrates how to create Secure and Non-Secure projects and their basic configuration using MCUXpresso IDE and Config Tools. LPCXpresso55S69 Board is used for the demonstration of functionality.
Project description
Two projects, a Secure and a Non-Secure, are created.
Both projects are used on a single core.
USART is used for sending data and it is configured as a Secure peripheral.
S1 (ISP) button is used for sending data from the Secure world.
S2 (WAKEUP) button is used for sending data from the Non-Secure world, which is not allowed due to a security violation.
Prerequisites
MCUXpresso IDE 11.3.0
LPCXpresso55S69 SDK 2.9.0
LPCXpresso55S69 Board
You are familiar with the security extension used on LPC55S69.
You are familiar with MCUXpresso IDE and Config Tools – Getting started with TEE.
Steps
1. Create a Secure project
Create a new project, select the security type (Secure), and set memory regions in New Project Wizard. You must do it as Secure and Non-Secure projects use different parts of memories. In addition, secure memories use aliases – the 28 th bit is set to 1. To download the firmware to the secure flash, select the Secure flash driver „LPC55xx_S.cfx“.
2. Create a Non-Secure project
Create a new project and set security and memories as follows.
3. Connect the projects
It is not mandatory but it makes things easier.
Reference the Secure project from the Non-Secure project. It makes importing memory regions into the TEE tool easier. The current and the linked or linking projects are preselected in the import dialog.
In the Secure project set the Non-Secure project to be preprogrammed. Both projects are automatically downloaded to the board prior to debugging the Secure project.
4. Disable generation of a Secure gateway library
This feature is not used in this tutorial, therefore it must be turned off to compile the project. Change it in project properties (right-click the project and select Properties).
5. Route Secure pins
Open Pins tool. Route S1 pin to SECGPIO. For detecting button press, peripheral SPINT is used and it must be routed to the same pin. Flexcom, which is used as USART, is routed by default in a board configuration. Do not change anything there.
6. Setup Secure peripherals
Flexcomm is used for USART communication. Open Peripherals tool. Add USART component in Peripherals tool. Use the default configuration.
Problems related to clocks must be resolved in the Clocks tool by enabling peripheral clock. Right-click the problem in Problems view and select Show problem. It opens the Clocks tool and highlights the problematic clock path.
Add PINT component. Uncheck the checkbox „Show only components in toolchain project“ as the PINT driver is not in the project yet. Otherwise, it is not listed in the dialog.
Select SECPINT peripheral. Configure it to invoke a callback function upon falling edge is detected on S1. Add the PINT driver to the project via quick-fix in the Problems view.
7. Setup security extension in TEE tool
Import memory regions from both projects in the User Memory Regions tab. As nothing is configured for the security extension, there are errors and warnings in the Security Level column.
In Security Access Configuration, Miscellaneous tab enable Secure check for AHB matrix and Non-Secure access to floating point extension (CP10 access). FPU is turned on by default.
Enable SAU and set Non-Secure regions. Other memory is considered Secure.
Set MPC to allow only Secure transactions for Secure memory regions. It resolves errors and warnings in User Memory regions.
Set SECGPIO and SECPINT peripherals as Secure. Keep Flexcomm as Non-Secure for now for demonstration purposes.
Set PINT interrupt security as Non-Secure. Sending data from the Non-Secure world is also triggered by button press so its interrupt security must be set accordingly.
It is the last setting of the Secure project in Config Tools, at this stage update the code.
8. Update Secure project settings
After updating the code, create a TrustZone folder. By default, new folders are excluded from the build. Right-click the folder and uncheck Exclude resource from build in the folder properties. Add the path to the folder into Include paths in project settings.
9. Add missing drivers
If you use this version of tools, add the inputmux driver in the Secure project. It is required for code generated by the Pins tool.
10. Update the Secure source code
Do the following updates in source/Secure.c file.
Add TEE initialization function call. As security is the first thing that should be configured, place it SystemInitHook function. This way it is called before entering the main function. The initialization function is implemented in resource_config.h which must be included.
/*!
* @brief Application-specific implementation of the SystemInitHook()
* weak function.
*/
void SystemInitHook(void)
{
BOARD_InitTEE();
}
Implement SECPINT callback function. After pressing S1, some data is sent from the Secure world via USART. For simplicity, character ‚s‘ is sent from the Secure world and character ‚n‘ is sent from the Non-Secure world.
/*
* @brief Send on byte over secure channel
* @param data data to be sent
*/
void sendSecureByte(uint8_t data) {
USART_WriteByte(FLEXCOMM0_PERIPHERAL, data);
}
/*
* @brief S1 button interrupt callback
* @param pintr pin interrupt type
* @param pmatch_status match status
*/
void secureButtonCallback(pint_pin_int_t pintr ,uint32_t pmatch_status) {
sendSecureByte('s');
}
When you do the initialization in the Secure world, the MCU can continue with executing instructions from the Non-Secure world. The switching consists of setting a Non-Secure stack, a vector table, and calling a reset handler. The Non-Secure flash was previously configured to start at address 0x10000.
/* Start address of Non-secure application */
#define NON_SECURE_START 0x10000
/* typedef for non-secure callback functions */
typedef void (*funcptr_ns)(void) __attribute__((cmse_nonsecure_call));
int main(void) {
/* Init board hardware. */
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitBootPeripherals();
#ifndef BOARD_INIT_DEBUG_CONSOLE_PERIPHERAL
/* Init FSL debug console. */
BOARD_InitDebugConsole();
#endif
PRINTF("Secure World\n");
/* Set non-secure main stack (MSP_NS) */
__TZ_set_MSP_NS(*((uint32_t *)(NON_SECURE_START)));
/* Set non-secure vector table */
SCB_NS->VTOR = NON_SECURE_START;
/* Get non-secure reset handler */
funcptr_ns ResetHandler_ns;
ResetHandler_ns = (funcptr_ns)(*((uint32_t *)((NON_SECURE_START) + 4U)));
/* Jump to normal world */
ResetHandler_ns();
/* Force the counter to be placed into memory. */
volatile static int i = 0 ;
/* Enter an infinite loop, just incrementing a counter. */
while(1) {
i++ ;
/* 'Dummy' NOP to allow source level single stepping of
tight while() loop */
__asm volatile ("nop");
}
return 0 ;
}
11. Route Non-Secure pins
Configure the Non-Secure project properly. Route S2 pin to GPIO as input. Route PINT for pin #64. Flexcomm is routed by default, remove this routing as it is already routed in the Secure project.
12. Setup Non-Secure peripherals
Set up PINT to use callback on falling edge of the S2 button press. Add the driver, for example, via quick fix.
13. Update the Non-Secure source code
Keep the initialization of Pins and Peripherals and remove the other initialization as it was done in the Secure world. That also includes the overriding SystemInit function.
/*
* @brief System initialization
*
* Intentionally empty. Required initialization was done in the Secure project.
*
*/
void SystemInit(void)
{
}
/*
* @brief Application entry point.
*/
int main(void) {
/* Init board hardware. */
BOARD_InitBootPins();
BOARD_InitBootPeripherals();
...
Add the code for sending data from the Non-Secure world. To use the USART_WriteByte function and the imputmux driver, include fsl_usart.h.
/*
* @brief S2 button interrupt callback
* @param pintr pin interrupt type
* @param pmatch_status match status
*/
void nonSecureButtonCallback(pint_pin_int_t pintr ,uint32_t pmatch_status) {
USART_WriteByte((USART_Type *)FLEXCOMM0, 'n');
}
Now the projects are ready. When debug is executed for the Secure project, the Non-Secure project is also downloaded to the board.
After pressing S1, 's' is sent from the Secure world. When S2 is pressed, 'n' is sent from the Non-Secure world because Flexcomm is configured as Non-Secure in the TEE tool.
14. Securing USART
Open the TEE tool from the Secure project and set the Flexcomm slave as Secure. After this change, you can send data from the Secure world but an attempt to send data from the Non-Secure world results in bus fault.
View full article