From 766a3f021c22c6ccdd007a2c3adf9d8bc0182d02 Mon Sep 17 00:00:00 2001 From: Oliver Walter Date: Fri, 2 Feb 2024 19:53:32 +0100 Subject: [PATCH] rework of the UsbDataHandler --- Application/Tasks/UsbDataHandler.c | 212 ++++++++++++++++------------- Application/Tasks/UsbDataHandler.h | 138 +++++++++++++++++-- 2 files changed, 251 insertions(+), 99 deletions(-) diff --git a/Application/Tasks/UsbDataHandler.c b/Application/Tasks/UsbDataHandler.c index fd780f9..571b775 100644 --- a/Application/Tasks/UsbDataHandler.c +++ b/Application/Tasks/UsbDataHandler.c @@ -1,26 +1,24 @@ +#include "UsbDataHandler.h" #include "cmsis_os2.h" +#include "firmware.pb.h" #include "usb_device.h" #include -#include "firmware.pb.h" -#include "UsbDataHandler.h" /* Declare the thread function */ -#define MAX_PACKET_SIZE 512-4 // Define your maximum packet size #define NUM_BUFFERS 4 // Define the number of buffers you want to use /* Define the task attributes */ #define TASK_STACK_SIZE 1024 -#define TASK_PRIORITY osPriorityNormal +#define TASK_PRIORITY osPriorityNormal /* Declare static memory for the task */ static uint32_t UsbDataHandler_TaskStack[TASK_STACK_SIZE]; static const osThreadAttr_t UsbDataHandler_TaskAttr = { .name = "UsbDataHandler", .stack_mem = UsbDataHandler_TaskStack, .stack_size = sizeof(UsbDataHandler_TaskStack), - .priority = TASK_PRIORITY -}; + .priority = TASK_PRIORITY}; // Static queue data structures @@ -33,66 +31,67 @@ static const osMessageQueueAttr_t usbDataHandlerQueueAttr = { .cb_mem = &usbDataHandlerQueueControlBlock, .cb_size = sizeof(usbDataHandlerQueueControlBlock), .mq_mem = usbDataHandlerQueueStorageArea, - .mq_size = sizeof(usbDataHandlerQueueStorageArea) -}; + .mq_size = sizeof(usbDataHandlerQueueStorageArea)}; -typedef struct { - uint16_t type; - uint16_t length; - uint8_t data[MAX_PACKET_SIZE]; -} Packet; typedef union { - Packet pack; - uint8_t bytes[sizeof(Packet)]; -}Packet_u; + UsbDataPacket pack; + uint8_t bytes[sizeof(UsbDataPacket)]; +} Packet_u; // static memory only for decoding messages union { - FirmwareStart msg_FirmwareStart; - FirmwarePackage msg_FirmwarePackage; - FirmwarePackageAck msg_FirmwarePackageAck; - FirmwareDone msg_FirmwareDone; + FirmwareStart msg_FirmwareStart; + FirmwarePackage msg_FirmwarePackage; + FirmwarePackageAck msg_FirmwarePackageAck; + FirmwareDone msg_FirmwareDone; } mem_msg_decode; -Packet_u buffers[NUM_BUFFERS]; -uint32_t bufferIndex = 0; -uint32_t dataIndex = 0; -uint16_t packetLength = 0; + +static Packet_u buffers[NUM_BUFFERS]; +static uint32_t bufferIndex = 0; +static uint32_t dataIndex = 0; +static uint16_t packetLength = 0; + void UsbDataHandler_Task(void *argument); void UsbDataHandler_Start() { - /* Create the task */ - osThreadId_t UsbDataHandler_TaskHandle = osThreadNew(UsbDataHandler_Task, NULL, &UsbDataHandler_TaskAttr); + /* Create the task */ + osThreadId_t UsbDataHandler_TaskHandle = osThreadNew(UsbDataHandler_Task, NULL, &UsbDataHandler_TaskAttr); - /* Create the message queue */ - usbDataHandlerQueue = osMessageQueueNew(NUM_BUFFERS, sizeof(uint32_t), &usbDataHandlerQueueAttr); + /* Create the message queue */ + usbDataHandlerQueue = osMessageQueueNew(NUM_BUFFERS, sizeof(uint32_t), &usbDataHandlerQueueAttr); - /* Check if the task was created successfully */ - if (UsbDataHandler_TaskHandle == NULL || usbDataHandlerQueue == NULL) { - /* Handle error */ - Error_Handler(); - } - - MX_USB_DEVICE_Init(); + /* Check if the task was created successfully */ + if (UsbDataHandler_TaskHandle == NULL || usbDataHandlerQueue == NULL) { + /* Handle error */ + Error_Handler(); + } + MX_USB_DEVICE_Init(); } -typedef void (*callback_func_t)(void*, uint32_t length); + +typedef void (*callback_func_t)(void *, uint32_t length); + typedef struct { - uint16_t type; - callback_func_t callback_func; - void *msg_ptr; - uint32_t msg_size; - const pb_msgdesc_t *fields; + uint16_t type; + callback_func_t callback_func; + void *msg_ptr; + uint32_t msg_size; + const pb_msgdesc_t *fields; } message_handler_t; -#define MESSAGE_HANDLER(type, message) {type, DataClbk_##message, &mem_msg_decode.msg_##message,message##_size , message##_fields} + +#define MESSAGE_HANDLER(type, message) \ + { type, DataClbk_##message, &mem_msg_decode.msg_##message, message##_size, message##_fields } + + message_handler_t message_handlers[] = { MESSAGE_HANDLER(0xF01, FirmwareStart), MESSAGE_HANDLER(0xF02, FirmwarePackage), @@ -100,62 +99,93 @@ message_handler_t message_handlers[] = { MESSAGE_HANDLER(0xF04, FirmwarePackageAck), }; + void UsbDataHandler_Task(void *argument) { - uint32_t msg_buffer_index; - bool status; - - while(1) { - /* Wait for a full packet */ - osMessageQueueGet(usbDataHandlerQueue, &msg_buffer_index, NULL, osWaitForever); - pb_istream_t stream = pb_istream_from_buffer(buffers[msg_buffer_index].pack.data, buffers[msg_buffer_index].pack.length); - - for (uint32_t i = 0; i < sizeof(message_handlers) / sizeof(message_handler_t); i++) { - if (buffers[msg_buffer_index].pack.type == message_handlers[i].type) { - status = pb_decode(&stream, message_handlers[i].fields, message_handlers[i].msg_ptr); - if (!status) { - // Handle decode error - } - message_handlers[i].callback_func(message_handlers[i].msg_ptr, message_handlers[i].msg_size); - break; - } - } - } + while (1) { + UsbDataHandler_Runner(); + } } -USBD_StatusTypeDef UsbDataHandler_RxCallback(uint8_t* Buf, uint32_t Len) { - /* Copy the data into the current buffer */ - for (uint32_t i = 0; i < Len; i++) { - buffers[bufferIndex].bytes[dataIndex] = Buf[i]; - dataIndex++; +void UsbDataHandler_Runner() { + uint32_t msg_buffer_index; + bool status; - /* Check if we have received the packet type and length */ - if (dataIndex == 4) { - /* Extract the packet length */ - packetLength = buffers[bufferIndex].pack.length; + /* Wait for a full packet */ + osStatus_t msg_stat = osMessageQueueGet(usbDataHandlerQueue, &msg_buffer_index, NULL, osWaitForever); + if (msg_stat != osOK) { + return; + } - if (packetLength >= MAX_PACKET_SIZE ) { - dataIndex = 0; - packetLength = 0; - return USBD_FAIL; - } - } - - /* Check if we have received a full packet */ - if (dataIndex - 4 == packetLength) { - /* Notify the task that a full packet is received */ - osMessageQueuePut(usbDataHandlerQueue, &bufferIndex, 0, 0); + pb_istream_t stream = + pb_istream_from_buffer(buffers[msg_buffer_index].pack.data, buffers[msg_buffer_index].pack.head.length); - /* Prepare for the next packet */ - bufferIndex = (bufferIndex + 1) % NUM_BUFFERS; - dataIndex = 0; - packetLength = 0; - } + for (uint32_t i = 0; i < sizeof(message_handlers) / sizeof(message_handler_t); i++) { + if (buffers[msg_buffer_index].pack.head.type == message_handlers[i].type) { + status = pb_decode(&stream, message_handlers[i].fields, message_handlers[i].msg_ptr); + if (!status) { + // Handle decode error + } + message_handlers[i].callback_func(message_handlers[i].msg_ptr, message_handlers[i].msg_size); + return; } - return USBD_OK; + } } -__weak void DataClbk_FirmwareStart(void * msg, uint32_t length) {} -__weak void DataClbk_FirmwarePackage(void * msg, uint32_t length) {} -__weak void DataClbk_FirmwarePackageAck(void * msg, uint32_t length) {} -__weak void DataClbk_FirmwareDone(void * msg, uint32_t length) {} \ No newline at end of file + +int UsbDataHandler_RxCallback(uint8_t *Buf, uint32_t Len) { + /* Copy the data into the current buffer */ + for (uint32_t i = 0; i < Len; i++) { + buffers[bufferIndex].bytes[dataIndex] = Buf[i]; + dataIndex++; + + /* Check if we have received the packet type and length */ + if (dataIndex == sizeof(UsbDataPacketHead)) { + /* Extract the packet length */ + packetLength = buffers[bufferIndex].pack.head.length; + + // the header checksum is invalid + if (!UsbDataPacket_head_check(&buffers[bufferIndex].pack)) { + dataIndex = 0; + packetLength = 0; + return -1; + } + + if (packetLength >= MAX_PACKET_SIZE) { + dataIndex = 0; + packetLength = 0; + return -1; + } + } + + /* Check if we have received a full packet */ + if (dataIndex - sizeof(UsbDataPacketHead) == packetLength) { + /* Notify the task that a full packet is received */ + osMessageQueuePut(usbDataHandlerQueue, &bufferIndex, 0, 0); + + /* Prepare for the next packet */ + bufferIndex = (bufferIndex + 1) % NUM_BUFFERS; + dataIndex = 0; + packetLength = 0; + } + } + return 0; +} + + +uint8_t UsbDataPacket_head_sum(const UsbDataPacket *p) { + const uint8_t *type = (const uint8_t *)&p->head.type; + const uint8_t *length = (const uint8_t *)&p->head.length; + return type[0] + type[1] + length[0] + length[1]; +} + + +bool UsbDataPacket_head_check(const UsbDataPacket *p) { + return p->head.check == UsbDataPacket_head_sum(p); +} + + +__attribute__((weak)) void DataClbk_FirmwareStart(void *msg, uint32_t length) {} +__attribute__((weak)) void DataClbk_FirmwarePackage(void *msg, uint32_t length) {} +__attribute__((weak)) void DataClbk_FirmwarePackageAck(void *msg, uint32_t length) {} +__attribute__((weak)) void DataClbk_FirmwareDone(void *msg, uint32_t length) {} \ No newline at end of file diff --git a/Application/Tasks/UsbDataHandler.h b/Application/Tasks/UsbDataHandler.h index d64960a..87296cc 100644 --- a/Application/Tasks/UsbDataHandler.h +++ b/Application/Tasks/UsbDataHandler.h @@ -1,22 +1,144 @@ #ifndef USBDATAHANDLER_H #define USBDATAHANDLER_H -#include "usbd_cdc_if.h" -#include "firmware.pb.h" +#include "stdbool.h" +#include "stdint.h" #ifdef __cplusplus extern "C" { #endif +#define MAX_PACKET_SIZE 512 - 4 // Define your maximum packet size -void UsbDataHandler_Start(); +/** + * @struct UsbDataPacketHead + * @brief This structure represents the header of a USB data packet. + * + * The header includes the length and type of the packet, as well as a check byte. + * The structure is packed to ensure that the memory layout is exactly as defined, + * without any padding bytes. + */ +typedef struct { + uint16_t length; // Length of the USB data packet + uint16_t type; // Type of the USB data packet(used to parse the message content). + uint8_t check; // Check byte of the USB data packet. +} __attribute__((packed)) UsbDataPacketHead; -USBD_StatusTypeDef UsbDataHandler_RxCallback(uint8_t* Buf, uint32_t Len); -void DataClbk_FirmwareStart(void * msg, uint32_t length); -void DataClbk_FirmwarePackage(void * msg, uint32_t length); -void DataClbk_FirmwarePackageAck(void * msg, uint32_t length); -void DataClbk_FirmwareDone(void * msg, uint32_t length); +/** + * @struct UsbDataPacket + * @brief This structure represents a USB data packet. + * + * The packet includes a header and a data array. The structure is packed to ensure + * that the memory layout is exactly as defined, without any padding bytes. + * + * @var UsbDataPacket::head + * + * + * @var UsbDataPacket::data + * + */ +typedef struct { + UsbDataPacketHead head; // Header of the USB data packet. + uint8_t data[MAX_PACKET_SIZE]; // Data of the USB data packet. +} __attribute__((packed)) UsbDataPacket; + +/** + * @brief Calculate the chekcsum of the header of a USB data packet. + * + * @param p Pointer to the USB data packet. + * @return Sum of the header of the USB data packet. + */ +uint8_t UsbDataPacket_head_sum(const UsbDataPacket* p); + +/** + * @brief Check the header of a USB data packet. + * + * @param p Pointer to the USB data packet. + * @return True if the header is valid, false otherwise. + */ +bool UsbDataPacket_head_check(const UsbDataPacket* p); + +/** + * @brief This function starts the USB data handler. + * + * It initializes any necessary hardware or software resources + * and prepares the data handler to process USB data. + * + * @return void + */ +void UsbDataHandler_Start(); + +/** + * @brief This function runs the USB data handler. + * + * It processes any pending USB data and performs any necessary + * tasks related to USB data handling. It should be called + * periodically in the main loop of your program. + * + * @return void + */ +void UsbDataHandler_Runner(); + +/** + * @brief This function is a callback that is invoked when USB data is received. + * + * It processes the received data and performs any necessary tasks. + * + * @param Buf A pointer to the buffer that contains the received data. + * @param Len The length of the received data, in bytes. + * + * @return int Returns 0 on success, or a non-zero error code on failure. + */ +int UsbDataHandler_RxCallback(uint8_t* Buf, uint32_t Len); + +/** + * @brief Callback function that is invoked when firmware update message is received. + * + * Other parts of the software can implement this function to handle the start of a firmware update. + * + * @param msg A pointer to the message related to the firmware start. + * @param length The length of the message, in bytes. + * + * @return void + */ +__attribute__((weak)) void DataClbk_FirmwareStart(void* msg, uint32_t length); + +/** + * @brief Callback function that is invoked when a firmware package message is received. + * + * Other parts of the software can implement this function to handle each received firmware package. + * + * @param msg A pointer to the message related to the received firmware package. + * @param length The length of the message, in bytes. + * + * @return void + */ +__attribute__((weak)) void DataClbk_FirmwarePackage(void* msg, uint32_t length); + +/** + * @brief Callback function that is invoked when a firmware package acknowledgment message is received. + * + * Other parts of the software can implement this function to handle the acknowledgment of a received firmware package. + * + * @param msg A pointer to the message related to the firmware package acknowledgment. + * @param length The length of the message, in bytes. + * + * @return void + */ +__attribute__((weak)) void DataClbk_FirmwarePackageAck(void* msg, uint32_t length); + +/** + * @brief Callback function that is invoked when firmware update done message. + * + * Other parts of the software can implement this function to handle the completion of a firmware update. + * + * @param msg A pointer to the message related to the completion of the firmware update. + * @param length The length of the message, in bytes. + * + * @return void + */ +__attribute__((weak)) void DataClbk_FirmwareDone(void* msg, uint32_t length); #ifdef __cplusplus }