Arm® TrustZone® Getting Started Application on SAM L11: Step 5
Add Application Code to the 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/Secure. 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.
Open the trustzone_sam_l11_xpro_Secure project main_l11.c in MPLAB® X IDE and add the application code by following the steps:
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 Secure application, which is configured through MPLAB Code Configurator (MCC).
In the main() function, below SYS_Initialize(), add the following code to register callback event handlers.
RTC_Timer32CallbackRegister(rtcEventHandler, 0);
EIC_CallbackRegister(EIC_PIN_5,EIC_User_Handler, 0);
Following the addition of the code above, add the function call.
Implement the registered callback event handlers for Secure RTC, Secure I²C, and Secure EIC PLIBs by adding the following code before the main() function in main_l11.c.
{
changeTempSamplingRate = true;
}
static void rtcEventHandler (RTC_TIMER32_INT_MASK intCause, uintptr_t context)
{
if (intCause & RTC_TIMER32_INT_MASK_CMP0)
{
isRTCTimerExpired = true;
}
}
static void i2cEventHandler(uintptr_t contextHandle)
{
if (SERCOM1_I2C_ErrorGet() == SERCOM_I2C_ERROR_NONE)
{
if(i2cAddress == TEMP_SENSOR_SLAVE_ADDR)
{
isTemperatureRead = true;
}
else if(isEEPROMReadReq == true)
{
isEEPROMReadReq = false;
eepromTemperatureDataReadStatus = true;
}
isI2CFree = true;
}
}
Implement the temperature conversion function to convert the temperature value read from sensor to a readable format (Degree Celsius) by adding the following code before the main() function in main_l11.c.
{
int16_t temp;
// Convert the temperature value read from sensor to readable format (Degree Celsius)
// For demonstration purpose, temperature value is assumed to be positive.
// The maximum positive temperature measured by sensor is +125 C
temp = (rawTempValue[0] << 8) | rawTempValue[1];
temp = (temp >> 7) * 0.5;
temp = (temp * 9/5) + 32;
return (uint8_t)temp;
}
Implement the EEPROM write function to write the temperature value read from the sensor into EEPROM by adding the following code before the main() function in main_l11.c.
{
eepromTxBuffer[0] = EEPROM_LOG_MEMORY_ADDR + wrIndex;
eepromTxBuffer[1] = temperature;
/* Submit I2C transfer to store the temperature value in EEPROM */
SERCOM1_I2C_Write(EEPROM_I2C_SLAVE_ADDR, (void *)eepromTxBuffer, 2);
/* Increment the EEPROM memory index */
if (++wrIndex >= EEPROM_MAX_LOG_VALUES)
{
wrIndex = 0;
}
}
Implement the secure application function by adding the following code before the main() function in main_l11.c.
{
if ((isI2CFree == true) &&
(isRTCTimerExpired == true)) //Temperature Reading from Sensor
{
isRTCTimerExpired = false;
isI2CFree = false;
i2cAddress = TEMP_SENSOR_SLAVE_ADDR;
SERCOM1_I2C_WriteRead(TEMP_SENSOR_SLAVE_ADDR, &i2cWrData, 1, i2cRdData, 2);
}
if ((isI2CFree == true) &&
(isTemperatureRead == true))
{
isTemperatureRead = false;
if(changeTempSamplingRate == false)
{
temperatureVal = getTemperature(i2cRdData);
memset((char*)secureUartTxBuffer, 0x00, 100);
sprintf((char*)secureUartTxBuffer, "Temperature = %02d F\r\n", temperatureVal);
LED_Toggle();
// Temperature Writing to EEPROM
i2cAddress = EEPROM_I2C_SLAVE_ADDR;
isI2CFree = false;
EEPROM_Write(temperatureVal);
}
else
{
changeTempSamplingRate = false;
if(tempSampleRate == TEMP_SAMPLING_RATE_500MS)
{
tempSampleRate = TEMP_SAMPLING_RATE_1S;
sprintf((char*)secureUartTxBuffer, "Sampling Temperature every 1 second \r\n");
RTC_Timer32CompareSet(PERIOD_1S);
}
else if(tempSampleRate == TEMP_SAMPLING_RATE_1S)
{
tempSampleRate = TEMP_SAMPLING_RATE_2S;
sprintf((char*)secureUartTxBuffer, "Sampling Temperature every 2 seconds \r\n");
RTC_Timer32CompareSet(PERIOD_2S);
}
else if(tempSampleRate == TEMP_SAMPLING_RATE_2S)
{
tempSampleRate = TEMP_SAMPLING_RATE_4S;
sprintf((char*)secureUartTxBuffer, "Sampling Temperature every 4 seconds \r\n");
RTC_Timer32CompareSet(PERIOD_4S);
}
else if(tempSampleRate == TEMP_SAMPLING_RATE_4S)
{
tempSampleRate = TEMP_SAMPLING_RATE_500MS;
sprintf((char*)secureUartTxBuffer, "Sampling Temperature every 500 ms \r\n");
RTC_Timer32CompareSet(PERIOD_500MS);
}
else
{
;
}
}
temperatureStatus = true;
}
if ((isI2CFree == true) &&
(isEEPROMRead == true)) //Temperature Reading from EEPROM
{
isI2CFree = false;
isEEPROMRead = false;
isEEPROMReadReq = true;
i2cAddress = EEPROM_I2C_SLAVE_ADDR;
eepromTxBuffer[0] = EEPROM_LOG_MEMORY_ADDR;
SERCOM1_I2C_WriteRead(EEPROM_I2C_SLAVE_ADDR, eepromTxBuffer, 1, eepromRxBuffer, 6);
}
}
The complete secure functionality must run in the while(1) super loop of the secure main() function in main_l11.c.
Under Source Files > trustZone, in the nonsecure_entry.c file, implement the following non-secure callables to access and request the secure application from the non-secure application.
/* Non-secure callable (entry) function */
bool __attribute__((cmse_nonsecure_entry)) readTemperatureData(uint8_t *lcluartTxBuffer)
{
bool lcltemperatureStatus = temperatureStatus;
if(lcltemperatureStatus == true)
{
memset((char*)lcluartTxBuffer, 0x00, 100);
memcpy(lcluartTxBuffer, secureUartTxBuffer, strlen((const char *)&secureUartTxBuffer[0]));
temperatureStatus = false;
}
return (lcltemperatureStatus);
}
void __attribute__((cmse_nonsecure_entry)) readEEPROMTemperatureDataReq(uint8_t *temperatureBuf)
{
isEEPROMRead = true;
eepromRxBuffer = temperatureBuf;
return ;
}
bool __attribute__((cmse_nonsecure_entry)) getEEPROMTemperatureDataReadStatus(uint8_t *LclWrIndex)
{
bool lclEEPROMTempDataReadStatus = eepromTemperatureDataReadStatus;
eepromTemperatureDataReadStatus = false;
*LclWrIndex = wrIndex;
return (lclEEPROMTempDataReadStatus);
}
void __attribute__((cmse_nonsecure_entry)) secureAppEntry(void)
{
secureApp();
}
Following the addition of the code above, add the header