Arm® TrustZone® Technology Getting Started Application on PIC32CK SG01: Step 6

Last modified by Microchip on 2024/03/26 15:02

Add Application Code to the Non-Secure Project

The application is already partially developed and is available in the main.c file under <your unzip folder>/getting_started_tz_pic32ck_sg01_cult/dev_files/Non-secure. The main.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 getting_started_tz_pic32ck_sg01_cult/dev_files/Non-secure folder and copy the pre-developed main.c file.
Replace the main.c file of your project available at <Your project folder>/getting_started_tz_pic32ck_sg01_cult/firmware/src by overwriting it with the copied file.
Go to the getting_started_tz_pic32ck_sg01_cult/dev_files/Non-secure/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>/getting_started_tz_pic32ck_sg01_cult/firmware/src/trustZone by over-writing it with the copied file.

Open the tz_pic32ck_sg01_cult project main.c in MPLAB® X IDE and add the application code by following the steps:

Under the main.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 Code Configurator (MCC).

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 code

Figure 1

Back to Top


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

    DMA0_ChannelCallbackRegister(DMA_CHANNEL_0, usartTxDmaChannelHandler, 0);
    DMA0_ChannelCallbackRegister(DMA_CHANNEL_1, usartRxDmaChannelHandler, 0);

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

    /* Invalidate cache lines before submitting DMA read request */
    DCACHE_INVALIDATE_BY_ADDR(uartRxBuffer, sizeof(uartRxBuffer));
    DMA0_ChannelTransfer(DMA_CHANNEL_1, (const void *)&(SERCOM5_REGS->USART_INT.SERCOM_DATA), \
            uartRxBuffer, 1);
added function call to receive a character from the serial terminal

Figure 2

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.

Back to Top


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.c.

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

static void usartRxDmaChannelHandler(DMA_TRANSFER_EVENT event, uintptr_t contextHandle)
{
   if (event == DMA_TRANSFER_EVENT_BLOCK_TRANSFER_COMPLETE)
    {
       isEEPROMReadReq = true;
    }
}
nonsecure app code 3

Figure 3

Back to Top


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

void eepromPrintTemperature(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");
    /* Clean cache lines having source buffer before submitting a transfer
     * request to DMA to load the latest data in the cache to the actual
     * memory */

   DCACHE_CLEAN_BY_ADDR(nonSecureUartTxBuffer, sizeof(nonSecureUartTxBuffer));
   DMA0_ChannelTransfer(DMA_CHANNEL_0, nonSecureUartTxBuffer, \
           (const void *)&(SERCOM5_REGS->USART_INT.SERCOM_DATA), \
           strlen((const char*)nonSecureUartTxBuffer));
}
nonsecure app code 4

Figure 4

Back to Top


Add the following code in the while() super-loop to print the received temperature values from the secure application on the serial terminal.

        if (readUartTxData(nonSecureUartTxBuffer) == true)
        {
       /* Maintain state machines of all polled MPLAB Harmony modules. */
          
           /* Clean cache lines having source buffer before submitting a transfer
            * request to DMA to load the latest data in the cache to the actual
            * memory */

           DCACHE_CLEAN_BY_ADDR(nonSecureUartTxBuffer, strlen(nonSecureUartTxBuffer));
           DMA0_ChannelTransfer(DMA_CHANNEL_0, nonSecureUartTxBuffer, \
                   (const void *)&(SERCOM5_REGS->USART_INT.SERCOM_DATA), \
                   strlen((const char*)nonSecureUartTxBuffer));
        }
nonsecure app code 5

Figure 5

Back to Top


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[0]);
        }
nonsecure app code 6

Figure 6

Back to Top


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 through keyboard press. Then the requested last five stored temperature values are read from the EEPROM in the secure application. Along with the printing function, an LED1 is toggled after every keyboard press action. 

        if (getEEPROMTemperatureDataReadStatus(&wrIndex) == true)   //Printing Temperature values read from EEPROM
        {
           isEEPROMReadReq = false;
           eepromPrintTemperature(&eepromRxBuffer[0], wrIndex);
           
           /* Invalidate cache lines before submitting DMA read request */
           DCACHE_INVALIDATE_BY_ADDR(uartRxBuffer, strlen(uartRxBuffer));
           DMA0_ChannelTransfer(DMA_CHANNEL_1, (const void *)&(SERCOM5_REGS->USART_INT.SERCOM_DATA), \
               &uartRxBuffer[0], 1);
           LED1_Toggle();
        }
       secureAppEntry();
nonsecure app code 7

Figure 7

 

Back to Top


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 code 8

Figure 8

You are now ready to build the code!

Back to Top