implement full fwupdate stack

This commit is contained in:
2024-02-06 01:52:44 +01:00
parent 74dcdfd19b
commit ff6fcb75f0
4 changed files with 205 additions and 10 deletions

View File

@@ -9,10 +9,12 @@ target_sources(${PROJECT_NAME}
${CMAKE_CURRENT_LIST_DIR}/UsbDataHandler.c ${CMAKE_CURRENT_LIST_DIR}/UsbDataHandler.c
${CMAKE_CURRENT_LIST_DIR}/CanDataTask.c ${CMAKE_CURRENT_LIST_DIR}/CanDataTask.c
${CMAKE_CURRENT_LIST_DIR}/FirmwareHandler.c ${CMAKE_CURRENT_LIST_DIR}/FirmwareHandler.c
${CMAKE_CURRENT_LIST_DIR}/FirmwareUpdate.c
INTERFACE INTERFACE
${CMAKE_CURRENT_LIST_DIR}/UsbDataHandler.h ${CMAKE_CURRENT_LIST_DIR}/UsbDataHandler.h
${CMAKE_CURRENT_LIST_DIR}/CanDataTask.h ${CMAKE_CURRENT_LIST_DIR}/CanDataTask.h
${CMAKE_CURRENT_LIST_DIR}/FirmwareUpdate.h
) )
target_include_directories(${PROJECT_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}) target_include_directories(${PROJECT_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})

View File

@@ -6,6 +6,7 @@
#include <pb_encode.h> #include <pb_encode.h>
#include "UsbDataHandler.h" #include "UsbDataHandler.h"
#include "crc.h" #include "crc.h"
#include "FirmwareUpdate.h"
// static memory only for decoding messages // static memory only for decoding messages
static FirmwareStart msg_FirmwareStart; static FirmwareStart msg_FirmwareStart;
@@ -123,14 +124,10 @@ void DataClbk_FirmwareDone(void *msg, uint32_t length) {
fresult_open = 0xFF; fresult_open = 0xFF;
FileOpen=false; FileOpen=false;
FirmwareUpdateArgs args;
args.device = msg_FirmwareDone.device_id;
memcpy(args.name, msg_FirmwareStart.name, sizeof(args.name));
// Spawn Task to Send this File over CAN FirmwareUpdateTask_start(args);
// this task should
// 1. send can message to send device with matching device id into bootloader mode
// - open the fw file on the SD card.
// 2. wait for the device to get ready.
// - send data 4x data
// - wait for ack
// 3 onec we are at the EOF
// - send done
} }

View File

@@ -0,0 +1,169 @@
#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();
}

View File

@@ -0,0 +1,27 @@
#pragma once
#include "stdint.h"
#define BOOTLOADER_CALL_RETRY_TIME 1000
#define BOOTLOADER_CALL_MAX_TRIES 10
#define TASK_FLAG_WAIT 1
#define TASK_FLAG_RUNNING 2
#define UPDATE_ACK_WINDOW 4
#define UPDATE_DONE_MSG 0xFFFFD04EFFFFD04E
typedef struct {
char name[32];
uint8_t device;
} FirmwareUpdateArgs;
typedef struct {
uint32_t counter;
uint8_t data[4];
} FwFrame;
void FirmwareUpdateTask_start(FirmwareUpdateArgs args);