@@ -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
0 commit comments