/** ****************************************************************************** * @file multi_uart_router.c * @brief 多UART统一路由核心模块实现 * @author Application Layer * @version 1.0 ****************************************************************************** * @attention * 本模块实现多UART端口的统一管理 * 设计依据:多通信接口统一指令处理系统开发计划 第3.1、3.3、3.5节及附录A * * 关键特性: * 1. 中断+环形缓冲区接收机制 * 2. 非阻塞发送机制 * 3. 端口上下文表管理 * 4. 响应路由表 ****************************************************************************** */ #include "multi_uart_router.h" #include "uart2_print.h" #include #include #include #define DEBUG_MULTI_UART 1 #if DEBUG_MULTI_UART #define DEBUG_LOG(fmt, ...) UART2_Print_Printf("[MUART] " fmt "\r\n", ##__VA_ARGS__) #else #define DEBUG_LOG(fmt, ...) #endif static uart_port_context_t g_port_ctx[PORT_COUNT]; static UART_HandleTypeDef *const g_port_uart_map[PORT_COUNT] = { [PORT_UART1] = &huart1, [PORT_UART2] = &huart2, [PORT_UART3] = &huart3, }; static const char *const g_port_name_map[PORT_COUNT] = { [PORT_UART1] = "UART1", [PORT_UART2] = "UART2", [PORT_UART3] = "UART3", }; static void rx_ring_init(uart_rx_ring_t *ring) { ring->head = 0; ring->tail = 0; ring->count = 0; ring->overflow_count = 0; } static void tx_ring_init(uart_tx_ring_t *ring) { ring->head = 0; ring->tail = 0; ring->count = 0; ring->is_sending = false; ring->overflow_count = 0; } static bool rx_ring_push(uart_rx_ring_t *ring, uint8_t byte) { bool success = true; __disable_irq(); if (ring->count >= UART_RX_BUFFER_SIZE) { ring->overflow_count++; success = false; } else { ring->buffer[ring->head] = byte; ring->head = (ring->head + 1) % UART_RX_BUFFER_SIZE; ring->count++; } __enable_irq(); return success; } static uint16_t rx_ring_pop(uart_rx_ring_t *ring, uint8_t *byte) { uint16_t result = 0; __disable_irq(); if (ring->count > 0) { *byte = ring->buffer[ring->tail]; ring->tail = (ring->tail + 1) % UART_RX_BUFFER_SIZE; ring->count--; result = 1; } __enable_irq(); return result; } static uint16_t tx_ring_push(uart_tx_ring_t *ring, const uint8_t *data, uint16_t len) { uint16_t written = 0; __disable_irq(); for (uint16_t i = 0; i < len; i++) { if (ring->count >= UART_TX_BUFFER_SIZE) { ring->overflow_count++; break; } ring->buffer[ring->head] = data[i]; ring->head = (ring->head + 1) % UART_TX_BUFFER_SIZE; ring->count++; written++; } __enable_irq(); return written; } static void tx_kickoff(port_id_t port_id) { uart_port_context_t *ctx = &g_port_ctx[port_id]; uart_tx_ring_t *ring = &ctx->tx_ring; uint8_t byte; bool has_data = false; __disable_irq(); if (!ring->is_sending && ring->count > 0) { byte = ring->buffer[ring->tail]; ring->tail = (ring->tail + 1) % UART_TX_BUFFER_SIZE; ring->count--; ring->is_sending = true; has_data = true; } __enable_irq(); if (has_data) { HAL_UART_Transmit_IT(ctx->huart, &byte, 1); } } void MultiUART_Init(void) { for (port_id_t i = 0; i < PORT_COUNT; i++) { uart_port_context_t *ctx = &g_port_ctx[i]; ctx->huart = g_port_uart_map[i]; ctx->name = g_port_name_map[i]; rx_ring_init(&ctx->rx_ring); tx_ring_init(&ctx->tx_ring); ctx->rx_tmp = 0; ctx->rx_count = 0; ctx->tx_count = 0; ctx->error_count = 0; ctx->initialized = true; } DEBUG_LOG("Init OK, %d ports configured", PORT_COUNT); } void MultiUART_FeedByte(port_id_t port_id, uint8_t byte) { if (port_id >= PORT_COUNT) { return; } uart_port_context_t *ctx = &g_port_ctx[port_id]; if (!ctx->initialized) { return; } if (!rx_ring_push(&ctx->rx_ring, byte)) { ctx->error_count++; DEBUG_LOG("%s RX overflow", ctx->name); } ctx->rx_count++; } void MultiUART_Task(void) { for (port_id_t i = 0; i < PORT_COUNT; i++) { uart_port_context_t *ctx = &g_port_ctx[i]; if (!ctx->initialized) { continue; } if (i == PORT_UART2) { continue; } tx_kickoff(i); } } void MultiUART_Send(port_id_t port_id, const uint8_t *data, uint16_t len) { if (port_id >= PORT_COUNT || data == NULL || len == 0) { return; } if (port_id == PORT_UART2) { UART2_Print_Send(data, len); return; } uart_port_context_t *ctx = &g_port_ctx[port_id]; if (!ctx->initialized) { return; } uint16_t written = tx_ring_push(&ctx->tx_ring, data, len); if (written > 0) { ctx->tx_count += written; tx_kickoff(port_id); } } void MultiUART_SendString(port_id_t port_id, const char *str) { if (str == NULL) { return; } MultiUART_Send(port_id, (const uint8_t *)str, strlen(str)); } void MultiUART_SendFmt(port_id_t port_id, const char *fmt, ...) { if (fmt == NULL) { return; } char buffer[128]; va_list args; va_start(args, fmt); int len = vsnprintf(buffer, sizeof(buffer), fmt, args); va_end(args); if (len > 0) { if (len >= (int)sizeof(buffer)) { len = sizeof(buffer) - 1; } MultiUART_Send(port_id, (const uint8_t *)buffer, len); } } void MultiUART_TxCpltCallback(port_id_t port_id) { if (port_id >= PORT_COUNT) { return; } if (port_id == PORT_UART2) { UART2_Print_TxCpltCallback(); return; } uart_port_context_t *ctx = &g_port_ctx[port_id]; uart_tx_ring_t *ring = &ctx->tx_ring; uint8_t byte; bool has_more = false; __disable_irq(); ring->is_sending = false; if (ring->count > 0) { byte = ring->buffer[ring->tail]; ring->tail = (ring->tail + 1) % UART_TX_BUFFER_SIZE; ring->count--; ring->is_sending = true; has_more = true; } __enable_irq(); if (has_more) { HAL_UART_Transmit_IT(ctx->huart, &byte, 1); } } const char *MultiUART_GetPortName(port_id_t port_id) { if (port_id >= PORT_COUNT) { return "UNKNOWN"; } return g_port_name_map[port_id]; } uint16_t MultiUART_GetRxCount(port_id_t port_id) { if (port_id >= PORT_COUNT) { return 0; } uint16_t count; __disable_irq(); count = g_port_ctx[port_id].rx_ring.count; __enable_irq(); return count; } uint16_t MultiUART_ReadByte(port_id_t port_id, uint8_t *byte) { if (port_id >= PORT_COUNT || byte == NULL) { return 0; } uart_rx_ring_t *ring = &g_port_ctx[port_id].rx_ring; __disable_irq(); if (ring->count == 0) { __enable_irq(); return 0; } *byte = ring->buffer[ring->tail]; ring->tail = (ring->tail + 1) % UART_RX_BUFFER_SIZE; ring->count--; __enable_irq(); return 1; } uint16_t MultiUART_GetTxAvailable(port_id_t port_id) { if (port_id >= PORT_COUNT) { return 0; } uint16_t available; __disable_irq(); available = UART_TX_BUFFER_SIZE - g_port_ctx[port_id].tx_ring.count; __enable_irq(); return available; } uint32_t MultiUART_GetOverflowCount(port_id_t port_id) { if (port_id >= PORT_COUNT) { return 0; } return g_port_ctx[port_id].rx_ring.overflow_count + g_port_ctx[port_id].tx_ring.overflow_count; }