167 lines
5.4 KiB
C
167 lines
5.4 KiB
C
|
|
#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 <pb_encode.h>
|
|
#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 {
|
|
|
|
FirmwareUpdateArgs args;
|
|
args.device = msg_cls_firmware_Done.device_id;
|
|
memcpy(args.name, msg_cls_firmware_Start.name, sizeof(args.name));
|
|
|
|
FirmwareUpdateTask_start(args);
|
|
}
|
|
} |