Secure Boot on PIC32CM LS60 Curiosity Pro Evaluation Kit Using MPLAB® Harmony v3 Software Framework: Step 2

Let's create a test application from scratch to test the Secure booting feature.

  • Once the test application is successfully loaded by the Secure Bootloader, a message will be printed in the Virtual COM, indicating that it was loaded from the Secure Bootloader, and the LED1 (Red-LED) will toggle. If SW0 is pressed and held, it will trigger the Secure Bootloader to program the application again with a new application. The following steps will show how to configure the components for the application and generate the code.

Step 2.1: Create a Test Application Project

The following steps explain the test application project creation.

Step 2.1.1: 32-bit MCC Harmony Project


Open MPLAB® X IDE. From the File menu, choose New Project. Choose the 32-bit MCC Harmony Project.


If you don't see it in the menu, install MCC.

Step 2.1.2: Harmony Installation Path


The path to your Harmony 3 installation folder should already be populated.

If not, create a folder somewhere on your computer, like C:/Microchip/Harmony/v3, and point the project to that path.

The necessary Harmony 3 files will be downloaded to that path later in these steps.


Step 2.1.3: Project Name and Location


In the Project Settings window, apply the following settings:

  • Location: Indicates the path to the root folder of the new project. All project files will be placed inside this folder. The project location can be any valid path, for example, C:/secure_boot/firmware/test_app.
  • Folder: Indicates the name of the MPLAB X IDE .X folder. Enter "pic32cm_ls60_cpro" to create a pic32cm_ls60_cpro.X folder.
  • Name: Indicates the name of the project that will be shown in MPLAB X IDE. Enter "app_pic32cm_ls60_cpro" to set the project's name.

Note: The Path box is read-only. It will update as you make changes to the entries.

  • Click Next to proceed to Configuration Settings.

Step 2.1.4: Project Configuration Name and Target Device


Give a name for the configuration. You could use "pic32cm_ls60_cpro".


The device used in the project is PIC32CM5164LS60100.


Copy the device name and paste it to the Device Filter to have the Target Device properly selected.



Click the Finish button.

Note: Since PIC32CM LS60 MCU has an Arm® TrustZone® module, MCC creates separate Secure and Nonsecure projects. MCC creates the following projects.

  1. secure_boot/firmware/test_app/NonSecure/firmware/pic32cm_ls60_cpro_NonSecure.X
  2. secure_boot/firmware/test_app/Secure/firmware/pic32cm_ls60_cpro_Secure.X

Step 2.3: MCC Content Manager Wizard

Step 2.3.1: Framework Selection


After the project has been created for MPLAB X IDE, MPLAB Code Configurator (MCC) will automatically start, asking for the Framework to use.

Press Select MPLAB Harmony.


Step 2.3.2: Required Content


The Content Manager Wizard will start by automatically adding the required content to be downloaded.
If the Harmony Framework is not downloaded yet on the user's computer, the required content should show the following packages to download:

  • bsp
  • csp
  • core
  • dev_packs
  • quick_docs

If the Framework is already present, then the required content could be empty or some updates available.

Step 2.3.3: Optional Content


If any content is needed for this application, it must be downloaded now using the Wizard. If the Harmony packages are installed, they will not appear in this list.


Usually, the application should work when using the latest available packages.

The list of the versions the latest built was tested with is available in the project. Each time when the project is generated successfully using Harmony, a file called harmony-manifest-success.yml is also created in the src/config/<config_name>/ folder, where the versions used for the tools are listed.

The following figure is the content of the .yml file created when the project was created:


Click on Finish to start downloading the content and have the MCC project created.

Step 2.3.4: Open the MCC Project


Choose the Harmony Framework path.

When finished, two windows will appear. Click Next.


Step 2.3.5: MCC Project View


Once open, the MCC Project Graph view appears as shown in the following figure.


Step 2.4: Configure the Test Application project Using MCC

Now you can start configuring the components needed for the test application.

Step 2.4.1: Project Graph View Management


It's crucial to maintain a neat Project Graph, so make sure to organize the components as you add them. The order of arranging components in the Project Graph is from right to left, starting from peripherals, followed by drivers, stack, and application.

To expand the space available in the Project Graph, click on the blue window button located in the Project Graph Toolbar.



To allow for more space at the bottom, it may be necessary to adjust the layout of the Project Graph. This is important because the right side is reserved for the Component Settings, and hiding components under it by mistake can cause problems.


If the width is set to 800 and the height to 1280, click OK. The Project Graph will provide more space for adding components and a vertical scroll bar will appear to navigate the added components. It is important to note that the right side of the window is reserved for the Component Settings, which should not be accidentally hidden under the added components.

Step 2.4.2: PIC32CM LS60 Curiosity Pro BSP Configuration


To add the board BSP, click on the PIC32CM LS60 Curiosity Pro BSP under Device Resources > Libraries > Harmony > Board Support Packages (BSPs) > PIC32CM LS60 Curiosity Pro BSP. This configures the onboard Switches and LEDs. i.e., SW0, SW1, LED0, and LED1.



After the successful addition of BSP, the Project Graph appears as shown.


Step 2.4.3: Fuse Configuration


As the Secure Bootloader updates the fuse configurations, the generation of fuse configurations has been disabled in the test application project. The User Row configurations, including the application's memory configurations and User NVM Rows, can be updated by the application. To update the fuse configurations while programming the application, the script will use the pre-generated application_user_configurations_out.txt configuration file, which is based on the test application's memory configurations. The following is the memory configuration diagram for the test application.


Step 2.4.4: SysTick Configuration


SysTick is enabled and a 1-second delay is added in the test application for the UART Console to get enumerated after reset.


Step 2.4.5: SERCOM3 and STDIO Configurations


SERCOM3 uses the STDIO interface to print log messages. Before adding SERCOM3, add the STDIO component and satisfy the STDIO dependency i.e., SERCOM3.


To configure the STDIO, click on Device Resources > Libraries > Harmony > Tools > STDIO.



After the addition of the STDIO, the Project Graph looks as follows.



Now connect SERCOM3 with the STDIO interface to print log messages.

  • Right-Click the red diamond in STDIO, click on Satisifiers and choose SERCOM3.
  • Now you can see that the SERCOM3 is connected to STDIO.


Select SERCOM3 and configure it as follows.


Note: In this lab, the SERCOM3 operating mode is configured as Blocking mode as the Test Application is running in the polling mode.

  1. The default Baud Rate is 115,200.
  2. Keep the default Transmit Pinout and configure the Receive Pinout as SERCOM PAD[1] as shown in the figure.

Step 2.4.6: Harmony Core Configuration


Harmony Core is used to generate the application template code, i.e., app.c and app.h files.


To configure the Harmony Core, click on Device Resources > Libraries > Harmony > Core > Core.



After the addition of the Harmony Core, a pop-up comes asking whether FreeRTOS needs to be activated.

  • Click No as you are not using the FreeRTOS in this project.


  • Finally, the Project Graph looks as follows.


Now select the Core component and perform the following configurations.

  • Enable the checkbox to Generate Harmony Application Files.

Step 2.4.7: Clock Configurations


Launch Clock Easy View by going to the Plugins drop-down in the Project Graph MCC window and then selecting Clock Configuration.


A new window, Clock Easy View, is opened inside MCC.


The Clock Easy View window will then appear on your screen.


Tool Tip:

  • The Clock Easy View window can be maximized by clicking the maximize button or by double-clicking on the Clock Easy View window, as shown below.
  • After maximizing the Clock Easy View window, you can switch between the windows by clicking the drop-down icon on the right-most side of the Clock Easy View tab in the MCC, as shown below.
  • The Clock Easy View window can be floated by clicking the float button on the Clock Easy View window, as shown below.
  • The Clock Easy View window can be docked by clicking the dock button on the Clock Easy View window, as shown below.
  • These tips apply to all other plug-in managers like Pin Configuration, DMA Configuration, Event System Configuration, Arm® TrustZone® for Armv8-M, and NVIC Configuration.


Verify the 16 MHz Internal Oscillator (OSC16M) is enabled and select the 12 MHz output in the Oscillator Controller box.



Verify the Digital Frequency Locked Loop (DFLLUP) is disabled.



Verify the Digital Frequency Locked Loop (DFLL48M) is enabled.



Verify the Functional Digital Frequency Locked Loop is disabled.



Verify the GCLK Generator 1 is disabled.



Verify the GCLK Generator 0 is enabled.


Step 2.4.8: TrustZone Memory Configuration


The TrustZone Memory Configurations can be done in two ways.

  1. Go to System > Device & Project Configuration > PIC32CM5164LS60100 Device Configuration > Memory Configuration or
  2. Launch Arm TrustZone for Armv8-M by going to the Plugins drop-down in the Project Graph window and then selecting Arm TrustZone for Armv8-M.
  • The Test Application is configured to use both Secure and Non-Secure memory regions.
  • The flash memory configurations for the test application are shown in the following figure.
  • The 512 KB flash is divided into three regions, i.e., Secure Boot, Secure, and Non-Secure Application regions.
  • Secure Boot region is already allocated to the Secure Bootloader project.
    • Secure Boot Protection size is configured as 4 KB, i.e., 4096 bytes.
  • The Test Application project uses the Secure and Non-Secure memory regions.
    • The Secure Application size is configured as 16 KB, i.e., 16384 bytes.
    • The remaining available memory is 512KB-4KB-16KB (492 KB), i.e., 503808 bytes configured as Non-Secure Application size.
    • The Non-Secure region is not present; hence the sizes for Application Non-Secure Callable and Boot Non-Secure Callable are set to 0 bytes.

Note: Ensure the entire DATA and SRAM flash is configured as Secure.

  • Data Secure size is 16 KB, i.e., 16384 bytes.
  • Secure RAM is divided into two regions, Secure and Non-Secure regions.
    • The Secure RAM size is 16 KB, i.e., 16384 bytes configured for the Secure region.
    • The remaining size is 48 KB, i.e., 49512 bytes is configured for the Non-Secure region.


Launch Arm TrustZone for Armv8-M by going to the Plugins drop-down in the Project Graph window and then selecting Arm TrustZone for Armv8-M.


A new window, Arm Trustzone for Armv8-M, is opened inside MCC.


Open the TrustZone Manager plugin under Plugins to view or modify the Memory Configurations in a graphical view.


Tool Tip:

  • You can use the mouse and click on the highlighted markers on the Flash, Data Flash, and SRAM to modify the memory region sizes as in the figure.
  • Left-click using the mouse on any one of the highlighted markers and move up and down to modify the size.
  • The green color indicates that the memory region is configured as Secure.
  • The red color indicates that the memory region is configured as Non-Secure.


  • The above steps explain the usage of the TrustZone plugin. Do not make the above memory configurations in your application.

Step 2.4.9: TrustZone Peripheral Configuration


To view the peripheral configurations, you can click on the Peripheral Configuration tab in the TrustZone Manager plugin. All peripherals are set to Secure mode by default, except for the DSU.

  • In this test application, SERCOM3 is configured as a Non-Secure peripheral. It will be used to print log messages when the test application firmware is loaded by the Secure Bootloader.
  • To configure the SERCOM3 as Non-Secure, click on Peripheral Configuration tab in the TrustZone Manager plugin and left-click on SERCOM3 using the mouse.
  • This makes the SERCOM3 a Non-Secure peripheral.

Tool Tip:

  • The green color indicates that the peripheral is configured as Secure.
  • The red color indicates that the peripheral is configured as Non-Secure.
  • You can use the mouse and left-click on any Peripherals or Mix-Secure Peripherals or System Resources to change a peripheral from Secure to Non-Secure or vice versa.


  • The above steps explain the usage of the TrustZone plugin. Do not configure other peripherals except the ones shown above.

Step 2.4.10: Pin Configuration


Launch Pin Configuration by going to the Plugins drop-down in the Project Graph window and then selecting Pin Configuration.


A new window, Pin Settings, is opened inside MCC.


Once the MCC Pin Settings window is opened, scroll down to pin numbers PB20 and PB21 and then configure these pins as follows:

  • Set the Pin Number #68 as SERCOM3_PAD0:
    • Pin ID: PB20
    • Function: SERCOM3_PAD0
    • Security Mode: NON-SECURE
  • Set the Pin Number #69 as SERCOM3_PAD1:
    • Pin ID: PB21
    • Function: SERCOM3_PAD1
    • Security Mode: NON-SECURE
  • The previous step configures the UART TX and RX pin.
  • The UART pins are configured as per the design schematic on the PIC32CM LS60 Curiosity Pro Evaluation Kit.
  • The LEDs and switches are configured when the PIC32CM LS60 Curiosity Pro Evaluation Kit BSP is added in the Step 2.4.2

Step 2.4.11: Generate Code


To generate the code, click on the Generate button in the Project Resource pane. This will generate the necessary code files based on the project configuration.


A popup will appear. Wait for the operation to finish.



  • MCC maintains a single configuration file for both Secure and Non-Secure projects, i.e., the app_pic32cm_ls60_cpro_NonSecure.mc3 configuration file in <Your_Secure_Bootloader_Downloaded_Path>/pic32cm_ls60_cpro_secure_boot/ and firmware/test_app/NonSecure/firmware/pic32cm_ls60_cpro_NonSecure.X.
  • Whenever a new TrustZone-based project is created using MCC, it creates both Secure and Non-Secure projects. It sets the Non-Secure project as a main project, e.g., app_pic32cm_ls60_cpro_NonSecure, as it consists of the MCC configuration file.
  • Hence, in the above steps you configured both the app_pic32cm_ls60_cpro_Secure and app_pic32cm_ls60_cpro_NonSecure project and generated the code for both Secure and Non-Secure projects except the Harmony manifest file for the app_pic32cm_ls60_cpro_Secure project.
    • MCC autogenerates the Harmony manifest file and contains the details about the project information like the date of creation, version details for MCC, MPLAB X IDE, XC32, and modules used while creating the project.

Steps to Generate the Harmony Manifest File for app_pic32cm_ls60_cpro_Secure Project:

  • Set Secure project as a Main Project i.e., app_pic32cm_ls60_cpro_Secure.
  • Launch MCC by clicking the MCC icon as shown in the following figure or by going to menu Tools > Embedded > MPLAB Harmony Code Configurator v5 Open/Close.
  • Once the project graph is launched, click on the Generate button in the Project Resource window.
  • A popup will appear, wait for the operation to finish.
  • This generates necessary code files based on the project configuration and the harmony-manifest-success.yml file for the app_pic32cm_ls60_cpro_Secure project.

Step 2.4.12: Post Build Configuration


Open the project properties and enable the post-build option as shown below and add the following command to copy the HEX and BIN file to the test application project path, <Your_Test_Application_Project_Path>/secure_boot/hex/test_app.

rm -rf ${ProjectDir}/../../../../../hex/test_app && mkdir ${ProjectDir}/../../../../../hex/test_app && cp ${ProjectDir}/${ImagePath} ${ProjectDir}/../../../../../hex/test_app && cp ${ProjectDir}/*.lib ${ProjectDir}/../../../../../hex/test_app && cp ${ProjectDir}/${ImageDir}/*.unified.hex ${ProjectDir}/../../../../../hex/test_app && ${MP_CC_DIR}"/xc32-objcopy" -I ihex -O binary ${DISTDIR}/${PROJECTNAME}.${IMAGE_TYPE}.unified.hex ${DISTDIR}/${PROJECTNAME}.${IMAGE_TYPE}.unified.bin && cp ${ProjectDir}/${ImageDir}/*.unified.bin ${ProjectDir}/../../../../../hex/test_app

Step 2.4.13: Add Test Application Code


Add the pre-developed test application code, which handles the task of printing a message on the console when it is loaded by the Secure Bootloader, and it also toggles LED0 to indicate that the application is running correctly. Compare the code in dev_files/test_app/NonSecure/firmware/src, and copy it as needed.

  • The test application is already partially developed and is available in the NonSecure/firmware/src/app.c, NonSecure/firmware/src/app.h, and NonSecure/firmware/src/config/pic32cm_ls60_cpro/user.h files under the path <Your_Secure_Bootloader_Downloaded_Path>/pic32cm_ls60_cpro_secure_boot/dev_files/test_app/


  • The app.c file contains the test application logic and app.h consists of the prototypes and definitions for the test application. It also contains placeholders that you will populate with the necessary code in the next step.
  • The user.h file contains user definitions of the test application project.
  • Go to the pic32cm_ls60_cpro_secure_boot/dev_files/test_app/ folder and copy the pre-developed NonSecure/firmware/src/app.c, NonSecure/firmware/src/app.h, and NonSecure/firmware/src/config/pic32cm_ls60_cpro/user.h files.
  • Replace (over-write) the app.c, app.h, and user.h files of your project available in <Your_Secure_Bootloader_Downloaded_Path>/pic32cm_ls60_cpro_secure_boot/firmware/test_app/NonSecure/firmware/src with the copied files.
  • Open app.c in MPLAB X IDE and add the test application code by following the steps below:


Under the app.c file, in the APP_Initialize() function, start the Application Timer.

void APP_Initialize ( void )
    appData.state = APP_INIT;



Under the app.c file, in the APP_Tasks() function add the code to print the message on the console when the Secure Bootloader loads the test application.

  • Also, the test application jumps to Secure Bootloader whenever switch SW0 is pressed and restarts the device.
void APP_Tasks ( void )
    /* Check the application's current state. */
    switch ( appData.state )
        /* Application's initial state. */
        case APP_INIT:
            /* Add Delay for the UART Console to get enumerated after reset */

            printf("\r\n\r\n####### Application loaded from Bootloader #######\r\n");

            appData.state = APP_SWITCH_PRESS_WAIT;

            if (SWITCH_GET() == SWITCH_PRESSED)
                appData.state = APP_TRIGGER_BOOTLOADER;




            printf("\r\n####### Bootloader Triggered #######\r\n");

            printf("\r\n####### Program new firmware from Bootloader #######\r\n");

            // The RAM location to load the Bootloader trigger pattern is located
            // in RAM secure region. Hence calling secure_bootloaderTrigger().
            // Never returns as it initiates a reset after loading the trigger pattern

            /* TODO: Handle error in application's state machine. */


The test application has two projects, Secure and Non-Secure. The Non-Secure application calls the Secure APIs using the Non-Secure entry interfaces present in the nonsecure_entry.h.

  • Since both the Secure and Non-Secure applications are developed by a single user, you need to add the Non-Secure entry function definition into the generated nonsecure_entry.c file.
  • The pre-developed code is kept in the dev_files/test_app/Secure/firmware/src/trustZone/nonsecure_entry.c
  • Replace (over-write) the nonsecure_entry.c and nonsecure_entry.h files of your project available at:

Secure/firmware/src/trustZone/nonsecure_entry.c and
NonSecure/firmware/src/trustZone/nonsecure_entry.h with the copied files.

  • Under the nonsecure_entry.c file, the secure_bootloaderTrigger() function is used to trigger the Secure Bootloader from the test application.
#include <stdio.h>
#include "device.h"

#define BTL_TRIGGER_RAM_START  0x20001000U

uint32_t __attribute((address(BTL_TRIGGER_RAM_START))) ramarray[4];

static uint32_t *ramStart = (uint32_t *)ramarray;

/* Non-secure callable (entry) function */
void __attribute__((cmse_nonsecure_entry)) secure_bootloaderTrigger(uint32_t triggerPattern)
    ramStart[0] = triggerPattern;
    ramStart[1] = triggerPattern;
    ramStart[2] = triggerPattern;
    ramStart[3] = triggerPattern;



Under the nonsecure_entry.h file, replace extern int secure_add(int x, int y); interface with extern void secure_bootloaderTrigger(uint32_t triggerPattern);.

extern void secure_bootloaderTrigger(uint32_t triggerPattern);

You are now ready to build the test application project and observe the results!

Step 2.4.14: Build the Test Application Project


To generate the test application unified binary, you need to build the test application project in the MPLAB X IDE. Once the build process is complete, the pic32cm_ls60_cpro_NonSecure.X.production.unified.bin file will be generated in the path where you created the test application project (<Your_Test_Application_Project_Path>/secure_boot/hex/test_app, e.g., C:/secure_boot/hex/test_app).

Note: The TrustZone-based projects generally have lengthy path names; hence, the project may fail to build when trying to build from the reference_apps or the downloaded path. To overcome this build error, copy the project to the root directory, i.e., C:/. Then open the project in the MPLAB X IDE and build.

Next Step >

© 2024 Microchip Technology, Inc.
Notice: ARM and Cortex are the registered trademarks of ARM Limited in the EU and other countries.
Information contained on this site regarding device applications and the like is provided only for your convenience and may be superseded by updates. It is your responsibility to ensure that your application meets with your specifications. MICROCHIP MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND WHETHER EXPRESS OR IMPLIED, WRITTEN OR ORAL, STATUTORY OR OTHERWISE, RELATED TO THE INFORMATION, INCLUDING BUT NOT LIMITED TO ITS CONDITION, QUALITY, PERFORMANCE, MERCHANTABILITY OR FITNESS FOR PURPOSE. Microchip disclaims all liability arising from this information and its use. Use of Microchip devices in life support and/or safety applications is entirely at the buyer's risk, and the buyer agrees to defend, indemnify and hold harmless Microchip from any and all damages, claims, suits, or expenses resulting from such use. No licenses are conveyed, implicitly or otherwise, under any Microchip intellectual property rights.