diff --git a/firmware/flashing/manifest_generator.py b/firmware/flashing/manifest_generator.py index 623e6e56a..0be27a790 100755 --- a/firmware/flashing/manifest_generator.py +++ b/firmware/flashing/manifest_generator.py @@ -107,15 +107,15 @@ def parse_file_version(version): if args.assets_file: j["files"].append(process_file(destination_dir, args.assets_file, "app", name="Assets", address=0xa00000)) + if args.wifi_fs_file: + j["files"].append(process_file(destination_dir, args.wifi_fs_file, "wifi", name="Wifi Filesystem", address=0x200000, compressed=True)) + if args.wifi_bl_file: j["files"].append(process_file(destination_dir, args.wifi_bl_file, "wifi", name="Wifi Bootloader", address=0x0)) if args.wifi_app_file: j["files"].append(process_file(destination_dir, args.wifi_app_file, "wifi", name="Wifi Application", address=0x10000)) - if args.wifi_fs_file: - j["files"].append(process_file(destination_dir, args.wifi_fs_file, "wifi", name="Wifi Filesystem", address=0x200000, compressed=True)) - with open(args.out_file, "w+") as out_file: data_json = json.dumps(j, indent=4) out_file.write(data_json) diff --git a/firmware/lib/esp-serial-flasher b/firmware/lib/esp-serial-flasher index a787644fd..daaaf43d0 160000 --- a/firmware/lib/esp-serial-flasher +++ b/firmware/lib/esp-serial-flasher @@ -1 +1 @@ -Subproject commit a787644fd7001ef82017737b46113961ddc94a1f +Subproject commit daaaf43d0d5f704d933b07d9aa897bd50e334e2d diff --git a/firmware/src/core_intercom/intercore_message.hh b/firmware/src/core_intercom/intercore_message.hh index 90fe0c5d8..eaac48720 100644 --- a/firmware/src/core_intercom/intercore_message.hh +++ b/firmware/src/core_intercom/intercore_message.hh @@ -34,6 +34,9 @@ struct IntercoreStorageMessage { ChecksumMatch, ChecksumMismatch, ChecksumFailed, + ReadFlashFailed, + WifiExpanderNotConnected, + WifiExpanderCommError, StartFlashing, // write to Flash or WifiExpander FlashingOk, @@ -41,7 +44,6 @@ struct IntercoreStorageMessage { RequestReadFlash, ReadFlashOk, - ReadFlashFailed, RequestWriteFile, WriteFileFail, diff --git a/firmware/src/fw_update/firmware_writer.cc b/firmware/src/fw_update/firmware_writer.cc index 368b92809..793a10234 100644 --- a/firmware/src/fw_update/firmware_writer.cc +++ b/firmware/src/fw_update/firmware_writer.cc @@ -68,17 +68,17 @@ IntercoreStorageMessage FirmwareWriter::compareChecksumWifi(uint32_t address, ui returnValue = {.message_type = ChecksumMismatch}; } else if (result == ESP_LOADER_SUCCESS) { - pr_dbg("-> Checksum matches\n"); + pr_trace("-> Checksum matches\n"); returnValue = {.message_type = ChecksumMatch}; } else { - pr_err("-> Cannot get checksum\n"); - returnValue = {.message_type = ChecksumFailed}; + pr_trace("-> Cannot get checksum\n"); + returnValue = {.message_type = WifiExpanderCommError}; } } else { pr_err("Cannot connect to wifi bootloader\n"); - returnValue = {.message_type = ChecksumFailed}; + returnValue = {.message_type = WifiExpanderNotConnected}; } Flasher::deinit(); @@ -102,6 +102,7 @@ IntercoreStorageMessage FirmwareWriter::flashWifi(std::span buffer, if (result == ESP_LOADER_SUCCESS) { const std::size_t BatchSize = 1024; + HAL_Delay(20); result = Flasher::flash_start(address, buffer.size(), BatchSize, uncompressed_size); if (result == ESP_LOADER_SUCCESS) { @@ -127,7 +128,7 @@ IntercoreStorageMessage FirmwareWriter::flashWifi(std::span buffer, } if (not error_during_writes) { - pr_dbg("-> Flashing completed\n"); + pr_trace("-> Flashing completed\n"); returnValue = {.message_type = FlashingOk}; } else { pr_trace("-> Flashing failed\n"); diff --git a/firmware/src/fw_update/updater_proxy.cc b/firmware/src/fw_update/updater_proxy.cc index b8b130405..7e478e100 100644 --- a/firmware/src/fw_update/updater_proxy.cc +++ b/firmware/src/fw_update/updater_proxy.cc @@ -59,6 +59,8 @@ bool FirmwareUpdaterProxy::start(std::string_view manifest_filename, } FirmwareUpdaterProxy::Status FirmwareUpdaterProxy::process() { + error_message = ""; + switch (state) { case Idle: case Success: @@ -187,10 +189,25 @@ FirmwareUpdaterProxy::Status FirmwareUpdaterProxy::process() { moveToState(Writing); break; + case FileStorageProxy::WifiExpanderCommError: + case FileStorageProxy::ReadFlashFailed: case FileStorageProxy::ChecksumFailed: abortWithMessage("Error when comparing checksums"); break; + case FileStorageProxy::WifiExpanderNotConnected: { + error_message = "No Wifi Expander: skipping "; + + auto full_path = manifest.files[current_file_idx].filename; + auto slash_pos = full_path.find_first_of("/"); + if (slash_pos != std::string::npos) + error_message += full_path.substr(slash_pos + 1); + else + error_message += full_path; + + proceedWithNextFile(); + } break; + default: break; } @@ -217,7 +234,8 @@ FirmwareUpdaterProxy::Status FirmwareUpdaterProxy::process() { &sharedMem->bytes_processed); if (not result) { - abortWithMessage("Cannot trigger flashing"); + // this is not an error, just need to retry + justEnteredState = true; } } else { abortWithMessage("Invalid update file type"); @@ -244,9 +262,7 @@ FirmwareUpdaterProxy::Status FirmwareUpdaterProxy::process() { abortWithMessage("Internal Error"); } - return state == State::Error ? - Status{state, current_file_name, current_file_size, sharedMem->bytes_processed, error_message} : - Status{state, current_file_name, current_file_size, sharedMem->bytes_processed}; + return Status{state, current_file_name, current_file_size, sharedMem->bytes_processed, error_message}; } void FirmwareUpdaterProxy::abortWithMessage(const char *message) { diff --git a/firmware/src/fw_update/updater_proxy.hh b/firmware/src/fw_update/updater_proxy.hh index 1790a0cac..f0956d4b5 100644 --- a/firmware/src/fw_update/updater_proxy.hh +++ b/firmware/src/fw_update/updater_proxy.hh @@ -18,7 +18,7 @@ public: std::string name; std::size_t file_size{0}; std::size_t bytes_completed{0}; - std::string error_message{}; + std::string message{}; }; FirmwareUpdaterProxy(FileStorageProxy &file_storage); diff --git a/firmware/src/gui/pages/firmware_update_tab.hh b/firmware/src/gui/pages/firmware_update_tab.hh index 7b0aeb52e..26abe38a7 100644 --- a/firmware/src/gui/pages/firmware_update_tab.hh +++ b/firmware/src/gui/pages/firmware_update_tab.hh @@ -31,6 +31,8 @@ struct FirmwareUpdateTab : SystemMenuTab { display_file_not_found(); confirm_popup.init(ui_SystemMenu, group); + lv_label_set_text(ui_SystemMenuUpdateLog, ""); + lv_hide(ui_SystemMenUpdateProgressBar); } // Returns true if this pages uses the back event @@ -84,8 +86,11 @@ struct FirmwareUpdateTab : SystemMenuTab { case State::Updating: { auto status = updater.process(); + if (status.state != FirmwareUpdaterProxy::Error && status.message.length()) + append_log_message(status.message); + if (status.state == FirmwareUpdaterProxy::Error) { - display_update_failed(status.error_message); + display_update_failed(status.message); state = State::Failed; } else if (status.state == FirmwareUpdaterProxy::LoadingUpdateFiles) { @@ -204,6 +209,13 @@ private: lv_hide(ui_SystemMenUpdateProgressBar); } + void append_log_message(std::string_view message) { + std::string log = lv_label_get_text(ui_SystemMenuUpdateLog); + lv_label_set_text_fmt(ui_SystemMenuUpdateLog, "%s\n%.*s", log.c_str(), (int)message.length(), message.data()); + lv_hide(ui_FWUpdateSpinner); + lv_hide(ui_SystemMenUpdateProgressBar); + } + void display_success() { lv_obj_set_style_text_color(ui_SystemMenuUpdateMessage, lv_palette_lighten(LV_PALETTE_GREEN, 1), LV_PART_MAIN); lv_label_set_text(ui_SystemMenuUpdateMessage, "Success! Firmware has been updated. Power off and back on now"); diff --git a/firmware/src/gui/slsexport/meta5/screens/ui_SystemMenu.c b/firmware/src/gui/slsexport/meta5/screens/ui_SystemMenu.c index caf2c5f2d..5db2aa76d 100644 --- a/firmware/src/gui/slsexport/meta5/screens/ui_SystemMenu.c +++ b/firmware/src/gui/slsexport/meta5/screens/ui_SystemMenu.c @@ -1299,4 +1299,13 @@ lv_obj_set_style_text_color(ui_SystemMenuUpdateLog, lv_color_hex(0xFFFFFF), LV_P lv_obj_set_style_text_opa(ui_SystemMenuUpdateLog, 255, LV_PART_MAIN| LV_STATE_DEFAULT); lv_obj_set_style_text_font(ui_SystemMenuUpdateLog, &ui_font_MuseoSansRounded50012, LV_PART_MAIN| LV_STATE_DEFAULT); +ui_SystemMenuUpdateLog = lv_label_create(ui_SystemMenuUpdateTab); +lv_obj_set_width( ui_SystemMenuUpdateLog, lv_pct(100)); +lv_obj_set_height( ui_SystemMenuUpdateLog, LV_SIZE_CONTENT); /// 1 +lv_obj_set_align( ui_SystemMenuUpdateLog, LV_ALIGN_CENTER ); +lv_label_set_text(ui_SystemMenuUpdateLog,""); +lv_obj_set_style_text_color(ui_SystemMenuUpdateLog, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT ); +lv_obj_set_style_text_opa(ui_SystemMenuUpdateLog, 255, LV_PART_MAIN| LV_STATE_DEFAULT); +lv_obj_set_style_text_font(ui_SystemMenuUpdateLog, &ui_font_MuseoSansRounded50012, LV_PART_MAIN| LV_STATE_DEFAULT); + } diff --git a/firmware/src/wifi/comm/flat b/firmware/src/wifi/comm/flat index fbf6d5eb9..0bc644914 160000 --- a/firmware/src/wifi/comm/flat +++ b/firmware/src/wifi/comm/flat @@ -1 +1 @@ -Subproject commit fbf6d5eb9ac7911417fa3186d2dfd3b83780cb90 +Subproject commit 0bc644914efbd5adfe72f6f4fccbf8d1a67b7cc0 diff --git a/firmware/src/wifi/comm/wifi_interface.cc b/firmware/src/wifi/comm/wifi_interface.cc index 25d7952c6..79deb3d76 100644 --- a/firmware/src/wifi/comm/wifi_interface.cc +++ b/firmware/src/wifi/comm/wifi_interface.cc @@ -21,24 +21,59 @@ namespace MetaModule::WifiInterface PatchStorage *patchStorage; flatbuffers::Offset constructPatchesMessage(flatbuffers::FlatBufferBuilder &fbb) { - auto CreateVector = [&fbb](auto fileList) { - std::vector> elems(fileList.files.size()); + + auto ExtractFileInfo = [&fbb](auto& thisFile) + { + auto thisName = fbb.CreateString(std::string_view(thisFile.patchname)); + auto thisFilename = fbb.CreateString(std::string_view(thisFile.filename)); + + return CreatePatchInfo(fbb, thisName, thisFilename, thisFile.filesize, thisFile.timestamp); + }; + + auto ExtractFileFromDir = [&fbb, &ExtractFileInfo](const auto& fileList) + { + std::vector> fileInfos(fileList.files.size()); for (std::size_t i = 0; i < fileList.files.size(); i++) { - auto thisName = fbb.CreateString(std::string_view(fileList.files[i].patchname)); + fileInfos[i] = ExtractFileInfo(fileList.files[i]); + }; + auto files = fbb.CreateVector(fileInfos); - auto thisFilename = fbb.CreateString(std::string_view(fileList.files[i].filename)); - auto thisInfo = CreatePatchInfo(fbb, thisName, thisFilename); - elems[i] = thisInfo; + return files; + }; + + auto ExtractDirFull = [&fbb, &ExtractFileFromDir](const auto& fileList, std::optional overrideName) + { + auto FixDirName = [](std::string_view in) + { + // remove extra leading slash + return in.substr(1); }; - //TODO: add directories, and files inside directories - return fbb.CreateVector(elems); + + std::vector> dirInfos(fileList.dirs.size()); + for (std::size_t i=0; igetPatchList(); - auto usbList = CreateVector(patchFileList.volume_root(Volume::USB)); - auto flashList = CreateVector(patchFileList.volume_root(Volume::NorFlash)); - auto sdcardList = CreateVector(patchFileList.volume_root(Volume::SDCard)); + auto usbList = ExtractDirFull(patchFileList.volume_root(Volume::USB), patchFileList.get_vol_name(Volume::USB)); + auto flashList = ExtractDirFull(patchFileList.volume_root(Volume::NorFlash), patchFileList.get_vol_name(Volume::NorFlash)); + auto sdcardList = ExtractDirFull(patchFileList.volume_root(Volume::SDCard), patchFileList.get_vol_name(Volume::SDCard)); auto patches = CreatePatches(fbb, usbList, flashList, sdcardList); auto message = CreateMessage(fbb, AnyMessage_Patches, patches.Union()); @@ -248,7 +283,6 @@ void handle_client_channel(uint8_t destination, std::span payload) { sendResponse(fbb.GetBufferSpan()); } else if (auto uploadPatchMessage = message->content_as_UploadPatch(); uploadPatchMessage) { - auto destination = uploadPatchMessage->destination(); assert(uploadPatchMessage->content()->is_span_observable); auto receivedPatchData = @@ -256,24 +290,33 @@ void handle_client_channel(uint8_t destination, std::span payload) { auto filename = flatbuffers::GetStringView(uploadPatchMessage->filename()); - pr_info("Received Patch of %u bytes for location %u\n", receivedPatchData.size(), destination); - - auto LocationToVolume = [](auto location) -> std::optional { - switch (location) { - case StorageLocation::StorageLocation_USB: - return Volume::USB; - case StorageLocation::StorageLocation_FLASH: - return Volume::NorFlash; - case StorageLocation::StorageLocation_SDCARD: - return Volume::SDCard; - default: - return std::nullopt; + pr_info("Received Patch %.*s of %u bytes\n", filename.size(), filename.data(), receivedPatchData.size()); + + auto ParseStorageString = [](std::string_view locationName) -> std::optional { + + if (locationName.compare(PatchDirList::get_vol_name(Volume::USB)) == 0) + { + return Volume::USB; + } + else if (locationName.compare(PatchDirList::get_vol_name(Volume::NorFlash)) == 0) + { + return Volume::NorFlash; + } + else if (locationName.compare(PatchDirList::get_vol_name(Volume::SDCard)) == 0) + { + return Volume::SDCard; + } + else + { + return std::nullopt; } }; flatbuffers::FlatBufferBuilder fbb; - if (auto thisVolume = LocationToVolume(destination); thisVolume) { + auto volumeString = flatbuffers::GetStringView(uploadPatchMessage->volume()); + + if (auto thisVolume = ParseStorageString(volumeString); thisVolume) { auto success = patchStorage->write_file(*thisVolume, filename, receivedPatchData); if (success) { @@ -307,6 +350,7 @@ void handle_client_channel(uint8_t destination, std::span payload) { sendResponse(fbb.GetBufferSpan()); + } else { pr_trace("Other option\n"); } diff --git a/firmware/src/wifi/flasher/images/application.bin b/firmware/src/wifi/flasher/images/application.bin index d220966ec..1a4301f1c 100644 Binary files a/firmware/src/wifi/flasher/images/application.bin and b/firmware/src/wifi/flasher/images/application.bin differ diff --git a/firmware/src/wifi/flasher/images/filesystem.img b/firmware/src/wifi/flasher/images/filesystem.img index b34675a78..240556d7c 100644 Binary files a/firmware/src/wifi/flasher/images/filesystem.img and b/firmware/src/wifi/flasher/images/filesystem.img differ