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.
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 28th bit is set to 1. To download the firmware to the secure flash, select the Secure flash driver „LPC55xx_S.cfx“.
Create a new project and set security and memories as follows.
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.
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).
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.
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
It is the last setting of the Secure project in Config Tools, at this stage update the code.
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.
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.
Do the following updates in source/Secure.c file.
/*!
* @brief Application-specific implementation of the SystemInitHook()
* weak function.
*/
void SystemInitHook(void)
{
BOARD_InitTEE();
}
/*
* @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');
}
/* 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 ;
}
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.
Set up PINT to use callback on falling edge of the S2 button press. Add the driver, for example, via quick fix.
/*
* @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();
...
/*
* @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.
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.