Skip to content

Commit

Permalink
Merge pull request #225 from arduino-libraries/portenta_ota
Browse files Browse the repository at this point in the history
Add support for OTA on Portenta H7
  • Loading branch information
aentinger authored Feb 2, 2021
2 parents dfe1894 + 43476ac commit 60cdc4d
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 13 deletions.
1 change: 1 addition & 0 deletions .github/workflows/compile-examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ jobs:
name: arduino:mbed
libraries: |
- name: ArduinoECCX08
- source-url: https://github.com/arduino-libraries/Arduino_Portenta_OTA.git
sketch-paths: |
- examples/utility/Provisioning
# ESP8266 boards
Expand Down
2 changes: 2 additions & 0 deletions extras/tools/bin2ota.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
magic_number = 0x23418054.to_bytes(4,byteorder='little')
elif board == "NANO_33_IOT":
magic_number = 0x23418057.to_bytes(4,byteorder='little')
elif board == "PORTENTA_H7_M7":
magic_number = 0x2341025B.to_bytes(4,byteorder='little')
else:
print ("Error,", board, "is not a supported board type")
sys.exit()
Expand Down
8 changes: 7 additions & 1 deletion src/AIoTC_Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,13 @@
#define OTA_STORAGE_SSU (0)
#endif

#if (OTA_STORAGE_SFU || OTA_STORAGE_SSU || OTA_STORAGE_SNU) && !defined(ARDUINO_AVR_UNO_WIFI_REV2)
#if defined(ARDUINO_PORTENTA_H7_M7)
#define OTA_STORAGE_PORTENTA_QSPI (1)
#else
#define OTA_STORAGE_PORTENTA_QSPI (0)
#endif

#if (OTA_STORAGE_SFU || OTA_STORAGE_SSU || OTA_STORAGE_SNU || OTA_STORAGE_PORTENTA_QSPI) && !defined(ARDUINO_AVR_UNO_WIFI_REV2)
#define OTA_ENABLED (1)
#else
#define OTA_ENABLED (0)
Expand Down
71 changes: 59 additions & 12 deletions src/ArduinoIoTCloudTCP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,12 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort)
* The bootloader is excluded from the calculation and occupies flash address
* range 0 to 0x2000, total flash size of 0x40000 bytes (256 kByte).
*/
#if defined(ARDUINO_PORTENTA_H7_M7)
// TODO: check if we need to checksum the whole flash or just the first megabyte
_ota_img_sha256 = FlashSHA256::calc(0x8040000, 0x200000 - 0x40000);
#else
_ota_img_sha256 = FlashSHA256::calc(0x2000, 0x40000 - 0x2000);
#endif
#endif /* OTA_ENABLED */

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

#if OTA_STORAGE_PORTENTA_QSPI
#define BOOTLOADER_ADDR (0x8000000)
uint32_t bootloader_data_offset = 0x1F000;
uint8_t* bootloader_data = (uint8_t*)(BOOTLOADER_ADDR + bootloader_data_offset);
uint8_t currentBootloaderVersion = bootloader_data[1];
if (currentBootloaderVersion < 22) {
_ota_cap = false;
DEBUG_WARNING("ArduinoIoTCloudTCP::%s In order to be ready for cloud OTA, update the bootloader", __FUNCTION__);
DEBUG_WARNING("ArduinoIoTCloudTCP::%s File -> Examples -> Portenta_System -> PortentaH7_updateBootloader", __FUNCTION__);
}
else {
_ota_cap = true;
}
#endif

#if OTA_STORAGE_SNU && OTA_ENABLED
String const nina_fw_version = WiFi.firmwareVersion();
if (nina_fw_version < "1.4.1") {
Expand Down Expand Up @@ -443,11 +463,6 @@ void ArduinoIoTCloudTCP::onOTARequest()
{
DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s _ota_url = %s", __FUNCTION__, _ota_url.c_str());

/* Status flag to prevent the reset from being executed
* when HTTPS download is not supported.
*/
bool ota_download_success = false;

#if OTA_STORAGE_SNU
/* Just to be safe delete any remains from previous updates. */
WiFiStorage.remove("/fs/UPDATE.BIN.LZSS");
Expand All @@ -462,15 +477,47 @@ void ArduinoIoTCloudTCP::onOTARequest()
return;
}

/* The download was a success. */
ota_download_success = true;
/* Perform the reset to reboot to SxU. */
NVIC_SystemReset();
#endif /* OTA_STORAGE_SNU */

#ifndef __AVR__
/* Perform the reset to reboot to SxU. */
if (ota_download_success)
NVIC_SystemReset();
#endif
#if OTA_STORAGE_PORTENTA_QSPI
Arduino_Portenta_OTA::Error ota_portenta_err = Arduino_Portenta_OTA::Error::None;
/* Use 2nd partition of QSPI (1st partition contains WiFi firmware) */
Arduino_Portenta_OTA_QSPI ota_portenta_qspi(QSPI_FLASH_FATFS_MBR, 2);

/* Initialize the QSPI memory for OTA handling. */
if((ota_portenta_err = ota_portenta_qspi.begin()) != Arduino_Portenta_OTA::Error::None) {
DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::begin() failed with %d", static_cast<int>(ota_portenta_err));
return;
}

/* Just to be safe delete any remains from previous updates. */
remove("/fs/UPDATE.BIN");
remove("/fs/UPDATE.BIN.LZSS");

/* Download the OTA file from the web storage location. */
int const ota_portenta_qspi_download_ret_code = ota_portenta_qspi.download((char*)(_ota_url.c_str()), true /* is_https */);
DEBUG_VERBOSE("Arduino_Portenta_OTA_QSPI::download(%s) returns %d", _ota_url.c_str(), ota_portenta_qspi_download_ret_code);

/* Decompress the LZSS compressed OTA file. */
int const ota_portenta_qspi_decompress_ret_code = ota_portenta_qspi.decompress();
DEBUG_VERBOSE("Arduino_Portenta_OTA_QSPI::decompress() returns %d", ota_portenta_qspi_decompress_ret_code);
if (ota_portenta_qspi_decompress_ret_code < 0)
{
DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::decompress() failed with %d", ota_portenta_qspi_decompress_ret_code);
return;
}

/* Schedule the firmware update. */
if((ota_portenta_err = ota_portenta_qspi.update()) != Arduino_Portenta_OTA::Error::None) {
DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::update() failed with %d", static_cast<int>(ota_portenta_err));
return;
}

/* Perform the reset to reboot - then the bootloader performs the actual application update. */
NVIC_SystemReset();
#endif /* OTA_STORAGE_PORTENTA_QSPI */
}
#endif

Expand Down
4 changes: 4 additions & 0 deletions src/utility/ota/OTA.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
#include <SFU.h>
#endif /* OTA_STORAGE_SFU */

#if OTA_STORAGE_PORTENTA_QSPI
#include <Arduino_Portenta_OTA.h>
#endif /* OTA_STORAGE_PORTENTA_QSPI */

/******************************************************************************
* TYPEDEF
******************************************************************************/
Expand Down

0 comments on commit 60cdc4d

Please sign in to comment.