/** ****************************************************************************** * @file uart3_passthrough.c * @brief UART3透传引擎模块实现 * @author Application Layer * @version 1.0 ****************************************************************************** * @attention * 设计依据:UART3智能数据路由与透传功能开发计划 第3.2节 * * 功能说明: * 本模块实现透传数据缓冲与发送功能,将UART3接收的透传数据转发至UART1 * * 工作流程(严格按文档3.2.3节伪代码实现): * 1. 检查是否有待发送数据 * 2. 检查UART1是否可发送 * 3. 获取当前处理节点 * 4. 发送一个字节 * 5. 更新队列状态和统计 * * 发送机制: * - 单字节每次发送,由UART1 TX完成中断驱动连续发送 * - 使用独立环形缓冲区,避免与指令解析争用 ****************************************************************************** */ #include "uart3_passthrough.h" #include "uart3_smart_router_config.h" #include "multi_uart_router.h" #include "uart2_print.h" #include /*============================================================================== * 调试宏定义 *============================================================================*/ #if DEBUG_PASSTHROUGH_ENGINE #define DEBUG_LOG(fmt, ...) UART2_Print_Printf("[PTX] " fmt "\r\n", ##__VA_ARGS__) #else #define DEBUG_LOG(fmt, ...) #endif /*============================================================================== * 全局变量定义 * 设计依据:文档第3.2.2节 *============================================================================*/ /** * @brief 透传引擎全局上下文 * @note 保存透传引擎全部状态信息 */ passthrough_context_t g_passthrough_ctx; /*============================================================================== * 公共函数实现 * 设计依据:文档第3.2.1节模块接口设计 *============================================================================*/ /** * @brief 透传引擎初始化 * @note 初始化透传队列和统计信息 */ void Passthrough_Init(void) { memset(&g_passthrough_ctx, 0, sizeof(g_passthrough_ctx)); for (uint8_t i = 0; i < PASSTHROUGH_MAX_NODES; i++) { g_passthrough_ctx.queue.nodes[i].valid = false; g_passthrough_ctx.queue.nodes[i].length = 0; g_passthrough_ctx.queue.nodes[i].offset = 0; } g_passthrough_ctx.queue.write_index = 0; g_passthrough_ctx.queue.read_index = 0; g_passthrough_ctx.queue.pending_count = 0; g_passthrough_ctx.stats.total_bytes_sent = 0; g_passthrough_ctx.stats.total_packets = 0; g_passthrough_ctx.stats.overflow_count = 0; g_passthrough_ctx.stats.busy_count = 0; g_passthrough_ctx.initialized = true; DEBUG_LOG("Passthrough engine initialized, buffer size: %d bytes", PASSTHROUGH_TOTAL_BUFFER); } /** * @brief 压入单字节到透传缓冲区 * @note 将单个字节添加到透传发送队列 * @param byte: 待发送字节 * @retval bool: true=成功,false=缓冲区满 */ bool Passthrough_PushByte(uint8_t byte) { passthrough_context_t *ctx = &g_passthrough_ctx; if (!ctx->initialized) { return false; } uint8_t next_index = (ctx->queue.write_index + 1) % PASSTHROUGH_MAX_NODES; if (next_index == ctx->queue.read_index && ctx->queue.pending_count > 0) { ctx->stats.overflow_count++; DEBUG_LOG("Buffer full, overflow count: %d", ctx->stats.overflow_count); return false; } passthrough_node_t *node = &ctx->queue.nodes[ctx->queue.write_index]; if (!node->valid || node->length >= PASSTHROUGH_NODE_SIZE) { if (node->valid) { ctx->queue.write_index = next_index; node = &ctx->queue.nodes[ctx->queue.write_index]; } node->length = 0; node->offset = 0; node->valid = true; } node->data[node->length++] = byte; ctx->queue.pending_count++; return true; } /** * @brief 压入数据块到透传缓冲区 * @note 将数据块添加到透传发送队列 * @param data: 数据缓冲区指针 * @param length: 数据长度 * @retval uint16_t: 实际写入的字节数 */ uint16_t Passthrough_PushBuffer(const uint8_t *data, uint16_t length) { if (data == NULL || length == 0) { return 0; } passthrough_context_t *ctx = &g_passthrough_ctx; uint16_t written = 0; for (uint16_t i = 0; i < length; i++) { uint8_t next_index = (ctx->queue.write_index + 1) % PASSTHROUGH_MAX_NODES; if (next_index == ctx->queue.read_index && ctx->queue.pending_count > 0) { ctx->stats.overflow_count++; DEBUG_LOG("Buffer overflow at byte %d/%d", i, length); break; } passthrough_node_t *node = &ctx->queue.nodes[ctx->queue.write_index]; if (!node->valid || node->length >= PASSTHROUGH_NODE_SIZE) { if (node->valid) { ctx->queue.write_index = next_index; node = &ctx->queue.nodes[ctx->queue.write_index]; } node->length = 0; node->offset = 0; node->valid = true; } node->data[node->length++] = data[i]; ctx->queue.pending_count++; written++; } if (written > 0) { ctx->stats.total_packets++; DEBUG_LOG("Pushed %d bytes to buffer, pending: %d", written, ctx->queue.pending_count); } return written; } /** * @brief 透传引擎任务 * @note 在主循环中周期性调用,每次尝试发送一个字节 * 配合UART1 TX完成中断实现连续发送 */ void Passthrough_Task(void) { passthrough_context_t *ctx = &g_passthrough_ctx; if (!ctx->initialized) { return; } if (ctx->queue.pending_count == 0) { return; } if (!Passthrough_CanSend()) { ctx->stats.busy_count++; return; } passthrough_node_t *node = &ctx->queue.nodes[ctx->queue.read_index]; if (!node->valid || node->offset >= node->length) { if (node->valid) { node->valid = false; } ctx->queue.read_index = (ctx->queue.read_index + 1) % PASSTHROUGH_MAX_NODES; return; } uint8_t byte = node->data[node->offset++]; MultiUART_Send(PORT_UART1, &byte, 1); ctx->queue.pending_count--; ctx->stats.total_bytes_sent++; DEBUG_LOG("Sent byte 0x%02X, pending: %d", byte, ctx->queue.pending_count); } /** * @brief UART1发送完成回调 * @note 应在HAL_UART_TxCpltCallback中调用,触发下一次发送 */ void Passthrough_OnTxComplete(void) { Passthrough_Task(); } /** * @brief 检查UART1是否可发送 * @note 检查UART1发送缓冲区是否有空间 * @retval bool: true=可发送,false=忙 */ bool Passthrough_CanSend(void) { return (MultiUART_GetTxAvailable(PORT_UART1) > 0) && (g_passthrough_ctx.queue.pending_count > 0); } /** * @brief 获取透传统计信息 * @note 获取透传引擎的运行统计 * @param stats: 统计结构指针 */ void Passthrough_GetStats(passthrough_stats_t *stats) { if (stats != NULL) { memcpy(stats, &g_passthrough_ctx.stats, sizeof(passthrough_stats_t)); } } /** * @brief 重置统计信息 * @note 清零所有统计计数器 */ void Passthrough_ResetStats(void) { passthrough_context_t *ctx = &g_passthrough_ctx; ctx->stats.total_bytes_sent = 0; ctx->stats.total_packets = 0; ctx->stats.overflow_count = 0; ctx->stats.busy_count = 0; DEBUG_LOG("Stats reset"); } /** * @brief 获取待发送字节数 * @note 获取队列中等待发送的字节总数 * @retval uint16_t: 待发送字节数 */ uint16_t Passthrough_GetPendingCount(void) { return g_passthrough_ctx.queue.pending_count; }