rework of the UsbDataHandler

This commit is contained in:
2024-02-02 19:53:32 +01:00
parent 83830808a9
commit 766a3f021c
2 changed files with 251 additions and 99 deletions

View File

@@ -1,12 +1,11 @@
#include "UsbDataHandler.h"
#include "cmsis_os2.h" #include "cmsis_os2.h"
#include "firmware.pb.h"
#include "usb_device.h" #include "usb_device.h"
#include <pb_decode.h> #include <pb_decode.h>
#include "firmware.pb.h"
#include "UsbDataHandler.h"
/* Declare the thread function */ /* 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 NUM_BUFFERS 4 // Define the number of buffers you want to use
@@ -19,8 +18,7 @@ static const osThreadAttr_t UsbDataHandler_TaskAttr = {
.name = "UsbDataHandler", .name = "UsbDataHandler",
.stack_mem = UsbDataHandler_TaskStack, .stack_mem = UsbDataHandler_TaskStack,
.stack_size = sizeof(UsbDataHandler_TaskStack), .stack_size = sizeof(UsbDataHandler_TaskStack),
.priority = TASK_PRIORITY .priority = TASK_PRIORITY};
};
// Static queue data structures // Static queue data structures
@@ -33,19 +31,13 @@ static const osMessageQueueAttr_t usbDataHandlerQueueAttr = {
.cb_mem = &usbDataHandlerQueueControlBlock, .cb_mem = &usbDataHandlerQueueControlBlock,
.cb_size = sizeof(usbDataHandlerQueueControlBlock), .cb_size = sizeof(usbDataHandlerQueueControlBlock),
.mq_mem = usbDataHandlerQueueStorageArea, .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 { typedef union {
Packet pack; UsbDataPacket pack;
uint8_t bytes[sizeof(Packet)]; uint8_t bytes[sizeof(UsbDataPacket)];
} Packet_u; } Packet_u;
@@ -57,10 +49,12 @@ union {
FirmwareDone msg_FirmwareDone; FirmwareDone msg_FirmwareDone;
} mem_msg_decode; } mem_msg_decode;
Packet_u buffers[NUM_BUFFERS];
uint32_t bufferIndex = 0; static Packet_u buffers[NUM_BUFFERS];
uint32_t dataIndex = 0; static uint32_t bufferIndex = 0;
uint16_t packetLength = 0; static uint32_t dataIndex = 0;
static uint16_t packetLength = 0;
void UsbDataHandler_Task(void *argument); void UsbDataHandler_Task(void *argument);
@@ -79,11 +73,12 @@ void UsbDataHandler_Start() {
} }
MX_USB_DEVICE_Init(); MX_USB_DEVICE_Init();
} }
typedef void (*callback_func_t)(void *, uint32_t length); typedef void (*callback_func_t)(void *, uint32_t length);
typedef struct { typedef struct {
uint16_t type; uint16_t type;
callback_func_t callback_func; callback_func_t callback_func;
@@ -92,7 +87,11 @@ typedef struct {
const pb_msgdesc_t *fields; const pb_msgdesc_t *fields;
} message_handler_t; } 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_t message_handlers[] = {
MESSAGE_HANDLER(0xF01, FirmwareStart), MESSAGE_HANDLER(0xF01, FirmwareStart),
MESSAGE_HANDLER(0xF02, FirmwarePackage), MESSAGE_HANDLER(0xF02, FirmwarePackage),
@@ -100,49 +99,67 @@ message_handler_t message_handlers[] = {
MESSAGE_HANDLER(0xF04, FirmwarePackageAck), MESSAGE_HANDLER(0xF04, FirmwarePackageAck),
}; };
void UsbDataHandler_Task(void *argument) { void UsbDataHandler_Task(void *argument) {
while (1) {
UsbDataHandler_Runner();
}
}
void UsbDataHandler_Runner() {
uint32_t msg_buffer_index; uint32_t msg_buffer_index;
bool status; bool status;
while(1) {
/* Wait for a full packet */ /* Wait for a full packet */
osMessageQueueGet(usbDataHandlerQueue, &msg_buffer_index, NULL, osWaitForever); osStatus_t msg_stat = 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); if (msg_stat != osOK) {
return;
}
pb_istream_t stream =
pb_istream_from_buffer(buffers[msg_buffer_index].pack.data, buffers[msg_buffer_index].pack.head.length);
for (uint32_t i = 0; i < sizeof(message_handlers) / sizeof(message_handler_t); i++) { 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) { 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); status = pb_decode(&stream, message_handlers[i].fields, message_handlers[i].msg_ptr);
if (!status) { if (!status) {
// Handle decode error // Handle decode error
} }
message_handlers[i].callback_func(message_handlers[i].msg_ptr, message_handlers[i].msg_size); message_handlers[i].callback_func(message_handlers[i].msg_ptr, message_handlers[i].msg_size);
break; return;
}
} }
} }
} }
USBD_StatusTypeDef UsbDataHandler_RxCallback(uint8_t* Buf, uint32_t Len) { int UsbDataHandler_RxCallback(uint8_t *Buf, uint32_t Len) {
/* Copy the data into the current buffer */ /* Copy the data into the current buffer */
for (uint32_t i = 0; i < Len; i++) { for (uint32_t i = 0; i < Len; i++) {
buffers[bufferIndex].bytes[dataIndex] = Buf[i]; buffers[bufferIndex].bytes[dataIndex] = Buf[i];
dataIndex++; dataIndex++;
/* Check if we have received the packet type and length */ /* Check if we have received the packet type and length */
if (dataIndex == 4) { if (dataIndex == sizeof(UsbDataPacketHead)) {
/* Extract the packet length */ /* Extract the packet length */
packetLength = buffers[bufferIndex].pack.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) { if (packetLength >= MAX_PACKET_SIZE) {
dataIndex = 0; dataIndex = 0;
packetLength = 0; packetLength = 0;
return USBD_FAIL; return -1;
} }
} }
/* Check if we have received a full packet */ /* Check if we have received a full packet */
if (dataIndex - 4 == packetLength) { if (dataIndex - sizeof(UsbDataPacketHead) == packetLength) {
/* Notify the task that a full packet is received */ /* Notify the task that a full packet is received */
osMessageQueuePut(usbDataHandlerQueue, &bufferIndex, 0, 0); osMessageQueuePut(usbDataHandlerQueue, &bufferIndex, 0, 0);
@@ -152,10 +169,23 @@ USBD_StatusTypeDef UsbDataHandler_RxCallback(uint8_t* Buf, uint32_t Len) {
packetLength = 0; packetLength = 0;
} }
} }
return USBD_OK; return 0;
} }
__weak void DataClbk_FirmwareStart(void * msg, uint32_t length) {}
__weak void DataClbk_FirmwarePackage(void * msg, uint32_t length) {} uint8_t UsbDataPacket_head_sum(const UsbDataPacket *p) {
__weak void DataClbk_FirmwarePackageAck(void * msg, uint32_t length) {} const uint8_t *type = (const uint8_t *)&p->head.type;
__weak void DataClbk_FirmwareDone(void * msg, uint32_t length) {} 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) {}

View File

@@ -1,22 +1,144 @@
#ifndef USBDATAHANDLER_H #ifndef USBDATAHANDLER_H
#define USBDATAHANDLER_H #define USBDATAHANDLER_H
#include "usbd_cdc_if.h" #include "stdbool.h"
#include "firmware.pb.h" #include "stdint.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define MAX_PACKET_SIZE 512 - 4 // Define your maximum packet size
/**
* @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;
/**
* @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(); void UsbDataHandler_Start();
USBD_StatusTypeDef UsbDataHandler_RxCallback(uint8_t* Buf, uint32_t Len); /**
* @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();
void DataClbk_FirmwareStart(void * msg, uint32_t length); /**
void DataClbk_FirmwarePackage(void * msg, uint32_t length); * @brief This function is a callback that is invoked when USB data is received.
void DataClbk_FirmwarePackageAck(void * msg, uint32_t length); *
void DataClbk_FirmwareDone(void * msg, uint32_t length); * 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 #ifdef __cplusplus
} }