1. Introduction
Firmware over-the-air update is a feature that allows updating the firmware image wirelessly. This feature ensures that devices can be maintained and improved without physical access. It is particularly important in Internet of Things (IoT) deployments, where devices may be distributed across wide areas.
Thread is a networking protocol managed by OpenThread (see the Introduction to Thread wiki page). Firmware over-the-air (FUOTA) updates are application-level features and are not defined within OpenThread.
This wiki describes an example of a FUOTA application that uses the Thread protocol on STM32WBA boards.
2. STM32WBA Thread FUOTA Use Case
The Thread OTA application is available in the STM32CubeWBA release.
To run the Thread OTA use case, at least two STM32WBAxx boards are required:
- Thread OTA server board: This board runs the Thread OTA server application, a Thread CoAP application that manages and distributes firmware updates to other nodes in the network.
- Thread OTA client board(s): One or more boards run the Thread OTA client application, a Thread CoAP application that receives, validates, and executes firmware updates.
To begin, flash the binary file to be downloaded onto the free memory region of the server. Use tools such as STM32CubeProgrammer to flash the binary at address 0x08080000.
The server initiates an over-the-air provisioning process and proposes the update to the clients. The clients can accept and proceed with the upgrade.
Flash the binary onto the free memory region of the client devices. In this scenario, flash the binary at address0x08080000.
3. CoAP Protocol
The Constrained Application Protocol (CoAP) is an application layer protocol designed for use in resource-constrained Internet of Things (IoT) devices.
3.1. CoAP in the Context of Thread
Thread is a network layer protocol designed for low-power Internet of Things (IoT) devices. The Constrained Application Protocol (CoAP) is often used in Thread networks because of its efficiency in constrained environments.
3.2. Why Use CoAP for OTA Upgrades?
The Thread over-the-air (OTA) procedure is defined at the application layer and requires a message passing protocol between devices. The Constrained Application Protocol (CoAP) is suitable for OTA upgrades for the following reasons:
- Efficiency: CoAP is lightweight and has low overhead. It is suitable for constrained environments where devices have limited resources.
- Reliability: CoAP supports confirmable messages. This feature ensures that the data is received correctly, which is essential for OTA updates.
- Interoperability: CoAP is designed to work with other web protocols. This design makes integration with existing systems easier.
- Multicast support: CoAP can use multicast to send messages to multiple devices at the same time. This capability is useful for broadcasting firmware updates.
4. Thread FUOTA Process
These are the steps for the OTA server and client to perform firmware update over the air.
4.1. FUOTA Provisioning Request
OTA provisioning refers specifically to the process of updating or modifying firmware wirelessly.
4.1. Server sends provisioning request and FUOTA parameters
The server validates the image by checking the attached magic keyword at the end. The server then calculates the CRC for the image and attaches it in the first word of the next 16-byte block.The server initiates the FUOTA process by sending a provisioning request to the OTA client over CoAP.After the OTA server receives the acknowledgment from the OTA client, it sends another CoAP message containing the FUOTA parameters, including the following:
- Binary size in bytes
- Magic keyword: a predefined word known to both the client and the server. It is used to verify the validity of the image and ensure it was sent by the server. The address of this keyword is placed at a specific location, which in this case is the base address of the binary plus
0x160. - Binary CRC address: a 4-byte value that indicates the location of the binary CRC, as it may not be directly after the magic keyword.
- The client and the server must know the base address for the sent binary to determine the address of the magic keyword.
Client Receives and Confirms Provisioning Request:
- The OTA client receives the provisioning request.
- The client sends a confirmation response back to the server, indicating that it is ready to receive the firmware update.
- Then the client receives the FUOTA parameters message.
4.1.1. Firmware Download
Server sends firmware over CoAP:
After receiving confirmation, the server sends the firmware image to the OTA client over CoAP. The server transmits the firmware in 400-byte chunks
Client receives firmware:
The OTA client receives each firmware chunk and writes it to flash memory, starting from the base address of the binary. The client then sends an acknowledgment for each chunk. The client tracks the received chunks to ensure the complete firmware image is downloaded correctly.
4.1.2. Firmware Validation
Magic word validation:
- After receiving the complete firmware image, the client performs magic word validation.
CRC validation:
The client computes the cyclic redundancy check (CRC) of the received firmware image. For more information, see CRC Validation.
The client compares the computed CRC with the CRC value attached to the firmware image.
Update marker:
- Upon successful validation, the client updates a specific location in RAM to indicate that a new valid application is available. This update is valid only across a software reset.
4.1.3. Reset OTA client
Restart OTA client:
The OTA client initiates a system restart to apply new firmware. During the restart process, the client checks a specific memory location to determine whether a valid image is available.
Run new application:
If a valid image is found, the client loads and runs the new application. The client continues normal operation with updated firmware.
4.1.4. Run the Downloaded binary
Capabilities of the new application:
The new application can be any Thread application. However, it must support rebooting to the OTA client. In this example, the new application supports receiving a specific message, "FUOTA_REBOOT," from the OTA server. When the "FUOTA_REBOOT" message is received, the application updates the image marker in RAM and performs a software reset to run the Thread OTA client again.
4.1.5. More Information about the Process
The firmware image size for the Thread_Coap_Generic_OTA application is 346 KB.
The time required for the firmware update over-the-air (FUOTA) is approximately 45 seconds.
5. Thread FUOTA Sequence Diagram
The sequence diagram shows the interactions between the server and the client during the Thread over-the-air (OTA) process.
6. OTA Client States
This flowchart describes the states of a device that includes the Thread over-the-air (OTA) client application.
7. CRC Validation
The CRC checksum validation is used to ensure that the image is complete and unchanged in its content, with no data lost.
The OTA server:
- Calculates the image CRC when it sends the firmware image for the first time.
- Attaches the CRC to the flash memory in the first available 16-byte block after the firmware image.
- Updates the binary CRC address field in FUOTA parameters to be sent to the OTA client.
The OTA client:
- Calculates the image CRC over the full received image.
- Reads the attached CRC with the image using the binary CRC address in the received FUOTA parameters.
- Compares the two CRCs to validate the received image and resets to the new image if it is valid.
Both the OTA client and server calculate the CRC using this function.
/**
* @brief OTA compute CRC in hardware
* @param pstCrcHandle: CRC handle
* @param plBuffer: Buffer to compute CRC over
* @param lBufferSize: Buffer size in bytes
* @param plCrc: Computed CRC
* @retval False if HAL_CRC_Init failed
*/
static bool APP_THREAD_OTA_HardwareCalculateCrc( CRC_HandleTypeDef * pstCrcHandle, uint32_t* plBuffer, uint32_t lBufferSize, uint32_t* plCrc )
{
HAL_StatusTypeDef eHalStatus;
if ( HAL_CRC_GetState( pstCrcHandle ) == HAL_CRC_STATE_RESET )
{
/* Initialize the CRC */
LOG_INFO_APP( "[OTA] Initializing the CRC module" );
pstCrcHandle->Instance = CRC;
pstCrcHandle->Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE;
pstCrcHandle->Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE;
pstCrcHandle->Init.CRCLength = CRC_POLYLENGTH_32B;
pstCrcHandle->Init.InitValue = 0xFFFFFFFF;
pstCrcHandle->Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_BYTE;
pstCrcHandle->Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE;
pstCrcHandle->InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
eHalStatus = HAL_CRC_Init( pstCrcHandle );
if ( eHalStatus != HAL_OK )
{
LOG_ERROR_APP( "[OTA] Error, HAL_CRC_Init failed (0x%08X)", eHalStatus );
return false;
}
}
/* Compute the CRC */
*plCrc = ~HAL_CRC_Calculate( pstCrcHandle, plBuffer, lBufferSize );
return true;
}
8. Used APIs
8.1. OTA Server APIs
| API | Description |
|---|---|
| APP_THREAD_CoapReqHandlerFuotaProvisioning | Send a CoAP request, The server uses it to send the Provisioning request, FUOTA Parameters, FUOTA Packets, FUOTA Reboot request. |
| APP_THREAD_ProvisioningRespHandler | Callback function for the response of the Provisioning request, if the server receives an ACK, it will send the Binary Information. |
| APP_THREAD_CoapRespHandlerFuotaSend | Callback function for the response of Sending FUOTA packet, if the server receives an ACK, it will send the next one. |
| APP_THREAD_CoapRespHandlerFuotaParameters | Callback function for the response of Sending the Binary Information, if the server receives an ACK, it will start the FUOTA process. |
| APP_THREAD_CoapRespHandlerFuotaReboot | Callback function for the response of Sending FUOTA Reboot Request, if the server receives an ACK, it will know that the OTA client will be ready soon. |
8.2. OTA client APIs
| API | Description |
|---|---|
| APP_THREAD_CoapReqHandlerFuotaProvisioning | Callback function for the FUOTA Provisioning request, used to let it know the client is ready by responding with an ACK. |
| APP_THREAD_CoapReqHandlerFuotaParameters | Callback function for FUOTA Binary Information request, used to validate if there is enough space in the client flash to download this binary. |
| APP_THREAD_CoapReqHandlerFuota | Callback function for the FUOTA packets request, used to receive the firmware chunks and writes them into the flash. |
8.3. Downloaded Binary OTA APIs
| API | Description |
|---|---|
| APP_THREAD_CoapRequestHandlerFuotaReboot | Callback function for the FUOTA Reboot request, used to update the Binary Marker and make reset to run the OTA client. |