Harmony v3 Drivers and System Services on SAM E70/S70/V70/V71: Step 5

Step 5: Add application code to the project

The application is already developed and is available in the files main_e70.c, app_sensor.c, app_eeprom.c, and usart_common.c under
<your unzip folder>/getting_started_drv/dev_files/sam_e70_xult.
The application files app_sensor.c and app_eeprom.c contain the application logic. They also contain placeholders that you will populate with the necessary code in the next step.

  • Go to the getting_started_drv/dev_files/sam_e70_xult folder and copy the pre-developed files main_e70.c, app_sensor.c, app_eeprom.c, usart_common.c, app_sensor.h, app_eeprom.h, and usart_common.h file.
  • Paste and replace (over-write) the files of your project available at <Your project folder>/getting_started_drv/firmware/src with the copied files.
  • Add the application file usart_common.c to your project.
usart_common1.png
usart_common2.png
usart_common3.png

1

For an Harmony v3 application, MPLAB® Harmony Configurator (MHC) generates the application template files (app_sensor.c, app_sensor.h, app_eeprom.c, app_eeprom.h, and main_e70.c). The main_e70.c file calls the SYS_Tasks() routine which runs the sensor and the EEPROM application tasks (and driver/middleware tasks if added to the project).

main_task.png

2

The app_sensor.h and app_eeprom.h files define the states of the application.Try to relate the states with the state diagram shown at the beginning of this lab.

app_states.png

3

The app_sensor.h and app_eeprom.h files also define the application data structure APP_SENSOR_DATA and APP_EEPROM_DATA.

app_data_structures.png

4

The APP_SENSOR_Tasks() function in the app_sensor.c file and the APP_EEPROM_Tasks() in app_eeprom.c file implement the application state machine.

5

The sensor application task in app_sensor.c and the EEPROM application task in app_eeprom.c acts as the two clients to the I²C driver instance 0.

6

Open app_sensor.c and add application code by following the below steps.

a

Open the I²C driver instance 0 (which is associated with TWIHS0). The call to DRV_I2C_Open() Application Programming Interface (API) will associate the sensor client with the I²C driver instance 0. The returned handle will be used by the application in all the subsequent calls (related to the sensor client) to the driver.

app_sensorData.i2cHandle = DRV_I2C_Open( DRV_I2C_INDEX_0, DRV_IO_INTENT_READWRITE );
i2c_open_sensor.png

b

Set the transfer parameters for the sensor client after a valid handle to the driver is obtained. The transfer parameter sets the I²C clock speed to 100 kHz for this client.

DRV_I2C_TransferSetup(app_sensorData.i2cHandle, &app_sensorData.i2cSetup);
i2c_set_transfer_sensor.png

c

Register an event handler (callback) with the I²C driver for the sensor client. The event handler is called by the I²C driver when any request submitted by the sensor application client is completed.

DRV_I2C_TransferEventHandlerSet(app_sensorData.i2cHandle, 
               APP_SENSOR_I2CEventHandler, 0);
i2c_event_handler.png

d

Register a periodic callback with the Timer System Service for every 1000 milliseconds.

SYS_TIME_CallbackRegisterMS(APP_SENSOR_TimerEventHandler, 0, 
         (1000*APP_SENSOR_SAMPLING_RATE_IN_HZ), SYS_TIME_PERIODIC);
timer_ss_callback.png

e

Open the Universal Synchronous Asynchronous Receiver Transmitter (USART) driver instance 0 (which is associated with USART1). The call to DRV_USART_Open() API will return a handle to the USART driver instance 0. The returned handle will be used by the application (by sensor task and EEPROM task) in all the subsequent calls to the driver.

usartHandle = DRV_USART_Open(DRV_USART_INDEX_0, DRV_IO_INTENT_READWRITE);
usart_open_sensor.png

f

Register an event handler (callback) with the USART driver. The event handler is called by the USART driver when any request submitted by the sensor or EEPROM application tasks is completed.

DRV_USART_BufferEventHandlerSet(usartHandle, APP_USARTBufferEventHandler, 0);
usart_set_transfer_sensor.png

g

Set a flag in the periodic timer event handler. The sensor task will read the temperature when the flag is set, and also toggle an LED.

app_sensorData.isTimerExpired = true;

LED_Toggle();
timer_flag_sensor.png

h

When the periodic timer expires, submit an I²C transfer to read the temperature sensor value using the I²C driver write-then-read API. The I²C driver calls back the sensor event handler (registered in the step 6 C above) when the submitted request is complete.

DRV_I2C_WriteReadTransferAdd( app_sensorData.i2cHandle, 
         APP_SENSOR_I2C_SLAVE_ADDR, 
         (void*)app_sensorData.i2cTxBuffer, 1,  
         (void *) app_sensorData.i2cRxBuffer, 2, 
         &app_sensorData.transferHandle );
i2c_sensor_write_read.png

i

In the I²C event handler for sensor client, set a flag to indicate that the I²C read (temperature sensor value) is completed.

app_sensorData.isTemperatureReadComplete = true;
i2c_sensor_read_complete.png

j

Print the latest temperature value and notify the EEPROM application task to log the temperature value to EEPROM.

APP_SENSOR_PrintTemperature(app_sensorData.usartTxBuffer, 
                      (int8_t *)"Temperature = %d F\r\n", 
                      app_sensorData.temperature);   

APP_EEPROM_SetTempWriteRequest(app_sensorData.temperature);
snesor_print_notify.png

The implementation of APP_SENSOR_PrintTemperature makes a call to USART driver function DRV_USART_WriteBufferAdd.

app_sensor_printf.png
  • The DRV_USART_WriteBufferAdd function performs transfers for the formatted message with temperature value from data memory to the serial terminal using Direct Memory Access (DMA).
  • If the USART driver was not configured (in MHC) to use DMA for TX operation, the same function (DRV_USART_WriteBufferAdd) would be used to transfer the formatted message with temperature value from data memory to serial terminal.
  • The above points imply if a Harmony v3 driver is configured to use DMA or not for data transfer operation, the application code remains unchanged. The Harmony data transfer APIs seamlessly handles the data transfer operation through the same API.

7

Open app_eeprom.c and add application code by following the below steps.

a

Associate the second client (the EEPROM client), with the I²C driver instance 0. This is done by opening the I²C driver instance 0 again. The call to DRV_I2C_Open () API will now associate the EEPROM client with the I²C driver instance 0. The returned handle will be used by the application in all the subsequent calls (related to the EEPROM client) to the driver.

app_eepromData.i2cHandle = DRV_I2C_Open( DRV_I2C_INDEX_0, DRV_IO_INTENT_READWRITE );
i2c_open_eeprom.png

b

Like the sensor client, setup the transfer parameters for the EEPROM client after a valid handle to the driver is obtained. The transfer parameters sets the I²C clock speed to 400 kHz for this client.

DRV_I2C_TransferSetup(app_eepromData.i2cHandle, &app_eepromData.i2cSetup);
i2c_set_transfer_eeprom.png
  • The call to DRV_I2C_TransferSetup overrides the baud rate set in the I²C driver configuration using MHC.
  • I²C was configured to run at 400 kHz using MHC. While in the application, the sensor task has reconfigured it to run at 100 kHz and the EEPROM task configured it to run at 400 kHz. This illustrates how the Harmony I²C driver handles the peripheral module-specific configuration depending on the client accessing the peripheral.

c

Like the sensor client, register an event handler (callback) with the I²C driver for the EEPROM client. The event handler would be called by the I²C driver when any request submitted by the EEPROM application client is completed.

DRV_I2C_TransferEventHandlerSet(app_eepromData.i2cHandle, APP_EEPROM_I2CEventHandler, 0);
i2c_eeprom_transfer_set.png

d

Submit a USART read request to receive a character on the serial terminal. When the user enters a character, a USART interrupt occurs. In the USART event handler the application sets the usartReadRequest flag to true.

DRV_USART_ReadBufferAdd(usartHandle, (void*)app_eepromData.usartRxBuffer, 1, &usartReadBufferHandle);
usart_read_buffer_add.png

The DRV_USART_ReadBufferAdd API submits a read request to read a character from the serial terminal. The USART driver responds to a character read by interrupting the CPU and calling back the registered event handler (APP_USARTBufferEventHandler).

e

When the user enters a character on the serial terminal, submit an I²C transfer to read back the written temperature sensor values from the EEPROM, using the write-then-read API. The I²C driver calls back the EEPROM event handler (APP_EEPROM_I2CEventHandler) when the submitted request is complete.

DRV_I2C_WriteReadTransferAdd(app_eepromData.i2cHandle, 
              APP_EEPROM_I2C_SLAVE_ADDR, app_eepromData.i2cTxBuffer, 
              1, app_eepromData.i2cRxBuffer, 5, &app_eepromData.transferHandle);
i2c_eeprom_read.png

f

In the I²C event handler of the EEPROM client, update the status to indicate that the I²C read/write (corresponding to EEPROM read/write) is completed.

app_eepromData.reqStatus = APP_EEPROM_REQ_STATUS_DONE;
eeprom_read_complete.png

g

Print the temperature values read from the EEPROM and submit a USART read request to receive subsequent character on the serial terminal.

APP_EEPROM_PrintTemperature(app_eepromData.i2cRxBuffer, app_eepromData.wrIndex);  

DRV_USART_ReadBufferAdd(usartHandle, (void*)app_eepromData.usartRxBuffer, 1, &usartReadBufferHandle);
print_eeprom_values.png

Similar to the implementation APP_SENSOR_PrintTemperature, the implementation of APP_EEPROM_PrintTemperature makes a call to USART driver function DRV_USART_WriteBufferAdd.

The DRV_USART_WriteBufferAdd function performs transfer for the formatted message with the last five temperature values from data memory (read from EEPROM) to the serial terminal using DMA.

You are now ready to build the code!


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.