#ifndef _CAN_H #define _CAN_H /** * @file Can.h * @brief Bootloader CAN-FD 通信适配层头文件。 * * 定义 CAN 初始化、收发队列与 OTA 回包接口。 */ #include #include "config.h" #ifdef __cplusplus extern "C" { #endif #include "gd32e50x_can.h" #include /** * @brief 初始化 CAN0 相关 GPIO 与引脚复用。 * * @return 0 表示初始化结束。 */ u8 can_gpio_init(void); /** * @brief 完成 CAN-FD 控制器、滤波器与中断配置。 * * @return 无。 */ void canfd_config(void); /** * @brief CAN0 FIFO0 接收中断服务函数。 * * @return 无。 */ void CAN0_RX0_IRQHandler(void); /** * @brief CAN0 发送邮箱空中断服务函数。 * * @return 无。 */ void CAN0_TX_IRQHandler(void); /** * @brief Bootloader 的 CAN-FD 通信适配层。 * * 负责初始化 CAN0 外设、收发 OTA 相关帧,并在发送邮箱繁忙时 * 通过软件队列缓存待发消息。 */ class CAN_transmiter { private: static constexpr u8 kTxQueueSize = 8U; typedef struct { u32 id; /**< 扩展帧 ID */ u8 length; /**< 有效载荷长度(CAN-FD DLC 归一化后的字节数) */ u8 data[64]; /**< 最多支持 64 字节 CAN-FD 载荷 */ u8 valid; /**< 当前槽位是否有效 */ } tx_queue_item_t; static tx_queue_item_t s_txQueue[kTxQueueSize]; /**< 软件发送环形队列。 */ static volatile u8 s_txQueueHead; /**< 软件发送队列头索引。 */ static volatile u8 s_txQueueTail; /**< 软件发送队列尾索引。 */ static volatile u8 s_txQueueCount; /**< 软件发送队列当前元素数。 */ static can_trasnmit_message_struct s_queueTransmitMessage; /**< 发送中断复用帧对象。 */ can_trasnmit_message_struct transmit_message; /**< 当前正在组装/发送的 CAN-FD 帧。 */ u8 transmit_mailbox = CAN_NOMAILBOX; /**< can_message_transmit() 返回的邮箱号。 */ u8 transmit_data[64]; /**< 通用发送缓冲区,最大支持 64 字节 CAN-FD 载荷。 */ /** @brief 向软件发送队列压入一帧待发消息。 */ static u8 queuePush(u32 id, u8 length, u8 *data); /** @brief 从软件发送队列弹出一帧待发消息。 */ static u8 queuePop(tx_queue_item_t *item); public: /** @brief 初始化 CAN 控制器与软件状态。 * * @return 0 表示初始化完成。 */ u8 init(void); can_receive_message_struct receive_message; /**< 最近收到的一帧 OTA 相关消息。 */ volatile u8 can0_receive_count; /**< 等待主循环处理的接收帧计数。 */ volatile FlagStatus can0_send_flag; /**< 发送完成标记。 */ /** * @brief 轮询处理最近收到的 CAN OTA 帧。 * * 该函数会根据接收帧 ID 把消息转交给 OTA 状态机处理。 * * @return 无。 */ void communication_check(); /** @brief 异步发送一帧 CAN-FD 数据。 * * 当硬件发送邮箱不可用时,函数会尝试把该帧压入软件队列。 * * @param ID 扩展帧 ID。 * @param length 原始数据长度。 * @param data 指向待发送数据缓冲区的指针。 * @return 1 表示发送成功或成功入队,0 表示失败。 */ u8 CANFD_AsyncSend(u32 ID, u8 length, u8 *data); /** @brief 发送「备份恢复」提示帧。 * * @return 1 表示发送成功或成功入队,0 表示失败。 */ u8 sendBackup(); /** @brief CAN RX0 中断实际处理逻辑。 */ static void onRx0Interrupt(); /** @brief CAN TX 中断实际处理逻辑。 */ static void onTxInterrupt(); }; #ifdef __cplusplus } #endif #endif