

# OTA tutorial


This section contains a tutorial for updating firmware on devices running FreeRTOS using OTA updates. In addition to firmware images, you can use an OTA update to send any type of file to a device connected to AWS IoT.

You can use the AWS IoT console or the AWS CLI to create an OTA update. The console is the easiest way to get started with OTA because it does a lot of the work for you. The AWS CLI is useful when you are automating OTA update jobs, working with a large number of devices, or are using devices that have not been qualified for FreeRTOS. For more information about qualifying devices for FreeRTOS, see the [FreeRTOS Partners](https://aws.amazon.com/partners/dqp/) website.<a name="create-update"></a>

**To create an OTA update**

1. Deploy an initial version of your firmware to one or more devices.

1. Verify that the firmware is running correctly.

1. When a firmware update is required, make the code changes and build the new image.

1. If you are manually signing your firmware, sign and then upload the signed firmware image to your Amazon S3 bucket. If you are using Code Signing for AWS IoT, upload your unsigned firmware image to an Amazon S3 bucket.

1. Create an OTA update.

When you create an OTA update, you specify the image delivery protocol (MQTT or HTTP) or specify both to allow the device to choose. The FreeRTOS OTA agent on the device receives the updated firmware image and verifies the digital signature, checksum, and version number of the new image. If the firmware update is verified, the device is reset and, based on application-defined logic, commits the update. If your devices are not running FreeRTOS, you must implement an OTA agent that runs on your devices. 

# Installing the initial firmware


To update firmware, you must install an initial version of the firmware that uses the OTA Agent library to listen for OTA update jobs. If you are not running FreeRTOS, skip this step. You must copy your OTA Agent implementation onto your devices instead.

**Topics**
+ [

# Install the initial version of firmware on the Texas Instruments CC3220SF-LAUNCHXL
](burn-initial-firmware-ti.md)
+ [

# Install the initial version of firmware on the Espressif ESP32
](burn-initial-firmware-esp.md)
+ [

# Install the initial version of firmware on the Nordic nRF52840 DK
](burn-initial-firmware-nordic.md)
+ [

# Initial firmware on the Windows simulator
](burn-initial-firmware-windows.md)
+ [

# Install the initial version of firmware on a custom board
](burn-initial-firmware-other.md)

# Install the initial version of firmware on the Texas Instruments CC3220SF-LAUNCHXL


**Important**  <a name="deprecation-message"></a>
This reference integration is hosted on the Amazon-FreeRTOS repository which is deprecated. We recommend that you [start here](freertos-getting-started-modular.md) when you create a new project. If you already have an existing FreeRTOS project based on the now deprecated Amazon-FreeRTOS repository, see the [Amazon-FreeRTOS Github Repository Migration Guide](github-repo-migration.md).

These steps are written with the assumption that you have already built the `aws_demos` project, as described in [Download, build, flash, and run the FreeRTOS OTA demo on the Texas Instruments CC3220SF-LAUNCHXL](download-ota-ti.md).<a name="burn-demo-ti"></a>

1. On your Texas Instruments CC3220SF-LAUNCHXL, place the SOP jumper on the middle set of pins (position = 1) and reset the board.

1. Download and install the [TI Uniflash tool](http://www.ti.com/tool/UNIFLASH).

1. Start Uniflash. From the list of configurations, choose **CC3220SF-LAUNCHXL**, and then choose **Start Image Creator**.

1. Choose **New Project**.

1. On the **Start new project** page, enter a name for your project. For **Device Type**, choose **CC3220SF**. For **Device Mode**, choose **Develop**. Choose **Create Project**.

1. Disconnect your terminal emulator.

1. On the right side of the Uniflash application window, choose **Connect**.

1. Under **Advanced**, **Files**, choose **User Files**.

1. In the **File** selector pane, choose the **Add File** icon ![\[Document icon representing a file or page.\]](http://docs.aws.amazon.com/freertos/latest/userguide/images/add-file.png).

1. Browse to the `/Applications/Ti/simplelink_cc32xx_sdk_version/tools/cc32xx_tools/certificate-playground` directory, select `dummy-root-ca-cert`, choose **Open**, and then choose **Write**.

1. In the **File** selector pane, choose the **Add File** icon ![\[Document icon representing a file or page.\]](http://docs.aws.amazon.com/freertos/latest/userguide/images/add-file.png).

1. Browse to the working directory where you created the code-signing certificate and private key, choose `tisigner.crt.der`, choose **Open**, and then choose **Write**.

1. From the **Action** drop-down list, choose **Select MCU Image**, and then choose **Browse** to choose the firmware image to use write to your device (**aws\$1demos.bin**). This file is located in the `freertos/vendors/ti/boards/cc3220_launchpad/aws_demos/ccs/Debug` directory. Choose **Open**.

   1. In the file dialog box, confirm the file name is set to `mcuflashimg.bin`.

   1. Select the **Vendor** check box.

   1. Under **File Token**, type **1952007250**.

   1. Under **Private Key File Name**, choose **Browse**, and then choose `tisigner.key` from the working directory where you created the code-signing certificate and private key.

   1. Under **Certification File Name**, choose `tisigner.crt.der`.

   1. Choose **Write**.

1. In the left pane, under **Files**, choose **Service Pack**.

1. Under **Service Pack File Name**, choose **Browse**, browse to `simplelink_cc32x_sdk_version/tools/cc32xx_tools/servicepack-cc3x20`, choose `sp_3.7.0.1_2.0.0.0_2.2.0.6.bin`, and then choose **Open**.

1. In the left pane, under **Files**, choose **Trusted Root-Certificate Catalog**.

1. Clear the **Use default Trusted Root-Certificate Catalog** check box.

1. Under **Source File**, choose **Browse**, choose **simplelink\$1cc32xx\$1sdk\$1*version*/tools/cc32xx\$1tools/certificate-playground/certcatalogPlayGround20160911.lst**, and then choose **Open**.

1. Under **Signature Source File**, choose **Browse**, choose **simplelink\$1cc32xx\$1sdk\$1*version*/tools/cc32xx\$1tools/certificate-playground/certcatalogPlayGround20160911.lst.signed\$13220.bin**, and then choose **Open**.

1. Choose the ![\[Floppy disk icon representing a save or storage function.\]](http://docs.aws.amazon.com/freertos/latest/userguide/images/save.png) button to save your project.

1. Choose the ![\[Feather icon representing a lightweight or simplified feature or concept.\]](http://docs.aws.amazon.com/freertos/latest/userguide/images/flame.png) button.

1. Choose **Program Image (Create and Program)**.

1. After the programming process is complete, place the SOP jumper onto the first set of pins (position = 0), reset the board, and reconnect your terminal emulator to make sure the output is the same as when you debugged the demo with Code Composer Studio. Make a note of the application version number in the terminal output. You use this version number later to verify that your firmware has been updated by an OTA update.

   The terminal should display output like the following.

   ```
   0 0 [Tmr Svc] Simple Link task created
   
   Device came up in Station mode
   
   1 369 [Tmr Svc] Starting key provisioning...
   2 369 [Tmr Svc] Write root certificate...
   3 467 [Tmr Svc] Write device private key...
   4 568 [Tmr Svc] Write device certificate...
   SL Disconnect...
   
   5 664 [Tmr Svc] Key provisioning done...
   Device came up in Station mode
   
   Device disconnected from the AP on an ERROR..!! 
   
   [WLAN EVENT] STA Connected to the AP: Guest , BSSID: 11:22:a1:b2:c3:d4
   
   [NETAPP EVENT] IP acquired by the device
   
   
   Device has connected to Guest
   
   Device IP Address is 111.222.3.44 
   
   
   6 1716 [OTA] OTA demo version 0.9.0
   7 1717 [OTA] Creating MQTT Client...
   8 1717 [OTA] Connecting to broker...
   9 1717 [OTA] Sending command to MQTT task.
   10 1717 [MQTT] Received message 10000 from queue.
   11 2193 [MQTT] MQTT Connect was accepted. Connection established.
   12 2193 [MQTT] Notifying task.
   13 2194 [OTA] Command sent to MQTT task passed.
   14 2194 [OTA] Connected to broker.
   15 2196 [OTA Task] Sending command to MQTT task.
   16 2196 [MQTT] Received message 20000 from queue.
   17 2697 [MQTT] MQTT Subscribe was accepted. Subscribed.
   18 2697 [MQTT] Notifying task.
   19 2698 [OTA Task] Command sent to MQTT task passed.
   20 2698 [OTA Task] [OTA] Subscribed to topic: $aws/things/TI-LaunchPad/jobs/$next/get/accepted
   
   21 2699 [OTA Task] Sending command to MQTT task.
   22 2699 [MQTT] Received message 30000 from queue.
   23 2800 [MQTT] MQTT Subscribe was accepted. Subscribed.
   24 2800 [MQTT] Notifying task.
   25 2801 [OTA Task] Command sent to MQTT task passed.
   26 2801 [OTA Task] [OTA] Subscribed to topic: $aws/things/TI-LaunchPad/jobs/notify-next
   
   27 2814 [OTA Task] [OTA] Check For Update #0
   28 2814 [OTA Task] Sending command to MQTT task.
   29 2814 [MQTT] Received message 40000 from queue.
   30 2916 [MQTT] MQTT Publish was successful.
   31 2916 [MQTT] Notifying task.
   32 2917 [OTA Task] Command sent to MQTT task passed.
   33 2917 [OTA Task] [OTA] Set job doc parameter [ clientToken: 0:TI-LaunchPad ]
   34 2917 [OTA Task] [OTA] Missing job parameter: execution
   35 2917 [OTA Task] [OTA] Missing job parameter: jobId
   36 2918 [OTA Task] [OTA] Missing job parameter: jobDocument
   37 2918 [OTA Task] [OTA] Missing job parameter: ts_ota
   38 2918 [OTA Task] [OTA] Missing job parameter: files
   39 2918 [OTA Task] [OTA] Missing job parameter: streamname
   40 2918 [OTA Task] [OTA] Missing job parameter: certfile
   41 2918 [OTA Task] [OTA] Missing job parameter: filepath
   42 2918 [OTA Task] [OTA] Missing job parameter: filesize
   43 2919 [OTA Task] [OTA] Missing job parameter: sig-sha1-rsa
   44 2919 [OTA Task] [OTA] Missing job parameter: fileid
   45 2919 [OTA Task] [OTA] Missing job parameter: attr
   47 3919 [OTA] [OTA] Queued: 1   Processed: 1   Dropped: 0
   48 4919 [OTA] [OTA] Queued: 1   Processed: 1   Dropped: 0
   49 5919 [OTA] [OTA] Queued: 1   Processed: 1   Dropped: 0
   ```

# Install the initial version of firmware on the Espressif ESP32


**Important**  <a name="deprecation-message"></a>
This reference integration is hosted on the Amazon-FreeRTOS repository which is deprecated. We recommend that you [start here](freertos-getting-started-modular.md) when you create a new project. If you already have an existing FreeRTOS project based on the now deprecated Amazon-FreeRTOS repository, see the [Amazon-FreeRTOS Github Repository Migration Guide](github-repo-migration.md).

This guide is written with the assumption that you have already performed the steps in [Getting Started with the Espressif ESP32-DevKitC and the ESP-WROVER-KIT](https://docs.aws.amazon.com/freertos/latest/userguide/getting_started_espressif.html) and [Over-the-Air Update Prerequisites](https://docs.aws.amazon.com/freertos/latest/userguide/ota-prereqs.html). Before you attempt an OTA update, you might want to run the MQTT demo project described in [Getting Started with FreeRTOS](https://docs.aws.amazon.com/freertos/latest/userguide/freertos-getting-started.html) to ensure that your board and tool chain are set up correctly.

**To flash an initial factory image to the board**

1. Open `freertos/vendors/vendor/boards/board/aws_demos/config_files/aws_demo_config.h`, comment out `#define CONFIG_CORE_MQTT_MUTUAL_AUTH_DEMO_ENABLED`, and define `CONFIG_OTA_MQTT_UPDATE_DEMO_ENABLED` or `CONFIG_OTA_HTTP_UPDATE_DEMO_ENABLED`.

1. Copy your SHA-256/ECDSA PEM-formatted code-signing certificate that you generated in the [OTA update prerequisites](ota-prereqs.md) to `vendors/vendor/boards/board/aws_demos/config_files/ota_demo_config.h`. It should be formatted in following way.

   ```
   #define otapalconfigCODE_SIGNING_CERTIFICATE  \
   "-----BEGIN CERTIFICATE-----\n" \
   "...base64 data...\n" \
   "-----END CERTIFICATE-----\n";
   ```

1. With the OTA Update demo selected, follow the same steps outlined in [Getting Started with ESP32](https://docs.aws.amazon.com/freertos/latest/userguide/getting_started_espressif.html) to build and flash the image. If you have previously built and flashed the project, you might need to run `make clean` first. After you run `make flash monitor`, you should see something like the following. The ordering of some messages might vary, because the demo application runs multiple tasks at once.

   ```
   I (28) boot: ESP-IDF v3.1-dev-322-gf307f41-dirty 2nd stage bootloader
   I (28) boot: compile time 16:32:33
   I (29) boot: Enabling RNG early entropy source...
   I (34) boot: SPI Speed : 40MHz
   I (38) boot: SPI Mode : DIO
   I (42) boot: SPI Flash Size : 4MB
   I (46) boot: Partition Table:
   I (50) boot: ## Label Usage Type ST Offset Length
   I (57) boot: 0 nvs WiFi data 01 02 00010000 00006000
   I (64) boot: 1 otadata OTA data 01 00 00016000 00002000
   I (72) boot: 2 phy_init RF data 01 01 00018000 00001000
   I (79) boot: 3 ota_0 OTA app 00 10 00020000 00100000
   I (87) boot: 4 ota_1 OTA app 00 11 00120000 00100000
   I (94) boot: 5 storage Unknown data 01 82 00220000 00010000
   I (102) boot: End of partition table
   I (106) esp_image: segment 0: paddr=0x00020020 vaddr=0x3f400020 size=0x14784 ( 83844) map
   I (144) esp_image: segment 1: paddr=0x000347ac vaddr=0x3ffb0000 size=0x023ec ( 9196) load
   I (148) esp_image: segment 2: paddr=0x00036ba0 vaddr=0x40080000 size=0x00400 ( 1024) load
   I (151) esp_image: segment 3: paddr=0x00036fa8 vaddr=0x40080400 size=0x09068 ( 36968) load
   I (175) esp_image: segment 4: paddr=0x00040018 vaddr=0x400d0018 size=0x719b8 (465336) map
   I (337) esp_image: segment 5: paddr=0x000b19d8 vaddr=0x40089468 size=0x04934 ( 18740) load
   I (345) esp_image: segment 6: paddr=0x000b6314 vaddr=0x400c0000 size=0x00000 ( 0) load
   I (353) boot: Loaded app from partition at offset 0x20000
   I (353) boot: ota rollback check done
   I (354) boot: Disabling RNG early entropy source...
   I (360) cpu_start: Pro cpu up.
   I (363) cpu_start: Single core mode
   I (368) heap_init: Initializing. RAM available for dynamic allocation:
   I (375) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
   I (381) heap_init: At 3FFC0748 len 0001F8B8 (126 KiB): DRAM
   I (387) heap_init: At 3FFE0440 len 00003BC0 (14 KiB): D/IRAM
   I (393) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
   I (400) heap_init: At 4008DD9C len 00012264 (72 KiB): IRAM
   I (406) cpu_start: Pro cpu start user code
   I (88) cpu_start: Starting scheduler on PRO CPU.
   I (113) wifi: wifi firmware version: f79168c
   I (113) wifi: config NVS flash: enabled
   I (113) wifi: config nano formating: disabled
   I (113) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
   I (123) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
   I (133) wifi: Init dynamic tx buffer num: 32
   I (143) wifi: Init data frame dynamic rx buffer num: 32
   I (143) wifi: Init management frame dynamic rx buffer num: 32
   I (143) wifi: wifi driver task: 3ffc73ec, prio:23, stack:4096
   I (153) wifi: Init static rx buffer num: 10
   I (153) wifi: Init dynamic rx buffer num: 32
   I (163) wifi: wifi power manager task: 0x3ffcc028 prio: 21 stack: 2560
   0 6 [main] WiFi module initialized. Connecting to AP <Your_WiFi_SSID>...
   I (233) phy: phy_version: 383.0, 79a622c, Jan 30 2018, 15:38:06, 0, 0
   I (233) wifi: mode : sta (30:ae:a4:80:0a:04)
   I (233) WIFI: SYSTEM_EVENT_STA_START
   I (363) wifi: n:1 0, o:1 0, ap:255 255, sta:1 0, prof:1
   I (1343) wifi: state: init -> auth (b0)
   I (1343) wifi: state: auth -> assoc (0)
   I (1353) wifi: state: assoc -> run (10)
   I (1373) wifi: connected with <Your_WiFi_SSID>, channel 1
   I (1373) WIFI: SYSTEM_EVENT_STA_CONNECTED
   1 302 [IP-task] vDHCPProcess: offer c0a86c13ip
   I (3123) event: sta ip: 192.168.108.19, mask: 255.255.224.0, gw: 192.168.96.1
   I (3123) WIFI: SYSTEM_EVENT_STA_GOT_IP
   2 302 [IP-task] vDHCPProcess: offer c0a86c13ip
   3 303 [main] WiFi Connected to AP. Creating tasks which use network...
   4 304 [OTA] OTA demo version 0.9.6
   5 304 [OTA] Creating MQTT Client...
   6 304 [OTA] Connecting to broker...
   I (4353) wifi: pm start, type:0
   
   I (8173) PKCS11: Initializing SPIFFS
   I (8183) PKCS11: Partition size: total: 52961, used: 0
   7 1277 [OTA] Connected to broker.
   8 1280 [OTA Task] [prvSubscribeToJobNotificationTopics] OK: $aws/things/<Your_Thing_Name>/jobs/$next/get/accepted
   I (12963) ota_pal: prvPAL_GetPlatformImageState
   I (12963) esp_ota_ops: [0] aflags/seq:0x2/0x1, pflags/seq:0xffffffff/0x0
   9 1285 [OTA Task] [prvSubscribeToJobNotificationTopics] OK: $aws/things/<Your_Thing_Name>/jobs/notify-next
   10 1286 [OTA Task] [OTA_CheckForUpdate] Request #0
   11 1289 [OTA Task] [prvParseJSONbyModel] Extracted parameter [ clientToken: 0:<Your_Thing_Name> ]
   12 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: execution
   13 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: jobId
   14 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: jobDocument
   15 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: afr_ota
   16 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: streamname
   17 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: files
   18 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: filepath
   19 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: filesize
   20 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: fileid
   21 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: certfile
   22 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: sig-sha256-ecdsa
   23 1289 [OTA Task] [prvParseJobDoc] Ignoring job without ID.
   24 1289 [OTA Task] [prvOTA_Close] Context->0x3ffbb4a8
   25 1290 [OTA] [OTA_AgentInit] Ready.
   26 1390 [OTA] State: Ready Received: 1 Queued: 1 Processed: 1 Dropped: 0
   27 1490 [OTA] State: Ready Received: 1 Queued: 1 Processed: 1 Dropped: 0
   28 1590 [OTA] State: Ready Received: 1 Queued: 1 Processed: 1 Dropped: 0
   29 1690 [OTA] State: Ready Received: 1 Queued: 1 Processed: 1 Dropped: 0
   [ ... ]
   ```

1. The ESP32 board is now listening for OTA updates. The ESP-IDF monitor is launched by the `make flash monitor` command. You can press **Ctrl\$1]** to quit. You can also use your favorite TTY terminal program (for example, PuTTY, Tera Term, or GNU Screen) to listen to the board's serial output. Be aware that connecting to the board's serial port might cause it to reboot.

# Install the initial version of firmware on the Nordic nRF52840 DK


**Important**  <a name="deprecation-message"></a>
This reference integration is hosted on the Amazon-FreeRTOS repository which is deprecated. We recommend that you [start here](freertos-getting-started-modular.md) when you create a new project. If you already have an existing FreeRTOS project based on the now deprecated Amazon-FreeRTOS repository, see the [Amazon-FreeRTOS Github Repository Migration Guide](github-repo-migration.md).

This guide is written with the assumption that you have already performed the steps in [Getting started with the Nordic nRF52840-DK](getting_started_nordic.md) and [Over-the-Air Update Prerequisites](https://docs.aws.amazon.com/freertos/latest/userguide/ota-prereqs.html). Before you attempt an OTA update, you might want to run the MQTT demo project described in [Getting Started with FreeRTOS](https://docs.aws.amazon.com/freertos/latest/userguide/freertos-getting-started.html) to ensure that your board and toolchain are set up correctly.

**To flash an initial factory image to the board**

1. Open `freertos/vendors/nordic/boards/nrf52840-dk/aws_demos/config_files/aws_demo_config.h`.

1. Replace `#define CONFIG_CORE_MQTT_MUTUAL_AUTH_DEMO_ENABLED` with `CONFIG_OTA_MQTT_UPDATE_DEMO_ENABLED` or `CONFIG_OTA_HTTP_UPDATE_DEMO_ENABLED`.

1. With the OTA Update demo selected, follow the same steps outlined in [Getting started with the Nordic nRF52840-DK](getting_started_nordic.md) to build and flash the image.

   You should see output similar to the following.

   ```
   9 1285 [OTA Task] [prvSubscribeToJobNotificationTopics] OK: $aws/things/your-thing-name/jobs/notify-next
   10 1286 [OTA Task] [OTA_CheckForUpdate] Request #0
   11 1289 [OTA Task] [prvParseJSONbyModel] Extracted parameter [ clientToken: 0:your-thing-name ]
   12 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: execution
   13 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: jobId
   14 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: jobDocument
   15 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: afr_ota
   16 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: streamname
   17 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: files
   18 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: filepath
   19 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: filesize
   20 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: fileid
   21 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: certfile
   22 1289 [OTA Task] [prvParseJSONbyModel] parameter not present: sig-sha256-ecdsa
   23 1289 [OTA Task] [prvParseJobDoc] Ignoring job without ID.
   24 1289 [OTA Task] [prvOTA_Close] Context->0x3ffbb4a8
   25 1290 [OTA] [OTA_AgentInit] Ready.
   26 1390 [OTA] State: Ready Received: 1 Queued: 1 Processed: 1 Dropped: 0
   27 1490 [OTA] State: Ready Received: 1 Queued: 1 Processed: 1 Dropped: 0
   28 1590 [OTA] State: Ready Received: 1 Queued: 1 Processed: 1 Dropped: 0
   29 1690 [OTA] State: Ready Received: 1 Queued: 1 Processed: 1 Dropped: 0
   ```

   Your board is now listening for OTA updates.

# Initial firmware on the Windows simulator


When you use the Windows simulator, there is no need to flash an initial version of the firmware. The Windows simulator is part of the `aws_demos` application, which also includes the firmware. 

# Install the initial version of firmware on a custom board


Using your IDE, build the `aws_demos` project, making sure to include the OTA library. For more information about the structure of the FreeRTOS source code, see [FreeRTOS demos](freertos-next-steps.md).

Make sure to include your code-signing certificate, private key, and certificate trust chain either in the FreeRTOS project or on your device.

Using the appropriate tool, burn the application onto your board and make sure it is running correctly.

# Update the version of your firmware


The OTA Agent included with FreeRTOS checks the version of any update and installs it only if it is more recent than the existing firmware version. The following steps show you how to increment the firmware version of the OTA demo application.

1. Open the `aws_demos` project in your IDE.

1. Locate the file ` /vendors/vendor/boards/board/aws_demos/config_files/ota_demo_config.h` and increment the value of **APP\$1VERSION\$1BUILD**. 

1. To schedule an update to a Renesas rx65n platform with a filetype other than 0 (non-firmware files), you must sign the file with the Renesas Secure Flash Programmer tool, otherwise it will fail the signature check on the device. The tool creates a signed file package with the extension `.rsu` which is a proprietary file type for Renesas. The tool can be found on [Github](https://github.com/renesas/Amazon-FreeRTOS-Tools). You can use the following example command to generate the image:

   ```
   "Renesas Secure Flash Programmer.exe" CUI Update "RX65N(ROM 2MB)/Secure Bootloader=256KB" "sig-sha256-ecdsa" 1 "file_name" "output_file_name.rsu"
   ```

1. Rebuild the project.

You must copy your firmware update into the Amazon S3 bucket that you created as described in [Create an Amazon S3 bucket to store your update](dg-ota-bucket.md). The name of the file you need to copy to Amazon S3 depends on the hardware platform you are using: 
+ Texas Instruments CC3220SF-LAUNCHXL: `vendors/ti/boards/cc3220_launchpad/aws_demos/ccs/debug/aws_demos.bin`
+ Espressif ESP32: `vendors/espressif/boards/esp32/aws_demos/make/build/aws_demos.bin`

# Creating an OTA update (AWS IoT console)


1. In the navigation pane of the AWS IoT console, under **Manage** select **Remote actions**, and then choose **Jobs**.

1. Choose **Create job**.

1. Under **Job type** select **Create FreeRTOS OTA update job**, then choose **Next**.

1. In **Job properties**, enter a **Job name** and (optionally) enter a **Description** of the job, then choose **Next**.

1. You can deploy an OTA update to a single device or a group of devices. Under **Devices to update**, choose one or more things or thing groups from the dropdown.

1. Under **Select the protocol for the file transfer**, select either **HTTP** or **MQTT**, or select both to allow each device to determine the protocol to use.

1. Under **Sign and choose your file**, select **Sign a new file for me**.

1. Under **Code signing profile**, choose **Create new profile**.

1. In **Create a code signing profile**, enter a name for your code-signing profile.

   1. Under **Device hardware platform**, choose your hardware platform.
**Note**  
Only hardware platforms that have been qualified for FreeRTOS are displayed in this list. If you are testing a non-qualified platform, and you are using the ECDSA P-256 SHA-256 ciphersuite for signing, you can pick the Windows Simulator code signing profile to produce a compatible signature. If you are using a non-qualified platform, and you are using a ciphersuite other than ECDSA P-256 SHA-256 for signing, you can use Code Signing for AWS IoT, or you can sign your firmware update yourself. For more information, see [Digitally signing your firmware update](ota-cli-workflow.md#ota-sign-cli).

   1. Under **Code signing certificate**, choose **Select an existing certificate** and then select a previously imported certificate, or choose **Import a new code signing certificate**, choose your files and select **Import** to import a new certificate.

   1. Under **Pathname of code signing certificate on device**, enter the fully qualified path name to the code signing certificate on your device. For most devices you can leave this field blank. For the Windows simulator and for devices that do place the certificate in a specific file location, enter the pathname here.
**Important**  
On the Texas Instruments CC3220SF-LAUNCHXL, do not include a leading forward slash (**/**) in front of the file name if your code signing certificate exists in the root of the file system. Otherwise, the OTA update fails during authentication with a `file not found` error.

   1. Select **Create**.

1. Under **File** select **Select an existing file** then choose **Browse S3**. A list of your Amazon S3 buckets is displayed. Choose the bucket that contains your firmware update, and then choose your firmware update in the bucket.
**Note**  
The Microchip Curiosity PIC32MZEF demo projects produce two binary images with default names of `mplab.production.bin` and `mplab.production.ota.bin`. Use the second file when you upload an image for OTA updating.

1. Under **Pathname of file on device**, enter the fully qualified path name to the location on your device where the OTA job will copy the firmware image. This location varies by platform.
**Important**  
On the Texas Instruments CC3220SF-LAUNCHXL, due to security restrictions, the firmware image path name must be `/sys/mcuflashimg.bin`.

1. Open **File Type** and enter an integer value in the range 0-255. The file type you enter will be added to the Job document that is delivered to the MCU. The MCU firmware/software developer has full ownership on what to do with this value. Possible scenarios include an MCU that has a secondary processor whose firmware can be updated independently from the primary processor. When the device receives an OTA update job, it can use the File Type to identify which processor the update is for.

1. Under **IAM role**, choose a role according to the instructions in [Create an OTA Update service role](create-service-role.md). 

1. Choose **Next**.

1. Enter an ID and description for your OTA update job.

1. Under **Job type**, choose **Your job will complete after deploying to the selected devices/groups (snapshot)**.

1. Choose any appropriate optional configurations for your job (**Job executions rollout**, **Job abort**, **Job executions timeout**, and **Tags**).

1. Choose **Create**.<a name="previously-signed"></a>

**To use a previously signed firmware image**

1. Under **Select and sign your firmware image**, choose **Select a previously signed firmware image**.

1. Under **Pathname of firmware image on device**, enter the fully qualified path name to the location on your device where the OTA job will copy the firmware image. This location varies by platform.

1. Under **Previous code signing job**, choose **Select**, and then choose the previous code-signing job used to sign the firmware image you are using for the OTA update.<a name="custom-signed"></a>

**Using a custom signed firmware image**

1. Under **Select and sign your firmware image**, choose **Use my custom signed firmware image**.

1. Under **Pathname of code signing certificate on device**, enter the fully qualified path name to the code signing certificate on your device. For most devices you can leave this field blank. For the Windows simulator and for devices that do place the certificate in a specific file location, enter the pathname here.

1. Under **Pathname of firmware image on device**, enter the fully qualified path name to the location on your device where the OTA job will copy the firmware image. This location varies by platform.

1. Under **Signature**, paste your PEM format signature.

1. Under **Original hash algorithm**, choose the hash algorithm that was used when you created your file signature.

1. Under **Original encryption algorithm**, choose the algorithm that was used when you created your file signature.

1. Under **Select your firmware image in Amazon S3**, choose the Amazon S3 bucket and the signed firmware image in the Amazon S3 bucket.

After you have specified the code-signing information, specify the OTA update job type, service role, and an ID for your update.

**Note**  
Do not use any personally identifiable information in the job ID for your OTA update. Examples of personally identifiable information include:  
Names.
IP addresses.
Email addresses.
Locations.
Bank details.
Medical information.

1. Under **Job type**, choose **Your job will complete after deploying to the selected devices/groups (snapshot)**.

1. Under **IAM role for OTA update job**, choose your OTA service role.

1. Enter an alphanumeric ID for your job, and then choose **Create**.

The job appears in the AWS IoT console with a status of **IN PROGRESS**.

**Note**  
The AWS IoT console does not update the state of jobs automatically. Refresh your browser to see updates.

Connect your serial UART terminal to your device. You should see output that indicates the device is downloading the updated firmware.

After the device downloads the updated firmware, it restarts and then installs the firmware. You can see what's happening in the UART terminal.

For a tutorial that shows you how to use the console to create an OTA update, see [Over-the-air updates demo application](ota-demo.md).

# Creating an OTA update with the AWS CLI


When you use the AWS CLI to create an OTA update, you:

1. Digitally sign your firmware image.

1. Create a stream of your digitally signed firmware image.

1. Start an OTA update job.

## Digitally signing your firmware update


When you use the AWS CLI to perform OTA updates, you can use Code Signing for AWS IoT, or you can sign your firmware update yourself. For a list of the cryptographic signing and hashing algorithms supported by Code Signing for AWS IoT, see [ SigningConfigurationOverrides](https://docs.aws.amazon.com/signer/latest/api/API_SigningConfigurationOverrides.html). If you want to use a cryptographic algorithm that is not supported by Code Signing for AWS IoT, you must sign your firmware binary before you upload it to Amazon S3.

### Signing your firmware image with Code Signing for AWS IoT


To sign your firmware image using Code Signing for AWS IoT, you can use one of the [AWS SDKs or command line tools](https://aws.amazon.com/tools/). For more information about Code Signing for AWS IoT, see [ Code Signing for AWS IoT](https://docs.aws.amazon.com/signer/latest/developerguide/Welcome.html).

After you install and configure the code-signing tools, copy your unsigned firmware image to your Amazon S3 bucket and start a code-signing job with the following AWS CLI commands. The **put-signing-profile** command creates a reusable code-signing profile. The **start-signing-job** command starts the signing job.

```
aws signer put-signing-profile \
    --profile-name your_profile_name \
    --signing-material certificateArn=arn:aws:acm::your-region:your-aws-account-id:certificate/your-certificate-id \
    --platform your-hardware-platform \
    --signing-parameters certname=your_certificate_path_on_device
```

```
aws signer start-signing-job \
    --source 's3={bucketName=your_s3_bucket,key=your_s3_object_key,version=your_s3_object_version_id}' \
    --destination 's3={bucketName=your_destination_bucket}' \
    --profile-name your_profile_name
```

**Note**  
*your-source-bucket-name* and *your-destination-bucket-name* can be the same Amazon S3 bucket.

These are the parameters for the **put-signing-profile** and **start-signing-job** commands:

**`source`**  
Specifies the location of the unsigned firmware in an S3 bucket.  
+ `bucketName`: The name of your S3 bucket.
+ `key`: The key (file name) of your firmware in your S3 bucket.
+ `version`: The S3 version of your firmware in your S3 bucket. This is different from your firmware version. You can find it by browsing to the Amazon S3 console, choosing your bucket, and at the top of the page, next to **Versions**, choosing **Show**.

**`destination`**  
The destination on the device to which the signed firmware in the S3 bucket will be copied. The format of this parameter is the same as the `source` parameter.

**`signing-material`**  
The ARN of your code-signing certificate. This ARN is generated when you import your certificate into ACM.

**`signing-parameters`**  
A map of key-value pairs for signing. These can include any information that you want to use during signing.  
This parameter is required when you are creating a code-signing profile for signing OTA updates with Code Signing for AWS IoT.

**`platform`**  
The `platformId` of the hardware platform to which you are distributing the OTA update.  
To return a list of the available platforms and their `platformId` values, use the `aws signer list-signing-platforms` command.

The signing job starts and writes the signed firmware image into the destination Amazon S3 bucket. The file name for the signed firmware image is a GUID. You need this file name when you create a stream. You can find the file name by browsing to the Amazon S3 console and choosing your bucket. If you don't see a file with a GUID file name, refresh your browser.

The command displays a job ARN and job ID. You need these values later on. For more information about Code Signing for AWS IoT, see [Code Signing for AWS IoT](https://docs.aws.amazon.com/signer/latest/developerguide/Welcome.html).

### Signing your firmware image manually


Digitally sign your firmware image and upload your signed firmware image into your Amazon S3 bucket.

## Creating a stream of your firmware update


A stream is an abstract interface to data that can be consumed by a device. A stream can hide the complexity of accessing data stored in different locations or different cloud-based services. The OTA Update Manager service enables you to use multiple pieces of data, stored in various locations in Amazon S3, to perform an OTA Update.

When you create an AWS IoT OTA Update, you can also create a stream that contains your signed firmware update. Make a JSON file (`stream.json`) that identifies your signed firmware image. The JSON file should contain the following.

```
[
  {
    "fileId":"your_file_id",
    "s3Location":{
      "bucket":"your_bucket_name",
      "key":"your_s3_object_key"
    }
  }   
]
```

These are the attributes in the JSON file:

**`fileId`**  
An arbitrary integer between 0–255 that identifies your firmware image.

**`s3Location`**  
The bucket and key for the firmware to stream.    
**`bucket`**  
The Amazon S3 bucket where your unsigned firmware image is stored.  
**`key`**  
The file name of your signed firmware image in the Amazon S3 bucket. You can find this value in the Amazon S3 console by looking at the contents of your bucket.  
If you are using Code Signing for AWS IoT, the file name is a GUID generated by Code Signing for AWS IoT.

Use the **create-stream** AWS CLI command to create a stream.

```
aws iot create-stream \
    --stream-id your_stream_id \
    --description your_description \
    --files file://stream.json \
    --role-arn your_role_arn
```

These are the arguments for the **create-stream** AWS CLI command:

**`stream-id`**  
An arbitrary string to identify the stream.

**`description`**  
An optional description of the stream.

**`files`**  
One or more references to JSON files that contain data about firmware images to stream. The JSON file must contain the following attributes:    
**`fileId`**  
An arbitrary file ID.  
**`s3Location`**  
The bucket name where the signed firmware image is stored and the key (file name) of the signed firmware image.  
**`bucket`**  
The Amazon S3 bucket where the signed firmware image is stored.  
**`key`**  
The key (file name) of the signed firmware image.  
When you use Code Signing for AWS IoT, this key is a GUID.
The following is an example `stream.json` file.  

```
[
    {
        "fileId":123,
        "s3Location": {
            "bucket":"codesign-ota-bucket",
            "key":"48c67f3c-63bb-4f92-a98a-4ee0fbc2bef6"
        }
    }
]
```

**`role-arn`**  
The [OTA service role](create-service-role.md) that also grants access to the Amazon S3 bucket where the firmware image is stored.

To find the Amazon S3 object key of your signed firmware image, use the **aws signer describe-signing-job --job-id *my-job-id*** command where `my-job-id` is the job ID displayed by the **create-signing-job** AWS CLI command. The output of the **describe-signing-job** command contains the key of the signed firmware image. 

```
... text deleted for brevity ...
  "signedObject": {
    "s3": {
      "bucketName": "ota-bucket",
      "key": "7309da2c-9111-48ac-8ee4-5a4262af4429"
    }
  }
... text deleted for brevity ...
```

## Creating an OTA update


Use the **create-ota-update** AWS CLI command to create an OTA update job.

**Note**  
Do not use any personally identifiable information (PII) in your OTA update job ID. Examples of personally identifiable information include:  
Names.
IP addresses.
Email addresses.
Locations.
Bank details.
Medical information.

```
aws iot  create-ota-update \
    --ota-update-id value \
    [--description value] \
    --targets value \
    [--protocols value] \
    [--target-selection value] \
    [--aws-job-executions-rollout-config value] \
    [--aws-job-presigned-url-config value] \
    [--aws-job-abort-config value] \
    [--aws-job-timeout-config value] \
    --files value \
    --role-arn value \
    [--additional-parameters value] \
    [--tags value]  \
    [--cli-input-json value] \
    [--generate-cli-skeleton]
```

 `cli-input-json` format

```
{
  "otaUpdateId": "string",
  "description": "string",
  "targets": [
    "string"
  ],
  "protocols": [
    "string"
  ],
  "targetSelection": "string",
  "awsJobExecutionsRolloutConfig": {
    "maximumPerMinute": "integer",
    "exponentialRate": {
      "baseRatePerMinute": "integer",
      "incrementFactor": "double",
      "rateIncreaseCriteria": {
        "numberOfNotifiedThings": "integer",
        "numberOfSucceededThings": "integer"
      }
    }
  },
  "awsJobPresignedUrlConfig": {
    "expiresInSec": "long"
  },
  "awsJobAbortConfig": {
    "abortCriteriaList": [
      {
        "failureType": "string",
        "action": "string",
        "thresholdPercentage": "double",
        "minNumberOfExecutedThings": "integer"
      }
    ]
  },
  "awsJobTimeoutConfig": {
    "inProgressTimeoutInMinutes": "long"
  },
  "files": [
    {
      "fileName": "string",
      "fileType": "integer",
      "fileVersion": "string",
      "fileLocation": {
        "stream": {
          "streamId": "string",
          "fileId": "integer"
        },
        "s3Location": {
          "bucket": "string",
          "key": "string",
          "version": "string"
        }
      },
      "codeSigning": {
        "awsSignerJobId": "string",
        "startSigningJobParameter": {
          "signingProfileParameter": {
            "certificateArn": "string",
            "platform": "string",
            "certificatePathOnDevice": "string"
          },
          "signingProfileName": "string",
          "destination": {
            "s3Destination": {
              "bucket": "string",
              "prefix": "string"
            }
          }
        },
        "customCodeSigning": {
          "signature": {
            "inlineDocument": "blob"
          },
          "certificateChain": {
            "certificateName": "string",
            "inlineDocument": "string"
          },
          "hashAlgorithm": "string",
          "signatureAlgorithm": "string"
        }
      },
      "attributes": {
        "string": "string"
      }
    }
  ],
  "roleArn": "string",
  "additionalParameters": {
    "string": "string"
  },
  "tags": [
    {
      "Key": "string",
      "Value": "string"
    }
  ]
}
```


**`cli-input-json` fields**  

| Name | Type | Description | 
| --- | --- | --- | 
| `otaUpdateId` |  string  (max:128 min:1)  | The ID of the OTA update to be created. | 
| `description` |  string  (max:2028)  | The description of the OTA update. | 
| `targets` |  list  | The devices targeted to receive OTA updates. | 
| `protocols` |  list  |  The protocol used to transfer the OTA update image. Valid values are [HTTP], [MQTT], [HTTP, MQTT]. When both HTTP and MQTT are specified, the target device can choose the protocol.  | 
| `targetSelection` | string |  Specifies whether the update will continue to run (CONTINUOUS), or will be complete after all the things specified as targets have completed the update (SNAPSHOT). If continuous, the update may also be run on a thing when a change is detected in a target. For example, an update will run on a thing when the thing is added to a target group, even after the update was completed by all things originally in the group. Valid values: CONTINUOUS \$1 SNAPSHOT. enum: CONTINUOUS \$1 SNAPSHOT  | 
| `awsJobExecutionsRolloutConfig` |  | Configuration for the rollout of OTA updates. | 
| `maximumPerMinute` |  integer  (max:1000 min:1)  | The maximum number of OTA update job executions started per minute. | 
| `exponentialRate` |  |  The rate of increase for a job rollout. This parameter allows you to define an exponential rate increase for a job rollout.  | 
| `baseRatePerMinute` |  integer  (max:1000 min:1)  |  The minimum number of things that will be notified of a pending job, per minute, at the start of the job rollout. This is the initial rate of the rollout.  | 
|   `rateIncreaseCriteria`  |   |  The criteria to initiate the increase in rate of rollout for a job. AWS IoT supports up to one digit after the decimal (for example, 1.5, but not 1.55).  | 
|   `numberOfNotifiedThings`  |  integer  (min:1)  |  When this number of things have been notified, it will initiate an increase in the rollout rate.  | 
|   `numberOfSucceededThings`  |  integer  (min:1)  |  When this number of things have succeeded in their job execution, it will initiate an increase in the rollout rate.  | 
| `awsJobPresignedUrlConfig` |  |  Configuration information for pre-signed URLs. | 
|   `expiresInSec`  |  long |  How long (in seconds) pre-signed URLs are valid. Valid values are 60 - 3600, the default value is 1800 seconds. Pre-signed URLs are generated when a request for the job document is received.  | 
|   `awsJobAbortConfig`  |   |  The criteria that determine when and how a job stoppage takes place. | 
|   `abortCriteriaList`  |  list  |  The list of criteria that determine when and how to stop the job. | 
|   `failureType`  |  string |  The type of job execution failures that can initiate a job stoppage.  enum: FAILED \$1 REJECTED \$1 TIMED\$1OUT \$1 ALL  | 
|   `action`  |  string |  The type of job action to take to initiate the job stoppage.  enum: CANCEL  | 
|   `minNumberOfExecutedThings`  |  integer  (min:1)  |  The minimum number of things which must receive job execution notifications before the job can be stopped.  | 
|   `awsJobTimeoutConfig`  |   |  Specifies the amount of time each device has to finish its execution of the job. A timer is started when the job execution status is set to `IN_PROGRESS`. If the job execution status is not set to another terminal state before the timer expires, it will be automatically set to `TIMED_OUT`.  | 
|   `inProgressTimeoutInMinutes`  |  long |  Specifies the amount of time, in minutes, this device has to finish execution of this job. The timeout interval can be anywhere between 1 minute and 7 days (1 to 10080 minutes). The in progress timer can't be updated and will apply to all job executions for the job. Whenever a job execution remains in the IN\$1PROGRESS status for longer than this interval, the job execution will fail and switch to the terminal `TIMED_OUT` status.  | 
|   `files`  |  list  |  The files to be streamed by the OTA update. | 
|   `fileName`  |  string |  The name of the file. | 
|   `fileType`  |  integer  range- max:255 min:0  |  An integer value you can include in the job document to allow your devices to identify the type of file received from the cloud.  | 
|   `fileVersion`  |  string |  The file version. | 
|   `fileLocation`  |   |  The location of the updated firmware. | 
|   `stream`  |   |  The stream that contains the OTA update. | 
|   `streamId`  |  string  (max:128 min:1)  |  The stream ID. | 
|   `fileId`  |  integer  (max:255 min:0)  |  The ID of a file associated with a stream. | 
|   `s3Location`  |   |  The location of the updated firmware in S3. | 
|   `bucket`  |  string  (min:1)  |  The S3 bucket. | 
|   `key`  |  string  (min:1)  |  The S3 key. | 
|   `version`  |  string |  The S3 bucket version. | 
|   `codeSigning`  |   |  The code signing method of the file. | 
|   `awsSignerJobId`  |  string |  The ID of the AWSSignerJob which was created to sign the file. | 
|   `startSigningJobParameter`  |   |  Describes the code-signing job. | 
|   `signingProfileParameter`  |   |  Describes the code-signing profile. | 
|   `certificateArn`  |  string |  Certificate ARN. | 
|   `platform`  |  string |  The hardware platform of your device. | 
|   `certificatePathOnDevice`  |  string |  The location of the code-signing certificate on your device. | 
|   `signingProfileName`  |  string |  The code-signing profile name. | 
|   `destination`  |   |  The location to write the code-signed file. | 
|   `s3Destination`  |   |  Describes the location in S3 of the updated firmware. | 
|   `bucket`  |  string  (min:1)  |  The S3 bucket that contains the updated firmware. | 
|   `prefix`  |  string |  The S3 prefix. | 
|   `customCodeSigning`  |   |  A custom method for code signing a file. | 
|   `signature`  |   |  The signature for the file. | 
|   `inlineDocument`  |  blob |  A base64 encoded binary representation of the code signing signature. | 
|   `certificateChain`  |   |  The certificate chain. | 
|   `certificateName`  |  string |  The name of the certificate. | 
|   `inlineDocument`  |  string |  A base64 encoded binary representation of the code signing certificate chain. | 
|   `hashAlgorithm`  |  string |  The hash algorithm used to code sign the file. | 
|   `signatureAlgorithm`  |  string |  The signature algorithm used to code sign the file. | 
|   `attributes`  |  map |  A list of name/attribute pairs. | 
|   `roleArn`  |  string  (max:2048 min:20)  |  The IAM role that grants AWS IoT access to the Amazon S3, AWS IoT jobs and AWS Code Signing resources to create an OTA update job. | 
|   `additionalParameters`  |  map |  A list of additional OTA update parameters which are name-value pairs. | 
|   `tags`  |  list  |  Metadata which can be used to manage updates. | 
|   `Key`  |  string  (max:128 min:1)  |  The tag's key. | 
|   `Value`  |  string  (max:256 min:1)  |  The tag's value. | 

Output

```
{
  "otaUpdateId": "string",
  "awsIotJobId": "string",
  "otaUpdateArn": "string",
  "awsIotJobArn": "string",
  "otaUpdateStatus": "string"
}
```


**AWS CLI output fields**  

|  Name |  Type |  Description | 
| --- | --- | --- | 
|   `otaUpdateId`  |  string  (max:128 min:1)  |  The OTA update ID. | 
|   `awsIotJobId`  |  string |  The AWS IoT job ID associated with the OTA update. | 
|   `otaUpdateArn`  |  string |  The OTA update ARN. | 
|   `awsIotJobArn`  |  string |  The AWS IoT job ARN associated with the OTA update. | 
|   `otaUpdateStatus`  |  string |  The OTA update status.  enum: CREATE\$1PENDING \$1 CREATE\$1IN\$1PROGRESS \$1 CREATE\$1COMPLETE \$1 CREATE\$1FAILED  | 

The following is an example of a JSON file passed into the **create-ota-update** command that uses Code Signing for AWS IoT.

```
[
  {
    "fileName": "firmware.bin",                
    "fileType": 1,
    "fileLocation": {
      "stream": {
        "streamId": "004",                         
        "fileId":123
      }                        
    },
    "codeSigning": {
      "awsSignerJobId": "48c67f3c-63bb-4f92-a98a-4ee0fbc2bef6"     
    }
  }
]
```

The following is an example of a JSON file passed into the **create-ota-update** AWS CLI command that uses an inline file to provide custom code-signing material.

```
[
  {
    "fileName": "firmware.bin",
    "fileType": 1,
    "fileLocation": {
      "stream": {
        "streamId": "004",
        "fileId": 123
      }
    },
    "codeSigning": {
      "customCodeSigning":{
        "signature":{
          "inlineDocument":"your_signature"
        },
        "certificateChain": {
          "certificateName": "your_certificate_name",
          "inlineDocument":"your_certificate_chain"
        },
        "hashAlgorithm":"your_hash_algorithm",
        "signatureAlgorithm":"your_signature_algorithm"
      }
    }
  }
]
```

The following is an example of a JSON file passed into the **create-ota-update** AWS CLI command that allows FreeRTOS OTA to start a code-signing job and create a code-signing profile and stream.

```
[
  {
    "fileName": "your_firmware_path_on_device",
    "fileType": 1,
    "fileVersion": "1",
    "fileLocation": {
      "s3Location": {
        "bucket": "your_bucket_name",
        "key": "your_object_key",
        "version": "your_S3_object_version"
      }
    },
    "codeSigning":{
      "startSigningJobParameter":{
        "signingProfileName": "myTestProfile",
        "signingProfileParameter": {
          "certificateArn": "your_certificate_arn",
          "platform": "your_platform_id",
          "certificatePathOnDevice": "certificate_path"
        },
        "destination": {
          "s3Destination": {
            "bucket": "your_destination_bucket"
          }
        }
      }
    }  
  }
]
```

The following is an example of a JSON file passed into the **create-ota-update** AWS CLI command that creates an OTA update that starts a code-signing job with an existing profile and uses the specified stream.

```
[
  {
    "fileName": "your_firmware_path_on_device",
    "fileType": 1,
    "fileVersion": "1",
    "fileLocation": {
      "s3Location": {
        "bucket": "your_s3_bucket_name",
        "key": "your_object_key",
        "version": "your_S3_object_version"
      }
    },
    "codeSigning":{
      "startSigningJobParameter":{
        "signingProfileName": "your_unique_profile_name",
        "destination": {
          "s3Destination": {
            "bucket": "your_destination_bucket"
          }
        }
      }
    }  
  }
]
```

The following is an example of a JSON file passed into the **create-ota-update** AWS CLI command that allows FreeRTOS OTA to create a stream with an existing code-signing job ID.

```
[
  {
    "fileName": "your_firmware_path_on_device",
    "fileType": 1,
    "fileVersion": "1",
    "codeSigning":{
      "awsSignerJobId": "your_signer_job_id"
    }  
  }
]
```

The following is an example of a JSON file passed into the **create-ota-update** AWS CLI command that creates an OTA update. The update creates a stream from the specified S3 object and uses custom code signing.

```
[
  {
    "fileName": "your_firmware_path_on_device",
    "fileType": 1,
    "fileVersion": "1",
    "fileLocation": {
      "s3Location": {
        "bucket": "your_bucket_name",
        "key": "your_object_key",
        "version": "your_S3_object_version"
      }
    },
    "codeSigning":{
      "customCodeSigning": {
        "signature":{
          "inlineDocument":"your_signature"
        },
        "certificateChain": {
          "inlineDocument":"your_certificate_chain",
          "certificateName": "your_certificate_path_on_device"
        },
        "hashAlgorithm":"your_hash_algorithm",
        "signatureAlgorithm":"your_sig_algorithm"
      }
    }  
  }
]
```

## Listing OTA updates


You can use the **list-ota-updates** AWS CLI command to get a list of all OTA updates.

```
aws iot list-ota-updates
```

The output from the **list-ota-updates** command looks like this.

```
{
  "otaUpdates": [
     
    {
      "otaUpdateId": "my_ota_update2",
      "otaUpdateArn": "arn:aws:iot:us-west-2:123456789012:otaupdate/my_ota_update2",
      "creationDate": 1522778769.042
    },
    {
      "otaUpdateId": "my_ota_update1",
      "otaUpdateArn": "arn:aws:iot:us-west-2:123456789012:otaupdate/my_ota_update1",
      "creationDate": 1522775938.956
    },
    {
      "otaUpdateId": "my_ota_update",
      "otaUpdateArn": "arn:aws:iot:us-west-2:123456789012:otaupdate/my_ota_update",
      "creationDate": 1522775151.031
    }
  ]
}
```

## Getting information about an OTA update


You can use the **get-ota-update** AWS CLI command to get the creation or deletion status of an OTA update.

```
aws iot get-ota-update --ota-update-id your-ota-update-id
```

The output from the **get-ota-update** command looks like the following.

```
{ 
    "otaUpdateInfo": { 
        "otaUpdateId": "ota-update-001", 
        "otaUpdateArn": "arn:aws:iot:region:123456789012:otaupdate/ota-update-001", 
        "creationDate": 1575414146.286, 
        "lastModifiedDate": 1575414149.091, 
        "targets": [ 
            "arn:aws:iot:region:123456789012:thing/myDevice" 
        ], 
        "protocols": [ "HTTP" ], 
        "awsJobExecutionsRolloutConfig": { 
            "maximumPerMinute": 0 
        }, 
        "awsJobPresignedUrlConfig": { 
            "expiresInSec": 1800 
        }, 
        "targetSelection": "SNAPSHOT", 
        "otaUpdateFiles": [ 
            { 
                "fileName": "my_firmware.bin", 
                "fileType": 1,
                "fileLocation": { 
                    "s3Location": { 
                        "bucket": "my-bucket", 
                        "key": "my_firmware.bin", 
                        "version": "AvP3bfJC9gyqnwoxPHuTqM5GWENt4iii" 
                    } 
                }, 
                "codeSigning": { 
                    "awsSignerJobId": "b7a55a54-fae5-4d3a-b589-97ed103737c2", 
                    "startSigningJobParameter": { 
                        "signingProfileParameter": {}, 
                        "signingProfileName": "my-profile-name", 
                        "destination": { 
                            "s3Destination": { 
                                "bucket": "some-ota-bucket", 
                                "prefix": "SignedImages/" 
                            } 
                        } 
                    }, 
                    "customCodeSigning": {} 
                } 
            } 
        ], 
        "otaUpdateStatus": "CREATE_COMPLETE", 
        "awsIotJobId": "AFR_OTA-ota-update-001", 
        "awsIotJobArn": "arn:aws:iot:region:123456789012:job/AFR_OTA-ota-update-001" 
    } 
}
```

The values returned for `otaUpdateStatus` include the following:

**`CREATE_PENDING`**  
The creation of an OTA update is pending.

**`CREATE_IN_PROGRESS`**  
An OTA update is being created.

**`CREATE_COMPLETE`**  
An OTA update has been created.

**`CREATE_FAILED`**  
The creation of an OTA update failed.

**`DELETE_IN_PROGRESS`**  
An OTA update is being deleted.

**`DELETE_FAILED`**  
The deletion of an OTA update failed.

**Note**  
To get the execution status of an OTA update after it is created, you need to use the **describe-job-execution** command. For more information, see [ Describe Job Execution](https://docs.aws.amazon.com/iot/latest/developerguide/manage-job-cli.html#describe-job-execution).

## Deleting OTA-related data


Currently, you cannot use the AWS IoT console to delete streams or OTA updates. You can use the AWS CLI to delete streams, OTA updates, and the AWS IoT jobs created during an OTA update.

### Deleting an OTA stream


When you create an OTA update that uses MQTT, either you can use the command-line or the AWS IoT console to create a stream to break the firmware up into chunks so it can be sent over MQTT. You can delete this stream with the **delete-stream** AWS CLI command, as shown in the following example.

```
aws iot delete-stream --stream-id your_stream_id
```

### Deleting an OTA update


When you create an OTA update, the following are created:
+ An entry in the OTA update job database.
+ An AWS IoT job to perform the update.
+ An AWS IoT job execution for each device being updated.

The **delete-ota-update** command deletes the entry in the OTA update job database only. You must use the **delete-job** command to delete the AWS IoT job.

Use the **delete-ota-update** command to delete an OTA update.

```
aws iot delete-ota-update --ota-update-id your_ota_update_id
```

**`ota-update-id`**  
The ID of the OTA update to delete.

**`delete-stream`**  
Deletes the stream associated with the OTA update.

**`force-delete-aws-job`**  
Deletes the AWS IoT job associated with the OTA update. If this flag is not set and the job is in the `In_Progress` state, the job is not deleted.

### Deleting an IoT job created for an OTA update


FreeRTOS creates an AWS IoT job when you create an OTA update. A job execution is also created for each device that processes the job. You can use the **delete-job** AWS CLI command to delete a job and its associated job executions.

```
aws iot delete-job --job-id your-job-id --no-force
```

The `no-force` parameter specifies that only jobs that are in a terminal state (COMPLETED or CANCELLED) can be deleted. You can delete a job that is in a non-terminal state by passing the `force` parameter. For more information, see [DeleteJob API](https://docs.aws.amazon.com/iot/latest/apireference/API_DeleteJob.html).

**Note**  
Deleting a job with a status of IN\$1PROGRESS interrupts any job executions that are IN\$1PROGRESS on your devices and can result in a device being left in a nondeterministic state. Make sure that each device executing a job that has been deleted can recover to a known state.

Depending on the number of job executions created for the job and other factors, it can take a few minutes to delete a job. While the job is being deleted, its status is DELETION\$1IN\$1PROGRESS. Attempting to delete or cancel a job whose status is already DELETION\$1IN\$1PROGRESS results in an error.

You can use the **delete-job-execution** to delete a job execution. You might want to delete a job execution when a small number of devices are unable to process a job. This deletes the job execution for a single device, as shown in the following example.

```
aws iot delete-job-execution --job-id your-job-id --thing-name
                    your-thing-name --execution-number your-job-execution-number --no-force
```

As with the **delete-job** AWS CLI command, you can pass the `--force` parameter to the **delete-job-execution** to force the deletion of a job execution. For more information , see [DeleteJobExecution API](https://docs.aws.amazon.com/iot/latest/apireference/API_DeleteJobExecution.html).

**Note**  
Deleting a job execution with a status of IN\$1PROGRESS interrupts any job executions that are IN\$1PROGRESS on your devices and can result in a device being left in a nondeterministic state. Make sure that each device executing a job that has been deleted can recover to a known state.

For more information about using the OTA update demo application, see [Over-the-air updates demo application](ota-demo.md).