Skip to content

Commit

Permalink
Anjay-pico-client 24.05
Browse files Browse the repository at this point in the history
Features
- Updated FOTA example
  • Loading branch information
JZimnol committed May 24, 2024
1 parent e42f21f commit 15b3759
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 22 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## Anjay-pico 24.05 (May 24th, 2024)

### Features
- Updated FOTA example

## Anjay-pico 24.02 (Feb 16th, 2024)

### Features
Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,19 @@ Download and install the following tools and programs:
* [CMake](https://cmake.org/download/)
* [Python](https://www.python.org/downloads/windows/)

### Aditional dependencies

[Firmware Update](firmware_update) application requires the following `python`
packages for the SHA256 calculation and AES ECB image encryption: `argparse`,
`pycryptodome`.

### Setting up the workspace

In order to successfully build the client, you need Raspberry Pi Pico SDK and FreeRTOS kernel cloned into a base directory, parallel to this repository. Creating a workspace from scratch could look like this:
```
mkdir pico
cd pico
git clone -b 1.4.0 https://github.com/raspberrypi/pico-sdk.git
git clone -b 1.5.1 https://github.com/raspberrypi/pico-sdk.git
cd pico-sdk/
git submodule update --init
cd ..
Expand Down
14 changes: 13 additions & 1 deletion common/config/avsystem/coap/avs_coap_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,23 @@
*/
#define WITH_AVS_COAP_OBSERVE

/**
* Turn on cancelling observation on a timeout.
*
* Only meaningful if <c>WITH_AVS_COAP_OBSERVE</c> is enabled.
*
* NOTE: LwM2M specification requires LwM2M server to send Cancel Observation
* request. Meanwhile CoAP RFC 7641 states that timeout on notification should
* cancel it. This setting is to enable both of these behaviors with default
* focused on keeping observations in case of bad connectivity.
*/
/* #undef WITH_AVS_COAP_OBSERVE_CANCEL_ON_TIMEOUT */

/**
* Enable support for observation persistence (<c>avs_coap_observe_persist()</c>
* and <c>avs_coap_observe_restore()</c> calls).
*
* Only meaningful <c>WITH_AVS_COAP_OBSERVE</c> is enabled.
* Only meaningful if <c>WITH_AVS_COAP_OBSERVE</c> is enabled.
*/
#define WITH_AVS_COAP_OBSERVE_PERSISTENCE

Expand Down
3 changes: 1 addition & 2 deletions firmware_update/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ target_compile_definitions(firmware_update PRIVATE
PSK_KEY=\"${PSK_KEY}\"
)

target_link_options(firmware_update PRIVATE "-L${CMAKE_CURRENT_SOURCE_DIR}/pico_fota_bootloader/linker_common")
pico_set_linker_script(firmware_update ${CMAKE_CURRENT_SOURCE_DIR}/pico_fota_bootloader/linker_common/application.ld)
pfb_compile_with_bootloader(firmware_update)

pico_enable_stdio_usb(firmware_update 1)
pico_enable_stdio_uart(firmware_update 0)
Expand Down
50 changes: 35 additions & 15 deletions firmware_update/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,29 @@

This application demonstrates an example use case of object 5 - Firmware
Update. It utilizes the
[pico_fota_bootloader](https://github.com/JZimnol/pico_fota_bootloader) to swap
the flash partitions after downloading the appropriate binary file from [Coiote
IoT
[pico_fota_bootloader](https://github.com/JZimnol/pico_fota_bootloader) to
encrypt and decrypt the FOTA image, check the SHA256 of the FOTA image, and
swap the flash partitions after downloading the appropriate binary file from
[Coiote IoT
DM](https://www.avsystem.com/products/coiote-iot-device-management-platform/).

### Flashing the bootloader and the application

#### Available compilation option

[pico_fota_bootloader](https://github.com/JZimnol/pico_fota_bootloader) provides
AES ECB image decryption. To set a custom encryption password, use
`-DPFB_AES_KEY=<value>` option when invoking the `cmake` command, otherwise the
default password will be used. Please refer to
[pico_fota_bootloader README](https://github.com/JZimnol/pico_fota_bootloader/blob/master/README.md)
for more information.

**NOTE**: While rebuilding the application, once set, the `PFB_AES_KEY`
CMake option should not be changed, otherwise the Raspberry Pi Pico W won't be
able to decrypt downloaded image properly.

#### Flashing the board

After compiling the application, you should have output similar to:

```
Expand All @@ -21,6 +37,8 @@ build
├── firmware_update.dis
├── firmware_update.elf
├── firmware_update.elf.map
├── firmware_update_fota_image.bin
├── firmware_update_fota_image_encrypted.bin
├── firmware_update.hex
├── firmware_update.uf2
├── Makefile
Expand All @@ -39,24 +57,26 @@ build

To flash the application, set Raspberry Pi Pico W to the `BOOTSEL` state (by
powering it up with the `BOOTSEL` button pressed) and copy the
`pico_fota_bootloader.uf2` file into it. Right now the Raspberry Pi Pico W is
flashed with the bootloader but does not have proper application in the
application FLASH memory slot yet. Then, set Raspberry Pi Pico W to the
`BOOTSEL` state again and copy the `firmware_update.uf2` file. The board should
reboot and start the `firmware_update` application.
`build/firmware_update/pico_fota_bootloader/pico_fota_bootloader.uf2` file into
it. Right now the Raspberry Pi Pico W is flashed with the bootloader but does
not have proper application in the application FLASH memory slot yet. Then, set
Raspberry Pi Pico W to the `BOOTSEL` state again and copy the
`build/firmware_update/firmware_update.uf2` file. The board should reboot and
start the `firmware_update` application.

**NOTE**: you can also look at the serial output logs to monitor the
application state.

### Performing Firmware Update

To perform a Firmware Update Over the Air, the `firmware_update.bin` file
should be sent to or downloaded by the Raspberry Pi Pico W. To do so, open your
Device Page in Coiote DM Platform and go to the `Firmware update` tab. Then
click the `Update firmware` button and then select `Basic Firmware Update`.
Upload `firmware_update.bin` file to Coiote DM, click `Next` button twice and
then `Schedule Update`. After doing so, a Firmware Update process will begin.
Check the serial output logs - the `INFO [fw_update]
To perform a Firmware Update Over the Air, the
`build/firmware_update/firmware_update_fota_image_encrypted.bin` file should be
sent to or downloaded by the Raspberry Pi Pico W. To do so, open your Device
Page in Coiote DM Platform and go to the `Firmware update` tab. Then click the
`Update firmware` button and then select `Basic Firmware Update`. Upload
`firmware_update_fota_image_encrypted.bin` file to Coiote DM, click `Next`
button twice and then `Schedule Update`. After doing so, a Firmware Update
process will begin. Check the serial output logs - the `INFO [fw_update]
[/anjay-pico-client/firmware_update/firmware_update.c]: Downloaded X bytes`
logs should appear. For more detailed information, see [AVSystem
Devzone](https://iotdevzone.avsystem.com/docs/Coiote_IoT_DM/firmware_update/).
Expand Down
13 changes: 11 additions & 2 deletions firmware_update/firmware_update.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,19 @@
#include <avsystem/commons/avs_sched.h>
#include <avsystem/commons/avs_time.h>

#include <pico_fota_bootloader.h>

#include "hardware/flash.h"
#include "hardware/sync.h"
#include "hardware/watchdog.h"

#include "firmware_update.h"
#include "flash_aligned_writer.h"
#include "pico_fota_bootloader.h"

static bool update_initialized;
static size_t downloaded_bytes;

static uint8_t writer_buf[256];
static uint8_t writer_buf[PFB_ALIGN_SIZE];
static flash_aligned_writer_t writer;

static int fw_stream_open(void *user_ptr,
Expand Down Expand Up @@ -88,6 +89,11 @@ static int fw_stream_finish(void *user_ptr) {
return -1;
}

if (pfb_firmware_sha256_check(downloaded_bytes)) {
avs_log(fw_update, ERROR, "SHA256 check failed");
return -1;
}

return 0;
}

Expand Down Expand Up @@ -129,6 +135,9 @@ int fw_update_install(anjay_t *anjay) {
if (pfb_is_after_firmware_update()) {
state.result = ANJAY_FW_UPDATE_INITIAL_SUCCESS;
avs_log(fw_update, INFO, "Running on a new firmware");
} else if (pfb_is_after_rollback()) {
state.result = ANJAY_FW_UPDATE_INITIAL_NEUTRAL;
avs_log(fw_update, WARNING, "Rollback performed");
}

return anjay_fw_update_install(anjay, &handlers, anjay, &state);
Expand Down
4 changes: 4 additions & 0 deletions firmware_update/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#include <avsystem/commons/avs_prng.h>
#include <avsystem/commons/avs_time.h>

#include <pico_fota_bootloader.h>

#include "firmware_update.h"

#ifndef RUN_FREERTOS_ON_CORE
Expand Down Expand Up @@ -142,6 +144,8 @@ void main_loop(void) {
void anjay_task(__unused void *params) {
init_wifi();

pfb_firmware_commit();

anjay_configuration_t config = {
.endpoint_name = ENDPOINT_NAME,
.in_buffer_size = 2048,
Expand Down

0 comments on commit 15b3759

Please sign in to comment.