Over-The-Air (OTA) Updates with the Arduino Portenta H7

Learn how to perform an OTA update of the firmware on the Arduino Portenta H7

Overview

In this tutorial, you will learn how to use and allow firmware updates via OTA (Over-The-Air) feature with the Arduino Portenta H7. With this tutorial, you will be able to create a binary file to be used with the OTA feature and use the internal QSPI or a external SD card to accomplish the OTA (Over-The-Air) process.

To proceed with OTA using a SD Card, you will need to use a carrier or shield with a SD card slot, e.g Portenta Breakout, Portenta Max Carrier, Portenta Vision Shield.

Goals

The goals of this tutorial are:

  • Create an OTA file required to use the OTA (Over-The-Air) feature.
  • Use QSPI or SD card storage to load the firmware downloaded using the OTA feature.

Hardware and Software Needed

  • Arduino Portenta H7
  • Operative System: Linux or MacOS system, this procedure is not 100% compatible on Windows.
  • Arduino IDE 1.8.10+ or Arduino Pro IDE 0.0.4+
  • USB-C® type cable (either USB-A to USB-C® or USB-C® to USB-C®)
  • Arduino IoT Cloud and Arduino_Portenta_OTA libraries
  • SD card (optional, you can use QSPI instead)
  • Carrier or shield compatible with the Portenta H7 with a SD Card slot, in case you choose to use the SD Card.

What OTA Means

OTA (Over-The-Air) is a method of distributing wirelessly to end devices to update their firmware, configuration or security-related protocols. The purpose of this method is to change a device’s behavior or its settings for better performance, for adding new features or to change its targeted usage.

Instructions

We will explain briefly the steps required to be able to use OTA (Over-The-Air) process with Arduino Portenta H7. It will consist of firmware OTA file creation and use of preferred storage mode (QSPI or SD card).

Firmware OTA File Creation

You will need to create the binary file required for the OTA (Over-The-Air) process to be able use it with either storage option stated previously. For the purpose of this tutorial, you will have to use the following script to create the binary file.

1/*
2 This sketch can be used to generate an example binary that can be uploaded to Portenta via OTA.
3 It needs to be used together with
4 - 'OTA_Qspi_Flash.ino' if you want to use the Qspi Flash as storage system
5 OR
6 - 'SD_Qspi_Flash.ino' if you want to use the SD card as storage system
7
8 Steps to test OTA on Portenta:
9 1) Upload this sketch or any other sketch (this one lights up the RGB LED with different colours).
10 2) In the IDE select: Sketch -> Export compiled Binary
11 3) Upload the exported binary to a server
12 4) Choose a storage mechanism (SD or QSPI), open the related OTA_*_Portenta.ino sketch,
13 eventually update the OTA_FILE_LOCATION
14 5) Upload the sketch OTA_*_Portenta.ino to perform OTA via SD or QSPI Flash
15*/
16
17void setLed(int blue, int green, int red) {
18 digitalWrite(LEDB, blue);
19 digitalWrite(LEDG, green);
20 digitalWrite(LEDR, red);
21}
22
23
24void setup()
25{
26 pinMode(LEDB, OUTPUT);
27 pinMode(LEDG, OUTPUT);
28 pinMode(LEDR, OUTPUT);
29}
30
31void loop()
32{ //led BLUE ON
33 setLed(1, 0, 0);
34 delay(1000);
35 //led GREEN ON
36 setLed(0, 1, 0);
37 delay(1000);
38 //led RED ON
39 setLed(0, 0, 1);
40 delay(1000);
41}

This script will light up the RGB LED with 3 different colors in sequence. This code will need to be uploaded to the Arduino Portenta H7 firsthand. This is to verify whether the sketch compiles and is working correctly. After verifying this, in Arduino IDE, you will search for Sketch > Export Compiled Binary.

Exporting Binary for the Sketch
Exporting Binary for the Sketch

With the binary file ready, you can now create the OTA file needed to enable Over-The-Air process.

To continue, macOS or Linux environment is required. For Windows environment, it is possible to use virtualization software such as Oracle VM Virtualbox using your preferred choice of compatible Linux distribution. If you're not familiar with Linux environments, Ubuntu is one of many distributions that can help you explore Linux environment with ease of access.

Once you're comfortable with an environment, you will need a tool which can be found at the following link.

Arduino IoT Cloud Library - Over-The-Air Tools

You will have to extract the library at a preferred location to be able to use the tools. Then, you will need to run on the terminal the following commands in sequence to be able to create the OTA file.

Copy the binary file into the library tool's folder

1// Exported binary format reference: sketch.bin
2cp OTA_Usage_Portenta.ino.PORTENTA_H7_M7.bin ~/Arduino/libraries/ArduinoIoTCloud/extras/tools/

Go inside that directory

1cd ~/Arduino/libraries/ArduinoIoTCloud/extras/tools

Encode your binary file into

OTA_Usage_Portenta.ino.PORTENTA_H7_M7.lzss

1// Argument format: ./lzss.py --encode sketch.bin sketch.lzss
2./lzss.py --encode OTA_Usage_Portenta.ino.PORTENTA_H7_M7.bin OTA_Usage_Portenta.ino.PORTENTA_H7_M7.lzss

Convert your encoded file into

.ota
format

1// Argument format: ./bin2ota.py PORTENTA_H7_M7 sketch.lzss sketch.ota
2./bin2ota.py PORTENTA_H7_M7 OTA_Usage_Portenta.ino.PORTENTA_H7_M7.lzss OTA_Usage_Portenta.ino.PORTENTA_H7_M7.ota

You can use

OTA_Usage_Portenta.ino.PORTENTA_H7_M7
as a sketch name for facilitated identification of the file. After this, you will have the
.ota
file of the sketch that you will use with the OTA process.

Installing Python 3 On Linux

If you are using Linux, maybe you cannot run the bin2ota.py script. This may be because you need to install Python 3 and the necessary modules. To do it execute the next command on your Linux terminal:

1sudo apt install python-is-python3

You will also need to install the crccheck module on python by following the next instructions:

Installing pip on python:

1//Necessary to install python modules:
2sudo apt install python3-pip

Installing the crccheck necessary module on python:

1//Necessary to run the script:
2pip install crccheck

Once you have done it, you should be able to run the bin2ota.py script successfully.

Uploading OTA file to the net

Now you can upload your .OTA file to an online reachable location, e.g. OTA_Usage_Portenta.ino.PORTENTA_H7_M7.ota has been uploaded to:

https://downloads.arduino.cc/ota/OTA_Usage_Portenta.ino.PORTENTA_H7_M7.ota

You can change the default file location on the code by modifying the next line on the *"OTA_Qspi_Flash" sketch or in the "OTA_SD_Portenta" sketch depending on which method are you going to follow:

1static char const OTA_FILE_LOCATION[] = "Introduce here your online OTA file location";

It is important to know that if your OTA file is uploaded to an HTTPS website you will need to modify the next line in the code:

1int const ota_download = ota.download(OTA_FILE_LOCATION, true /* is_https */);

This line is in line 87 for the "OTA_Qspi_Flash" sketch or in line 88 on the "OTA_SD_Portenta" sketch.

If you are going to use the example OTA file used in this tutorial you don't need to follow the steps in this section, just execute the sketch with the default file location.

Now you have two options to choose, use QSPI or use an SD Card to storage your OTA file. You can use the left side index to jump to the option that you may need.

QSPI Storage Mode

Setting Up

To use internal QSPI storage for downloading the binary file via OTA (Over-The-Air), you will only need the Arduino Portenta H7 board connected to the computer with the Arduino IDE. With it, you will need to have selected the Arduino Portenta H7 (M7 Core) with the Flash split of 1 MB M7 + 1 MB M4 for the purpose of this tutorial and the corresponding port.

Arduino Portenta H7 Board Connection
Arduino Portenta H7 Board Connection

Writing the Script

To proceed with a OTA using the QSPI flash, you can open the sketch from Examples >Arduino_Portenta_OTA > OTA_Qspi_Flash.

Do not forget to fill your Wi-Fi AP SSID and password on the

arduino_secrets.h
tab.

This sketch will connect to your Wi-Fi, verify whether the OTA feature is available by checking the installed firmware on your Portenta.

Then prepare the OTA storage, download the .ota file from the internet, decompress it, reset the board so after the reboot it will swipe the new firmware and you will notice it by checking the Built-in LED flashing on red, green and blue.

SD Card Storage Mode

Setting Up

To use the SD card as the preferred OTA (Over-The-Air) storage device, you can use the Arduino Portenta Vision Shield and Portenta H7 connected via HD (High-Density) Connectors.

Arduino Portenta H7 with Portenta Vision Shield - Ethernet

With this, you will need the Arduino Portenta H7 board connected to the computer with the Arduino IDE. You will need to have selected the Arduino Portenta H7 (M7 Core) with the Flash split of 1MB M7 + 1 MB M4 for the purpose of this tutorial and the corresponding port.

Writing the Script

As same as QSPI storage mode, to proceed with a OTA using the SD Card, you can open the sketch from Examples > Arduino_Portenta_OTA > OTA_SD_Portenta.

Do not forget to fill your Wi-Fi AP SSID and password on the

arduino_secrets.h
tab.

This sketch will connect to your Wi-Fi, verify whether the OTA feature is available by checking the installed firmware on your Portenta.

Then prepare the OTA storage, download the .ota file from the internet, decompress it, reset the board so after the reboot it will swipe the new firmware and you will notice it by checking the Built-in LED flashing on red, green and blue.

Testing the Code

Having successfully uploaded the code and completed the OTA process, you will be able to see the Arduino Portenta H7 blinking LED Red, Blue, Green in a cyclic manner. You will also be able to see process log in the Serial Monitor provided by Arduino IDE for more details.

Arduino Portenta H7 OTA Completion with Cyclic RGB Blink
Arduino Portenta H7 OTA QSPI Serial Monitor Log
Arduino Portenta H7 OTA QSPI Serial Monitor Log
Arduino Portenta H7 OTA SD Card Serial Monitor Log
Arduino Portenta H7 OTA SD Card Serial Monitor Log

Conclusion

You have now learned how to use the OTA feature provided by the Arduino Portenta H7, by updating its firmware. You will now be able to create the OTA file with the sketch designed by yourself and use this to update Arduino Portenta H7’s firmware via OTA (Over-The-Air) feature with either QSPI or SD card storage mechanism.

Next Steps

Now, with the OTA capability in place, you can design future-proof system based on Arduino Portenta H7 or try different system disciplines using the OTA capability.

Full Sketches

The complete script is as follows.

QSPI Storage Mode

1#include <Arduino_Portenta_OTA.h>
2#include <WiFi.h>
3#include "arduino_secrets.h"
4
5static char const SSID[] = SSID_NAME; /* your network SSID (name) */
6static char const PASS[] = SSID_PASS; /* your network password (use for WPA, or use as key for WEP) */
7
8static char const OTA_FILE_LOCATION[] = "https://downloads.arduino.cc/ota/OTA_Usage_Portenta.ino.PORTENTA_H7_M7.ota";
9
10void setup()
11{
12 Serial.begin(115200);
13 while (!Serial) {}
14
15 if (WiFi.status() == WL_NO_SHIELD)
16 {
17 Serial.println("Communication with WiFi module failed!");
18 return;
19 }
20
21 int status = WL_IDLE_STATUS;
22 while (status != WL_CONNECTED)
23 {
24 Serial.print ("Attempting to connect to '");
25 Serial.print (SSID);
26 Serial.println("'");
27 status = WiFi.begin(SSID, PASS);
28 delay(10000);
29 }
30 Serial.print ("You're connected to '");
31 Serial.print (WiFi.SSID());
32 Serial.println("'");
33
34 Arduino_Portenta_OTA_QSPI ota(QSPI_FLASH_FATFS_MBR, 2);
35 Arduino_Portenta_OTA::Error ota_err = Arduino_Portenta_OTA::Error::None;
36
37 if (!ota.isOtaCapable())
38 {
39 Serial.println("Higher version bootloader required to perform OTA.");
40 Serial.println("Please update the bootloader.");
41 Serial.println("File -> Examples -> STM32H747_System -> STM32H747_updateBootloader");
42 return;
43 }
44
45 Serial.println("Initializing OTA storage");
46 if ((ota_err = ota.begin()) != Arduino_Portenta_OTA::Error::None)
47 {
48 Serial.print ("Arduino_Portenta_OTA::begin() failed with error code ");
49 Serial.println((int)ota_err);
50 return;
51 }
52
53 Serial.println("Starting download to QSPI ...");
54 int const ota_download = ota.download(OTA_FILE_LOCATION, false /* is_https */);
55 if (ota_download <= 0)
56 {
57 Serial.print ("Arduino_Portenta_OTA_QSPI::download failed with error code ");
58 Serial.println(ota_download);
59 return;
60 }
61 Serial.print (ota_download);
62 Serial.println(" bytes stored.");
63
64
65 Serial.println("Decompressing LZSS compressed file ...");
66 int const ota_decompress = ota.decompress();
67 if (ota_decompress < 0)
68 {
69 Serial.print("Arduino_Portenta_OTA_QSPI::decompress() failed with error code");
70 Serial.println(ota_decompress);
71 return;
72 }
73 Serial.print(ota_decompress);
74 Serial.println(" bytes decompressed.");
75
76
77 Serial.println("Storing parameters for firmware update in bootloader accessible non-volatile memory ...");
78 if ((ota_err = ota.update()) != Arduino_Portenta_OTA::Error::None)
79 {
80 Serial.print ("ota.update() failed with error code ");
81 Serial.println((int)ota_err);
82 return;
83 }
84
85 Serial.println("Performing a reset after which the bootloader will update the firmware.");
86 Serial.println("Hint: Portenta H7 LED will blink Red-Blue-Green.");
87 delay(1000); /* Make sure the serial message gets out before the reset. */
88 ota.reset();
89}
90
91void loop()
92{
93}

SD Card Storage Mode

1#include <Arduino_Portenta_OTA.h>
2#include <WiFi.h>
3#include "arduino_secrets.h"
4
5static char const SSID[] = SSID_NAME; /* your network SSID (name) */
6static char const PASS[] = SSID_PASS; /* your network password (use for WPA, or use as key for WEP) */
7
8static char const OTA_FILE_LOCATION[] = "https://downloads.arduino.cc/ota/OTA_Usage_Portenta.ino.PORTENTA_H7_M7.ota";
9
10void setup()
11{
12 Serial.begin(115200);
13 while (!Serial) {}
14
15 if (WiFi.status() == WL_NO_SHIELD)
16 {
17 Serial.println("Communication with WiFi module failed!");
18 return;
19 }
20
21 int status = WL_IDLE_STATUS;
22 while (status != WL_CONNECTED)
23 {
24 Serial.print ("Attempting to connect to '");
25 Serial.print (SSID);
26 Serial.println("'");
27 status = WiFi.begin(SSID, PASS);
28 delay(10000);
29 }
30 Serial.print ("You're connected to '");
31 Serial.print (WiFi.SSID());
32 Serial.println("'");
33
34 Arduino_Portenta_OTA_SD ota(SD_FATFS_MBR, 1);
35 Arduino_Portenta_OTA::Error ota_err = Arduino_Portenta_OTA::Error::None;
36
37 if (!ota.isOtaCapable())
38 {
39 Serial.println("Higher version bootloader required to perform OTA.");
40 Serial.println("Please update the bootloader.");
41 Serial.println("File -> Examples -> STM32H747_System -> STM32H747_updateBootloader ");
42 return;
43 }
44
45 Serial.println("Initializing OTA storage");
46 if ((ota_err = ota.begin()) != Arduino_Portenta_OTA::Error::None)
47 {
48 Serial.print ("Arduino_Portenta_OTA::begin() failed with error code ");
49 Serial.println((int)ota_err);
50 return;
51 }
52
53
54 Serial.println("Starting download to SD ...");
55 int const ota_download = ota.download(OTA_FILE_LOCATION, false /* is_https */);
56 if (ota_download <= 0)
57 {
58 Serial.print ("Arduino_Portenta_OTA_SD::download failed with error code ");
59 Serial.println(ota_download);
60 return;
61 }
62 Serial.print (ota_download);
63 Serial.println(" bytes stored.");
64
65
66 Serial.println("Decompressing LZSS compressed file ...");
67 int const ota_decompress = ota.decompress();
68 if (ota_decompress < 0)
69 {
70 Serial.print("Arduino_Portenta_OTA_SD::decompress() failed with error code");
71 Serial.println(ota_decompress);
72 return;
73 }
74 Serial.print(ota_decompress);
75 Serial.println(" bytes decompressed.");
76
77
78 Serial.println("Storing parameters for firmware update in bootloader accessible non-volatile memory");
79 if ((ota_err = ota.update()) != Arduino_Portenta_OTA::Error::None)
80 {
81 Serial.print ("Arduino_Portenta_OTA::update() failed with error code ");
82 Serial.println((int)ota_err);
83 return;
84 }
85
86 Serial.println("Performing a reset after which the bootloader will update the firmware.");
87 Serial.println("Hint: Portenta H7 LED will blink Red-Blue-Green.");
88 delay(1000);
89 ota.reset();
90}
91
92void loop()
93{
94}

Troubleshooting

For troubleshooting the issues that might have arose following the tutorial, you can use following tips to solve the issue.

  • If there has been an issue with Wi-Fi module, it means the device may have suffered from losing the Wi-Fi firmware partition. To solve this, you will have to use PortentaWiFiFirmwareupdater sketch found on Arduino IDE examples to fix the issue.
  • QSPI storage may throw error -3 while running Portenta H7 OTA QSPI example. To fix this, you can use this guide of Reading and Writing Flash Memory in the section Programming the QSPI Flash. At this point, run the example and it should have been solved by eliminating error -3 (OTA Storage initialization error).

Suggest changes

The content on docs.arduino.cc is facilitated through a public GitHub repository. If you see anything wrong, you can edit this page here.

License

The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike 4.0 license.