Skip to content

Commit 60cdc4d

Browse files
authored
Merge pull request #225 from arduino-libraries/portenta_ota
Add support for OTA on Portenta H7
2 parents dfe1894 + 43476ac commit 60cdc4d

File tree

5 files changed

+73
-13
lines changed

5 files changed

+73
-13
lines changed

.github/workflows/compile-examples.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ jobs:
137137
name: arduino:mbed
138138
libraries: |
139139
- name: ArduinoECCX08
140+
- source-url: https://github.com/arduino-libraries/Arduino_Portenta_OTA.git
140141
sketch-paths: |
141142
- examples/utility/Provisioning
142143
# ESP8266 boards

extras/tools/bin2ota.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
magic_number = 0x23418054.to_bytes(4,byteorder='little')
2323
elif board == "NANO_33_IOT":
2424
magic_number = 0x23418057.to_bytes(4,byteorder='little')
25+
elif board == "PORTENTA_H7_M7":
26+
magic_number = 0x2341025B.to_bytes(4,byteorder='little')
2527
else:
2628
print ("Error,", board, "is not a supported board type")
2729
sys.exit()

src/AIoTC_Config.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,13 @@
100100
#define OTA_STORAGE_SSU (0)
101101
#endif
102102

103-
#if (OTA_STORAGE_SFU || OTA_STORAGE_SSU || OTA_STORAGE_SNU) && !defined(ARDUINO_AVR_UNO_WIFI_REV2)
103+
#if defined(ARDUINO_PORTENTA_H7_M7)
104+
#define OTA_STORAGE_PORTENTA_QSPI (1)
105+
#else
106+
#define OTA_STORAGE_PORTENTA_QSPI (0)
107+
#endif
108+
109+
#if (OTA_STORAGE_SFU || OTA_STORAGE_SSU || OTA_STORAGE_SNU || OTA_STORAGE_PORTENTA_QSPI) && !defined(ARDUINO_AVR_UNO_WIFI_REV2)
104110
#define OTA_ENABLED (1)
105111
#else
106112
#define OTA_ENABLED (0)

src/ArduinoIoTCloudTCP.cpp

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,12 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort)
123123
* The bootloader is excluded from the calculation and occupies flash address
124124
* range 0 to 0x2000, total flash size of 0x40000 bytes (256 kByte).
125125
*/
126+
#if defined(ARDUINO_PORTENTA_H7_M7)
127+
// TODO: check if we need to checksum the whole flash or just the first megabyte
128+
_ota_img_sha256 = FlashSHA256::calc(0x8040000, 0x200000 - 0x40000);
129+
#else
126130
_ota_img_sha256 = FlashSHA256::calc(0x2000, 0x40000 - 0x2000);
131+
#endif
127132
#endif /* OTA_ENABLED */
128133

129134
#ifdef BOARD_HAS_OFFLOADED_ECCX08
@@ -186,6 +191,21 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort)
186191
addPropertyReal(_ota_req, "OTA_REQ", Permission::ReadWrite).onSync(DEVICE_WINS);
187192
#endif /* OTA_ENABLED */
188193

194+
#if OTA_STORAGE_PORTENTA_QSPI
195+
#define BOOTLOADER_ADDR (0x8000000)
196+
uint32_t bootloader_data_offset = 0x1F000;
197+
uint8_t* bootloader_data = (uint8_t*)(BOOTLOADER_ADDR + bootloader_data_offset);
198+
uint8_t currentBootloaderVersion = bootloader_data[1];
199+
if (currentBootloaderVersion < 22) {
200+
_ota_cap = false;
201+
DEBUG_WARNING("ArduinoIoTCloudTCP::%s In order to be ready for cloud OTA, update the bootloader", __FUNCTION__);
202+
DEBUG_WARNING("ArduinoIoTCloudTCP::%s File -> Examples -> Portenta_System -> PortentaH7_updateBootloader", __FUNCTION__);
203+
}
204+
else {
205+
_ota_cap = true;
206+
}
207+
#endif
208+
189209
#if OTA_STORAGE_SNU && OTA_ENABLED
190210
String const nina_fw_version = WiFi.firmwareVersion();
191211
if (nina_fw_version < "1.4.1") {
@@ -443,11 +463,6 @@ void ArduinoIoTCloudTCP::onOTARequest()
443463
{
444464
DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s _ota_url = %s", __FUNCTION__, _ota_url.c_str());
445465

446-
/* Status flag to prevent the reset from being executed
447-
* when HTTPS download is not supported.
448-
*/
449-
bool ota_download_success = false;
450-
451466
#if OTA_STORAGE_SNU
452467
/* Just to be safe delete any remains from previous updates. */
453468
WiFiStorage.remove("/fs/UPDATE.BIN.LZSS");
@@ -462,15 +477,47 @@ void ArduinoIoTCloudTCP::onOTARequest()
462477
return;
463478
}
464479

465-
/* The download was a success. */
466-
ota_download_success = true;
480+
/* Perform the reset to reboot to SxU. */
481+
NVIC_SystemReset();
467482
#endif /* OTA_STORAGE_SNU */
468483

469-
#ifndef __AVR__
470-
/* Perform the reset to reboot to SxU. */
471-
if (ota_download_success)
472-
NVIC_SystemReset();
473-
#endif
484+
#if OTA_STORAGE_PORTENTA_QSPI
485+
Arduino_Portenta_OTA::Error ota_portenta_err = Arduino_Portenta_OTA::Error::None;
486+
/* Use 2nd partition of QSPI (1st partition contains WiFi firmware) */
487+
Arduino_Portenta_OTA_QSPI ota_portenta_qspi(QSPI_FLASH_FATFS_MBR, 2);
488+
489+
/* Initialize the QSPI memory for OTA handling. */
490+
if((ota_portenta_err = ota_portenta_qspi.begin()) != Arduino_Portenta_OTA::Error::None) {
491+
DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::begin() failed with %d", static_cast<int>(ota_portenta_err));
492+
return;
493+
}
494+
495+
/* Just to be safe delete any remains from previous updates. */
496+
remove("/fs/UPDATE.BIN");
497+
remove("/fs/UPDATE.BIN.LZSS");
498+
499+
/* Download the OTA file from the web storage location. */
500+
int const ota_portenta_qspi_download_ret_code = ota_portenta_qspi.download((char*)(_ota_url.c_str()), true /* is_https */);
501+
DEBUG_VERBOSE("Arduino_Portenta_OTA_QSPI::download(%s) returns %d", _ota_url.c_str(), ota_portenta_qspi_download_ret_code);
502+
503+
/* Decompress the LZSS compressed OTA file. */
504+
int const ota_portenta_qspi_decompress_ret_code = ota_portenta_qspi.decompress();
505+
DEBUG_VERBOSE("Arduino_Portenta_OTA_QSPI::decompress() returns %d", ota_portenta_qspi_decompress_ret_code);
506+
if (ota_portenta_qspi_decompress_ret_code < 0)
507+
{
508+
DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::decompress() failed with %d", ota_portenta_qspi_decompress_ret_code);
509+
return;
510+
}
511+
512+
/* Schedule the firmware update. */
513+
if((ota_portenta_err = ota_portenta_qspi.update()) != Arduino_Portenta_OTA::Error::None) {
514+
DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::update() failed with %d", static_cast<int>(ota_portenta_err));
515+
return;
516+
}
517+
518+
/* Perform the reset to reboot - then the bootloader performs the actual application update. */
519+
NVIC_SystemReset();
520+
#endif /* OTA_STORAGE_PORTENTA_QSPI */
474521
}
475522
#endif
476523

src/utility/ota/OTA.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737
#include <SFU.h>
3838
#endif /* OTA_STORAGE_SFU */
3939

40+
#if OTA_STORAGE_PORTENTA_QSPI
41+
#include <Arduino_Portenta_OTA.h>
42+
#endif /* OTA_STORAGE_PORTENTA_QSPI */
43+
4044
/******************************************************************************
4145
* TYPEDEF
4246
******************************************************************************/

0 commit comments

Comments
 (0)