#include "fatfs.h" #include "usbd_cdc_if.h" #include "firmware.pb.h" #include "cls_device.pb.h" #include "usb.pb.h" #include "cmsis_os2.h" #include #include "UsbDataHandler.h" #include "crc.h" #include "FirmwareUpdate.h" #include "stdbool.h" #include "CLS.h" #include "stdbool.h" #include "ram_loader.h" // static memory only for decoding messages static cls_firmware_Start msg_cls_firmware_Start; static cls_firmware_Package msg_cls_firmware_Package; static cls_firmware_PackageAck msg_cls_firmware_PackageAck; static cls_firmware_Done msg_cls_firmware_Done; static cls_firmware_FileCheck msg_cls_firmware_FileCheck; static UsbDataPacket pack_cls_firmware_Package; static FIL FwFile = {0}; static bool FileOpen = false; static FRESULT fresult_open =0; static uint32_t fwStartTime = 0; static uint32_t fwPackageCounter =0; /** * @brief This function builds and sends a cls_firmware_PackageAck message over USB. * * @param ack A boolean flag indicating the acknowledgment status. * @param crc A 32-bit cyclic redundancy check (CRC) for the firmware package. * @param counter A 32-bit counter for the firmware packages. * @param device A 32-bit identifier for the device. */ void DataSend_FirmwarePackgeAck(bool ack, uint32_t crc, uint32_t counter, uint32_t device) { msg_cls_firmware_PackageAck.ack = ack; msg_cls_firmware_PackageAck.counter= counter; msg_cls_firmware_PackageAck.crc_pac = crc; msg_cls_firmware_PackageAck.device_id =device; UsbDataPacketSendMessage(cls_usb_PackageType_FIRMWAREPACKAGEACK, &pack_cls_firmware_Package, cls_firmware_PackageAck_fields, &msg_cls_firmware_PackageAck); } void DataSend_FirmwareFileCheck(uint32_t crc, uint32_t device_id, bool ready_for_data, UINT size, char* name) { msg_cls_firmware_FileCheck.crc_fw = crc; msg_cls_firmware_FileCheck.device_id = device_id; msg_cls_firmware_FileCheck.ready_for_data = ready_for_data; msg_cls_firmware_FileCheck.size = size; memcpy(msg_cls_firmware_FileCheck.name, name, sizeof(msg_cls_firmware_FileCheck.name)); UsbDataPacketSendMessage(cls_usb_PackageType_FIRMWAREFILECHECK, &pack_cls_firmware_Package, cls_firmware_FileCheck_fields, &msg_cls_firmware_FileCheck); } #define CHUNK_SIZE 256 // Change this to the size of chunks you want to read static uint8_t crc_buffer[CHUNK_SIZE]; void fw_Start_Slave( cls_firmware_Start * msg) { uint32_t crc = 0; UINT totalRead = 0; UINT bytesRead = 0; // Check if file already exists if(f_open(&FwFile, msg->name, FA_READ) == FR_OK) { __HAL_CRC_DR_RESET(&hcrc); do { f_read(&FwFile, crc_buffer, CHUNK_SIZE, &bytesRead); crc = HAL_CRC_Accumulate(&hcrc, (uint32_t *)crc_buffer, bytesRead); totalRead+=bytesRead; } while(bytesRead == CHUNK_SIZE); f_close(&FwFile); if(crc == msg->crc_fw) { // CRC matches, no need for transfer DataSend_FirmwareFileCheck(crc, msg->device_id, false, totalRead, msg->name); return; } } fresult_open = f_open(&FwFile, msg->name, FA_CREATE_ALWAYS | FA_WRITE); FileOpen=true; DataSend_FirmwareFileCheck(crc, msg->device_id, fresult_open==FR_OK, totalRead, msg->name); } void fw_Start_Master( cls_firmware_Start * msg) { fresult_open = f_open(&FwFile, "firm.bin", FA_CREATE_ALWAYS | FA_WRITE); FileOpen=true; DataSend_FirmwareFileCheck(0, msg->device_id, fresult_open==FR_OK, 0, msg->name); } void DataClbk_cls_firmware_Start(void *msg, uint32_t length) { DATA_CLBK_SETUP(cls_firmware_Start); fwStartTime = osKernelGetSysTimerCount(); fwPackageCounter = 0; if(FileOpen) { f_close(&FwFile); } if(msg_cls_firmware_Start.device_id == gCLS_DEVICE_ADDRESS) { fw_Start_Master(&msg_cls_firmware_Start); } else { fw_Start_Slave(&msg_cls_firmware_Start); } } void DataClbk_cls_firmware_Package(void *msg, uint32_t length) { DATA_CLBK_SETUP(cls_firmware_Package); // check CRC and Package counter uint32_t crc_check = HAL_CRC_Calculate(&hcrc,(uint32_t *)msg_cls_firmware_Package.data.bytes, msg_cls_firmware_Package.data.size); if(msg_cls_firmware_Package.crc_pac != crc_check ) { DataSend_FirmwarePackgeAck(false, msg_cls_firmware_Package.crc_pac, msg_cls_firmware_Package.counter, msg_cls_firmware_Package.device_id); return; } if(msg_cls_firmware_Package.counter != fwPackageCounter) { DataSend_FirmwarePackgeAck(false, msg_cls_firmware_Package.crc_pac, msg_cls_firmware_Package.counter, msg_cls_firmware_Package.device_id); return; } if(fresult_open != 0) { DataSend_FirmwarePackgeAck(false, 0, 0, msg_cls_firmware_Package.device_id); return; } unsigned int bytes_written =0; f_write(&FwFile,msg_cls_firmware_Package.data.bytes, msg_cls_firmware_Package.data.size, &bytes_written); fwPackageCounter++; DataSend_FirmwarePackgeAck(true, msg_cls_firmware_Package.crc_pac, msg_cls_firmware_Package.counter, msg_cls_firmware_Package.device_id); } void DataClbk_cls_firmware_PackageAck(void *msg, uint32_t length) { DATA_CLBK_SETUP(cls_firmware_PackageAck); // Does notthing for the Master } void DataClbk_cls_firmware_Done(void *msg, uint32_t length) { DATA_CLBK_SETUP(cls_firmware_Done); // check CRC and Package counter f_close(&FwFile); fresult_open = 0xFF; FileOpen=false; if(msg_cls_firmware_Done.device_id == gCLS_DEVICE_ADDRESS) { RamLoader_LoadApplication(); } else if (msg_cls_firmware_Done.device_id == gCLS_DEVICE_ADDRESS +1) { // send fw to display // todo ! } { // send fw to slave FirmwareUpdateArgs args; args.device = msg_cls_firmware_Done.device_id; memcpy(args.name, msg_cls_firmware_Start.name, sizeof(args.name)); FirmwareUpdateTask_start(args); } }