diff --git a/assets/User_code/bsp/bsp.h b/assets/User_code/bsp/bsp.h index d1beac0..6a3171b 100644 --- a/assets/User_code/bsp/bsp.h +++ b/assets/User_code/bsp/bsp.h @@ -9,6 +9,7 @@ extern "C" { #define BSP_ERR_NULL (-2) #define BSP_ERR_INITED (-3) #define BSP_ERR_NO_DEV (-4) +#define BSP_ERR_TIMEOUT (-5) #ifdef __cplusplus } diff --git a/assets/User_code/bsp/can.c b/assets/User_code/bsp/can.c index 98acb19..d30c34f 100644 --- a/assets/User_code/bsp/can.c +++ b/assets/User_code/bsp/can.c @@ -3,47 +3,147 @@ #include "bsp/bsp.h" #include #include -#include #include /* Private define ----------------------------------------------------------- */ +#define CAN_QUEUE_MUTEX_TIMEOUT 100 /* 队列互斥锁超时时间(ms) */ /* Private macro ------------------------------------------------------------ */ /* Private typedef ---------------------------------------------------------- */ -typedef struct CAN_QueueNode { +typedef struct BSP_CAN_QueueNode { uint32_t can_id; osMessageQueueId_t queue; uint8_t queue_size; - struct CAN_QueueNode *next; -} CAN_QueueNode_t; + struct BSP_CAN_QueueNode *next; +} BSP_CAN_QueueNode_t; /* Private variables -------------------------------------------------------- */ -static CAN_QueueNode_t *can_queue_list = NULL; -static void (*CAN_Callback[BSP_CAN_NUM][BSP_CAN_CB_NUM])(void); +static BSP_CAN_QueueNode_t *g_can_queue_list = NULL; +static osMutexId_t g_can_queue_mutex = NULL; +static void (*g_can_callbacks[BSP_CAN_NUM][BSP_CAN_CB_NUM])(void); +static bool g_can_initialized = false; /* Private function prototypes ---------------------------------------------- */ -static BSP_CAN_t CAN_Get(CAN_HandleTypeDef *hcan); -static osMessageQueueId_t find_queue(uint32_t can_id); -static void can_rx_fifo0_handler(void); -static void can_rx_fifo1_handler(void); +static BSP_CAN_t BSP_CAN_GetInstance(CAN_HandleTypeDef *hcan); +static osMessageQueueId_t BSP_CAN_FindQueue(uint32_t can_id); +static int8_t BSP_CAN_CreateIdQueue(uint32_t can_id, uint8_t queue_size); +static int8_t BSP_CAN_DeleteIdQueue(uint32_t can_id); +static void BSP_CAN_RxFifo0Handler(void); +static void BSP_CAN_RxFifo1Handler(void); -/* AUTO GENERATED CAN_RX_CALLBACKS */ -/* Private function -------------------------------------------------------- */ +/* Private functions -------------------------------------------------------- */ -/* 查找指定CAN ID的队列 */ -static osMessageQueueId_t find_queue(uint32_t can_id) { - CAN_QueueNode_t *node = can_queue_list; - while (node) { - if (node->can_id == can_id) return node->queue; +/** + * @brief 根据CAN句柄获取BSP_CAN实例 + */ +static BSP_CAN_t BSP_CAN_GetInstance(CAN_HandleTypeDef *hcan) { + if (hcan == NULL) return BSP_CAN_ERR; + +/* AUTO GENERATED CAN_GET */ + else + return BSP_CAN_ERR; +} + +/** + * @brief 查找指定CAN ID的消息队列 + * @note 调用前需要获取互斥锁 + */ +static osMessageQueueId_t BSP_CAN_FindQueue(uint32_t can_id) { + BSP_CAN_QueueNode_t *node = g_can_queue_list; + while (node != NULL) { + if (node->can_id == can_id) { + return node->queue; + } node = node->next; } return NULL; } -/* FIFO0接收处理函数 */ -static void can_rx_fifo0_handler(void) { +/** + * @brief 创建指定CAN ID的消息队列 + * @note 内部函数,已包含互斥锁保护 + */ +static int8_t BSP_CAN_CreateIdQueue(uint32_t can_id, uint8_t queue_size) { + if (queue_size == 0) { + queue_size = BSP_CAN_DEFAULT_QUEUE_SIZE; + } + + // 获取互斥锁 + if (osMutexAcquire(g_can_queue_mutex, CAN_QUEUE_MUTEX_TIMEOUT) != osOK) { + return BSP_ERR_TIMEOUT; + } + + // 检查是否已存在 + BSP_CAN_QueueNode_t *node = g_can_queue_list; + while (node != NULL) { + if (node->can_id == can_id) { + osMutexRelease(g_can_queue_mutex); + return BSP_ERR; // 已存在 + } + node = node->next; + } + + // 创建新节点 + BSP_CAN_QueueNode_t *new_node = (BSP_CAN_QueueNode_t *)BSP_Malloc(sizeof(BSP_CAN_QueueNode_t)); + if (new_node == NULL) { + osMutexRelease(g_can_queue_mutex); + return BSP_ERR_NULL; + } + + // 创建消息队列 + new_node->queue = osMessageQueueNew(queue_size, sizeof(BSP_CAN_Message_t), NULL); + if (new_node->queue == NULL) { + BSP_Free(new_node); + osMutexRelease(g_can_queue_mutex); + return BSP_ERR; + } + + // 初始化节点 + new_node->can_id = can_id; + new_node->queue_size = queue_size; + new_node->next = g_can_queue_list; + g_can_queue_list = new_node; + + osMutexRelease(g_can_queue_mutex); + return BSP_OK; +} + +/** + * @brief 删除指定CAN ID的消息队列 + * @note 内部函数,已包含互斥锁保护 + */ +static int8_t BSP_CAN_DeleteIdQueue(uint32_t can_id) { + // 获取互斥锁 + if (osMutexAcquire(g_can_queue_mutex, CAN_QUEUE_MUTEX_TIMEOUT) != osOK) { + return BSP_ERR_TIMEOUT; + } + + BSP_CAN_QueueNode_t **current = &g_can_queue_list; + while (*current != NULL) { + if ((*current)->can_id == can_id) { + BSP_CAN_QueueNode_t *to_delete = *current; + *current = (*current)->next; + + // 删除队列和节点 + osMessageQueueDelete(to_delete->queue); + BSP_Free(to_delete); + + osMutexRelease(g_can_queue_mutex); + return BSP_OK; + } + current = &(*current)->next; + } + + osMutexRelease(g_can_queue_mutex); + return BSP_ERR; // 未找到 +} + +/** + * @brief FIFO0接收处理函数 + */ +static void BSP_CAN_RxFifo0Handler(void) { CAN_RxHeaderTypeDef rx_header; - uint8_t rx_data[8]; + uint8_t rx_data[BSP_CAN_MAX_DLC]; // 遍历所有CAN接口处理FIFO0 for (int can_idx = 0; can_idx < BSP_CAN_NUM; can_idx++) { @@ -53,24 +153,33 @@ static void can_rx_fifo0_handler(void) { while (HAL_CAN_GetRxFifoFillLevel(hcan, CAN_RX_FIFO0) > 0) { if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_header, rx_data) == HAL_OK) { uint32_t can_id = (rx_header.IDE == CAN_ID_STD) ? rx_header.StdId : rx_header.ExtId; - osMessageQueueId_t queue = find_queue(can_id); - if (queue) { - CAN_Message_t msg; - msg.header = rx_header; - memcpy(msg.data, rx_data, 8); - // 非阻塞发送,如果队列满了就丢弃 - osMessageQueuePut(queue, &msg, 0, 0); + + // 线程安全地查找队列 + if (osMutexAcquire(g_can_queue_mutex, CAN_QUEUE_MUTEX_TIMEOUT) == osOK) { + osMessageQueueId_t queue = BSP_CAN_FindQueue(can_id); + osMutexRelease(g_can_queue_mutex); + + if (queue != NULL) { + BSP_CAN_Message_t msg; + msg.header = rx_header; + memcpy(msg.data, rx_data, BSP_CAN_MAX_DLC); + + // 非阻塞发送,如果队列满了就丢弃 + osMessageQueuePut(queue, &msg, 0, BSP_CAN_TIMEOUT_IMMEDIATE); + } } - // 如果没有找到对应的队列,消息被直接丢弃 + // 如果没有找到对应的队列或获取互斥锁超时,消息被直接丢弃 } } } } -/* FIFO1接收处理函数 */ -static void can_rx_fifo1_handler(void) { +/** + * @brief FIFO1接收处理函数 + */ +static void BSP_CAN_RxFifo1Handler(void) { CAN_RxHeaderTypeDef rx_header; - uint8_t rx_data[8]; + uint8_t rx_data[BSP_CAN_MAX_DLC]; // 遍历所有CAN接口处理FIFO1 for (int can_idx = 0; can_idx < BSP_CAN_NUM; can_idx++) { @@ -80,269 +189,375 @@ static void can_rx_fifo1_handler(void) { while (HAL_CAN_GetRxFifoFillLevel(hcan, CAN_RX_FIFO1) > 0) { if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO1, &rx_header, rx_data) == HAL_OK) { uint32_t can_id = (rx_header.IDE == CAN_ID_STD) ? rx_header.StdId : rx_header.ExtId; - osMessageQueueId_t queue = find_queue(can_id); - if (queue) { - CAN_Message_t msg; - msg.header = rx_header; - memcpy(msg.data, rx_data, 8); - // 非阻塞发送,如果队列满了就丢弃 - osMessageQueuePut(queue, &msg, 0, 0); + + // 线程安全地查找队列 + if (osMutexAcquire(g_can_queue_mutex, CAN_QUEUE_MUTEX_TIMEOUT) == osOK) { + osMessageQueueId_t queue = BSP_CAN_FindQueue(can_id); + osMutexRelease(g_can_queue_mutex); + + if (queue != NULL) { + BSP_CAN_Message_t msg; + msg.header = rx_header; + memcpy(msg.data, rx_data, BSP_CAN_MAX_DLC); + + // 非阻塞发送,如果队列满了就丢弃 + osMessageQueuePut(queue, &msg, 0, BSP_CAN_TIMEOUT_IMMEDIATE); + } } - // 如果没有找到对应的队列,消息被直接丢弃 + // 如果没有找到对应的队列或获取互斥锁超时,消息被直接丢弃 } } } } -static BSP_CAN_t CAN_Get(CAN_HandleTypeDef *hcan) { -/* AUTO GENERATED CAN_GET */ - else - return BSP_CAN_ERR; -} - /* HAL Callback Functions --------------------------------------------------- */ void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan) { - BSP_CAN_t bsp_can = CAN_Get(hcan); - if (bsp_can != BSP_CAN_ERR) { - if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX0_CPLT_CB]) - CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX0_CPLT_CB](); - } + BSP_CAN_t bsp_can = BSP_CAN_GetInstance(hcan); + if (bsp_can != BSP_CAN_ERR) { + if (g_can_callbacks[bsp_can][BSP_CAN_TX_MAILBOX0_CPLT_CB] != NULL) { + g_can_callbacks[bsp_can][BSP_CAN_TX_MAILBOX0_CPLT_CB](); + } + } } void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan) { - BSP_CAN_t bsp_can = CAN_Get(hcan); - if (bsp_can != BSP_CAN_ERR) { - if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX1_CPLT_CB]) - CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX1_CPLT_CB](); - } + BSP_CAN_t bsp_can = BSP_CAN_GetInstance(hcan); + if (bsp_can != BSP_CAN_ERR) { + if (g_can_callbacks[bsp_can][BSP_CAN_TX_MAILBOX1_CPLT_CB] != NULL) { + g_can_callbacks[bsp_can][BSP_CAN_TX_MAILBOX1_CPLT_CB](); + } + } } void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan) { - BSP_CAN_t bsp_can = CAN_Get(hcan); - if (bsp_can != BSP_CAN_ERR) { - if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX2_CPLT_CB]) - CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX2_CPLT_CB](); - } + BSP_CAN_t bsp_can = BSP_CAN_GetInstance(hcan); + if (bsp_can != BSP_CAN_ERR) { + if (g_can_callbacks[bsp_can][BSP_CAN_TX_MAILBOX2_CPLT_CB] != NULL) { + g_can_callbacks[bsp_can][BSP_CAN_TX_MAILBOX2_CPLT_CB](); + } + } } void HAL_CAN_TxMailbox0AbortCallback(CAN_HandleTypeDef *hcan) { - BSP_CAN_t bsp_can = CAN_Get(hcan); - if (bsp_can != BSP_CAN_ERR) { - if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX0_ABORT_CB]) - CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX0_ABORT_CB](); - } + BSP_CAN_t bsp_can = BSP_CAN_GetInstance(hcan); + if (bsp_can != BSP_CAN_ERR) { + if (g_can_callbacks[bsp_can][BSP_CAN_TX_MAILBOX0_ABORT_CB] != NULL) { + g_can_callbacks[bsp_can][BSP_CAN_TX_MAILBOX0_ABORT_CB](); + } + } } void HAL_CAN_TxMailbox1AbortCallback(CAN_HandleTypeDef *hcan) { - BSP_CAN_t bsp_can = CAN_Get(hcan); - if (bsp_can != BSP_CAN_ERR) { - if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX1_ABORT_CB]) - CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX1_ABORT_CB](); - } + BSP_CAN_t bsp_can = BSP_CAN_GetInstance(hcan); + if (bsp_can != BSP_CAN_ERR) { + if (g_can_callbacks[bsp_can][BSP_CAN_TX_MAILBOX1_ABORT_CB] != NULL) { + g_can_callbacks[bsp_can][BSP_CAN_TX_MAILBOX1_ABORT_CB](); + } + } } void HAL_CAN_TxMailbox2AbortCallback(CAN_HandleTypeDef *hcan) { - BSP_CAN_t bsp_can = CAN_Get(hcan); - if (bsp_can != BSP_CAN_ERR) { - if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX2_ABORT_CB]) - CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX2_ABORT_CB](); - } + BSP_CAN_t bsp_can = BSP_CAN_GetInstance(hcan); + if (bsp_can != BSP_CAN_ERR) { + if (g_can_callbacks[bsp_can][BSP_CAN_TX_MAILBOX2_ABORT_CB] != NULL) { + g_can_callbacks[bsp_can][BSP_CAN_TX_MAILBOX2_ABORT_CB](); + } + } } void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { - BSP_CAN_t bsp_can = CAN_Get(hcan); - if (bsp_can != BSP_CAN_ERR) { - if (CAN_Callback[bsp_can][HAL_CAN_RX_FIFO0_MSG_PENDING_CB]) - CAN_Callback[bsp_can][HAL_CAN_RX_FIFO0_MSG_PENDING_CB](); - } + BSP_CAN_t bsp_can = BSP_CAN_GetInstance(hcan); + if (bsp_can != BSP_CAN_ERR) { + if (g_can_callbacks[bsp_can][BSP_CAN_RX_FIFO0_MSG_PENDING_CB] != NULL) { + g_can_callbacks[bsp_can][BSP_CAN_RX_FIFO0_MSG_PENDING_CB](); + } + } } void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan) { - BSP_CAN_t bsp_can = CAN_Get(hcan); - if (bsp_can != BSP_CAN_ERR) { - if (CAN_Callback[bsp_can][HAL_CAN_RX_FIFO0_FULL_CB]) - CAN_Callback[bsp_can][HAL_CAN_RX_FIFO0_FULL_CB](); - } + BSP_CAN_t bsp_can = BSP_CAN_GetInstance(hcan); + if (bsp_can != BSP_CAN_ERR) { + if (g_can_callbacks[bsp_can][BSP_CAN_RX_FIFO0_FULL_CB] != NULL) { + g_can_callbacks[bsp_can][BSP_CAN_RX_FIFO0_FULL_CB](); + } + } } void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan) { - BSP_CAN_t bsp_can = CAN_Get(hcan); - if (bsp_can != BSP_CAN_ERR) { - if (CAN_Callback[bsp_can][HAL_CAN_RX_FIFO1_MSG_PENDING_CB]) - CAN_Callback[bsp_can][HAL_CAN_RX_FIFO1_MSG_PENDING_CB](); - } + BSP_CAN_t bsp_can = BSP_CAN_GetInstance(hcan); + if (bsp_can != BSP_CAN_ERR) { + if (g_can_callbacks[bsp_can][BSP_CAN_RX_FIFO1_MSG_PENDING_CB] != NULL) { + g_can_callbacks[bsp_can][BSP_CAN_RX_FIFO1_MSG_PENDING_CB](); + } + } } void HAL_CAN_RxFifo1FullCallback(CAN_HandleTypeDef *hcan) { - BSP_CAN_t bsp_can = CAN_Get(hcan); - if (bsp_can != BSP_CAN_ERR) { - if (CAN_Callback[bsp_can][HAL_CAN_RX_FIFO1_FULL_CB]) - CAN_Callback[bsp_can][HAL_CAN_RX_FIFO1_FULL_CB](); - } + BSP_CAN_t bsp_can = BSP_CAN_GetInstance(hcan); + if (bsp_can != BSP_CAN_ERR) { + if (g_can_callbacks[bsp_can][BSP_CAN_RX_FIFO1_FULL_CB] != NULL) { + g_can_callbacks[bsp_can][BSP_CAN_RX_FIFO1_FULL_CB](); + } + } } void HAL_CAN_SleepCallback(CAN_HandleTypeDef *hcan) { - BSP_CAN_t bsp_can = CAN_Get(hcan); - if (bsp_can != BSP_CAN_ERR) { - if (CAN_Callback[bsp_can][HAL_CAN_SLEEP_CB]) - CAN_Callback[bsp_can][HAL_CAN_SLEEP_CB](); - } + BSP_CAN_t bsp_can = BSP_CAN_GetInstance(hcan); + if (bsp_can != BSP_CAN_ERR) { + if (g_can_callbacks[bsp_can][BSP_CAN_SLEEP_CB] != NULL) { + g_can_callbacks[bsp_can][BSP_CAN_SLEEP_CB](); + } + } } void HAL_CAN_WakeUpFromRxMsgCallback(CAN_HandleTypeDef *hcan) { - BSP_CAN_t bsp_can = CAN_Get(hcan); - if (bsp_can != BSP_CAN_ERR) { - if (CAN_Callback[bsp_can][HAL_CAN_WAKEUP_FROM_RX_MSG_CB]) - CAN_Callback[bsp_can][HAL_CAN_WAKEUP_FROM_RX_MSG_CB](); - } + BSP_CAN_t bsp_can = BSP_CAN_GetInstance(hcan); + if (bsp_can != BSP_CAN_ERR) { + if (g_can_callbacks[bsp_can][BSP_CAN_WAKEUP_FROM_RX_MSG_CB] != NULL) { + g_can_callbacks[bsp_can][BSP_CAN_WAKEUP_FROM_RX_MSG_CB](); + } + } } void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan) { - BSP_CAN_t bsp_can = CAN_Get(hcan); - if (bsp_can != BSP_CAN_ERR) { - if (CAN_Callback[bsp_can][HAL_CAN_ERROR_CB]) - CAN_Callback[bsp_can][HAL_CAN_ERROR_CB](); - } + BSP_CAN_t bsp_can = BSP_CAN_GetInstance(hcan); + if (bsp_can != BSP_CAN_ERR) { + if (g_can_callbacks[bsp_can][BSP_CAN_ERROR_CB] != NULL) { + g_can_callbacks[bsp_can][BSP_CAN_ERROR_CB](); + } + } } /* Exported functions ------------------------------------------------------- */ + +int8_t BSP_CAN_Init(void) { + if (g_can_initialized) { + return BSP_ERR_INITED; + } + + // 清零回调函数数组 + memset(g_can_callbacks, 0, sizeof(g_can_callbacks)); + + // 创建互斥锁 + g_can_queue_mutex = osMutexNew(NULL); + if (g_can_queue_mutex == NULL) { + return BSP_ERR; + } + +/* AUTO GENERATED CAN_INIT */ + + // 注册默认的接收中断处理函数 + for (int can_idx = 0; can_idx < BSP_CAN_NUM; can_idx++) { + BSP_CAN_RegisterCallback((BSP_CAN_t)can_idx, BSP_CAN_RX_FIFO0_MSG_PENDING_CB, BSP_CAN_RxFifo0Handler); + BSP_CAN_RegisterCallback((BSP_CAN_t)can_idx, BSP_CAN_RX_FIFO1_MSG_PENDING_CB, BSP_CAN_RxFifo1Handler); + } + + g_can_initialized = true; + return BSP_OK; +} + +int8_t BSP_CAN_DeInit(void) { + if (!g_can_initialized) { + return BSP_ERR; + } + + // 删除所有队列 + if (osMutexAcquire(g_can_queue_mutex, CAN_QUEUE_MUTEX_TIMEOUT) == osOK) { + BSP_CAN_QueueNode_t *current = g_can_queue_list; + while (current != NULL) { + BSP_CAN_QueueNode_t *next = current->next; + osMessageQueueDelete(current->queue); + BSP_Free(current); + current = next; + } + g_can_queue_list = NULL; + osMutexRelease(g_can_queue_mutex); + } + + // 删除互斥锁 + if (g_can_queue_mutex != NULL) { + osMutexDelete(g_can_queue_mutex); + g_can_queue_mutex = NULL; + } + + // 清零回调函数数组 + memset(g_can_callbacks, 0, sizeof(g_can_callbacks)); + + g_can_initialized = false; + return BSP_OK; +} + CAN_HandleTypeDef *BSP_CAN_GetHandle(BSP_CAN_t can) { - switch (can) { + if (can >= BSP_CAN_NUM) { + return NULL; + } + + switch (can) { /* AUTO GENERATED BSP_CAN_GET_HANDLE */ - default: - return NULL; - } + default: + return NULL; + } } int8_t BSP_CAN_RegisterCallback(BSP_CAN_t can, BSP_CAN_Callback_t type, void (*callback)(void)) { - if (callback == NULL) return BSP_ERR_NULL; - if (can >= BSP_CAN_NUM) return BSP_ERR_INITED; - if (type >= BSP_CAN_CB_NUM) return BSP_ERR; - - CAN_Callback[can][type] = callback; - return BSP_OK; -} - -int BSP_CAN_GetMessage(uint32_t can_id, CAN_Message_t *msg, uint32_t timeout) { - if (msg == NULL) return BSP_ERR_NULL; - osMessageQueueId_t queue = find_queue(can_id); - if (!queue) return BSP_ERR_NO_DEV; // 没有该队列 - if (osMessageQueueGet(queue, msg, NULL, timeout) == osOK) { - return BSP_OK; // 成功 + if (!g_can_initialized) { + return BSP_ERR_INITED; } - return BSP_ERR; // 超时或队列为空 -} - -int8_t BSP_CAN_CreateIdQueue(uint32_t can_id, uint8_t queue_size) { - // 检查是否已存在 - CAN_QueueNode_t *node = can_queue_list; - while (node) { - if (node->can_id == can_id) { - return BSP_ERR; // 已存在 - } - node = node->next; + if (callback == NULL) { + return BSP_ERR_NULL; } - // 创建新节点 - CAN_QueueNode_t *new_node = malloc(sizeof(CAN_QueueNode_t)); - if (new_node == NULL) return BSP_ERR_NULL; - new_node->can_id = can_id; - new_node->queue_size = queue_size; - new_node->queue = osMessageQueueNew(queue_size, sizeof(CAN_Message_t), NULL); - if (new_node->queue == NULL) { - free(new_node); + if (can >= BSP_CAN_NUM) { return BSP_ERR; } - new_node->next = can_queue_list; - can_queue_list = new_node; + if (type >= BSP_CAN_CB_NUM) { + return BSP_ERR; + } + + g_can_callbacks[can][type] = callback; return BSP_OK; } - -int8_t BSP_CAN_DeleteIdQueue(uint32_t can_id) { - CAN_QueueNode_t **current = &can_queue_list; - while (*current) { - if ((*current)->can_id == can_id) { - CAN_QueueNode_t *to_delete = *current; - *current = (*current)->next; - osMessageQueueDelete(to_delete->queue); - free(to_delete); - return BSP_OK; - } - current = &(*current)->next; - } - return BSP_ERR; // 未找到 -} - - -void BSP_CAN_RegisterId(uint32_t can_id, uint8_t queue_size) { - BSP_CAN_CreateIdQueue(can_id, queue_size); -} - - int8_t BSP_CAN_Transmit(BSP_CAN_t can, BSP_CAN_Format_t format, uint32_t id, uint8_t *data, uint8_t dlc) { - if (can >= BSP_CAN_NUM) return BSP_ERR; - if (data == NULL) return BSP_ERR_NULL; - if (dlc > 8) return BSP_ERR; - - CAN_HandleTypeDef *hcan = BSP_CAN_GetHandle(can); - if (hcan == NULL) return BSP_ERR_NULL; - - CAN_TxHeaderTypeDef header; - uint32_t mailbox; - - switch (format) { - case CAN_FORMAT_STD_DATA: - header.StdId = id; - header.IDE = CAN_ID_STD; - header.RTR = CAN_RTR_DATA; - header.TransmitGlobalTime = DISABLE; - header.DLC = dlc; - break; - case CAN_FORMAT_EXT_DATA: - header.ExtId = id; - header.IDE = CAN_ID_EXT; - header.RTR = CAN_RTR_DATA; - header.TransmitGlobalTime = DISABLE; - header.DLC = dlc; - break; - case CAN_FORMAT_STD_REMOTE: - header.StdId = id; - header.IDE = CAN_ID_STD; - header.RTR = CAN_RTR_REMOTE; - header.TransmitGlobalTime = DISABLE; - header.DLC = dlc; - break; - case CAN_FORMAT_EXT_REMOTE: - header.ExtId = id; - header.IDE = CAN_ID_EXT; - header.RTR = CAN_RTR_REMOTE; - header.TransmitGlobalTime = DISABLE; - header.DLC = dlc; - break; - default: - return BSP_ERR; - } + if (!g_can_initialized) { + return BSP_ERR_INITED; + } + if (can >= BSP_CAN_NUM) { + return BSP_ERR; + } + if (data == NULL) { + return BSP_ERR_NULL; + } + if (dlc > BSP_CAN_MAX_DLC) { + return BSP_ERR; + } + + CAN_HandleTypeDef *hcan = BSP_CAN_GetHandle(can); + if (hcan == NULL) { + return BSP_ERR_NULL; + } + + CAN_TxHeaderTypeDef header = {0}; + uint32_t mailbox; + + switch (format) { + case BSP_CAN_FORMAT_STD_DATA: + header.StdId = id; + header.IDE = CAN_ID_STD; + header.RTR = CAN_RTR_DATA; + break; + case BSP_CAN_FORMAT_EXT_DATA: + header.ExtId = id; + header.IDE = CAN_ID_EXT; + header.RTR = CAN_RTR_DATA; + break; + case BSP_CAN_FORMAT_STD_REMOTE: + header.StdId = id; + header.IDE = CAN_ID_STD; + header.RTR = CAN_RTR_REMOTE; + break; + case BSP_CAN_FORMAT_EXT_REMOTE: + header.ExtId = id; + header.IDE = CAN_ID_EXT; + header.RTR = CAN_RTR_REMOTE; + break; + default: + return BSP_ERR; + } + + header.DLC = dlc; + header.TransmitGlobalTime = DISABLE; + + HAL_StatusTypeDef result = HAL_CAN_AddTxMessage(hcan, &header, data, &mailbox); + return (result == HAL_OK) ? BSP_OK : BSP_ERR; +} - HAL_StatusTypeDef res = HAL_CAN_AddTxMessage(hcan, &header, data, &mailbox); +int8_t BSP_CAN_RegisterId(uint32_t can_id, uint8_t queue_size) { + if (!g_can_initialized) { + return BSP_ERR_INITED; + } + + return BSP_CAN_CreateIdQueue(can_id, queue_size); +} - if (res == HAL_OK) { +int8_t BSP_CAN_UnregisterIdQueue(uint32_t can_id) { + if (!g_can_initialized) { + return BSP_ERR_INITED; + } + + return BSP_CAN_DeleteIdQueue(can_id); +} + +int8_t BSP_CAN_GetMessage(uint32_t can_id, BSP_CAN_Message_t *msg, uint32_t timeout) { + if (!g_can_initialized) { + return BSP_ERR_INITED; + } + if (msg == NULL) { + return BSP_ERR_NULL; + } + + // 线程安全地查找队列 + if (osMutexAcquire(g_can_queue_mutex, CAN_QUEUE_MUTEX_TIMEOUT) != osOK) { + return BSP_ERR_TIMEOUT; + } + + osMessageQueueId_t queue = BSP_CAN_FindQueue(can_id); + osMutexRelease(g_can_queue_mutex); + + if (queue == NULL) { + return BSP_ERR_NO_DEV; // 队列不存在 + } + + osStatus_t result = osMessageQueueGet(queue, msg, NULL, timeout); + return (result == osOK) ? BSP_OK : BSP_ERR; +} + +int32_t BSP_CAN_GetQueueCount(uint32_t can_id) { + if (!g_can_initialized) { + return -1; + } + + // 线程安全地查找队列 + if (osMutexAcquire(g_can_queue_mutex, CAN_QUEUE_MUTEX_TIMEOUT) != osOK) { + return -1; + } + + osMessageQueueId_t queue = BSP_CAN_FindQueue(can_id); + osMutexRelease(g_can_queue_mutex); + + if (queue == NULL) { + return -1; // 队列不存在 + } + + return (int32_t)osMessageQueueGetCount(queue); +} + +int8_t BSP_CAN_FlushQueue(uint32_t can_id) { + if (!g_can_initialized) { + return BSP_ERR_INITED; + } + + // 线程安全地查找队列 + if (osMutexAcquire(g_can_queue_mutex, CAN_QUEUE_MUTEX_TIMEOUT) != osOK) { + return BSP_ERR_TIMEOUT; + } + + osMessageQueueId_t queue = BSP_CAN_FindQueue(can_id); + osMutexRelease(g_can_queue_mutex); + + if (queue == NULL) { + return BSP_ERR_NO_DEV; // 队列不存在 + } + + // 清空队列中的所有消息 + BSP_CAN_Message_t temp_msg; + while (osMessageQueueGet(queue, &temp_msg, NULL, BSP_CAN_TIMEOUT_IMMEDIATE) == osOK) { + // 继续取出消息直到队列为空 + } + return BSP_OK; - } else { - return BSP_ERR; - } -} - -int8_t BSP_CAN_Init(void) { -/* AUTO GENERATED CAN_INIT */ - - // 注册接收中断处理函数 - for (int can_idx = 0; can_idx < BSP_CAN_NUM; can_idx++) { - BSP_CAN_RegisterCallback((BSP_CAN_t)can_idx, HAL_CAN_RX_FIFO0_MSG_PENDING_CB, can_rx_fifo0_handler); - BSP_CAN_RegisterCallback((BSP_CAN_t)can_idx, HAL_CAN_RX_FIFO1_MSG_PENDING_CB, can_rx_fifo1_handler); - } - - return BSP_OK; } +/* USER CAN FUNCTIONS BEGIN */ +/* USER CAN FUNCTIONS END */ \ No newline at end of file diff --git a/assets/User_code/bsp/can.h b/assets/User_code/bsp/can.h index 709d37c..c589e72 100644 --- a/assets/User_code/bsp/can.h +++ b/assets/User_code/bsp/can.h @@ -7,117 +7,138 @@ extern "C" { /* Includes ----------------------------------------------------------------- */ #include #include "bsp/bsp.h" +#include "bsp/mm.h" #include #include #include /* Exported constants ------------------------------------------------------- */ - +#define BSP_CAN_MAX_DLC 8 +#define BSP_CAN_DEFAULT_QUEUE_SIZE 10 +#define BSP_CAN_TIMEOUT_IMMEDIATE 0 +#define BSP_CAN_TIMEOUT_FOREVER osWaitForever /* Exported macro ----------------------------------------------------------- */ /* Exported types ----------------------------------------------------------- */ typedef enum { /* AUTO GENERATED BSP_CAN_NAME */ BSP_CAN_NUM, - BSP_CAN_ERR, + BSP_CAN_ERR = 0xFF, } BSP_CAN_t; typedef enum { - HAL_CAN_TX_MAILBOX0_CPLT_CB, - HAL_CAN_TX_MAILBOX1_CPLT_CB, - HAL_CAN_TX_MAILBOX2_CPLT_CB, - HAL_CAN_TX_MAILBOX0_ABORT_CB, - HAL_CAN_TX_MAILBOX1_ABORT_CB, - HAL_CAN_TX_MAILBOX2_ABORT_CB, - HAL_CAN_RX_FIFO0_MSG_PENDING_CB, - HAL_CAN_RX_FIFO0_FULL_CB, - HAL_CAN_RX_FIFO1_MSG_PENDING_CB, - HAL_CAN_RX_FIFO1_FULL_CB, - HAL_CAN_SLEEP_CB, - HAL_CAN_WAKEUP_FROM_RX_MSG_CB, - HAL_CAN_ERROR_CB, + BSP_CAN_TX_MAILBOX0_CPLT_CB, + BSP_CAN_TX_MAILBOX1_CPLT_CB, + BSP_CAN_TX_MAILBOX2_CPLT_CB, + BSP_CAN_TX_MAILBOX0_ABORT_CB, + BSP_CAN_TX_MAILBOX1_ABORT_CB, + BSP_CAN_TX_MAILBOX2_ABORT_CB, + BSP_CAN_RX_FIFO0_MSG_PENDING_CB, + BSP_CAN_RX_FIFO0_FULL_CB, + BSP_CAN_RX_FIFO1_MSG_PENDING_CB, + BSP_CAN_RX_FIFO1_FULL_CB, + BSP_CAN_SLEEP_CB, + BSP_CAN_WAKEUP_FROM_RX_MSG_CB, + BSP_CAN_ERROR_CB, BSP_CAN_CB_NUM } BSP_CAN_Callback_t; typedef enum { - CAN_FORMAT_STD_DATA, /* 标准数据帧 */ - CAN_FORMAT_EXT_DATA, /* 扩展数据帧 */ - CAN_FORMAT_STD_REMOTE, /* 标准远程帧 */ - CAN_FORMAT_EXT_REMOTE, /* 扩展远程帧 */ + BSP_CAN_FORMAT_STD_DATA, /* 标准数据帧 */ + BSP_CAN_FORMAT_EXT_DATA, /* 扩展数据帧 */ + BSP_CAN_FORMAT_STD_REMOTE, /* 标准远程帧 */ + BSP_CAN_FORMAT_EXT_REMOTE, /* 扩展远程帧 */ } BSP_CAN_Format_t; typedef struct { CAN_RxHeaderTypeDef header; - uint8_t data[8]; -} CAN_Message_t; + uint8_t data[BSP_CAN_MAX_DLC]; +} BSP_CAN_Message_t; /* Exported functions prototypes -------------------------------------------- */ + +/** + * @brief 初始化 CAN 模块 + * @return BSP_OK 成功,其他值失败 + */ +int8_t BSP_CAN_Init(void); + +/** + * @brief 反初始化 CAN 模块 + * @return BSP_OK 成功,其他值失败 + */ +int8_t BSP_CAN_DeInit(void); + /** * @brief 获取 CAN 句柄 - * @param can CAN 枚举类型 + * @param can CAN 枚举 * @return CAN_HandleTypeDef 指针,失败返回 NULL */ CAN_HandleTypeDef *BSP_CAN_GetHandle(BSP_CAN_t can); /** - * @brief 注册 CAN 回调 - * @param can CAN 枚举类型 + * @brief 注册 CAN 回调函数 + * @param can CAN 枚举 * @param type 回调类型 * @param callback 回调函数指针 - * @return BSP_OK 成功,BSP_ERR_NULL/BSP_ERR_INVALID_PARAM 失败 + * @return BSP_OK 成功,其他值失败 */ int8_t BSP_CAN_RegisterCallback(BSP_CAN_t can, BSP_CAN_Callback_t type, void (*callback)(void)); /** * @brief 发送 CAN 消息 - * @param can CAN 枚举类型 + * @param can CAN 枚举 * @param format 消息格式 * @param id CAN ID * @param data 数据指针 * @param dlc 数据长度 - * @return BSP_OK 成功,BSP_ERR/BSP_ERR_NULL/BSP_ERR_INVALID_PARAM 失败 + * @return BSP_OK 成功,其他值失败 */ int8_t BSP_CAN_Transmit(BSP_CAN_t can, BSP_CAN_Format_t format, uint32_t id, uint8_t *data, uint8_t dlc); /** - * @brief 初始化 CAN - * @return BSP_OK 成功,BSP_ERR/BSP_ERR_NULL/BSP_ERR_INITED 失败 + * @brief 注册 CAN ID 接收队列 + * @param can_id CAN ID + * @param queue_size 队列大小,0使用默认值 + * @return BSP_OK 成功,其他值失败 */ -int8_t BSP_CAN_Init(void); +int8_t BSP_CAN_RegisterId(uint32_t can_id, uint8_t queue_size); /** - * @brief 获取 CAN 消息 + * @brief 注销 CAN ID 接收队列 + * @param can_id CAN ID + * @return BSP_OK 成功,其他值失败 + */ +int8_t BSP_CAN_UnregisterIdQueue(uint32_t can_id); + +/** + * @brief 获取 CAN 消息(阻塞方式) * @param can_id CAN ID * @param msg 存储消息的结构体指针 - * @param timeout 超时时间(毫秒) - * @return BSP_OK 成功,BSP_ERR/BSP_ERR_NULL/BSP_ERR_NO_DEV 失败 + * @param timeout 超时时间(毫秒),0为立即返回,osWaitForever为永久等待 + * @return BSP_OK 成功,其他值失败 */ -int BSP_CAN_GetMessage(uint32_t can_id, CAN_Message_t *msg, uint32_t timeout); +int8_t BSP_CAN_GetMessage(uint32_t can_id, BSP_CAN_Message_t *msg, uint32_t timeout); /** - * @brief 注册 CAN ID + * @brief 获取指定ID队列中的消息数量 * @param can_id CAN ID - * @param queue_size 队列大小 - * @return 无 + * @return 消息数量,-1表示队列不存在 */ -void BSP_CAN_RegisterId(uint32_t can_id, uint8_t queue_size); +int32_t BSP_CAN_GetQueueCount(uint32_t can_id); /** - * @brief 创建指定 CAN ID 的队列 + * @brief 清空指定ID队列中的所有消息 * @param can_id CAN ID - * @param queue_size 队列大小 - * @return BSP_OK 成功,BSP_ERR/BSP_ERR_NULL/BSP_ERR_INVALID_PARAM 失败 + * @return BSP_OK 成功,其他值失败 */ -int8_t BSP_CAN_CreateIdQueue(uint32_t can_id, uint8_t queue_size); - -/** - * @brief 删除指定 CAN ID 的队列 - * @param can_id CAN ID - * @return BSP_OK 成功,BSP_ERR/BSP_ERR_INVALID_PARAM 失败 - */ -int8_t BSP_CAN_DeleteIdQueue(uint32_t can_id); +int8_t BSP_CAN_FlushQueue(uint32_t can_id); /* USER CAN FUNCTIONS BEGIN */ -/* USER CAN FUNCTIONS END */ \ No newline at end of file +/* USER CAN FUNCTIONS END */ + +#ifdef __cplusplus +} +#endif \ No newline at end of file