|
| 1 | +# SFU Library Examples - Over-The-Air (OTA) Update Workflows |
| 2 | + |
| 3 | +This directory contains examples demonstrating Over-The-Air (OTA) firmware update workflows for Arduino Portenta C33 using the SFU (Second stage bootloader Firmware Update) library. |
| 4 | + |
| 5 | +**Structure:** |
| 6 | +- **2 OTA Update Approaches**: `OTAUpdate` and `UpdateFromFile` - showing different methods to deliver and apply firmware updates |
| 7 | +- **1 Test Sketch**: `OTAUsage` - a simple demo application used as the target firmware for both OTA approaches |
| 8 | + |
| 9 | +--- |
| 10 | + |
| 11 | +## OTA Update Approaches |
| 12 | + |
| 13 | +### Approach 1: OTAUpdate (Network-Based OTA) |
| 14 | +Downloads firmware from a remote server over WiFi. |
| 15 | + |
| 16 | +### Approach 2: UpdateFromFile (Local/Embedded OTA) |
| 17 | +Embeds the firmware update directly in the sketch: useful for testing, offline updates, or pre-loaded production devices. |
| 18 | + |
| 19 | +--- |
| 20 | + |
| 21 | +## Overview: General OTA Update Process |
| 22 | + |
| 23 | +Both OTA approaches follow a similar workflow: |
| 24 | +1. **Create** a new firmware binary (sketch) |
| 25 | +2. **Compress & Package** the binary into OTA format |
| 26 | +3. **Store** the OTA file (on server or embedded in sketch) |
| 27 | +4. **Download** the OTA file to the board's QSPI flash |
| 28 | +5. **Apply** the update via bootloader |
| 29 | + |
| 30 | +--- |
| 31 | + |
| 32 | +## Test Sketch: OTAUsage |
| 33 | + |
| 34 | +**File:** [OTAUsage/OTAUsage.ino](OTAUsage/OTAUsage.ino) |
| 35 | + |
| 36 | +### Purpose |
| 37 | +This is a simple test application designed to be packaged as the target firmware that will be delivered and installed via OTA updates. Used to verify that the OTA update process succeeded. |
| 38 | + |
| 39 | +### What It Does |
| 40 | +- Controls the RGB LED on Portenta C33 |
| 41 | +- Cycles through three colors: Blue → Green → Red (1-second intervals each) |
| 42 | +- Acts as a visible indicator that OTA completed successfully |
| 43 | + |
| 44 | +### ⚠️ Important: Always Include SFU.h |
| 45 | + |
| 46 | +Notice that OTAUsage.ino includes `#include "SFU.h"` at the top. **This is critical for any firmware that will be deployed via OTA.** |
| 47 | + |
| 48 | +**Why?** The SFU library embeds the second-stage bootloader binary. By including it, the linker script (see [variants/PORTENTA_C33/fsp.ld](../../variants/PORTENTA_C33/fsp.ld)) properly reserves memory for the bootloader, ensuring that your application is placed in flash *after* the bootloader—not overwriting it. |
| 49 | + |
| 50 | +**Best Practice:** Always include `#include "SFU.h"` in sketches intended for OTA deployment. |
| 51 | + |
| 52 | +### How to Use It |
| 53 | +1. Open OTAUsage.ino and verify it compiles and runs on Portenta C33 |
| 54 | +2. Export compiled binary: `Sketch → Export Compiled Binary` |
| 55 | +3. Package the binary as an OTA file (see tools and steps below) |
| 56 | +4. Use the packaged OTA file with either **OTAUpdate** or **UpdateFromFile** approach |
| 57 | + |
| 58 | +--- |
| 59 | + |
| 60 | +## OTA Approach 1: OTAUpdate (Network-Based) |
| 61 | + |
| 62 | +**File:** [OTAUpdate/OTAUpdate.ino](OTAUpdate/OTAUpdate.ino) |
| 63 | + |
| 64 | +### Purpose |
| 65 | +This example demonstrates **downloading an OTA update from a remote server** over WiFi and applying it to the board. |
| 66 | + |
| 67 | +### What It Does |
| 68 | +1. Connects to WiFi network (credentials from `arduino_secrets.h`) |
| 69 | +2. Mounts the QSPI flash filesystem |
| 70 | +3. **Downloads** an OTA file from a remote URL |
| 71 | +4. Saves it to QSPI at `/ota/UPDATE.BIN.OTA` |
| 72 | +5. **Applies** the update (bootloader takes over on next reset) |
| 73 | + |
| 74 | +### Key Features |
| 75 | +- **Network-based OTA**: Fetches firmware from `http://downloads.arduino.cc/ota/OTAUsage.ino.PORTENTA_C33.ota` |
| 76 | +- **Requires WiFi**: Uses `WiFiC3` library to connect to network |
| 77 | +- **Error handling**: Validates filesystem mount/unmount operations |
| 78 | +- **Real-world deployment**: Suitable for production firmware distribution |
| 79 | + |
| 80 | + |
| 81 | +### Complete OTA Workflow |
| 82 | +``` |
| 83 | +Step 1: Prepare firmware image |
| 84 | + - Create & test a sketch (e.g., OTAUsage.ino) |
| 85 | + - Export compiled binary: Sketch → Export Compiled Binary |
| 86 | + |
| 87 | +Step 2: Package for OTA |
| 88 | + - Download tools: https://github.com/arduino-libraries/ArduinoIoTCloud/tree/master/extras/tools |
| 89 | + - Compress: ./lzss.py --encode YourSketch.bin YourSketch.lzss |
| 90 | + - Package: ./bin2ota.py PORTENTA_C33 YourSketch.lzss YourSketch.ota |
| 91 | + |
| 92 | +Step 3: Upload to server |
| 93 | + - Host the .ota file at a publicly accessible URL |
| 94 | + - Example: http://your-server.com/ota/YourSketch.ota |
| 95 | + |
| 96 | +Step 4: Deploy OTA update |
| 97 | + - Upload OTAUpdate.ino to Portenta C33 |
| 98 | + - Update the OTA_FILE_LOCATION constant with your URL |
| 99 | + - Board connects to WiFi, downloads, and applies update |
| 100 | +``` |
| 101 | + |
| 102 | +--- |
| 103 | + |
| 104 | +## OTA Approach 2: UpdateFromFile (Local/Embedded) |
| 105 | + |
| 106 | +**File:** [UpdateFromFile/UpdateFromFile.ino](UpdateFromFile/UpdateFromFile.ino) |
| 107 | + |
| 108 | +### Purpose |
| 109 | +This example demonstrates **storing an OTA update locally** on the device (embedded in firmware) and applying it. Useful for testing, offline updates, or pre-loading updates on production devices. |
| 110 | + |
| 111 | +### What It Does |
| 112 | +1. Reformats the QSPI filesystem |
| 113 | +2. **Copies** a pre-compiled OTA file (from `update.h` header) into QSPI flash |
| 114 | +3. Saves it to `/ota/UPDATE.BIN.OTA` |
| 115 | +4. **Applies** the update immediately |
| 116 | +5. Resets the board to trigger bootloader firmware installation |
| 117 | + |
| 118 | +### Preparation Steps |
| 119 | +``` |
| 120 | +Step 1: Create and export firmware binary |
| 121 | + - Create your target sketch (e.g., OTAUsage.ino) |
| 122 | + - Verify it works on the board |
| 123 | + - Export: Sketch → Export Compiled Binary |
| 124 | + |
| 125 | +Step 2: Compress and package |
| 126 | + - ./lzss.py --encode OTAUsage.ino.bin OTAUsage.ino.lzss |
| 127 | + - ./bin2ota.py PORTENTA_C33 OTAUsage.ino.lzss OTAUsage.ino.ota |
| 128 | + |
| 129 | +Step 3: Convert to header file |
| 130 | + - xxd -i OTAUsage.ino.ota > update.h |
| 131 | + - Creates array: OTAUsage_ino_PORTENTA_C33_ota[] |
| 132 | + |
| 133 | +Step 4: Include and deploy |
| 134 | + - Copy update.h to UpdateFromFile sketch folder |
| 135 | + - Upload UpdateFromFile.ino |
| 136 | + - Update executes immediately |
| 137 | +``` |
| 138 | + |
| 139 | +--- |
| 140 | + |
| 141 | +## OTA Packaging (Common to Both Approaches) |
| 142 | + |
| 143 | +Both OTA approaches use the same OTA file format (`.ota`) and packaging process. Only the delivery method differs. |
| 144 | + |
| 145 | +### Packaging Steps (Detailed) |
| 146 | + |
| 147 | +1. **Export binary from Arduino IDE** |
| 148 | + ```bash |
| 149 | + # Generated as: YourSketch.ino.PORTENTA_C33.bin |
| 150 | + ``` |
| 151 | + |
| 152 | +2. **Compress with LZSS** |
| 153 | + ```bash |
| 154 | + ./lzss.py --encode YourSketch.ino.PORTENTA_C33.bin YourSketch.ino.lzss |
| 155 | + ``` |
| 156 | + |
| 157 | +3. **Package for OTA** |
| 158 | + ```bash |
| 159 | + ./bin2ota.py PORTENTA_C33 YourSketch.ino.lzss YourSketch.ino.ota |
| 160 | + ``` |
| 161 | + |
| 162 | +4. **For embedded use (UpdateFromFile): Convert to header** |
| 163 | + ```bash |
| 164 | + xxd -i YourSketch.ino.ota > update.h |
| 165 | + ``` |
| 166 | + |
| 167 | +### Download Tools |
| 168 | +Repository: https://github.com/arduino-libraries/ArduinoIoTCloud/tree/master/extras/tools |
| 169 | +- `lzss.py` - LZSS compression encoder |
| 170 | +- `bin2ota.py` - OTA file format generator |
| 171 | + |
| 172 | +--- |
| 173 | + |
| 174 | + |
| 175 | + |
0 commit comments