Arm® TrustZone® Getting Started Application on SAM L11: Step 6

Step 6: Add Application Code to the Non-Secure Project

The application is already partially developed and is available in the main_l11.c file under <your unzip folder>/saml11_getting_started/dev_files/NonSecure. The main_l11.c file contains the application logic. It also contains placeholders that you will populate with the necessary code in the next step.

  • Go to the saml11_getting_started/dev_files/NonSecure folder and copy the pre-developed main_l11.c file.
  • Replace the main_l11.c file of your project available at <Your project folder>/saml11_getting_started/firmware/NonSecure/firmware/src by over-writing it with the copied file.
  • Go to the saml11_getting_started/dev_files/NonSecure/trustZone folder and copy the pre-developed nonsecure_entry.h file.
  • Replace the nonsecure_entry.h file of your project available at <Your project folder>/saml11_getting_started/firmware/NonSecure/firmware/src/trustZone by over-writing it with the copied file.
  • Open the trustzone_sam_l11_xpro_NonSecure project main_l11.c in MPLAB® X IDE and add the application code by following the steps below:

1

Under the main_l11.c file, in function main, notice the call to the SYS_Initialize function. The generated SYS_Initialize function initializes all the peripheral modules used in the non-secure application, which is configured through MPLAB Harmony Configurator (MHC).

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

nonsecure_app_code1.png

2

In the main() function, below SYS_Initialize(), add the following code to register callback event handlers.

DMAC_ChannelCallbackRegister(DMAC_CHANNEL_0, usartTxDmaChannelHandler, 0);
DMAC_ChannelCallbackRegister(DMAC_CHANNEL_1, usartRxDmaChannelHandler, 0);

Following the addition of the code above, add the function call to receive a character from serial terminal.

DMAC_ChannelTransfer(DMAC_CHANNEL_1, (const void *)&(SERCOM0_REGS->USART_INT.SERCOM_DATA), uartRxBuffer, 1);
nonsecure_app_code2.png

Note:

  • The function call DMAC_ChannelCallbackRegister registers a callback event handler with the Direct Memory Access (DMA) PLIB. The callback event handler is called by the DMA PLIB when the DMA transfer (of temperature sensor data to serial terminal) is completed on DMA Channel 0.
  • The function call DMAC_ChannelCallbackRegister registers a callback event handler with the Direct Memory Access (DMA) PLIB. The callback event handler is called by the DMA PLIB when the DMA transfer (receives a character from the serial terminal) is completed on DMA Channel 1.

3

Implement the registered callback event handlers for the DMA PLIB (for both channels) by adding the following code before the non-secure main() function in main_l11.c.

static void usartTxDmaChannelHandler(DMAC_TRANSFER_EVENT event, uintptr_t contextHandle)
{
    if (event == DMAC_TRANSFER_EVENT_COMPLETE)
    {
        isUSARTTxComplete = true;
    }
}

static void usartRxDmaChannelHandler(DMAC_TRANSFER_EVENT event, uintptr_t contextHandle)
{
    if (event == DMAC_TRANSFER_EVENT_COMPLETE)
    {
        isEEPROMReadReq = true;
    }
}
nonsecure_app_code3.png

4

Implement the EEPROM data print function to print the last five temperature values received from the secure application.

void EEPROM_PrintTemperature(uint8_t* pTemperatureValue, uint8_t wrIndex)
{
    char* pBuffer = (char*)nonSecureUartTxBuffer;
    uint8_t len;
    uint8_t i;

    len = sprintf((char*)pBuffer, "EEPROM:");
    for (i = wrIndex; i < EEPROM_MAX_LOG_VALUES; i++)
    {
        len += sprintf((char*)&pBuffer[len], "%dF|", (int8_t)pTemperatureValue[i]);
    }
    if (wrIndex > 0)
    {
        for (i = 0; i < wrIndex; i++ )
        {
            len += sprintf((char*)&pBuffer[len], "%dF|", (int8_t)pTemperatureValue[i]);
        }
    }
    len += sprintf((char*)&pBuffer[len], "\r\n");

    DMAC_ChannelTransfer(DMAC_CHANNEL_0, nonSecureUartTxBuffer, \
            (const void *)&(SERCOM0_REGS->USART_INT.SERCOM_DATA), \
            strlen((const char*)nonSecureUartTxBuffer));
}
nonsecure_app_code4.png

5

Add the following code to print the received temperature values from the secure application on the serial terminal.

if (readTemperatureData(nonSecureUartTxBuffer) == true)
{
    // Printing Temperature value read from Sensor
    DMAC_ChannelTransfer(DMAC_CHANNEL_0, nonSecureUartTxBuffer, \
            (const void *)&(SERCOM0_REGS->USART_INT.SERCOM_DATA), \
            strlen((const char*)nonSecureUartTxBuffer));
}
nonsecure_app_code5.png

6

Add the following code to request the secure application to read the last five values stored in the EEPROM by using non-secure Callables (NSCs) when a character on the serial terminal is received.

if (isEEPROMReadReq == true)       //Request to Temperature Reading from EEPROM
{
    isEEPROMReadReq     = false;
    readEEPROMTemperatureDataReq(&eepromRxBuffer[1]);
}
nonsecure_app_code6.png

7

Add the following code to print the last five temperature values on the serial terminal and also a function call to receive a character from the serial terminal when the requested last five stored temperature values are read from the EEPROM in the secure application.

if (getEEPROMTemperatureDataReadStatus(&wrIndex) == true)   //Printing Temperature values read from EEPROM
{
    isEEPROMReadReq = false;
    EEPROM_PrintTemperature(&eepromRxBuffer[1], wrIndex);
    DMAC_ChannelTransfer(DMAC_CHANNEL_1, (const void *)&(SERCOM0_REGS->USART_INT.SERCOM_DATA), \
        &uartRxBuffer[1], 1);
}

Add the below code to run the complete secure functionality from this non-secure application.

secureApp();
nonsecure_app_code7.png

8

Under Header Files > trustZone, in the nonsecure_entry.h file, add the following code to extern the NSCs to access and request the secure application from the non-secure application.

/* Non-secure callable functions */
extern bool readTemperatureData(uint8_t *lcluartTxBuffer);
extern void readEEPROMTemperatureDataReq(uint8_t *temperatureBuf);
extern bool getEEPROMTemperatureDataReadStatus(uint8_t *LclWrIndex);
extern void secureAppEntry(void);
nonsecure_app_code8.png

You are now ready to build the code!


Next Step >

© 2022 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.