Step 4: Add Application Code to the Project

Last modified by Microchip on 2026/07/01 09:20

This example application on the PIC32CM LS00 Curiosity Nano+ Touch Evaluation Kit demonstrates communication between Secure and Non-Secure regions in an Arm® TrustZone®-enabled project. The External Interrupt Controller (EIC) peripheral is configured as Non-Secure, while the LED peripheral is set as Secure. A Non-Secure interrupt triggers a Secure LED toggle operation via a Secure Gateway function, using the cmse_nonsecure_entry attribute. Secure Gateway function declarations are included in the nonsecure_entry.c and nonsecure_entry.h files.

Information

Tip: Press the CTRL key and left-click on the SYS_Initialize function. The click will open the implementation for the SYS_Initialize function.

Application Code for the Project

Open the main.c file in the Non-Secure project and add the EIC_CallbackRegister function call after SYS_Initialize(NULL) within the int main(void) function. This callback registration allows the application to automatically execute a specified function when an external interrupt occurs, such as a button press.

Code(Non-Secure - main.c)

EIC_CallbackRegister(EIC_PIN_2, EIC_User_Handler, 0);

                                    code

Information

Note: EIC_CallbackRegister is the function used to register a callback, with EIC_PIN_2 specifying the pin that generates the interrupt in the Non-Secure region. EIC_User_Handler is the user-defined callback function in the Non-Secure region. When an interrupt (such as a switch press) is detected on EIC_PIN_2, the EIC peripheral automatically invokes the registered callback function to handle the event.

Add the user-defined EIC handler function above the int main(void) function and declare the secureAppEntry_Led function below the inclusion of the header files.

Code: (Non-Secure - main.c)

extern void secureAppEntry_Led(void);

static void EIC_User_Handler(uintptr_t context)
{
    secureAppEntry_Led();
}

                                   code

To invoke a Secure function from the Non-Secure project, first declare the Secure function prototype in the Non-Secure source file using the extern keyword, which informs the compiler that the function is defined in the Secure project. Then, call this function within the Non-Secure interrupt handler, such as the EIC callback. This approach enables the Non-Secure application to access a Secure function located in the Non-Secure Callable (NSC) region via the Secure Gateway mechanism, ensuring secure and isolated cross-domain communication when an interrupt event occurs.

Open the nonsecure_entry.h file from lab14_trustzone_basic Non-Secure project. To do this, navigate to the Header Files section, then open the trustZone folder, and double-click on nonsecure_entry.h to access the Non-Secure Callable header file. Next, add the prototype for the Non-Secure Callable function secureAppEntry_Led, using the extern keyword. This allows the Non-Secure region to access the Secure region through this function.

Code: (nonsecure_entry.h)

extern void secureAppEntry_Led(void);

       nonsecure_entry.h

Open the nonsecure_entry.c file from the Secure project, lab14_trustzone_basic_secure. To do this, navigate to the Source Files section, then open the trustZone folder, and double-click on the nonsecure_entry.c file.

Code: (nonsecure_entry.c)

extern void LED_Toggle_Func(void);

void __attribute__((cmse_nonsecure_entry)) secureAppEntry_Led(void)
{
    LED_Toggle_Func();
}

            nonsecure_entry.c

In the Secure project, the code described above is added to the nonsecure_entry.c file to enable the Non-Secure application to toggle an LED located in the Secure region. The declaration extern void LED_Toggle_Func(void); references the Secure LED toggle function, which is defined elsewhere in the Secure code. The function secureAppEntry_Led() is annotated with the cmse_nonsecure_entry attribute, placing it in the NSC region and allowing access through the Secure Gateway mechanism. When this function is called from the Non-Secure side, the processor safely transitions to the Secure state.

Now open the main.c file located under the Source Files section of the Secure project. Add the LED toggle function definition under the typedef for the Non-Secure callback function.

Code: (Secure main.c)

void LED_Toggle_Func(void)
{
    LED_Toggle();
}

main.c

The function LED_Toggle_Func() is implemented in the Secure main.c file and is responsible for controlling the LED configured in the Secure region. It internally calls LED_Toggle() to perform the actual General Purpose Input/Output (GPIO) toggle operation. When an EIC interrupt occurs in the Non-Secure region, the Non-Secure callback invokes the Secure Gateway function, which then calls LED_Toggle_Func(). This ensures that the LED is accessed only through a controlled Secure entry point, maintaining proper TrustZone isolation.

Information

Note: At this point, proceed to Step 5: Build, Program, and Observe the output to demonstrate the results of this project. To observe a manual access violation in this TrustZone-based project, follow the steps below.


Access Violation Between Secure/Non-Secure Zones

To demonstrate a manual violation, intentionally bypass the Secure Gateway mechanism by omitting nonsecure_entry.h and nonsecure_entry.c, and attempt to call the Secure LED_Toggle_Func directly from the Non-Secure code in the EIC callback handler. This approach will cause a build failure in MPLAB® X IDE, clearly illustrating that direct access to Secure functions from the Non-Secure region is not permitted. This exercise highlights the importance of using the Secure Gateway interface for proper Non-Secure to Secure communication and maintaining TrustZone isolation.     main.c                    

In the above image, the Secure Gateway interface is not used; instead, the function in the Secure region is called directly from the Non-Secure region. This results in a BUILD FAILED message, as shown in the following image. This violation occurs due to the security enforcement of the TrustZone architecture, which prevents unauthorized direct access between Secure and Non-Secure regions.

build failed example                     

Back to Top