Files
cls_master/Application/Tasks/FirmwareUpdate.c

169 lines
5.0 KiB
C

#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();
}