

# FreeRTOS Over-the-Air Updates
<a name="freertos-ota-dev"></a>

**Note**  
See [AWS IoT Over-the-Air (OTA)](https://www.freertos.org/ota/index.html) on the FreeRTOS website for recent information on performing Over-the-air (OTA) updates.

Over-the-air (OTA) updates allow you to deploy firmware updates to one or more devices in your fleet. Although OTA updates were designed to update device firmware, you can use them to send any files to one or more devices registered with AWS IoT. When you send updates over the air, we recommend that you digitally sign them so that the devices that receive the files can verify they haven't been tampered with en route.

You can use [Code Signing for AWS IoT](https://docs.aws.amazon.com/signer/latest/developerguide/Welcome.html) to sign your files, or you can sign your files with your own code-signing tools.

When you create an OTA update, the [OTA Update Manager service](ota-manager.md) creates an [AWS IoT job](https://docs.aws.amazon.com/iot/latest/developerguide/iot-jobs.html) to notify your devices that an update is available. The OTA demo application runs on your device and creates a FreeRTOS task that subscribes to notification topics for AWS IoT jobs and listens for update messages. When an update is available, the OTA Agent publishes requests to AWS IoT and receives updates using the HTTP or MQTT protocol, depending on the settings you chose. The OTA Agent checks the digital signature of the downloaded files and, if the files are valid, installs the firmware update. If you don't use the FreeRTOS OTA Update demo application, you must integrate the [AWS IoT Over the air (OTA) library](ota-update-library.md) into your own application to get the firmware update capability.

FreeRTOS over-the-air updates make it possible for you to:
+ Digitally sign firmware before deployment.
+ Deploy new firmware images to a single device, a group of devices, or your entire fleet.
+ Deploy firmware to devices as they are added to groups, reset, or reprovisioned.
+ Verify the authenticity and integrity of new firmware after it's deployed to devices.
+ Monitor the progress of a deployment.
+ Debug a failed deployment.

## Tagging OTA resources
<a name="ota-tagging"></a>

To help you manage your OTA resources, you can optionally assign your own metadata to updates and streams in the form of tags. Tags make it possible for you to categorize your AWS IoT resources in different ways (for example, by purpose, owner, or environment). This is useful when you have many resources of the same type. You can quickly identify a resource based on the tags you've assigned to it.

For more information, see [Tagging Your AWS IoT Resources](https://docs.aws.amazon.com/iot/latest/developerguide/tagging-iot.html).

# OTA update prerequisites
<a name="ota-prereqs"></a>

To use over-the-air (OTA) updates, do the following:
+ Check the [Prerequisites for OTA updates using HTTP](ota-http-freertos.md) or the [Prerequisites for OTA updates using MQTT](ota-mqtt-freertos.md).
+ [Create an Amazon S3 bucket to store your update](dg-ota-bucket.md).
+ [Create an OTA Update service role](create-service-role.md).
+ [Create an OTA user policy](create-ota-user-policy.md).
+ [Create a code-signing certificate](ota-code-sign-cert.md).
+ If you are using Code Signing for AWS IoT, [Grant access to code signing for AWS IoT](code-sign-policy.md).
+ [Download FreeRTOS with the OTA library](ota-download-freertos.md).

# Create an Amazon S3 bucket to store your update
<a name="dg-ota-bucket"></a>

OTA update files are stored in Amazon S3 buckets.

If you're using Code Signing for AWS IoT, the command that you use to create a code-signing job takes a source bucket (where the unsigned firmware image is located) and a destination bucket (where the signed firmware image is written). You can specify the same bucket for the source and destination. The file names are changed to GUIDs so the original files are not overwritten.<a name="create-bucket"></a>

**To create an Amazon S3 bucket**

1. Sign in to the Amazon S3 console at [https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/).

1. Choose **Create bucket**.

1. Enter a **bucket name**.

1. Under **Bucket settings for Block Public Access** keep **Block all public access** selected to accept the default permissions.

1. Under **Bucket Versioning**, select **Enable** to keep all versions in the same bucket.

1. Choose **Create bucket**.

For more information about Amazon S3, see [Amazon Simple Storage Service User Guide](https://docs.aws.amazon.com/AmazonS3/latest/userguide/).

# Create an OTA Update service role
<a name="create-service-role"></a>

The OTA Update service assumes this role to create and manage OTA update jobs on your behalf.<a name="create-service-role-steps"></a>

**To create an OTA service role**

1. Sign in to the [https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/).

1. From the navigation pane, choose **Roles**.

1. Choose **Create role**.

1. Under **Select type of trusted entity**, choose **AWS Service**.

1. Choose **IoT** from the list of AWS services.

1. Under **Select your use case**, choose **IoT**.

1. Choose **Next: Permissions**.

1. Choose **Next: Tags**.

1. Choose **Next: Review**.

1. Enter a role name and description, and then choose **Create role**.

For more information about IAM roles, see [IAM Roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html).

**Important**  
To address the confused deputy security issue, you must follow instructions in the [AWS IoT Core](https://docs.aws.amazon.com/iot/latest/developerguide/cross-service-confused-deputy-prevention.html) guide.<a name="add-ota-permissions"></a>

**To add OTA update permissions to your OTA service role**

1. In the search box on the IAM console page, enter the name of your role, and then choose it from the list.

1. Choose **Attach policies**.

1. In the **Search** box, enter "AmazonFreeRTOSOTAUpdate", select **AmazonFreeRTOSOTAUpdate** from the list of filtered policies, and then choose **Attach policy** to attach the policy to your service role.<a name="add-iam-permissions"></a>

**To add the required IAM permissions to your OTA service role**

1. In the search box on the IAM console page, enter the name of your role, and then choose it from the list.

1. Choose **Add inline policy**.

1. Choose the **JSON** tab.

1. Copy and paste the following policy document into the text box:

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "iam:GetRole",
                   "iam:PassRole"
               ],
               "Resource": "arn:aws:iam::111122223333:role/your_role_name"
           }
       ]
   }
   ```

------

   Make sure that you replace *your\$1account\$1id* with your AWS account ID, and *your\$1role\$1name* with the name of the OTA service role.

1. Choose **Review policy**.

1. Enter a name for the policy, and then choose **Create policy**.

**Note**  
The following procedure isn't required if your Amazon S3 bucket name begins with "afr-ota". If it does, the AWS managed policy `AmazonFreeRTOSOTAUpdate` already includes the required permissions. <a name="add-s3-permissions"></a>

****To add the required Amazon S3 permissions to your OTA service role****

1. In the search box on the IAM console page, enter the name of your role, and then choose it from the list.

1. Choose **Add inline policy**.

1. Choose the **JSON** tab.

1. Copy and paste the following policy document into the box.

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "s3:GetObjectVersion",
                   "s3:GetObject",
                   "s3:PutObject"
               ],
               "Resource": [
                   "arn:aws:s3:::example-bucket/*"
               ]
           }
       ]
   }
   ```

------

   This policy grants your OTA service role permission to read Amazon S3 objects. Make sure that you replace *example-bucket* with the name of your bucket.

1. Choose **Review policy**.

1. Enter a name for the policy, and then choose **Create policy**.

# Create an OTA user policy
<a name="create-ota-user-policy"></a>

You must grant your user permission to perform over-the-air updates. Your user must have permissions to:
+ Access the S3 bucket where your firmware updates are stored.
+ Access certificates stored in AWS Certificate Manager.
+ Access the AWS IoT MQTT-based file delivery feature.
+ Access FreeRTOS OTA updates.
+ Access AWS IoT jobs.
+ Access IAM.
+ Access Code Signing for AWS IoT. See [Grant access to code signing for AWS IoT](code-sign-policy.md).
+ List FreeRTOS hardware platforms.
+ Tag and untag AWS IoT resources.

To grant your user the required permissions, see [IAM Policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html). Also see [Authorizing users and cloud services to use AWS IoT Jobs](https://docs.aws.amazon.com/iot/latest/developerguide/iam-policy-users-jobs.html).

To provide access, add permissions to your users, groups, or roles:
+ Users and groups in AWS IAM Identity Center:

  Create a permission set. Follow the instructions in [Create a permission set](https://docs.aws.amazon.com//singlesignon/latest/userguide/howtocreatepermissionset.html) in the *AWS IAM Identity Center User Guide*.
+ Users managed in IAM through an identity provider:

  Create a role for identity federation. Follow the instructions in [Create a role for a third-party identity provider (federation)](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_roles_create_for-idp.html) in the *IAM User Guide*.
+ IAM users:
  + Create a role that your user can assume. Follow the instructions in [Create a role for an IAM user](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_roles_create_for-user.html) in the *IAM User Guide*.
  + (Not recommended) Attach a policy directly to a user or add a user to a user group. Follow the instructions in [Adding permissions to a user (console)](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_users_change-permissions.html#users_change_permissions-add-console) in the *IAM User Guide*.

# Create a code-signing certificate
<a name="ota-code-sign-cert"></a>

To digitally sign firmware images, you need a code-signing certificate and private key. For testing purposes, you can create a self‐signed certificate and private key. For production environments, purchase a certificate through a well‐known certificate authority (CA).

Different platforms require different types of code-signing certificates. The following sections describe how to create code-signing certificates for different FreeRTOS-qualified platforms.

**Topics**
+ [Creating a code-signing certificate for the Texas Instruments CC3220SF-LAUNCHXL](ota-code-sign-cert-ti.md)
+ [Creating a code-signing certificate for the Espressif ESP32](ota-code-sign-cert-esp.md)
+ [Creating a code-signing certificate for the Nordic nrf52840-dk](ota-code-sign-cert-nordic.md)
+ [Creating a code-signing certificate for the FreeRTOS Windows simulator](ota-code-sign-cert-win.md)
+ [Creating a code-signing certificate for custom hardware](ota-code-sign-cert-other.md)

# Creating a code-signing certificate for the Texas Instruments CC3220SF-LAUNCHXL
<a name="ota-code-sign-cert-ti"></a>

**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).

The SimpleLink Wi-Fi CC3220SF Wireless Microcontroller Launchpad Development Kit supports two certificate chains for firmware code signing:
+ Production (certificate-catalog)

  To use the production certificate chain, you must purchase a commercial code-signing certificate and use the [TI Uniflash tool](http://www.ti.com/tool/UNIFLASH) to set the board to production mode.
+ Testing and development (certificate-playground) 

  The playground certificate chain allows you to try out OTA updates with a self‐signed code-signing certificate.

Use the AWS Command Line Interface to import your code-signing certificate, private key, and certificate chain into AWS Certificate Manager. For more information see [ Installing the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html) in the *AWS Command Line Interface User Guide*.

Download and install the latest version of [SimpleLink CC3220 SDK](http://www.ti.com/tool/download/SIMPLELINK-CC3220-SDK). By default, the files you need are located here:

`C:\ti\simplelink_cc32xx_sdk_version\tools\cc32xx_tools\certificate-playground` (Windows) 

`/Applications/Ti/simplelink_cc32xx_version/tools/cc32xx_tools/certificate-playground` (macOS)

The certificates in the SimpleLink CC3220 SDK are in DER format. To create a self‐signed code-signing certificate, you must convert them to PEM format.

Follow these steps to create a code-signing certificate that is linked to the Texas Instruments playground certificate hierarchy and meets AWS Certificate Manager and Code Signing for AWS IoT criteria.

**Note**  
To create a code signing certificate, install [ OpenSSL](https://www.openssl.org/) on your machine. After you install OpenSSL, make sure that `openssl` is assigned to the OpenSSL executable in your command prompt or terminal environment.

**To create a self‐signed code signing certificate**

1. Open a command prompt or terminal with administrator permissions.

1. In your working directory, use the following text to create a file named `cert_config.txt`. Replace *test\$1signer@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 a private key and certificate signing request (CSR):

   ```
   openssl req -config cert_config.txt -extensions my_exts -nodes -days 365 -newkey rsa:2048 -keyout tisigner.key -out tisigner.csr
   ```

1. Convert the Texas Instruments playground root CA private key from DER format to PEM format.

   The TI playground root CA private key is located here:

   `C:\ti\simplelink_cc32xx_sdk_version\tools\cc32xx_tools\certificate-playground\dummy-root-ca-cert-key` (Windows) 

   `/Applications/Ti/simplelink_cc32xx_sdk_version/tools/cc32xx_tools/certificate-playground/dummy-root-ca-cert-key` (macOS)

   ```
   openssl rsa -inform DER -in dummy-root-ca-cert-key -out dummy-root-ca-cert-key.pem
   ```

1. Convert the Texas Instruments playground root CA certificate from DER format to PEM format.

   The TI playground root certificate is located here:

   `C:\ti\simplelink_cc32xx_sdk_version\tools\cc32xx_tools\certificate-playground/dummy-root-ca-cert` (Windows) 

   `/Applications/Ti/simplelink_cc32xx_sdk_version/tools/cc32xx_tools/certificate-playground/dummy-root-ca-cert` (macOS)

   ```
   openssl x509 -inform DER -in dummy-root-ca-cert -out dummy-root-ca-cert.pem
   ```

1. Sign the CSR with the Texas Instruments root CA:

   ```
   openssl x509 -extfile cert_config.txt -extensions my_exts  -req -days 365 -in tisigner.csr -CA dummy-root-ca-cert.pem -CAkey dummy-root-ca-cert-key.pem -set_serial 01 -out tisigner.crt.pem -sha1
   ```

1. Convert your code-signing certificate (`tisigner.crt.pem`) to DER format: 

   ```
   openssl x509 -in tisigner.crt.pem -out tisigner.crt.der -outform DER
   ```
**Note**  
You write the `tisigner.crt.der` certificate onto the TI development board later.

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

   ```
   aws acm import-certificate --certificate fileb://tisigner.crt.pem --private-key fileb://tisigner.key --certificate-chain fileb://dummy-root-ca-cert.pem
   ```

   This command displays an ARN for your certificate. You need this ARN when you create an OTA update job.
**Note**  
This step is written with the assumption that you are going to use Code Signing for AWS IoT to sign your firmware images. Although the use of Code Signing for AWS IoT is recommended, you can sign your firmware images manually.

# Creating a code-signing certificate for the Espressif ESP32
<a name="ota-code-sign-cert-esp"></a>

**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).

The Espressif ESP32 boards support a self-signed SHA-256 with ECDSA code-signing certificate.

**Note**  
To create a code signing certificate, install [ OpenSSL](https://www.openssl.org/) on your machine. After you install OpenSSL, make sure that `openssl` is assigned to the OpenSSL executable in your command prompt or terminal environment.  
Use the AWS Command Line Interface to import your code-signing certificate, private key, and certificate chain into AWS Certificate Manager. For information about installing the AWS CLI, see [Installing the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html).

1. In your working directory, use the following text to create a file named `cert_config.txt`. Replace *test\$1signer@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.key
   ```

1. Create an ECDSA code-signing certificate:

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

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

   ```
   aws acm import-certificate --certificate fileb://ecdsasigner.crt --private-key fileb://ecdsasigner.key
   ```

   This command displays an ARN for your certificate. You need this ARN when you create an OTA update job.
**Note**  
This step is written with the assumption that you are going to use Code Signing for AWS IoT to sign your firmware images. Although the use of Code Signing for AWS IoT is recommended, you can sign your firmware images manually.

# Creating a code-signing certificate for the Nordic nrf52840-dk
<a name="ota-code-sign-cert-nordic"></a>

**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).

The Nordic nrf52840-dk supports a self-signed SHA256 with ECDSA code-signing certificate.

**Note**  
To create a code signing certificate, install [OpenSSL](https://www.openssl.org/) on your machine. After you install OpenSSL, make sure that `openssl` is assigned to the OpenSSL executable in your command prompt or terminal environment.  
Use the AWS Command Line Interface to import your code-signing certificate, private key, and certificate chain into AWS Certificate Manager. For information about installing the AWS CLI, see [Installing the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html).

1. In your working directory, use the following text to create a file named `cert_config.txt`. Replace *test\$1signer@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.key
   ```

1. Create an ECDSA code-signing certificate:

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

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

   ```
   aws acm import-certificate --certificate fileb://ecdsasigner.crt --private-key fileb://ecdsasigner.key
   ```

   This command displays an ARN for your certificate. You need this ARN when you create an OTA update job.
**Note**  
This step is written with the assumption that you are going to use Code Signing for AWS IoT to sign your firmware images. Although the use of Code Signing for AWS IoT is recommended, you can sign your firmware images manually.

# Creating a code-signing certificate for the FreeRTOS Windows simulator
<a name="ota-code-sign-cert-win"></a>

The FreeRTOS Windows simulator requires a code-signing certificate with an ECDSA P-256 key and SHA-256 hash to perform OTA updates. If you don't have a code-signing certificate, follow these steps to create one.

**Note**  
To create a code-signing certificate, install [ OpenSSL](https://www.openssl.org/) on your machine. After you install OpenSSL, make sure that `openssl` is assigned to the OpenSSL executable in your command prompt or terminal environment.  
Use the AWS Command Line Interface to import your code-signing certificate, private key, and certificate chain into AWS Certificate Manager. For information about installing the AWS CLI, see [Installing the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html).

1. In your working directory, use the following text to create a file named `cert_config.txt`. Replace *test\$1signer@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.key
   ```

1. Create an ECDSA code-signing certificate:

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

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

   ```
   aws acm import-certificate --certificate fileb://ecdsasigner.crt --private-key fileb://ecdsasigner.key
   ```

   This command displays an ARN for your certificate. You need this ARN when you create an OTA update job.
**Note**  
This step is written with the assumption that you are going to use Code Signing for AWS IoT to sign your firmware images. Although the use of Code Signing for AWS IoT is recommended, you can sign your firmware images manually.

# Creating a code-signing certificate for custom hardware
<a name="ota-code-sign-cert-other"></a>

Using an appropriate toolset, create a self-signed certificate and private key for your hardware.

Use the AWS Command Line Interface to import your code-signing certificate, private key, and certificate chain into AWS Certificate Manager. For information about installing the AWS CLI, see [ Installing the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html).

After you create your code-signing certificate, you can use the AWS CLI to import it into ACM:

```
aws acm import-certificate --certificate fileb://code-sign.crt --private-key fileb://code-sign.key
```

The output from this command displays an ARN for your certificate. You need this ARN when you create an OTA update job.

ACM requires certificates to use specific algorithms and key sizes. For more information, see [Prerequisites for Importing Certificates](https://docs.aws.amazon.com/acm/latest/userguide/import-certificate-prerequisites.html). For more information about ACM, see [Importing Certificates into AWS Certificate Manager](https://docs.aws.amazon.com/acm/latest/userguide/import-certificate.html).

You must copy, paste, and format the contents of your code-signing certificate into the `vendors/vendor/boards/board/aws_demos/config_files/ota_demo_config.h` file that is part of the FreeRTOS code you download later.

# Grant access to code signing for AWS IoT
<a name="code-sign-policy"></a>

To provide access, add permissions to your users, groups, or roles:
+ Users and groups in AWS IAM Identity Center:

  Create a permission set. Follow the instructions in [Create a permission set](https://docs.aws.amazon.com//singlesignon/latest/userguide/howtocreatepermissionset.html) in the *AWS IAM Identity Center User Guide*.
+ Users managed in IAM through an identity provider:

  Create a role for identity federation. Follow the instructions in [Create a role for a third-party identity provider (federation)](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_roles_create_for-idp.html) in the *IAM User Guide*.
+ IAM users:
  + Create a role that your user can assume. Follow the instructions in [Create a role for an IAM user](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_roles_create_for-user.html) in the *IAM User Guide*.
  + (Not recommended) Attach a policy directly to a user or add a user to a user group. Follow the instructions in [Adding permissions to a user (console)](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_users_change-permissions.html#users_change_permissions-add-console) in the *IAM User Guide*.

# Download FreeRTOS with the OTA library
<a name="ota-download-freertos"></a>

You can clone or download FreeRTOS from [GitHub](https://github.com/freertos/freertos). See the [README.md](https://github.com/freertos/freertos/blob/main/README.md) file for instructions.

For information about setting up and running the OTA demo application, see [Over-the-air updates demo application](ota-demo.md).

**Important**  
In this topic, the path to the FreeRTOS download directory is referred to as `freertos`.
Space characters in the `freertos` path can cause build failures. When you clone or copy the repository, make sure the path you that create doesn't contain space characters.
The maximum length of a file path on Microsoft Windows is 260 characters. Long FreeRTOS download directory paths can cause build failures.
Because the source code may contain symbolic links, if you're using Windows to extract the archive, you may have to:  
Enable [ Developer Mode](https://docs.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development) or, 
Use a console that is elevated as administrator.
In this way, Windows can properly create symbolic links when it extracts the archive. Otherwise, symbolic links will be written as normal files that contain the paths of the symbolic links as text or are empty. For more information, see the blog entry [ Symlinks in Windows 10\$1](https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10/).  
If you use Git under Windows, you must enable Developer Mode or you must:   
Set `core.symlinks` to true with the following command:  

    ```
    git config --global core.symlinks true
    ```
Use a console that is elevated as administrator whenever you use a git command that writes to the system (for example, **git pull**, **git clone**, and **git submodule update --init --recursive**).

# Prerequisites for OTA updates using MQTT
<a name="ota-mqtt-freertos"></a>

This section describes the general requirements for using MQTT to perform over-the-air (OTA updates).

## Minimum requirements
<a name="ota-mqtt-freertos-min-requirements"></a>
+ Device firmware must include the necessary FreeRTOS libraries (coreMQTT Agent, OTA update, and their dependencies).
+ FreeRTOS version 1.4.0 or later is required. However, we recommend that you use the latest version when possible.

## Configurations
<a name="ota-mqtt-freertos-config"></a>

Beginning with version 201912.00, FreeRTOS OTA can use either the HTTP or MQTT protocol to transfer firmware update images from AWS IoT to devices. If you specify both protocols when you create an OTA update in FreeRTOS, each device will determine the protocol used to transfer the image. See [Prerequisites for OTA updates using HTTP](ota-http-freertos.md) for more information.

By default, the configuration of the OTA protocols in [https://github.com/aws/amazon-freertos/blob/main/vendors/vendor/boards/board/aws_demos/config_files/ota_config.h](https://github.com/aws/amazon-freertos/blob/main/vendors/vendor/boards/board/aws_demos/config_files/ota_config.h) is to use the MQTT protocol.

## Device specific configurations
<a name="ota-mqtt-freertos-dev-config"></a>

None.

## Memory usage
<a name="ota-mqtt-freertos-memory"></a>

When MQTT is used for data transfer, no additional memory is required for the MQTT connection because it's shared between control and data operations. 

## Device policy
<a name="ota-mqtt-freertos-device-policy"></a>

Each device that receives an OTA update using MQTT must be registered as a thing in AWS IoT and the thing must have an attached policy like the one listed here. You can find more information about the items in the `"Action"` and `"Resource"` objects at [AWS IoT Core Policy Actions](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policy-actions.html) and [AWS IoT Core Action Resources](https://docs.aws.amazon.com/iot/latest/developerguide/iot-action-resources.html).

**Notes**
+ The `iot:Connect` permissions allow your device to connect to AWS IoT over MQTT.
+ The `iot:Subscribe` and `iot:Publish` permissions on the topics of AWS IoT jobs (`.../jobs/*`) allow the connected device to receive job notifications and job documents, and to publish the completion state of a job execution.
+ The `iot:Subscribe` and `iot:Publish` permissions on the topics of AWS IoT OTA streams (`.../streams/*`) allow the connected device to fetch OTA update data from AWS IoT. These permissions are required to perform firmware updates over MQTT.
+ The `iot:Receive` permissions allow AWS IoT Core to publish messages on those topics to the connected device. This permission is checked on every delivery of an MQTT message. You can use this permission to revoke access to clients that are currently subscribed to a topic.

# Prerequisites for OTA updates using HTTP
<a name="ota-http-freertos"></a>

This section describes the general requirements for using HTTP to perform over-the-air (OTA) updates. Beginning with version 201912.00, FreeRTOS OTA can use either the HTTP or MQTT protocol to transfer firmware update images from AWS IoT to devices. 

**Note**  
Although the HTTP protocol might be used to transfer the firmware image, the coreMQTT Agent library is still required because other interactions with AWS IoT Core use the coreMQTT Agent library, including sending or receiving job execution notifications, job documents, and execution status updates. 
When you specify both MQTT and HTTP protocols for the OTA update job, the setup of the OTA Agent software on each individual device determines the protocol used to transfer the firmware image. To change the OTA Agent from the default MQTT protocol method to the HTTP protocol, you can modify the header files used to compile the FreeRTOS source code for the device.

## Minimum requirements
<a name="ota-http-freertos-min-requirements"></a>
+ Device firmware must include the necessary FreeRTOS libraries (coreMQTT Agent, HTTP, OTA Agent, and their dependencies).
+ FreeRTOS version 201912.00 or later is required to change the configuration of the OTA protocols to enable OTA data transfer over HTTP.

## Configurations
<a name="ota-http-freertos-config"></a>

See the following configuration of the OTA protocols in the [https://github.com/aws/amazon-freertos/blob/main/vendors/vendor/boards/board/aws_demos/config_files/ota_config.h](https://github.com/aws/amazon-freertos/blob/main/vendors/vendor/boards/board/aws_demos/config_files/ota_config.h) file.

**To enable OTA data transfer over HTTP**

1. Change `configENABLED_DATA_PROTOCOLS` to `OTA_DATA_OVER_HTTP`.

1. When the OTA updates, you can specify both protocols so that either MQTT or HTTP protocol can be used., You can set the primary protocol used by the device to HTTP by changing `configOTA_PRIMARY_DATA_PROTOCOL` to `OTA_DATA_OVER_HTTP`. 

**Note**  
HTTP is only supported for OTA data operations. For control operations, you must use MQTT.

## Device specific configurations
<a name="ota-http-freertos-device-configuration"></a>

**ESP32**  
Due to a limited amount of RAM, you must turn off BLE when you enable HTTP as an OTA data protocol. In the [https://github.com/aws/amazon-freertos/blob/main/vendors/espressif/boards/esp32/aws_demos/config_files/aws_iot_network_config.h](https://github.com/aws/amazon-freertos/blob/main/vendors/espressif/boards/esp32/aws_demos/config_files/aws_iot_network_config.h) file, change `configENABLED_NETWORKS` to `AWSIOT_NETWORK_TYPE_WIFI` only.  

```
/**
     * @brief Configuration flag which is used to enable one or more network interfaces for a board.
     *
     * The configuration can be changed any time to keep one or more network enabled or disabled.
     * More than one network interfaces can be enabled by using 'OR' operation with flags for
     * each network types supported. Flags for all supported network types can be found
     * in "aws_iot_network.h"
     *
     */
    #define configENABLED_NETWORKS      ( AWSIOT_NETWORK_TYPE_WIFI )
```

## Memory usage
<a name="ota-http-freertos-memory"></a>

When MQTT is used for data transfer, no additional heap memory is required for the MQTT connection because it's shared between control and data operations. However, enabling data over HTTP requires additional heap memory. The following is the heap memory usage data for all supported platforms, calculated using the FreeRTOS `xPortGetFreeHeapSize` API. You must make sure there is enough RAM to use the OTA library.

****Texas Instruments CC3220SF-LAUNCHXL****  
Control operations (MQTT): 12 KB  
Data operations (HTTP): 10 KB  
 TI uses significantly less RAM because it does SSL on hardware, so it doesn't use the mbedtls library.

****Microchip Curiosity PIC32MZEF****  
Control operations (MQTT): 65 KB  
Data operations (HTTP): 43 KB

****Espressif ESP32****  
Control operations (MQTT): 65 KB  
Data operations (HTTP): 45 KB  
BLE on ESP32 takes about 87 KB RAM. There's not enough RAM to enable all of them, which is mentioned in the device specific configurations above.

****Windows simulator****  
Control operations (MQTT): 82 KB   
Data operations (HTTP): 63 KB 

****Nordic nrf52840-dk****  
HTTP is not supported.

## Device policy
<a name="ota-http-freertos-device-policy"></a>

This policy allows you to use either MQTT or HTTP for OTA updates.

Each device that receives an OTA update using HTTP must be registered as a thing in AWS IoT and the thing must have an attached policy like the one listed here. You can find more information about the items in the `"Action"` and `"Resource"` objects at [AWS IoT Core Policy Actions](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policy-actions.html) and [AWS IoT Core Action Resources](https://docs.aws.amazon.com/iot/latest/developerguide/iot-action-resources.html).

**Notes**
+ The `iot:Connect` permissions allow your device to connect to AWS IoT over MQTT. 
+ The `iot:Subscribe` and `iot:Publish` permissions on the topics of AWS IoT jobs (`.../jobs/*`) allow the connected device to receive job notifications and job documents, and to publish the completion state of a job execution.
+ The `iot:Receive` permissions allow AWS IoT Core to publish messages on those topics to the current connected device. This permission is checked on every delivery of an MQTT message. You can use this permission to revoke access to clients that are currently subscribed to a topic.

# OTA tutorial
<a name="dev-guide-ota-workflow"></a>

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
<a name="dg-ota-initial-firmware"></a>

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
<a name="burn-initial-firmware-ti"></a>

**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
<a name="burn-initial-firmware-esp"></a>

**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
<a name="burn-initial-firmware-nordic"></a>

**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
<a name="burn-initial-firmware-windows"></a>

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
<a name="burn-initial-firmware-other"></a>

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
<a name="dg-ota-update-firmware"></a>

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)
<a name="ota-console-workflow"></a>

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
<a name="ota-cli-workflow"></a>

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
<a name="ota-sign-cli"></a>

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
<a name="ota-sign-csfa"></a>

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
<a name="ota-sign-manual"></a>

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

## Creating a stream of your firmware update
<a name="ota-stream"></a>

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
<a name="create-ota-update"></a>

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
<a name="list-ota-updates"></a>

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
<a name="get-ota-updates"></a>

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
<a name="delete-ota-data"></a>

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
<a name="delete-ota-stream"></a>

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
<a name="delete-ota-update"></a>

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
<a name="delete-ota-job"></a>

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).

# OTA Update Manager service
<a name="ota-manager"></a>

The over-the-air (OTA) Update Manager service provides a way to:
+ Create an OTA update and the resources it uses, including an AWS IoT job, an AWS IoT stream, and code signing.
+ Get information about an OTA update. 
+ List all OTA updates associated with your AWS account.
+ Delete an OTA update.

An OTA update is a data structure maintained by the OTA Update Manager service. It contains:
+ An OTA update ID.
+ An optional OTA update description.
+ A list of devices to update (*targets*).
+ The type of OTA update: CONTINUOUS or SNAPSHOT. See the [Jobs](https://docs.aws.amazon.com/iot/latest/developerguide/iot-jobs.html) section of the *AWS IoT Developer Guide* for a discussion of the type of update that you need.
+ The protocol used to perform the OTA update: [MQTT], [HTTP] or [MQTT, HTTP]. When you specify MQTT and HTTP, the device setup determines the protocol used.
+ A list of files to send to the target devices.
+ 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.
+ An optional list of user-defined name-value pairs.

OTA updates were designed to update device firmware, but you can use them to send any files that you want to one or more devices registered with AWS IoT. When you send firmware updates over the air, we recommend that you digitally sign them so that the devices that receive them can verify they haven't been tampered with en route.

You can send updated firmware images using the HTTP or MQTT protocol, depending on the settings that you choose. You can sign your firmware updates with [Code Signing for FreeRTOS](https://docs.aws.amazon.com/signer/latest/developerguide/Welcome.html) or you can use your own code-signing tools.

For more control over the process, you can use the [ CreateStream](https://docs.aws.amazon.com/iot/latest/apireference/API_CreateStream.html) API to create a stream when sending updates over MQTT. In some instances, you can modify the FreeRTOS Agent [code](https://github.com/aws/amazon-freertos/tree/202012.00/libraries/freertos_plus/aws/ota/src) to adjust the size of the blocks that you send and receive.

When you create an OTA update, the OTA Manager service creates an [AWS IoT job](https://docs.aws.amazon.com/iot/latest/developerguide/iot-jobs.html) to notify your devices that an update is available. The FreeRTOS OTA Agent runs on your devices and listens for update messages. When an update is available, it requests the firmware update image over HTTP or MQTT and stores the files locally. It checks the digital signature of the downloaded files and, if valid, installs the firmware update. If you're not using FreeRTOS, you must implement your own OTA Agent to listen for and download updates and perform any installation operations.

# Integrating the OTA Agent into your application
<a name="integrate-ota-agent"></a>

The over-the-air (OTA) Agent is designed to simplify the amount of code you must write to add OTA update functionality to your product. That integration burden consists primarily of initialization of the OTA Agent and creating a custom callback function for responding to the OTA Agent event messages. During initialization OS, MQTT, HTTP (if HTTP is used for file download) and platform specific implementation (PAL) interfaces are passed to the OTA Agent. Buffers can also be initialized and passed to the OTA Agent.

**Note**  
Although the integration of the OTA update feature into your application is rather simple, the OTA update system requires an understanding of more than just device code integration. To familiarize yourself with how to configure your AWS account with AWS IoT things, credentials, code-signing certificates, provisioning devices, and OTA update jobs, see [FreeRTOS Prerequisites](https://docs.aws.amazon.com/freertos/latest/userguide/freertos-prereqs.html). 

## Connection management
<a name="ota-agent-http-mqtt"></a>

The OTA Agent uses the MQTT protocol for all control communication operations involving AWS IoT services, but it doesn't manage the MQTT connection. To ensure that the OTA Agent doesn't interfere with the connection management policy of your application, the MQTT connection (including disconnect and any reconnect functionality) must be handled by the main user application. The file can be downloaded over the MQTT or HTTP protocol. You can choose which protocol when you create the OTA job. If you choose MQTT, the OTA Agent uses the same connection for control operations and for downloading files.

## Simple OTA demo
<a name="simple-demo-agent"></a>

The following is an excerpt of a simple OTA demo that shows you how the Agent connects to the MQTT broker and initializes the OTA Agent. In this example, we configure the demo to use the default OTA application callback and to return some statistics once per second. For brevity, we leave out some details from this demo.

The OTA demo also demonstrates MQTT connection management by monitoring the disconnect callback and reestablishing the connection. When a disconnect happens, the demo first suspends the OTA Agent operations and then attempts to reestablish the MQTT connection. The MQTT reconnection attempts are delayed by a time which is exponentially increased up to a maximum value and a jitter is also added. If the connection is reestablished, the OTA Agent continues its operations. 

For a working example that uses the AWS IoT MQTT broker, see the OTA demo code in the `demos/ota` directory.

Because the OTA Agent is its own task, the intentional one-second delay in this example affects this application only. It has no impact on the performance of the Agent.

```
static BaseType_t prvRunOTADemo( void )
{
    /* Status indicating a successful demo or not. */
    BaseType_t xStatus = pdFAIL;

    /* OTA library return status. */
    OtaErr_t xOtaError = OtaErrUninitialized;

    /* OTA event message used for sending event to OTA Agent.*/
    OtaEventMsg_t xEventMsg = { 0 };

    /* OTA interface context required for library interface functions.*/
    OtaInterfaces_t xOtaInterfaces;

    /* OTA library packet statistics per job.*/
    OtaAgentStatistics_t xOtaStatistics = { 0 };

    /* OTA Agent state returned from calling OTA_GetState.*/
    OtaState_t xOtaState = OtaAgentStateStopped;

    /* Set OTA Library interfaces.*/
    prvSetOtaInterfaces( &xOtaInterfaces );

    /*************************** Init OTA Library. ***************************/

    if( ( xOtaError = OTA_Init( &xOtaBuffer,
                                &xOtaInterfaces,
                                ( const uint8_t * ) ( democonfigCLIENT_IDENTIFIER ),
                                prvOtaAppCallback ) ) != OtaErrNone )
    {
        LogError( ( "Failed to initialize OTA Agent, exiting = %u.",
                    xOtaError ) );
    }
    else
    {
        xStatus = pdPASS;
    }

    /************************ Create OTA Agent Task. ************************/

    if( xStatus == pdPASS )
    {
        xStatus = xTaskCreate( prvOTAAgentTask,
                               "OTA Agent Task",
                               otaexampleAGENT_TASK_STACK_SIZE,
                               NULL,
                               otaexampleAGENT_TASK_PRIORITY,
                               NULL );

        if( xStatus != pdPASS )
        {
            LogError( ( "Failed to create OTA agent task:" ) );
        }
    }

    /****************************** Start OTA ******************************/

    if( xStatus == pdPASS )
    {
        /* Send start event to OTA Agent.*/
        xEventMsg.eventId = OtaAgentEventStart;
        OTA_SignalEvent( &xEventMsg );
    }

    /******************** Loop and display OTA statistics ********************/

    if( xStatus == pdPASS )
    {
        while( ( xOtaState = OTA_GetState() ) != OtaAgentStateStopped )
        {
            /* Get OTA statistics for currently executing job. */
            if( xOtaState != OtaAgentStateSuspended )
            {
                OTA_GetStatistics( &xOtaStatistics );

                LogInfo( ( " Received: %u   Queued: %u   Processed: %u   Dropped: %u",
                           xOtaStatistics.otaPacketsReceived,
                           xOtaStatistics.otaPacketsQueued,
                           xOtaStatistics.otaPacketsProcessed,
                           xOtaStatistics.otaPacketsDropped ) );
            }

            vTaskDelay( pdMS_TO_TICKS( otaexampleEXAMPLE_TASK_DELAY_MS ) );
        }
    }

    return xStatus;
}
```

Here is the high-level flow of this demo application:
+ Create an MQTT Agent context.
+ Connect to your AWS IoT endpoint.
+ Initialize the OTA Agent.
+ Loop that allows an OTA update job and outputs statistics once a second.
+ If MQTT disconnects, suspend the OTA Agent operations.
+ Try connecting again with exponential delay and jitter.
+ If reconnected, resume OTA Agent operations.
+ If the Agent stops, delay one second, and then try reconnecting.

## Using application callback for OTA Agent events
<a name="application-callback-ota"></a>

The previous example used `prvOtaAppCallback` as the callback handler for OTA Agent events. (See the fourth parameter to the `OTA_Init` API call). If you want to implement custom handling of the completion events, you must change the default handling in the OTA demo/application. During the OTA process, the OTA Agent can send one of the following event enums to the callback handler. It is up to the application developer to decide how and when to handle these events.

```
/**
 * @ingroup ota_enum_types
 * @brief OTA Job callback events.
 *
 * After an OTA update image is received and authenticated, the agent calls the user
 * callback (set with the @ref OTA_Init API) with the value OtaJobEventActivate to
 * signal that the device must be rebooted to activate the new image. When the device
 * boots, if the OTA job status is in self test mode, the agent calls the user callback
 * with the value OtaJobEventStartTest, signaling that any additional self tests
 * should be performed.
 *
 * If the OTA receive fails for any reason, the agent calls the user callback with
 * the value OtaJobEventFail instead to allow the user to log the failure and take
 * any action deemed appropriate by the user code.
 *
 * See the OtaImageState_t type for more information.
 */
typedef enum OtaJobEvent
{
    OtaJobEventActivate = 0,       /*!< @brief OTA receive is authenticated and ready to activate. */
    OtaJobEventFail = 1,           /*!< @brief OTA receive failed. Unable to use this update. */
    OtaJobEventStartTest = 2,      /*!< @brief OTA job is now in self test, perform user tests. */
    OtaJobEventProcessed = 3,      /*!< @brief OTA event queued by OTA_SignalEvent is processed. */
    OtaJobEventSelfTestFailed = 4, /*!< @brief OTA self-test failed for current job. */
    OtaJobEventParseCustomJob = 5, /*!< @brief OTA event for parsing custom job document. */
    OtaJobEventReceivedJob = 6,    /*!< @brief OTA event when a new valid AFT-OTA job is received. */
    OtaJobEventUpdateComplete = 7, /*!< @brief OTA event when the update is completed. */
    OtaLastJobEvent = OtaJobEventStartTest
} OtaJobEvent_t;
```

The OTA Agent can receive an update in the background during active processing of the main application. The purpose of delivering these events is to allow the application to decide if action can be taken immediately or if it should be deferred until after completion of some other application-specific processing. This prevents an unanticipated interruption of your device during active processing (for example, vacuuming) that would be caused by a reset after a firmware update. These are the job events received by the callback handler:

**`OtaJobEventActivate `**  
When the callback handler receives this event, you can either reset the device immediately or schedule a call to reset the device later. This allows you to postpone the device reset and self-test phase, if necessary.

**`OtaJobEventFail`**  
When the callback handler receives this event, the update has failed. You do not need to do anything in this case. You might want to output a log message or do something application-specific.

**`OtaJobEventStartTest`**  
The self-test phase is meant to allow newly updated firmware to execute and test itself before it determines whether it is functioning properly and commit itself to be the latest permanent application image. When a new update is received and authenticated and the device has been reset, the OTA Agent sends the `OtaJobEventStartTest` event to the callback function when it is ready for testing. The developer can add any required tests to determine if the device firmware is functioning properly after update. When the device firmware is deemed reliable by the self tests, the code must commit the firmware as the new permanent image by calling the `OTA_SetImageState( OtaImageStateAccepted )` function.

**`OtaJobEventProcessed`**  
The OTA event queued by `OTA_SignalEvent` is processed, so cleanup operations like freeing the OTA buffers can be done.

**`OtaJobEventSelfTestFailed`**  
The OTA self-test failed for the current job. The default handling for this event is to shut down the OTA Agent and restart it so that the device rolls back to the previous image.

**`OtaJobEventUpdateComplete`**  
The notification event for OTA job update completion.

# OTA security
<a name="dev-guide-ota-security"></a>

The following are three aspects of over-the-air (OTA) security:

**Connection security**  
The OTA Update Manager service relies on existing security mechanisms, such as Transport Layer Security (TLS) mutual authentication, used by AWS IoT. OTA update traffic passes through the AWS IoT device gateway and uses AWS IoT security mechanisms. Each incoming and outgoing HTTP or MQTT message through the device gateway undergoes strict authentication and authorization.

**Authenticity and integrity of OTA updates**  
Firmware can be digitally signed before an OTA update to ensure that it is from a reliable source and has not been tampered with.   
The FreeRTOS OTA Update Manager service uses Code Signing for AWS IoT to automatically sign your firmware. For more information, see [Code Signing for AWS IoT](https://docs.aws.amazon.com/signer/latest/developerguide/Welcome.html).   
The OTA Agent, which runs on your devices, performs integrity checks on the firmware when it arrives on the device.

**Operator security**  
Every API call made through the control plane API undergoes standard IAM Signature Version 4 authentication and authorization. To create a deployment, you must have permissions to invoke the `CreateDeployment`, `CreateJob`, and `CreateStream` APIs. In addition, in your Amazon S3 bucket policy or ACL, you must give read permissions to the AWS IoT service principal so that the firmware update stored in Amazon S3 can be accessed during streaming. 

## Code Signing for AWS IoT
<a name="dev-guide-code-signing"></a>

The AWS IoT console uses [Code Signing for AWS IoT](https://docs.aws.amazon.com/signer/latest/developerguide/Welcome.html) to automatically sign your firmware image for any device supported by AWS IoT.

Code Signing for AWS IoT uses a certificate and private key that you import into ACM. You can use a self–signed certificate for testing, but we recommend that you obtain a certificate from a well–known commercial certificate authority (CA).

Code–signing certificates use the X.509 version 3 `Key Usage` and `Extended Key Usage` extensions. The `Key Usage` extension is set to `Digital Signature` and the `Extended Key Usage` extension is set to `Code Signing`. For more information about signing your code image, see the [Code Signing for AWS IoT Developer Guide](https://docs.aws.amazon.com/signer/latest/developerguide/Welcome.html) and the [Code Signing for AWS IoT API Reference](https://docs.aws.amazon.com/signer/latest/api/Welcome.html).

**Note**  
You can download the Code Signing for AWS IoT SDK from [Tools for Amazon Web Services](https://aws.amazon.com/tools/). 

# OTA troubleshooting
<a name="ota-troubleshooting"></a>

The following sections contain information to help you troubleshoot issues with OTA updates.

**Topics**
+ [Set up CloudWatch Logs for OTA updates](ota-logging.md)
+ [Log AWS IoT OTA API calls with AWS CloudTrail](iot-using-cloudtrail-afr.md)
+ [Get CreateOTAUpdate failure details using the AWS CLI](ota-create-failure.md)
+ [Get OTA failure codes with the AWS CLI](ota-failure-codes.md)
+ [Troubleshoot OTA updates of multiple devices](ota-troubleshooting-multi-thing.md)
+ [Troubleshoot OTA updates with the Texas Instruments CC3220SF Launchpad](ota-troubleshooting-ti.md)

# Set up CloudWatch Logs for OTA updates
<a name="ota-logging"></a>

The OTA Update service supports logging with Amazon CloudWatch. You can use the AWS IoT console to enable and configure Amazon CloudWatch logging for OTA updates. For more information, see [Cloudwatch Logs](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html).

To enable logging, you must create an IAM role and configure OTA update logging.

**Note**  
Before you enable OTA update logging, make sure you understand the CloudWatch Logs access permissions. Users with access to CloudWatch Logs can see your debugging information. For information, see [Authentication and Access Control for Amazon CloudWatch Logs](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/auth-and-access-control-cwl.html).

## Create a logging role and enable logging
<a name="create-ota-logging-role"></a>

Use the [AWS IoT console](https://console.aws.amazon.com/iot/home) to create a logging role and enable logging.

1. From the navigation pane, choose **Settings**.

1. Under **Logs**, choose **Edit**.

1. Under **Level of verbosity**, choose **Debug**.

1. Under **Set role**, choose **Create new** to create an IAM role for logging.

1. Under **Name**, enter a unique name for your role. Your role will be created with all required permissions.

1. Choose **Update**.

## OTA update logs
<a name="ota-logs"></a>

The OTA Update service publishes logs to your account when one of the following occurs:
+ An OTA update is created.
+ An OTA update is completed.
+ A code-signing job is created.
+ A code-signing job is completed.
+ An AWS IoT job is created.
+ An AWS IoT job is completed.
+ A stream is created.

You can view your logs in the [CloudWatch console.](https://console.aws.amazon.com/cloudwatch/home)

**To view an OTA update in CloudWatch Logs**

1. From the navigation pane, choose **Logs**.

1. In **Log Groups**, choose **AWSIoTLogsV2**.

OTA update logs can contain the following properties:

**accountId**  
The AWS account ID in which the log was generated.

**actionType**  
The action that generated the log. This can be set to one of the following values:  
+ `CreateOTAUpdate`: An OTA update was created.
+ `DeleteOTAUpdate`: An OTA update was deleted.
+ `StartCodeSigning`: A code-signing job was started.
+ `CreateAWSJob`: An AWS IoT job was created.
+ `CreateStream`: A stream was created.
+ `GetStream`: A request for a stream was sent to the AWS IoT MQTT-based file delivery feature.
+ `DescribeStream`: A request for information about a stream was sent to the AWS IoT MQTT-based file delivery feature.

**awsJobId**  
The AWS IoT job ID that generated the log.

**clientId**  
The MQTT client ID that made the request that generated the log.

**clientToken**  
The client token associated with the request that generated the log.

**details**  
More information about the operation that generated the log.

**logLevel**  
The logging level of the log. For OTA update logs, this is always set to `DEBUG`.

**otaUpdateId**  
The ID of the OTA update that generated the log.

**protocol**  
The protocol used to make the request that generated the log.

**status**  
The status of the operation that generated the log. Valid values are:  
+ Success
+ Failure

**streamId**  
The AWS IoT stream ID that generated the log.

**timestamp**  
The time when the log was generated.

**topicName**  
An MQTT topic used to make the request that generated the log.

### Example logs
<a name="ota-example-logs"></a>

The following is an example log generated when a code-signing job is started:

```
{ 
    "timestamp": "2018-07-23 22:59:44.955", 
    "logLevel": "DEBUG", 
    "accountId": "123456789012", 
    "status": "Success", 
    "actionType": "StartCodeSigning", 
    "otaUpdateId": "08957b03-eea3-448a-87fe-743e6891ca3a", 
    "details": "Start code signing job. The request status is SUCCESS." 
}
```

The following is an example log generated when an AWS IoT job is created:

```
{ 
    "timestamp": "2018-07-23 22:59:45.363", 
    "logLevel": "DEBUG", 
    "accountId": "123456789012", 
    "status": "Success", 
    "actionType": "CreateAWSJob", 
    "otaUpdateId": "08957b03-eea3-448a-87fe-743e6891ca3a", 
    "awsJobId": "08957b03-eea3-448a-87fe-743e6891ca3a", 
    "details": "Create AWS Job The request status is SUCCESS." 
}
```

The following is an example log generated when an OTA update is created:

```
{ 
    "timestamp": "2018-07-23 22:59:45.413", 
    "logLevel": "DEBUG", 
    "accountId": "123456789012", 
    "status": "Success", 
    "actionType": "CreateOTAUpdate", 
    "otaUpdateId": "08957b03-eea3-448a-87fe-743e6891ca3a", 
    "details": "OTAUpdate creation complete. The request status is SUCCESS." 
}
```

The following is an example log generated when a stream is created:

```
{ 
    "timestamp": "2018-07-23 23:00:26.391", 
    "logLevel": "DEBUG", 
    "accountId": "123456789012", 
    "status": "Success", 
    "actionType": "CreateStream", 
    "otaUpdateId": "3d3dc5f7-3d6d-47ac-9252-45821ac7cfb0", 
    "streamId": "6be2303d-3637-48f0-ace9-0b87b1b9a824", 
    "details": "Create stream. The request status is SUCCESS." 
}
```

The following is an example log generated when an OTA update is deleted:

```
{ 
    "timestamp": "2018-07-23 23:03:09.505", 
    "logLevel": "DEBUG", 
    "accountId": "123456789012", 
    "status": "Success", 
    "actionType": "DeleteOTAUpdate", 
    "otaUpdateId": "9bdd78fb-f113-4001-9675-1b595982292f", 
    "details": "Delete OTA Update. The request status is SUCCESS." 
}
```

The following is an example log generated when a device requests a stream from the MQTT-based file delivery feature:

```
{ 
    "timestamp": "2018-07-25 22:09:02.678", 
    "logLevel": "DEBUG", 
    "accountId": "123456789012", 
    "status": "Success", 
    "actionType": "GetStream", 
    "protocol": "MQTT", 
    "clientId": "b9d2e49c-94fe-4ed1-9b07-286afed7e4c8", 
    "topicName": "$aws/things/b9d2e49c-94fe-4ed1-9b07-286afed7e4c8/streams/1e51e9a8-9a4c-4c50-b005-d38452a956af/get/json", 
    "streamId": "1e51e9a8-9a4c-4c50-b005-d38452a956af", 
    "details": "The request status is SUCCESS." 
}
```

The following is an example log generated when a device calls the `DescribeStream` API:

```
{ 
    "timestamp": "2018-07-25 22:10:12.690", 
    "logLevel": "DEBUG", 
    "accountId": "123456789012", 
    "status": "Success", 
    "actionType": "DescribeStream", 
    "protocol": "MQTT", 
    "clientId": "581075e0-4639-48ee-8b94-2cf304168e43", 
    "topicName": "$aws/things/581075e0-4639-48ee-8b94-2cf304168e43/streams/71c101a8-bcc5-4929-9fe2-af563af0c139/describe/json", 
    "streamId": "71c101a8-bcc5-4929-9fe2-af563af0c139", 
    "clientToken": "clientToken", 
    "details": "The request status is SUCCESS." 
}
```

# Log AWS IoT OTA API calls with AWS CloudTrail
<a name="iot-using-cloudtrail-afr"></a>

FreeRTOS is integrated with CloudTrail, a service that captures AWS IoT OTA API calls and delivers the log files to an Amazon S3 bucket that you specify. CloudTrail captures API calls from your code to the AWS IoT OTA APIs. Using the information collected by CloudTrail, you can determine the request that was made to AWS IoT OTA, the source IP address from which the request was made, who made the request, when it was made, and so on. 

For more information about CloudTrail, including how to configure and enable it, see the [https://docs.aws.amazon.com/awscloudtrail/latest/userguide/](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/).

## FreeRTOS information in CloudTrail
<a name="aws-iot-info-in-cloudtrail-afr"></a>

When CloudTrail logging is enabled in your AWS account, API calls made to AWS IoT OTA actions are tracked in CloudTrail log files where they are written with other AWS service records. CloudTrail determines when to create and write to a new file based on a time period and file size.

The following AWS IoT OTA control plane actions are logged by CloudTrail:
+ [CreateStream](https://docs.aws.amazon.com/iot/latest/apireference/API_CreateStream.html)
+ [DescribeStream](https://docs.aws.amazon.com/iot/latest/apireference/API_DescribeStream.html)
+ [ListStreams](https://docs.aws.amazon.com/iot/latest/apireference/API_ListStreams.html)
+ [UpdateStream](https://docs.aws.amazon.com/iot/latest/apireference/API_UpdateStream.html)
+ [DeleteStream](https://docs.aws.amazon.com/iot/latest/apireference/API_DeleteStream.html)
+ [CreateOTAUpdate](https://docs.aws.amazon.com/iot/latest/apireference/API_CreateOTAUpdate.html)
+ [GetOTAUpdate](https://docs.aws.amazon.com/iot/latest/apireference/API_GetOTAUpdate.html)
+ [ListOTAUpdates](https://docs.aws.amazon.com/iot/latest/apireference/API_ListOTAUpdates.html)
+ [DeleteOTAUpdate](https://docs.aws.amazon.com/iot/latest/apireference/API_DeleteOTAUpdate.html)

**Note**  
AWS IoT OTA data plane actions (device side) are not logged by CloudTrail. Use CloudWatch to monitor these.

Every log entry contains information about who generated the request. The user identity information in the log entry helps you determine the following: 
+ Whether the request was made with root or IAM user credentials.
+ Whether the request was made with temporary security credentials for a role or federated user.
+ Whether the request was made by another AWS service.

For more information, see the [CloudTrail userIdentity Element](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference-user-identity.html). AWS IoT OTA actions are documented in the [AWS IoT OTA API Reference](https://docs.aws.amazon.com/iot/latest/apireference).

You can store your log files in your Amazon S3 bucket for as long as you want, but you can also define Amazon S3 lifecycle rules to archive or delete log files automatically. By default, your log files are encrypted with Amazon S3 server-side encryption (SSE).

If you want to be notified when log files are delivered, you can configure CloudTrail to publish Amazon SNS notifications. For more information, see [ Configuring Amazon SNS Notifications for CloudTrail](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/getting_notifications_top_level.html).

You can also aggregate AWS IoT OTA log files from multiple AWS Regions and multiple AWS accounts into a single Amazon S3 bucket. 

For more information, see [ Receiving CloudTrail Log Files from Multiple Regions](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-receive-logs-from-multiple-accounts.html) and [Receiving CloudTrail Log Files from Multiple Accounts](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-receive-logs-from-multiple-accounts.html).

## Understanding FreeRTOS log file entries
<a name="understanding-aws-iot-entries-afr"></a>

CloudTrail log files can contain one or more log entries. Each entry lists multiple JSON-formatted events. A log entry represents a single request from any source and includes information about the requested action, the date and time of the action, request parameters, and so on. Log entries are not an ordered stack trace of the public API calls, so they do not appear in any specific order. 

The following example shows a CloudTrail log entry that demonstrates the log from a call to `CreateOTAUpdate` action.

```
{
    "eventVersion": "1.05",
    "userIdentity": {
        "type": "IAMUser",
        "principalId": "EXAMPLE",
        "arn": "arn:aws:iam::your_aws_account:user/your_user_id",
        "accountId": "your_aws_account",
        "accessKeyId": "your_access_key_id",
        "userName": "your_username",
        "sessionContext": {
            "attributes": {
                "mfaAuthenticated": "false",
                "creationDate": "2018-08-23T17:27:08Z"
            }
        },
        "invokedBy": "apigateway.amazonaws.com"
    },
    "eventTime": "2018-08-23T17:27:19Z",
    "eventSource": "iot.amazonaws.com",
    "eventName": "CreateOTAUpdate",
    "awsRegion": "your_aws_region",
    "sourceIPAddress": "apigateway.amazonaws.com",
    "userAgent": "apigateway.amazonaws.com",
    "requestParameters": {
        "targets": [
            "arn:aws:iot:your_aws_region:your_aws_account:thing/Thing_CMH"
        ],
        "roleArn": "arn:aws:iam::your_aws_account:role/Role_FreeRTOSJob",
        "files": [
            {
                "fileName": "/sys/mcuflashimg.bin",
                "fileSource": {
                    "fileId": 0,
                    "streamId": "your_stream_id"
                },
                "codeSigning": {
                    "awsSignerJobId": "your_signer_job_id"
                }
            }
        ],
        "targetSelection": "SNAPSHOT",
        "otaUpdateId": "FreeRTOSJob_CMH-23-1535045232806-92"
    },
    "responseElements": {
        "otaUpdateArn": "arn:aws:iot:your_aws_region:your_aws_account:otaupdate/FreeRTOSJob_CMH-23-1535045232806-92",
        "otaUpdateStatus": "CREATE_PENDING",
        "otaUpdateId": "FreeRTOSJob_CMH-23-1535045232806-92"
    },
    "requestID": "c9649630-a6f9-11e8-8f9c-e1cf2d0c9d8e",
    "eventID": "ce9bf4d9-5770-4cee-acf4-0e5649b845c0",
    "eventType": "AwsApiCall",
    "recipientAccountId": "recipient_aws_account"
}
```

# Get CreateOTAUpdate failure details using the AWS CLI
<a name="ota-create-failure"></a>

If the process of creating an OTA update job fails, there may be actions you can take to remedy the problem. When you create an OTA update job, the OTA manager service creates an IoT job and schedules it for the target devices, and this process also creates or uses other types of AWS resources in your account (a code-signing job, an AWS IoT stream, an Amazon S3 object). Any error encountered may cause the process to fail without creating an AWS IoT job. In this troubleshooting section we give instructions on how to retrieve the details of the failure.

1. Install and configure the [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html).

1. Run `aws configure` and enter the following information.

   ```
   $ aws configure
   AWS Access Key ID [None]: AccessID
   AWS Secret Access Key [None]: AccessKey
   Default region name [None]: Region
   Default output format [None]: json
   ```

   For more information, see [ Quick configuration with `aws configure`](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config).

1. Run: 

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

   Where *ota\$1update\$1job\$1001* is the ID you gave the OTA update when you created it.

1. The output will look like this:

   ```
   {
       "otaUpdateInfo": {
           "otaUpdateId": "ota_update_job_001",
           "otaUpdateArn": "arn:aws:iot:region:account_id:otaupdate/ota_update_job_001",
           "creationDate": 1584646864.534,
           "lastModifiedDate": 1584646865.913,
           "targets": [
               "arn:aws:iot:region:account_id:thing/thing_001"
           ],
           "protocols": [
               "MQTT"
           ],
           "awsJobExecutionsRolloutConfig": {},
           "awsJobPresignedUrlConfig": {},
           "targetSelection": "SNAPSHOT",
           "otaUpdateFiles": [
               {
                  "fileName": "/12ds",
                   "fileLocation": {
                       "s3Location": {
                           "bucket": "bucket_name",
                           "key": "demo.bin",
                           "version": "Z7X.TWSAS7JSi4rybc02nMdcE41W1tV3"
                       }
                   },
                   "codeSigning": {
                       "startSigningJobParameter": {
                           "signingProfileParameter": {},
                           "signingProfileName": "signing_profile_name",
                           "destination": {
                               "s3Destination": {
                                   "bucket": "bucket_name",
                                   "prefix": "SignedImages/"
                               }
                           }
                       },
                       "customCodeSigning": {}
                   }
               }
           ],
           "otaUpdateStatus": "CREATE_FAILED",
           "errorInfo": {
               "code": "AccessDeniedException",
               "message": "S3 object demo.bin not accessible. Please check your permissions (Service: AWSSigner; Status Code: 403; Error Code: AccessDeniedException; Request ID: 01d8e7a1-8c7c-4d85-9fd7-dcde975fdd2d)"
           }
       }
   }
   ```

   If the create failed, the `otaUpdateStatus` field in the command output will contain `CREATE_FAILED` and the `errorInfo` field will contain the details of the failure.

# Get OTA failure codes with the AWS CLI
<a name="ota-failure-codes"></a>

1. Install and configure the [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html).

1. Run `aws configure` and enter following information.

   ```
   $ aws configure
   AWS Access Key ID [None]: AccessID
   AWS Secret Access Key [None]: AccessKey
   Default region name [None]: Region
   Default output format [None]: json
   ```

   For more information, see [ Quick configuration with `aws configure`](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config).

1. Run: 

   ```
   aws iot describe-job-execution --job-id JobID --thing-name ThingName
   ```

   Where *JobID* is the complete job ID string for the job whose status we want to get (it was associated with the OTA update job when it was created) and *ThingName* is the AWS IoT thing name that the device is registered as in AWS IoT

1. The output will look like this:

   ```
   {
       "execution": {
           "jobId": "AFR_OTA-****************",
           "status": "FAILED",
           "statusDetails": {
               "detailsMap": {
                   "reason": "0xEEEEEEEE: 0xffffffff"
               }
           },
           "thingArn": "arn:aws:iot:Region:AccountID:thing/ThingName",
           "queuedAt": 1569519049.9,
           "startedAt": 1569519052.226,
           "lastUpdatedAt": 1569519052.226,
           "executionNumber": 1,
           "versionNumber": 2
       }
   }
   ```

   In this example output, the "`reason`" in the "`detailsmap`" has two fields: the field shown as "0xEEEEEEEE" contains the generic error code from the OTA Agent; the field shown as "0xffffffff" contains the sub-code. The generic error codes are listed in [ https://docs.aws.amazon.com/freertos/latest/lib-ref/html1/aws\$1\$1ota\$1\$1agent\$18h.html](https://docs.aws.amazon.com/freertos/latest/lib-ref/html1/aws__ota__agent_8h.html). See error codes with the prefix "`kOTA_Err_`". The sub-code can be a platform specific code or provide more details about the generic error. 

# Troubleshoot OTA updates of multiple devices
<a name="ota-troubleshooting-multi-thing"></a>

To perform OTAs on multiple devices (things) using the same firmware image, implement a function (for example `getThingName()`) that retrieves `clientcredentialIOT_THING_NAME` from non-volatile memory. Make sure that this function reads the thing name from a part of non-volatile memory that is not overwritten by the OTA, and that the thing name is provisioned before running the first job. If you are using the JITP flow, you can read the thing name out of your device certificate's common name.

# Troubleshoot OTA updates with the Texas Instruments CC3220SF Launchpad
<a name="ota-troubleshooting-ti"></a>

The CC3220SF Launchpad platform provides a software tamper-detection mechanism. It uses a security alert counter that is incremented whenever there is an integrity violation. The device is locked when the security alert counter reaches a predetermined threshold (the default is 15) and the host receives the `SL_ERROR_DEVICE_LOCKED_SECURITY_ALERT` asynchronous event. The locked device then has limited accessibility. To recover the device, you can reprogram it or use the restore-to-factory process to revert to the factory image. You should program the desired behavior by updating the asynchronous event handler in `network_if.c`.