#include "CanDataHandler.h" #include "cmsis_os2.h" #include "FreeRTOS.h" #include "CLSAddress.h" #include "fatfs.h" #include "FirmwareUpdate.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 FirmwareUpdateArgs configuration = {0}; 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() { // 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() { 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); } 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); } if(CLS_FW_Task_FileLock == NULL) { // error cant create mutex return; } // 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) { configuration = args; CLS_FW_Task_id = osThreadNew(CLSFirmwareUpdateTask_func, NULL, &CLS_FW_Task_attr); } } void CLSFirmwareUpdateTask_func(void *argument) { char * filename = configuration.name; if( f_open(&fw_file, filename, FA_READ) != FR_OK) { // TODO: Logging osThreadExit(); } wait_for_start(); running(); f_close(&fw_file); osThreadExit(); }