193 lines
5.9 KiB
C
193 lines
5.9 KiB
C
#include "CanDataHandler.h"
|
|
#include "cmsis_os2.h"
|
|
#include "FreeRTOS.h"
|
|
#include "CLSAddress.h"
|
|
#include "fatfs.h"
|
|
#include "FirmwareUpdate.h"
|
|
#include "UsbDataHandler.h"
|
|
|
|
// Memory for the task
|
|
StaticTask_t CLS_FW_Task_cb;
|
|
uint32_t CLS_FW_Task_stk[512];
|
|
// Attributes for the task
|
|
osThreadId_t CLS_FW_Task_id;
|
|
const osThreadAttr_t CLS_FW_Task_attr = {
|
|
.name = "CLS_FW_Task",
|
|
.attr_bits = 0U,
|
|
.cb_mem = &CLS_FW_Task_cb,
|
|
.cb_size = sizeof(CLS_FW_Task_cb),
|
|
.stack_mem = CLS_FW_Task_stk,
|
|
.stack_size = sizeof(CLS_FW_Task_stk),
|
|
.priority = osPriorityNormal,
|
|
.reserved = 0U
|
|
};
|
|
|
|
osMutexId_t CLS_FW_Task_FileLock = NULL;
|
|
static FIL fw_file;
|
|
static FwFrame frame = {0};
|
|
|
|
|
|
|
|
// wait_for_start_callback to get notified when the slave is ready
|
|
void wait_for_start_callback(uint16_t canid, uint8_t * data, uint8_t size) {
|
|
osThreadFlagsSet(CLS_FW_Task_id, TASK_FLAG_WAIT);
|
|
}
|
|
|
|
void wait_for_start(FirmwareUpdateArgs * configuration) {
|
|
|
|
// setup wait_for_start_callback to get notified when the slave is ready
|
|
uint16_t ready_canid = GENERATE_CLS_ADDRESS(CLS_CODE_FIMWARE, configuration->device, CLS_CH_FW_MISO);
|
|
// wait_for_start_callback // MessageCode::Firmware(FirmwareChannel::SlaveOutMasterIn);
|
|
CanData_regEventMsg(ready_canid, wait_for_start_callback);
|
|
|
|
// setup the command to send the slave into booloader mode
|
|
uint16_t target_canid = GENERATE_CLS_ADDRESS(CLS_CODE_FIMWARE, configuration->device, CLS_CH_FW_BOOTCALL);
|
|
uint8_t bootloader_call[8] = {0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab};
|
|
|
|
|
|
// wait for the slave to be ready to update:
|
|
uint32_t counter = 0;
|
|
do {
|
|
// send bootloader command
|
|
CLS_BSP_TxHeaderType header = CREATE_BSP_CAN_HEADER(target_canid,CLS_BSP_DLC_BYTES_8);
|
|
CLS_BSP_CAN_AddMessageToSend(&header,bootloader_call);
|
|
counter++;
|
|
|
|
// after some time abort if we dont get a connection
|
|
if(counter > BOOTLOADER_CALL_MAX_TRIES) {
|
|
// TODO: Logging
|
|
CanData_removeEvent(ready_canid);
|
|
f_close(&fw_file);
|
|
osThreadExit();
|
|
}
|
|
|
|
// wait for the slave
|
|
} while(osThreadFlagsWait(TASK_FLAG_WAIT,osFlagsWaitAny,BOOTLOADER_CALL_RETRY_TIME) == (uint32_t)osErrorTimeout);
|
|
|
|
//remove the wait_for_start_callback again
|
|
CanData_removeEvent(ready_canid);
|
|
|
|
// reset the fw_file
|
|
f_lseek(&fw_file,0);
|
|
frame.counter = 0;
|
|
}
|
|
|
|
|
|
|
|
void running_callback_error(uint16_t canid, uint8_t * data, uint8_t size) {
|
|
osMutexAcquire(CLS_FW_Task_FileLock, osWaitForever);
|
|
f_lseek(&fw_file,0);
|
|
frame.counter = 0;
|
|
osMutexRelease(CLS_FW_Task_FileLock);
|
|
osThreadFlagsSet(CLS_FW_Task_id, TASK_FLAG_RUNNING);
|
|
}
|
|
|
|
void running_callback_ack(uint16_t canid, uint8_t * data, uint8_t size) {
|
|
osThreadFlagsSet(CLS_FW_Task_id, TASK_FLAG_RUNNING);
|
|
}
|
|
|
|
|
|
void running(FirmwareUpdateArgs * configuration) {
|
|
uint16_t error_canid = GENERATE_CLS_ADDRESS(CLS_CODE_FIMWARE, configuration->device, CLS_CH_FW_MISO);
|
|
uint16_t ack_canid = GENERATE_CLS_ADDRESS(CLS_CODE_FIMWARE, configuration->device, CLS_CH_FW_SLAVE_FEEDBACK);
|
|
uint16_t target_canid = GENERATE_CLS_ADDRESS(CLS_CODE_FIMWARE, configuration->device, CLS_CH_FW_MOSI);
|
|
CLS_BSP_TxHeaderType header = CREATE_BSP_CAN_HEADER(target_canid,CLS_BSP_DLC_BYTES_8);
|
|
|
|
CanData_regEventMsg(error_canid,running_callback_error);
|
|
CanData_regEventMsg(ack_canid, running_callback_ack);
|
|
|
|
unsigned int read_bytes = 0;
|
|
|
|
while (true)
|
|
{
|
|
|
|
// read fw file and and send data
|
|
osMutexAcquire(CLS_FW_Task_FileLock, osWaitForever);
|
|
f_read(&fw_file, &frame.data, sizeof(frame.data), &read_bytes);
|
|
CLS_BSP_CAN_AddMessageToSend(&header, (uint8_t*)&frame);
|
|
frame.counter++;
|
|
osMutexRelease(CLS_FW_Task_FileLock);
|
|
|
|
// transport window response
|
|
if(frame.counter % UPDATE_ACK_WINDOW == 0) {
|
|
osThreadFlagsWait(TASK_FLAG_RUNNING, osFlagsWaitAny, osWaitForever);
|
|
}
|
|
|
|
// end of file
|
|
if(read_bytes != sizeof(frame.data)) {
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
uint64_t done = UPDATE_DONE_MSG;
|
|
CLS_BSP_CAN_AddMessageToSend(&header,(uint8_t*)&done);
|
|
|
|
CanData_removeEvent(error_canid);
|
|
CanData_removeEvent(ack_canid);
|
|
}
|
|
|
|
|
|
#define MAX_FW_UPDATES 16
|
|
osMessageQueueId_t fwUpdateQueue;
|
|
|
|
void CLSFirmwareUpdateTask_func(void *argument);
|
|
|
|
void FirmwareUpdateTask_start(FirmwareUpdateArgs args) {
|
|
// Task functionality here
|
|
if(CLS_FW_Task_FileLock == NULL) {
|
|
CLS_FW_Task_FileLock = osMutexNew(NULL);
|
|
}
|
|
|
|
// Initialize the queue if it hasn't been initialized yet
|
|
if(fwUpdateQueue == NULL) {
|
|
fwUpdateQueue = osMessageQueueNew(MAX_FW_UPDATES, sizeof(FirmwareUpdateArgs), NULL);
|
|
}
|
|
|
|
if(CLS_FW_Task_FileLock == NULL) {
|
|
// error cant create mutex
|
|
return;
|
|
}
|
|
|
|
osMessageQueuePut(fwUpdateQueue, &args, 0, 0);
|
|
|
|
|
|
// check CLS_FW_Task_id is null or stopped
|
|
// only one Task can runn at once
|
|
if(CLS_FW_Task_id == NULL || osThreadGetState(CLS_FW_Task_id) == osThreadTerminated) {
|
|
CLS_FW_Task_id = osThreadNew(CLSFirmwareUpdateTask_func, NULL, &CLS_FW_Task_attr);
|
|
}
|
|
}
|
|
|
|
UsbDataPacket buffer;
|
|
void CLSFirmwareUpdateTask_func(void *argument) {
|
|
FirmwareUpdateArgs args;
|
|
osStatus_t status;
|
|
|
|
while(1) {
|
|
// Wait for a firmware update request
|
|
status = osMessageQueueGet(fwUpdateQueue, &args, NULL, 100);
|
|
|
|
// If the queue is empty, terminate the task
|
|
if (status != osOK) {
|
|
osThreadExit();
|
|
}
|
|
|
|
char * filename = args.name;
|
|
if(f_open(&fw_file, filename, FA_READ) != FR_OK) {
|
|
// TODO: Logging
|
|
continue;
|
|
}
|
|
|
|
wait_for_start(&args);
|
|
|
|
running(&args);
|
|
FirmwareUpdateDone done = {
|
|
.device_id = args.device,
|
|
};
|
|
|
|
//UsbDataPacketSendMessage(UsbPackageType_FIRMWAREUPDATEDONE, &buffer,FirmwareUpdateDone_fields,&done);
|
|
f_close(&fw_file);
|
|
}
|
|
} |