/** ****************************************************************************** * @file cmd_router.c * @brief 指令路由与响应分发模块实现 * @author Application Layer * @version 1.0 ****************************************************************************** * @attention * 本模块实现指令路由与响应分发功能 * 设计依据:多通信接口统一指令处理系统开发计划 第3.2节 * * 核心职责: * - 从各UART端口读取数据并喂入解析器 * - 根据指令来源端口路由响应 * - 管理响应路由表 * * 工作流程: * 1. 中断中将接收字节写入对应端口的环形缓冲区 * 2. 主循环中CmdRouter_Task轮询各端口缓冲区 * 3. 读取字节喂入CmdParser解析器 * 4. 解析完成后通过回调发送响应到源端口 ****************************************************************************** */ #include "cmd_router.h" #include "multi_uart_router.h" #include "cmd_parser.h" #include "uart2_print.h" #include "debug_log.h" #include #define DEBUG_CMD_ROUTER 1 #if DEBUG_CMD_ROUTER #define ROUTER_LOG(fmt, ...) UART2_Print_Printf("[ROUTER] " fmt "\r\n", ##__VA_ARGS__) #else #define ROUTER_LOG(fmt, ...) #endif #define RX_LOG_BUFFER_SIZE 128 typedef struct { uint8_t source_port; uint32_t last_feed_tick; uint32_t rx_count; bool active; } port_parser_state_t; static port_parser_state_t g_port_states[PORT_COUNT]; static cmd_response_handler_t g_response_handler = NULL; static uint32_t g_processed_count = 0; static uint32_t g_routed_count = 0; static uint8_t g_current_parsing_port = PORT_UART2; static uint8_t g_rx_log_buffer[PORT_COUNT][RX_LOG_BUFFER_SIZE]; static uint16_t g_rx_log_len[PORT_COUNT]; static uint32_t g_rx_log_last_tick[PORT_COUNT]; #define RX_LOG_TIMEOUT_MS 50 static void flush_rx_log(port_id_t port_id) { if (g_rx_log_len[port_id] == 0) { return; } UART2_Print_Printf("[ROUTER] %s RX: \"", MultiUART_GetPortName(port_id)); for (uint16_t i = 0; i < g_rx_log_len[port_id]; i++) { uint8_t c = g_rx_log_buffer[port_id][i]; if (c >= 0x20 && c < 0x7F) { UART2_Print_Send(&c, 1); } else if (c == '\r') { UART2_Print_Send((const uint8_t *)"\\r", 2); } else if (c == '\n') { UART2_Print_Send((const uint8_t *)"\\n", 2); } else { char hex[4]; snprintf(hex, sizeof(hex), "\\x%02X", c); UART2_Print_Send((const uint8_t *)hex, 4); } } UART2_Print_String("\"\r\n"); g_rx_log_len[port_id] = 0; } static void append_rx_log(port_id_t port_id, uint8_t byte) { if (g_rx_log_len[port_id] < RX_LOG_BUFFER_SIZE) { g_rx_log_buffer[port_id][g_rx_log_len[port_id]++] = byte; } g_rx_log_last_tick[port_id] = HAL_GetTick(); } static void cmd_parser_response_callback(uint8_t source_port, const char *response) { if (g_response_handler != NULL) { g_response_handler((port_id_t)source_port, response, strlen(response)); g_routed_count++; } else { MultiUART_SendString((port_id_t)source_port, response); g_routed_count++; } LOG_INFO("ROUTER", "TX[%s]: %s", MultiUART_GetPortName((port_id_t)source_port), response); } void CmdRouter_Init(void) { for (port_id_t i = 0; i < PORT_COUNT; i++) { g_port_states[i].source_port = i; g_port_states[i].last_feed_tick = 0; g_port_states[i].rx_count = 0; g_port_states[i].active = false; g_rx_log_len[i] = 0; g_rx_log_last_tick[i] = 0; } g_response_handler = NULL; g_processed_count = 0; g_routed_count = 0; g_current_parsing_port = PORT_UART2; CmdParser_SetResponseCallback(cmd_parser_response_callback); ROUTER_LOG("Init OK, %d ports registered", PORT_COUNT); } void CmdRouter_Task(void) { uint32_t current_tick = HAL_GetTick(); for (port_id_t port_id = 0; port_id < PORT_COUNT; port_id++) { if (port_id == PORT_UART2) { continue; } if (g_rx_log_len[port_id] > 0 && (current_tick - g_rx_log_last_tick[port_id]) >= RX_LOG_TIMEOUT_MS) { flush_rx_log(port_id); } } for (port_id_t port_id = 0; port_id < PORT_COUNT; port_id++) { if (port_id == PORT_UART2) { continue; } uint16_t rx_count = MultiUART_GetRxCount(port_id); if (rx_count == 0) { continue; } g_current_parsing_port = port_id; CmdParser_SetSourcePort(port_id); uint8_t byte; while (MultiUART_ReadByte(port_id, &byte) > 0) { append_rx_log(port_id, byte); CmdParser_FeedByte(byte, HAL_GetTick()); g_port_states[port_id].rx_count++; } if (CmdParser_HasCompleteFrame(NULL)) { flush_rx_log(port_id); g_processed_count++; g_port_states[port_id].active = true; } } CmdParser_Task(); } void CmdRouter_SetResponseHandler(cmd_response_handler_t handler) { g_response_handler = handler; ROUTER_LOG("Response handler %s", handler ? "set" : "cleared"); } void CmdRouter_SendResponse(port_id_t port, const char *response, uint16_t len) { if (port >= PORT_COUNT || response == NULL || len == 0) { return; } MultiUART_Send(port, (const uint8_t *)response, len); g_routed_count++; LOG_INFO("ROUTER", "SendResponse[%s]: %.*s", MultiUART_GetPortName(port), len, response); } void CmdRouter_BroadcastResponse(const char *response, uint16_t len) { if (response == NULL || len == 0) { return; } for (port_id_t port = 0; port < PORT_COUNT; port++) { MultiUART_Send(port, (const uint8_t *)response, len); g_routed_count++; } LOG_INFO("ROUTER", "Broadcast: %.*s", len, response); } uint32_t CmdRouter_GetProcessedCount(void) { return g_processed_count; } uint32_t CmdRouter_GetRoutedCount(void) { return g_routed_count; }