|
| 1 | +# Matter Over-The-Air Software Update with NXP RW61x example applications |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +The OTA Requestor feature enables the device to be informed of, download and |
| 6 | +apply a software update from an OTA Provider. |
| 7 | + |
| 8 | +This section explains how to perform an OTA Software Update with NXP RW61x |
| 9 | +example applications. Throughout this guide, the all-clusters application is |
| 10 | +used as an example. |
| 11 | + |
| 12 | +In general, the Over-The-Air Software Update process consists of the following |
| 13 | +steps : |
| 14 | + |
| 15 | +- The OTA Requestor queries an update image from the OTA Provider which |
| 16 | + responds according to its availability. |
| 17 | +- The update image is received in blocks and stored in the external flash of |
| 18 | + the device. |
| 19 | +- Once the update image is fully downloaded, the bootloader is notified and |
| 20 | + the device resets applying the update in test-mode. |
| 21 | +- If the test is successful, the update is applied permanently. Otherwise, the |
| 22 | + bootloader reverts back to the primary application, preventing any |
| 23 | + downgrade. |
| 24 | + |
| 25 | +### Flash Memory Layout |
| 26 | + |
| 27 | +The RW61x Flash is divided into different regions as follow : |
| 28 | + |
| 29 | +- Bootloader : MCUBoot resides at the base of the flash and occupies 0x20000 |
| 30 | + (128 kB). |
| 31 | +- Primary application partition : The example application which would be run |
| 32 | + by the bootloader (active application). The size reserved for this partition |
| 33 | + is 4.4 MB. |
| 34 | +- Secondary application partition : Update image received with the OTA |
| 35 | + (candidate application). The size reserved for the partition is 4.4 MB. |
| 36 | + |
| 37 | +Notes : |
| 38 | + |
| 39 | +- The CPU1/CPU2 firmware are embedded in the CPU3 example application. |
| 40 | +- The sizes of the primary and secondary applications are provided as an |
| 41 | + example (currently 4.4 MB is reserved for each partition). The size can be |
| 42 | + changed by modifying the `m_app_max_sectors` value in the linker script of |
| 43 | + the application (`RW610_flash.ld`). |
| 44 | + |
| 45 | +### MCUBoot Bootloader |
| 46 | + |
| 47 | +MCUBoot is an open-source secure bootloader used by RW61x to apply the |
| 48 | +self-upgrade. For more details, please refer to the |
| 49 | +[MCUBoot documentation](https://github.com/mcu-tools/mcuboot/blob/main/docs/design.md). |
| 50 | + |
| 51 | +In our use case, the bootloader runs the application residing in the primary |
| 52 | +partition. In order to run the OTA update image, the bootloader will swap the |
| 53 | +content of the primary and the secondary partitions. This type of upgrade is |
| 54 | +called swap-move and is the default upgrade configured by MCUBoot. |
| 55 | + |
| 56 | +## OTA Software Update process for RW61x example application |
| 57 | + |
| 58 | +### Flashing the bootloader |
| 59 | + |
| 60 | +In order for the device to perform the software update, the MCUBoot bootloader |
| 61 | +must be flashed first at the base of the flash. A step-by-step guide is given |
| 62 | +below. |
| 63 | + |
| 64 | +- It is recommended to start with erasing the external flash of the device, |
| 65 | + for this JLink from Segger can be used. It can be downloaded and installed |
| 66 | + from https://www.segger.com/products/debug-probes/j-link. Once installed, |
| 67 | + JLink can be run using the command line : |
| 68 | + |
| 69 | +``` |
| 70 | +$ JLink |
| 71 | +``` |
| 72 | + |
| 73 | +Run the following commands : |
| 74 | + |
| 75 | +``` |
| 76 | +J-Link > connect |
| 77 | +Device> ? # you will be presented with a dialog -> select `RW612` |
| 78 | +Please specify target interface: |
| 79 | +J) JTAG (Default) |
| 80 | +S) SWD |
| 81 | +T) cJTAG |
| 82 | +TIF> S |
| 83 | +Specify target interface speed [kHz]. <Default>: 4000 kHz |
| 84 | +Speed> # <enter> |
| 85 | +J-Link > exec EnableEraseAllFlashBanks |
| 86 | +J-Link > erase 0x8000000, 0x88a0000 |
| 87 | +``` |
| 88 | + |
| 89 | +- Using MCUXPresso, import the `mcuboot_opensource` demo example from the SDK |
| 90 | + previously downloaded. |
| 91 | +  |
| 92 | +- Before building the demo example, it should be specified that the |
| 93 | + application to be run by the bootloader is monolithic. As a result, only one |
| 94 | + image will be upgraded by the bootloader. This can be done by defining |
| 95 | + `MONOLITHIC_APP` as 1 in the settings of the `mcuboot_opensource` project : |
| 96 | + |
| 97 | +``` |
| 98 | +Right click on the Project -> Properties -> C/C++ Build -> Settings -> Tool Settings -> MCU C Compiler -> Preprocessor -> Add "MONOLITHIC_APP=1" in the Defined Symbols |
| 99 | +``` |
| 100 | + |
| 101 | + |
| 102 | + |
| 103 | +- Build the demo example project and program it to the target board. |
| 104 | +- To run the flashed demo, either press the reset button of the device or use |
| 105 | + the debugger IDE of MCUXpresso. If it runs successfully, the following logs |
| 106 | + will be displayed on the terminal : |
| 107 | + |
| 108 | +``` |
| 109 | +hello sbl. |
| 110 | +Bootloader Version 1.9.0 |
| 111 | +Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 |
| 112 | +Secondary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 |
| 113 | +Boot source: none |
| 114 | +Swap type: none |
| 115 | +erasing trailer; fa_id=2 |
| 116 | +Unable to find bootable image |
| 117 | +``` |
| 118 | + |
| 119 | +Note : By default, mcuboot application considers the primary and secondary |
| 120 | +partitions to be the size of 4.4 MB. If the size is to be changed, the partition |
| 121 | +addresses should be modified in the flash_partitioning.h accordingly. For more |
| 122 | +information about the flash partitioning with mcuboot, please refer to the |
| 123 | +dedicated readme.txt located in |
| 124 | +"`SDK_RW612/boards/rdrw612bga/ota_examples/mcuboot_opensource/`". |
| 125 | + |
| 126 | +### Generating and flashing the signed application image |
| 127 | + |
| 128 | +After flashing the bootloader, the application can be programmed to the board. |
| 129 | +The image must have the following format : |
| 130 | + |
| 131 | +- Header : contains general information about the image (version, size, |
| 132 | + magic...) |
| 133 | +- Code of the application : generated binary |
| 134 | +- Trailer : contains metadata needed by the bootloader such as the image |
| 135 | + signature, the upgrade type, the swap status... |
| 136 | + |
| 137 | +The all-clusters application can be generated using the instructions from the |
| 138 | +[README.md 'Building'](../../examples/all-clusters-app/nxp/rt/rw61x/README.md#building) |
| 139 | +section. The application is automatically linked to be executed from the primary |
| 140 | +image partition, taking into consideration the offset imposed by mcuboot. |
| 141 | + |
| 142 | +The resulting executable file found in out/debug/chip-rw61x-all-cluster-example |
| 143 | +needs to be converted into raw binary format as shown below. |
| 144 | + |
| 145 | +``` |
| 146 | +arm-none-eabi-objcopy -R .flash_config -R .NVM -O binary chip-rw61x-all-cluster-example chip-rw61x-all-cluster-example.bin |
| 147 | +``` |
| 148 | + |
| 149 | +To sign the image and wrap the raw binary of the application with the header and |
| 150 | +trailer, "`imgtool`" is provided in the SDK and can be found in |
| 151 | +"`/middleware/mcuboot_opensource/scripts/`". |
| 152 | + |
| 153 | +The following commands can be run (make sure to replace the /path/to/file/binary |
| 154 | +with the adequate files): |
| 155 | + |
| 156 | +``` |
| 157 | +user@ubuntu: cd ~/Desktop/SDK_RW612/middleware/mcuboot_opensource/scripts |
| 158 | +
|
| 159 | +user@ubuntu: python3 imgtool.py sign --key ~/Desktop/SDK_RW612/boards/rdrw612bga/ota_examples/mcuboot_opensource/keys/sign-rsa2048-priv.pem --align 4 --header-size 0x1000 --pad-header --slot-size 0x440000 --max-sectors 1088 --version "1.0" ~/Desktop/connectedhomeip/examples/all-clusters-app/nxp/rt/rw61x/out/debug/chip-rw61x-all-cluster-example.bin ~/Desktop/connectedhomeip/examples/all-clusters-app/nxp/rt/rw61x/out/debug/chip-rw61x-all-cluster-example_SIGNED.bin |
| 160 | +``` |
| 161 | + |
| 162 | +Notes : |
| 163 | + |
| 164 | +- If internal SDK is used instead, the key can be found in : |
| 165 | + "`~/Desktop/SDK_RW612/middleware/mcuboot_opensource/boot/nxp_mcux_sdk/keys/sign-rsa2048-priv.pem`". |
| 166 | +- The arguments `slot-size` and `max-sectors` should be adjusted to the size |
| 167 | + of the partitions reserved for the primary and the secondary applications. |
| 168 | + (By default the size considered is 4.4 MB) |
| 169 | +- In this example, the image is signed with the private key provided by the |
| 170 | + SDK as an example |
| 171 | + (`/path_to_sdk/middleware/mcuboot_opensource/boot/nxp_mcux_sdk/keys/sign-rsa2048-priv.pem`), |
| 172 | + MCUBoot is built with its corresponding public key which would be used to |
| 173 | + verify the integrity of the image. It is possible to generate a new pair of |
| 174 | + keys using the following commands. This procedure should be done prior to |
| 175 | + building the mcuboot application. |
| 176 | + |
| 177 | +- To generate the private key : |
| 178 | + |
| 179 | +``` |
| 180 | +user@ubuntu: python3 imgtool.py keygen -k priv_key.pem -t rsa-2048 |
| 181 | +``` |
| 182 | + |
| 183 | +- To extract the public key : |
| 184 | + |
| 185 | +``` |
| 186 | +user@ubuntu: python3 imgtool.py getpub -k priv_key.pem |
| 187 | +``` |
| 188 | + |
| 189 | +- The extracted public key can then be copied to the |
| 190 | + `/path_to_sdk/middleware/mcuboot_opensource/boot/nxp_mcux_sdk/keys/sign-rsa2048-pub.c`, |
| 191 | + given as a value to the rsa_pub_key[] array. |
| 192 | + |
| 193 | +The resulting output is the signed binary of the application version "1.0". |
| 194 | + |
| 195 | +JLink can be used to flash the application at the address 0x8020000, using the |
| 196 | +command : |
| 197 | + |
| 198 | +``` |
| 199 | +J-Link > loadbin chip-rw61x-all-cluster-example_SIGNED.bin 0x8020000 |
| 200 | +``` |
| 201 | + |
| 202 | +The bootloader should then be able to jump directly to the start of the |
| 203 | +application and run it. |
| 204 | + |
| 205 | +### Generating the OTA Update Image |
| 206 | + |
| 207 | +To generate the OTA update image the same procedure can be followed from the |
| 208 | +[Generating and flashing the signed application image](#generating-and-flashing-the-signed-application-image) |
| 209 | +sub-section, replacing the "--version "1.0"" argument with "--version "2.0"" |
| 210 | +(recent version of the update). |
| 211 | + |
| 212 | +When the signed binary of the update is generated, the file should be converted |
| 213 | +into OTA format. To do so, the ota_image_tool is provided in the repo and can be |
| 214 | +used to convert a binary file into an .ota file. |
| 215 | + |
| 216 | +``` |
| 217 | +user@ubuntu:~/connectedhomeip$ : ./src/app/ota_image_tool.py create -v 0xDEAD -p 0xBEEF -vn 2 -vs "2.0" -da sha256 chip-rw61x-all-cluster-example_SIGNED.bin chip-rw61x-all-cluster-example.ota |
| 218 | +``` |
| 219 | + |
| 220 | +The generated OTA file can be used to perform the OTA Software Update. The |
| 221 | +instructions below describe the procedure step-by-step. |
| 222 | + |
| 223 | +### Performing the OTA Software Update |
| 224 | + |
| 225 | +Setup example : |
| 226 | + |
| 227 | +- [Chip-tool](../../examples/chip-tool/README.md) application running on the |
| 228 | + RPi. |
| 229 | +- OTA Provider application built on the same RPi (as explained below). |
| 230 | +- RW61x board programmed with the example application (with the instructions |
| 231 | + above). |
| 232 | + |
| 233 | +Before starting the OTA process, the Linux OTA Provider application can be built |
| 234 | +on the RPi (if not already present in the pre-installed apps) : |
| 235 | + |
| 236 | +``` |
| 237 | +user@ubuntu:~/connectedhomeip$ : ./scripts/examples/gn_build_example.sh examples/ota-provider-app/linux out/ota-provider-app chip_config_network_layer_ble=false |
| 238 | +
|
| 239 | +user@ubuntu:~/connectedhomeip$ : rm -rf /tmp/chip_* |
| 240 | +user@ubuntu:~/connectedhomeip$ : ./out/ota-provider-app/chip-ota-provider-app -f chip-rw61x-all-cluster-example.ota |
| 241 | +``` |
| 242 | + |
| 243 | +The OTA Provider should first be provisioned with chip-tool by assigning it the |
| 244 | +node id 1, and then granted the ACL entries : |
| 245 | + |
| 246 | +``` |
| 247 | +user@ubuntu:~/connectedhomeip$ : ./out/chip-tool-app/chip-tool pairing onnetwork 1 20202021 |
| 248 | +user@ubuntu:~/connectedhomeip$ : ./out/chip-tool-app/chip-tool accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [112233], "targets": null}, {"fabricIndex": 1, "privilege": 3, "authMode": 2, "subjects": null, "targets": null}]' 1 0 |
| 249 | +``` |
| 250 | + |
| 251 | +The second step is to provision the device with the node id 2 using ble-wifi or |
| 252 | +ble-thread commissioning. For example : |
| 253 | + |
| 254 | +``` |
| 255 | +user@ubuntu:~/connectedhomeip$ : ./out/chip-tool-app/chip-tool pairing ble-wifi 2 WIFI_SSID WIFI_PASSWORD 20202021 3840 |
| 256 | +``` |
| 257 | + |
| 258 | +Once commissioned, the OTA process can be initiated with the |
| 259 | +"announce-ota-provider" command using chip-tool (the given numbers refer |
| 260 | +respectively to [ProviderNodeId][vendorid] [AnnouncementReason][endpoint] |
| 261 | +[node-id][endpoint-id]) : |
| 262 | + |
| 263 | +``` |
| 264 | +user@ubuntu:~/connectedhomeip$ : ./out/chip-tool-app/chip-tool otasoftwareupdaterequestor announce-otaprovider 1 0 0 0 2 0 |
| 265 | +``` |
| 266 | + |
| 267 | +When the full update image is downloaded and stored, the bootloader will be |
| 268 | +notified and the device will reboot with the update image. |
0 commit comments