cancel
Showing results for 
Search instead for 
Did you mean: 

How to do an OTA update with STM32U5 and AWS ?

This article demonstrates how to integrate modular AWS FreeRTOS™ software with hardware enforced security to help secure updatable cloud connected applications. The project is preconfigured to run on the STM32U585 IoT discovery kit and connect to AWS. This article focuses on the steps to run the OTA update on the non-trust zone version of the project.

The STM32U5 IoT discovery kit is equipped with a Wi-Fi and Bluetooth module, microphones, a temperature and humidity sensor, a magnetometer, an accelerometer, and gyroscope, a pressure sensor, as well as Time-of-Flight (ToF) and gesture-detection sensors.
 

The board also comes with 512-Mbit octal-SPI Flash memory, 64-Mbit octal-SPI PSRAM, 256-Kbit I²C EEPROM, as well as ARDUINO Uno V3, STMOD+, and Pmod expansion connectors, plus an expansion connector for a camera module, and STLink-V3E embedded debugger.
 

The following project folder consists of a Non-TrustZone version(b_u585i_iot02a_ntz) of the project and TF-M enabled version(b_u585i_iot02a_tfm) of the project. The following article contains instructions on getting the non-secure(b_u585i_iot02a_ntz) version of the project up and doing an OTA in AWS. For getting it running in Mac/Linux, refer to the following- https://github.com/FreeRTOS/iot-reference-stm32u5/blob/main/Getting_Started_Guide.md.
It connects to AWS Core and publishes data. It contains instructions on how to perform an OTA update. It shows the steps to connect the STM32U585 IoT discovery kit to AWS IoT core and use the FreeRTOS™ OTA update service. The demo connects to AWS IoT using the WiFi module. It then uses the coreMQTT-Agent library to enable multiple concurrent tasks to share a single MQTT connection. These tasks publish sensor data, and demonstrate use of the Device Shadow and Device Defender AWS IoT services.
This article assumes that you have followed through the article that takes you through the setup to get the demo(https://github.com/FreeRTOS/iot-reference-stm32u5) up and running. 
Article part 1: Getting started with STM32U5 IoT discovery kit and AWS

Performing Over-the-air (OTA) Firmware update

The project shows an IoT reference implementation of how to integrate FreeRTOS™ libraries on STM32U5 platform to perform OTA update with AWS IoT using the non TrustZone® hardware capabilities. The demo runs FreeRTOS™ OTA agent as one of the RTOS tasks in background, which waits for OTA updates from cloud. The non-trustzone version of the demo leverages internal flash memory's dual bank. The total 2MB internal flash is split into two banks of 1MB each. The main firmware is running on one bank, while downloading new firmware image into another bank. Thus, the total firmware image size should not exceed 1MB.

Provision code signing credentials

Devices use digital signatures to verify the authenticity of the firmware updates sent over the air. Images are signed by an authorized source who creates the image, and the device can verify the signature of the image, using the corresponding public key of the source. Steps below show how to setup and provision the code signing credentials so as to enable cloud to digitally sign the image and the device to verify the image signature before boot.

  1. In your working directory, use the following text to create a file named cert_config.txt. Replace test_signer@amazon.com with your email address:
[ req ]
prompt             = no
distinguished_name = my_dn

[ my_dn ]
commonName = test_signer@amazon.com

[ my_exts ]
keyUsage         = digitalSignature
extendedKeyUsage = codeSigning
  1. Create an ECDSA code-signing private key:
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -pkeyopt ec_param_enc:named_curve -outform PEM -out ecdsasigner-priv-key.pem

3.Create an ECDSA code-signing certificate to be uploaded to the AWS ACM service:

openssl req -new -x509 -config cert_config.txt -extensions my_exts -nodes -days 365 -key ecdsasigner-priv-key.pem -out ecdsasigner.crt

  1. Import the code-signing certificate and private key into AWS Certificate Manager:

NOTE: This command displays an ARN for your certificate. You need this ARN when you create an OTA update job later.

aws acm import-certificate --certificate fileb://ecdsasigner.crt --private-key fileb://ecdsasigner-priv-key.pem
  1. Connect the device to a terminal over serial port. On the command line prompt type following command to provision public key to device:

> pki import key ota_signer_pub

Press 

Enter
 then paste the contents of the PEM public key file 
ecdsasigner-pub-key.pem
 into the terminal. Press 
Enter
 again. Device should successfully provision the public key used to verify the digital signature.

ota_signer_pub
 is the label used to refer to the code signing key during verification of the firmware update.

  1. Create a signing profile in AWS to sign the firmware image.
aws signer put-signing-profile --profile-name <your profile name> --signing-material certificateArn=<certificate arn created in step 4> --platform AmazonFreeRTOS-Default --signing-parameters certname=ota_signer_pub

Setup OTA S3 bucket, Service role and policies in AWS

  1. S3 bucket is used to store the new firmware image to be updated. To create a new S3 bucket, follow these steps here: https://docs.aws.amazon.com/freertos/latest/userguide/dg-ota-bucket.html

  2. Create a service role that grants permission for OTA service to access the firmware image: https://docs.aws.amazon.com/freertos/latest/userguide/create-service-role.html

  3. Create an OTA update policy using the documentation here: https://docs.aws.amazon.com/freertos/latest/userguide/create-ota-user-policy.html

  4. Add a policy for AWS IoT to access the code signing profile: https://docs.aws.amazon.com/freertos/latest/userguide/code-sign-policy.html

Create a code signed firmware update job

  1. Bump up the version of the new firmware image to be updated. From the demo project, open File Common/config/ota_config.h and set APP_VERSION_MAJOR to 1 higher than the current version. Build the firmware image using STM32CubeIDE.

  2. Upload the new image to the s3 bucket created in the previous section.

aws s3 cp <image binary path> s3://<s3 bucket for image>/

Get the latest s3 file version of the binary image by executing the command below. The command returns an array of json structs containing details of all version. To get the latest version ID, look for VersionId field in the json struct where isLatest field is true.

aws s3api  list-object-versions --bucket <s3 bucket for image> --prefix <image binary name>
  1. Create a new OTA update job configuration json file (example: ota-update-job-config.json) in your filesystem as below. Substitute the parameters with the output obtained from steps above.
{
     "otaUpdateId": "<A unique job ID for the OTA job>",
     "targets": [
         "arn:aws:iot:<region>:<account id>:thing/<thing name>"
     ],
     "targetSelection": "SNAPSHOT",
     "files": [{
         "fileName": "<image binary name>",
         "fileType": 0,
         "fileVersion": "1",
         "fileLocation": {
             "s3Location": {
                 "bucket": "<s3 image bucket created above>",
                 "key": "<image binary name>",
                 "version": "<latest s3 file version of binary image>"
             }
         },
         "codeSigning": {
             "startSigningJobParameter": {
                 "signingProfileName": "<signing profile name>",
                 "destination": {
                     "s3Destination": {
                         "bucket": "<s3 image bucket created above>"
                     }
                 }
             }
         }
     }],
     "roleArn": "<ARN of the OTA service role created above>"
 }

Create a new OTA update job from the configuration file:

aws iot create-ota-update --cli-input-json file://<ota job configuration file path in your filesystem>

The command on success returns the OTA update identifier and status of the job as 

CREATE_PENDING
. To get the corresponding job ID of the OTA job, execute the following command and look for 
awsIotJobId
 field in json document returned.

aws iot get-ota-update --ota-update-id=<ota update id created above>

Note down the job ID to check the status of the job later.

Monitoring and verification of firmware update

Once the job is created on the terminal logs, you see that OTA job is accepted and device starts downloading image.

Create a new OTA update job from the configuration file:

aws iot create-ota-update --cli-input-json file://<ota job configuration file path in your filesystem>

The command on success returns the OTA update identifier and status of the job as CREATE_PENDING. To get the corresponding job ID of the OTA job, execute the following command and look for awsIotJobId field in json document returned.

aws iot get-ota-update --ota-update-id=<ota update id created above>

Note down the job ID to check the status of the job later.

Monitoring and verification of firmware update

  1. Once the job is created on the terminal logs, you will see that OTA job is accepted and device starts downloading the image.
<INF>    16351 [OTAAgent] Current State=[WaitingForFileBlock], Event=[RequestFileBlock], New state=[WaitingForFileBlock] (ota.c:2834)
<INF>    15293 [OTAAgent] Extracted parameter: [key: value]=[execution.jobDocument.afr_ota.streamname: AFR_OTA-eb53bc47-6918-4b2c-9c85-a4c74c44a04c] (ota.c:1642)
<INF>    15294 [OTAAgent] Extracted parameter: [key: value]=[execution.jobDocument.afr_ota.protocols: ["MQTT"]] (ota.c:1642)
<INF>    15296 [OTAAgent] Extracted parameter: [key: value]=[filepath: b_u585i_iot02a_ntz.bin] (ota.c:1642)
<INF>    17784 [OTAAgent] Current State=[WaitingForFileBlock], Event=[RequestFileBlock], New state=[WaitingForFileBlock] (ota.c:2834)
<INF>    15297 [OTAAgent] Extracted parameter: [key: value]=[fileid: 0] (ota.c:1683)
<INF>    15298 [OTAAgent] Extracted parameter: [key: value]=[certfile: ota_signer_pub] (ota.c:1642)
<INF>    15300 [OTAAgent] Extracted parameter [ sig-sha256-ecdsa: MEUCIGWRkFqcumdPZhoZ93ov5Npvsjj7... ] (ota.c:1573)
<INF>    15301 [OTAAgent] Extracted parameter: [key: value]=[fileType: 0] (ota.c:1683)
<INF>    15301 [OTAAgent] job document was accepted. Attempting to begin the update. (ota.c:2199)
<INF>    16533 [OTAAgent] Number of blocks remaining: 306 (ota.c:2683)
<INF>    15450 [OTAAgent] Setting OTA data interface. (ota.c:938)
<INF>    15450 [OTAAgent] Current State=[Creating

  1. Once the full image has been downloaded, the OTA library verifies the image signature and activates the new image in the unused flash bank.
<INF>    67405 [OTAAgent] Received final block of the update. (ota.c:2633)
<INF>    67405 [OTAAgent] Validating the integrity of OTA image using digital signature. (ota_pal.c:681)
<INF>    69643 [OTAAgent] Received entire update and validated the signature. (ota.c:2654)
  1. New image boots up and performs a self test, here it checks that the version is higher than the previous. If so it sets the new image as valid.
<INF>    15487 [OTAAgent] In self test mode. (ota.c:2102)
<INF>    15487 [OTAAgent] New image has a higher version number than the current image: New image version=1.9.0, Previous image version=0.9.0 (ota.c:1932)
  1. Checking the job status, should show the job as succeeded:
aws iot describe-job-execution --job-id=<Job ID created above> --thing-name=<thing name>

Troubleshooting

​​​​​​1
. For further information on how to run it in Mac/Linux, refer to https://github.com/FreeRTOS/iot-reference-stm32u5/blob/main/README.md
Version history
Last update:
‎2022-06-02 02:52 AM