#pragma once #include #include #include #include #include "hid_handler.h" const uint32_t CHUNK_SIZE = 32; const uint32_t APP_ADDRESS = 0x00404000; const uint32_t PAGE_SIZE = 0x200; const uint32_t SMALL_SUBSECTOR_SIZE = 0x2000; // There are two 8kB subsectors at the start of Flash const uint32_t LARGE_SUBSECTOR_SIZE = 0x1C000; // 128kB - 16kB subsector just after the two small ones const uint32_t SECTOR_SIZE = 0x20000; // 128kB sector size, there are 4 total and the first one is split into subsectors const uint32_t ALLOWED_APP_SIZE = LARGE_SUBSECTOR_SIZE + 3 * SECTOR_SIZE; const uint32_t MIN_ERASABLE_SIZE = 0x2000; // 16 pages = 8kB.Small subsector can erase in smaller increments, but // not the larger subsector or full - size sectors // FPGA DFU update constants const uint16_t FPGA_DFU_VID = 0x35BD; // Bigscreen's USB ID const uint16_t FPGA_DFU_PID = 0x0282; const uint16_t FPGA_MIN_ERASABLE_SIZE = 0x8000; // 32 kB block for the Winbond flash chip const uint16_t FPGA_FLASH_TOTAL_SIZE = 0x100000; // 1MB flash available. At least for the application. It's a 2MB chip, but 1MB is for bootloader. namespace Firmware_Status { enum Firmware_Status { File_Load_Failed = -1, Firmware_Params_Incorrect = -2, Page_Write_Failed = -3, Address_Invalid = -4, File_Not_Found = -5, Idle = 0, In_Progress = 1, Success = 2, }; } namespace DFU_Load_Status { enum DFU_Load_Status { Idle = 0, In_Progress = 1, Success = 2, Failure = 3, DFU_Not_Found = 4, DFU_File_Invalid = 5, Firmware_Not_Found = 6, Verification = 7 }; } struct semver_decode { unsigned int major_ver; unsigned int minor_ver; unsigned int patch_ver; semver_decode() :major_ver(0), minor_ver(0), patch_ver(0) {} semver_decode(std::string& semver) { auto first_dot = semver.find('.'); auto second_dot = semver.find('.', first_dot+1); if (first_dot == std::string::npos || second_dot == std::string::npos) { major_ver = 0; minor_ver = 0; patch_ver = 0; } else { auto maj_ver_str = semver.substr(0, first_dot); auto min_ver_str = semver.substr(first_dot + 1, second_dot - first_dot - 1); auto pat_ver_str = semver.substr(second_dot + 1, std::string::npos); major_ver = std::stoi(maj_ver_str); minor_ver = std::stoi(min_ver_str); patch_ver = std::stoi(pat_ver_str); } } bool operator<(const semver_decode& rhs) { if (this->major_ver < rhs.major_ver) return true; if (this->major_ver > rhs.major_ver) return false; if (this->minor_ver < rhs.minor_ver) return true; if (this->minor_ver > rhs.minor_ver) return false; if (this->patch_ver < rhs.patch_ver) return true; return false; } bool operator>(const semver_decode& rhs) { if (this->major_ver > rhs.major_ver) return true; if (this->major_ver < rhs.major_ver) return false; if (this->minor_ver > rhs.minor_ver) return true; if (this->minor_ver < rhs.minor_ver) return false; if (this->patch_ver > rhs.patch_ver) return true; return false; } bool operator==(const semver_decode& rhs) { return ((this->major_ver == rhs.major_ver) && (this->minor_ver == rhs.minor_ver) && (this->patch_ver == rhs.patch_ver)); } bool operator<=(const semver_decode& rhs) { return (*this < rhs) || (*this == rhs); } bool operator>=(const semver_decode& rhs) { return (*this > rhs) || (*this == rhs); } bool operator!=(const semver_decode& rhs) { return !(*this == rhs); } }; class firmware_update { public: firmware_update() { firmware_progress.store(0); firmware_status.store(Firmware_Status::Idle); } bool mcu_update_available(std::string current_version); bool dfu_update_available(std::string current_version); void update_firmware(HidHandler& hid); double get_update_progress(); int get_update_status(); void clear_status(); void clear_dfu_status(); void abort_dfu_update(); bool get_dfu_version(std::wstring filepath); bool load_firmware_file(std::wstring filepath); bool check_dfu_file(std::wstring firmwarePath); void load_dfu_firmware(HidHandler& hid, std::wstring firmwarePath); int get_dfu_status(); std::string latest_dfu_version; std::atomic dfu_progress; std::atomic previous_dfu_progress; uint64_t last_dfu_change; std::atomic dfu_load_status; private: std::thread mythread; std::thread dfuthread; uint32_t start_addr = 0; std::vector app_data; std::atomic firmware_progress; std::atomic firmware_status; PROCESS_INFORMATION dfu_upload_process = { 0 }; std::string latest_firmware_version; uint8_t crc8(uint8_t initval, std::vector& data); std::vector create_hid_message(uint8_t type, uint8_t len, uint32_t addr, const std::vector& data); std::vector create_hid_message_nodata(uint8_t type, uint8_t len, uint32_t addr); bool load_page(HidHandler& hid, uint32_t addr, const std::vector& data); bool load_chunk(HidHandler& hid, uint32_t addr, const std::vector& data); bool erase_app_region(HidHandler& hid); bool erase_app_by_blocks(HidHandler& hid, uint32_t erase_addr, uint32_t bytes_to_erase); bool erase_sector(HidHandler& hid, uint32_t erase_addr); bool erase_blocks(HidHandler& hid, uint32_t erase_addr, uint32_t bytes_to_erase); bool erase_8kB_block(HidHandler& hid, uint32_t erase_addr); bool erase_16kB_block(HidHandler& hid, uint32_t erase_addr); };