diff --git a/boards.txt b/boards.txt index 79a40e70e..048ca551d 100644 --- a/boards.txt +++ b/boards.txt @@ -444,7 +444,7 @@ nicla_sense.upload.native_usb=true nicla_sense.upload.maximum_size=527616 nicla_sense.upload.maximum_data_size=64288 nicla_sense.programmer.protocol=cmsis-dap -nicla_sense.programmer.transport_script={runtime.platform.path}/debugger/select_swd.cfg +nicla_sense.programmer.transport_script="{runtime.platform.path}/debugger/select_swd.cfg" nicla_sense.bootloader.tool=openocd nicla_sense.bootloader.tool.default=openocd @@ -499,7 +499,7 @@ nicla_voice.upload.native_usb=true nicla_voice.upload.maximum_size=527616 nicla_voice.upload.maximum_data_size=64288 nicla_voice.programmer.protocol=cmsis-dap -nicla_voice.programmer.transport_script={runtime.platform.path}/debugger/select_swd.cfg +nicla_voice.programmer.transport_script="{runtime.platform.path}/debugger/select_swd.cfg" nicla_voice.bootloader.tool=openocd nicla_voice.bootloader.tool.default=openocd diff --git a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino index 8d2b537dc..b3ecbf222 100644 --- a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino +++ b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino @@ -1,23 +1,28 @@ -#include "QSPIFBlockDevice.h" +#include "BlockDevice.h" #include "MBRBlockDevice.h" #include "LittleFileSystem.h" #include "FATFileSystem.h" +#include "wiced_resource.h" +#include "certificates.h" -#ifndef CORE_CM7 +#ifndef CORE_CM7 #error Format QSPI flash by uploading the sketch to the M7 core instead of the M4 core. #endif +using namespace mbed; -QSPIFBlockDevice root(QSPI_SO0, QSPI_SO1, QSPI_SO2, QSPI_SO3, QSPI_SCK, QSPI_CS, QSPIF_POLARITY_MODE_1, 40000000); -mbed::MBRBlockDevice wifi_data(&root, 1); -mbed::MBRBlockDevice ota_data(&root, 2); -mbed::MBRBlockDevice user_data(&root, 3); -mbed::FATFileSystem wifi_data_fs("wlan"); -mbed::FATFileSystem ota_data_fs("fs"); -mbed::FileSystem * user_data_fs; +BlockDevice* root = BlockDevice::get_default_instance(); +MBRBlockDevice wifi_data(root, 1); +MBRBlockDevice ota_data(root, 2); +MBRBlockDevice kvstore_data(root, 3); +MBRBlockDevice user_data(root, 4); +FATFileSystem wifi_data_fs("wlan"); +FATFileSystem ota_data_fs("fs"); +FileSystem * user_data_fs; bool waitResponse() { bool confirmation = false; + bool proceed = false; while (confirmation == false) { if (Serial.available()) { char choice = Serial.read(); @@ -25,18 +30,33 @@ bool waitResponse() { case 'y': case 'Y': confirmation = true; - return true; + proceed = true; break; case 'n': case 'N': confirmation = true; - return false; + proceed = false; break; default: continue; } } } + return proceed; +} + +void printProgress(uint32_t offset, uint32_t size, uint32_t threshold, bool reset) { + static int percent_done = 0; + if (reset == true) { + percent_done = 0; + Serial.println("Flashed " + String(percent_done) + "%"); + } else { + uint32_t percent_done_new = offset * 100 / size; + if (percent_done_new >= percent_done + threshold) { + percent_done = percent_done_new; + Serial.println("Flashed " + String(percent_done) + "%"); + } + } } void setup() { @@ -44,69 +64,142 @@ void setup() { Serial.begin(115200); while (!Serial); - Serial.println("Available partition schemes:"); - Serial.println("\nPartition scheme 1"); - Serial.println("Partition 1: WiFi firmware and certificates 1MB"); - Serial.println("Partition 2: OTA and user data 13MB"); - Serial.println("\nPartition scheme 2"); + Serial.println("\nWARNING! Running the sketch all the content of the QSPI flash will be erased."); + Serial.println("The following partitions will be created:"); Serial.println("Partition 1: WiFi firmware and certificates 1MB"); Serial.println("Partition 2: OTA 5MB"); - Serial.println("Partition 3: User data 8MB"), - Serial.println("\nDo you want to use partition scheme 1? Y/[n]"); - Serial.println("If No, partition scheme 2 will be used."); - bool default_scheme = waitResponse(); - - Serial.println("\nWARNING! Running the sketch all the content of the QSPI flash will be erased."); + Serial.println("Partition 3: Provisioning KVStore 1MB"); + Serial.println("Partition 4: User data / OPTA PLC runtime 7MB"), Serial.println("Do you want to proceed? Y/[n]"); if (true == waitResponse()) { - mbed::MBRBlockDevice::partition(&root, 1, 0x0B, 0, 1024 * 1024); - if(default_scheme) { - mbed::MBRBlockDevice::partition(&root, 3, 0x0B, 14 * 1024 * 1024, 14 * 1024 * 1024); - mbed::MBRBlockDevice::partition(&root, 2, 0x0B, 1024 * 1024, 14 * 1024 * 1024); - // use space from 15.5MB to 16 MB for another fw, memory mapped + if (root->init() != BD_ERROR_OK) { + Serial.println(F("Error: QSPI init failure.")); + return; + } + + Serial.println("Do you want to perform a full erase of the QSPI flash before proceeding? Y/[n]"); + if (true == waitResponse()) { + root->erase(0x0, root->size()); } else { - mbed::MBRBlockDevice::partition(&root, 2, 0x0B, 1024 * 1024, 6 * 1024 * 1024); - mbed::MBRBlockDevice::partition(&root, 3, 0x0B, 6 * 1024 * 1024, 14 * 1024 * 1024); - // use space from 15.5MB to 16 MB for another fw, memory mapped + // Erase only the first sector containing the MBR + root->erase(0x0, root->get_erase_size()); + } + + MBRBlockDevice::partition(root, 1, 0x0B, 0, 1 * 1024 * 1024); + MBRBlockDevice::partition(root, 2, 0x0B, 1 * 1024 * 1024, 6 * 1024 * 1024); + MBRBlockDevice::partition(root, 3, 0x0B, 6 * 1024 * 1024, 7 * 1024 * 1024); + MBRBlockDevice::partition(root, 4, 0x0B, 7 * 1024 * 1024, 14 * 1024 * 1024); + // use space from 15.5MB to 16 MB for another fw, memory mapped + + bool reformat = true; + if(!wifi_data_fs.mount(&wifi_data)) { + Serial.println("\nPartition 1 already contains a filesystem, do you want to reformat it? Y/[n]"); + wifi_data_fs.unmount(); + + reformat = waitResponse(); } - int err = wifi_data_fs.reformat(&wifi_data); - if (err) { + if (reformat && wifi_data_fs.reformat(&wifi_data)) { Serial.println("Error formatting WiFi partition"); return; } - - err = ota_data_fs.reformat(&ota_data); - if (err) { + + bool restore = true; + if (reformat) { + Serial.println("\nDo you want to restore the WiFi firmware and certificates? Y/[n]"); + restore = waitResponse(); + } + + if (reformat && restore) { + flashWiFiFirmwareAndCertificates(); + } + + reformat = true; + if(!ota_data_fs.mount(&ota_data)) { + Serial.println("\nPartition 2 already contains a filesystem, do you want to reformat it? Y/[n]"); + ota_data_fs.unmount(); + + reformat = waitResponse(); + } + + if (reformat && ota_data_fs.reformat(&ota_data)) { Serial.println("Error formatting OTA partition"); return; } - if(!default_scheme) { - Serial.println("\nDo you want to use LittleFS to format user data partition? Y/[n]"); - Serial.println("If No, FatFS will be used to format user partition."); + Serial.println("\nDo you want to use LittleFS to format user data partition? Y/[n]"); + Serial.println("If No, FatFS will be used to format user partition."); + Serial.println("Note: LittleFS is not supported by the OPTA PLC runtime."); + if (true == waitResponse()) { + Serial.println("Formatting user partition with LittleFS."); + user_data_fs = new mbed::LittleFileSystem("user"); + } else { + Serial.println("Formatting user partition with FatFS."); + user_data_fs = new mbed::FATFileSystem("user"); + } - if (true == waitResponse()) { - Serial.println("Formatting user partition with LittleFS."); - user_data_fs = new mbed::LittleFileSystem("user"); - } else { - Serial.println("Formatting user partition with FatFS."); - user_data_fs = new mbed::FATFileSystem("user"); - } + reformat = true; + if(!user_data_fs->mount(&user_data)) { + Serial.println("\nPartition 4 already contains a filesystem, do you want to reformat it? Y/[n]"); + user_data_fs->unmount(); - err = user_data_fs->reformat(&user_data); - if (err) { - Serial.println("Error formatting user partition"); - return; - } + reformat = waitResponse(); + } + + if (reformat && user_data_fs->reformat(&user_data)) { + Serial.println("Error formatting user partition"); + return; } + Serial.println("\nQSPI Flash formatted!"); } Serial.println("It's now safe to reboot or disconnect your board."); } +void flashWiFiFirmwareAndCertificates() { + extern const unsigned char wifi_firmware_image_data[]; + FILE* fp = fopen("/wlan/4343WA1.BIN", "wb"); + const uint32_t file_size = 421098; + uint32_t chunck_size = 1024; + uint32_t byte_count = 0; + + Serial.println("Flashing WiFi firmware"); + printProgress(byte_count, file_size, 10, true); + while (byte_count < file_size) { + if(byte_count + chunck_size > file_size) + chunck_size = file_size - byte_count; + int ret = fwrite(&wifi_firmware_image_data[byte_count], chunck_size, 1, fp); + if (ret != 1) { + Serial.println("Error writing firmware data"); + break; + } + byte_count += chunck_size; + printProgress(byte_count, file_size, 10, false); + } + fclose(fp); + + fp = fopen("/wlan/cacert.pem", "wb"); + + Serial.println("Flashing certificates"); + chunck_size = 128; + byte_count = 0; + printProgress(byte_count, cacert_pem_len, 10, true); + while (byte_count < cacert_pem_len) { + if(byte_count + chunck_size > cacert_pem_len) + chunck_size = cacert_pem_len - byte_count; + int ret = fwrite(&cacert_pem[byte_count], chunck_size, 1 ,fp); + if (ret != 1) { + Serial.println("Error writing certificates"); + break; + } + byte_count += chunck_size; + printProgress(byte_count, cacert_pem_len, 10, false); + } + fclose(fp); +} + void loop() { } diff --git a/libraries/STM32H747_System/examples/QSPIFormat/certificates.h b/libraries/STM32H747_System/examples/QSPIFormat/certificates.h new file mode 120000 index 000000000..7b4170776 --- /dev/null +++ b/libraries/STM32H747_System/examples/QSPIFormat/certificates.h @@ -0,0 +1 @@ +../WiFiFirmwareUpdater/certificates.h \ No newline at end of file