From 2679db41297a99607daafd36423fb36917f775b9 Mon Sep 17 00:00:00 2001 From: xiao Date: Fri, 8 May 2026 05:52:58 +0800 Subject: [PATCH] fix(uart): gate TCP forwarding by UART TX capacity --- App/uart_trans.c | 8 +++ App/uart_trans.h | 1 + Core/Src/main.c | 170 +++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 158 insertions(+), 21 deletions(-) diff --git a/App/uart_trans.c b/App/uart_trans.c index 0230008..c252a0a 100644 --- a/App/uart_trans.c +++ b/App/uart_trans.c @@ -281,6 +281,14 @@ uint16_t uart_trans_write(uart_channel_t channel, const uint8_t *data, uint16_t return written; } +uint16_t uart_trans_tx_free(uart_channel_t channel) +{ + if (channel >= UART_CHANNEL_MAX) { + return 0u; + } + return ring_free(g_channels[channel].tx_head, g_channels[channel].tx_tail, UART_TX_RING_BUFFER_SIZE); +} + void uart_trans_get_stats(uart_channel_t channel, uart_stats_t *stats) { if (channel < UART_CHANNEL_MAX && stats != NULL) { diff --git a/App/uart_trans.h b/App/uart_trans.h index 3024021..e7c8286 100644 --- a/App/uart_trans.h +++ b/App/uart_trans.h @@ -55,6 +55,7 @@ void uart_trans_poll(void); uint16_t uart_trans_rx_available(uart_channel_t channel); uint16_t uart_trans_read(uart_channel_t channel, uint8_t *data, uint16_t max_len); uint16_t uart_trans_write(uart_channel_t channel, const uint8_t *data, uint16_t len); +uint16_t uart_trans_tx_free(uart_channel_t channel); void uart_trans_get_stats(uart_channel_t channel, uart_stats_t *stats); void uart_trans_reset_stats(uart_channel_t channel); void uart_trans_idle_handler(uart_channel_t channel); diff --git a/Core/Src/main.c b/Core/Src/main.c index 7f7590e..cfa93a0 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -35,10 +35,11 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ -#define LED_PIN GPIO_PIN_13 -#define LED_PORT GPIOC -#define APP_ROUTE_BUFFER_SIZE 256u -#define STACK_GUARD_WORD 0xA5A5A5A5u +#define LED_PIN GPIO_PIN_13 +#define LED_PORT GPIOC +#define APP_ROUTE_BUFFER_SIZE 256u +#define APP_TCP_TO_UART_CHUNK_SIZE 128u +#define STACK_GUARD_WORD 0xA5A5A5A5u #define APP_HEALTH_CHECK_INTERVAL_MS 5000u /* USER CODE END PD */ @@ -67,6 +68,8 @@ static void App_RouteTcpTraffic(void); static void StackGuard_Init(void); static void StackGuard_Check(void); static bool App_SendToUart(uint8_t uart_index, uint8_t src_id, uint8_t dst_mask, const uint8_t *data, uint16_t len); +static uint16_t App_SendTcpPayloadToUartRaw(uint8_t uart_index, const uint8_t *data, uint16_t len); +static bool App_SendTcpPayloadToUartMux(uint8_t uart_index, uint8_t src_id, uint8_t dst_mask, const uint8_t *data, uint16_t len); static bool App_SendTcpServerPayload(uint8_t instance, const uint8_t *data, uint16_t len); static bool App_SendTcpClientPayload(uint8_t instance, const uint8_t *data, uint16_t len); /* USER CODE END PFP */ @@ -296,35 +299,159 @@ static bool App_SendToUart(uint8_t uart_index, uint8_t src_id, uint8_t dst_mask, } } +static uint16_t App_SendTcpPayloadToUartRaw(uint8_t uart_index, const uint8_t *data, uint16_t len) +{ + uart_channel_t channel = (uart_index == LINK_UART_U1) ? UART_CHANNEL_U1 : UART_CHANNEL_U0; + return uart_trans_write(channel, data, len); +} + +static bool App_SendTcpPayloadToUartMux(uint8_t uart_index, uint8_t src_id, uint8_t dst_mask, const uint8_t *data, uint16_t len) +{ + uart_channel_t channel = (uart_index == LINK_UART_U1) ? UART_CHANNEL_U1 : UART_CHANNEL_U0; + uint8_t frame[APP_TCP_TO_UART_CHUNK_SIZE + 6u]; + uint16_t frame_len = 0u; + + if (len == 0u || len > APP_TCP_TO_UART_CHUNK_SIZE) { + return false; + } + if (uart_trans_tx_free(channel) < (uint16_t)(len + 6u)) { + return false; + } + if (!uart_mux_encode_frame(src_id, dst_mask, data, len, frame, &frame_len, sizeof(frame))) { + return false; + } + return uart_trans_write(channel, frame, frame_len) == frame_len; +} + static void App_RouteTcpTraffic(void) { const device_config_t *cfg = config_get(); - uint8_t buffer[APP_ROUTE_BUFFER_SIZE]; + uint8_t buffer[APP_TCP_TO_UART_CHUNK_SIZE]; for (uint8_t i = 0; i < TCP_SERVER_INSTANCE_COUNT; ++i) { - int rc = tcp_server_recv(i, buffer, sizeof(buffer)); - if (rc > 0) { + uint16_t available = tcp_server_rx_available(i); + if (available > 0u) { uint8_t link_index = (i == 0u) ? CONFIG_LINK_S1 : CONFIG_LINK_S2; - if (!App_SendToUart(cfg->links[link_index].uart, - config_link_index_to_endpoint(link_index), - config_uart_index_to_endpoint(cfg->links[link_index].uart), - buffer, - (uint16_t)rc)) { - return; + uint8_t uart_index = cfg->links[link_index].uart; + uint8_t src_id = config_link_index_to_endpoint(link_index); + uint8_t dst_mask = config_uart_index_to_endpoint(uart_index); + uart_channel_t channel = (uart_index == LINK_UART_U1) ? UART_CHANNEL_U1 : UART_CHANNEL_U0; + + if (cfg->mux_mode == MUX_MODE_FRAME) { + uint16_t tx_free = uart_trans_tx_free(channel); + uint16_t payload_len; + if (tx_free <= 6u) { + return; + } + payload_len = available; + if (payload_len > APP_TCP_TO_UART_CHUNK_SIZE) { + payload_len = APP_TCP_TO_UART_CHUNK_SIZE; + } + if (payload_len > (uint16_t)(tx_free - 6u)) { + payload_len = (uint16_t)(tx_free - 6u); + } + if (payload_len == 0u) { + return; + } + payload_len = tcp_server_peek(i, buffer, payload_len); + if (payload_len == 0u) { + continue; + } + if (!App_SendTcpPayloadToUartMux(uart_index, src_id, dst_mask, buffer, payload_len)) { + return; + } + tcp_server_drop(i, payload_len); + } else { + uint16_t chunk = available; + uint16_t tx_free = uart_trans_tx_free(channel); + uint16_t written; + if (tx_free == 0u) { + return; + } + if (chunk > APP_TCP_TO_UART_CHUNK_SIZE) { + chunk = APP_TCP_TO_UART_CHUNK_SIZE; + } + if (chunk > tx_free) { + chunk = tx_free; + } + if (chunk == 0u) { + return; + } + chunk = tcp_server_peek(i, buffer, chunk); + if (chunk == 0u) { + continue; + } + written = App_SendTcpPayloadToUartRaw(uart_index, buffer, chunk); + if (written > 0u) { + tcp_server_drop(i, written); + } + if (written < chunk) { + return; + } } } } for (uint8_t i = 0; i < TCP_CLIENT_INSTANCE_COUNT; ++i) { - int rc = tcp_client_recv(i, buffer, sizeof(buffer)); - if (rc > 0) { + uint16_t available = tcp_client_rx_available(i); + if (available > 0u) { uint8_t link_index = (i == 0u) ? CONFIG_LINK_C1 : CONFIG_LINK_C2; - if (!App_SendToUart(cfg->links[link_index].uart, - config_link_index_to_endpoint(link_index), - config_uart_index_to_endpoint(cfg->links[link_index].uart), - buffer, - (uint16_t)rc)) { - return; + uint8_t uart_index = cfg->links[link_index].uart; + uint8_t src_id = config_link_index_to_endpoint(link_index); + uint8_t dst_mask = config_uart_index_to_endpoint(uart_index); + uart_channel_t channel = (uart_index == LINK_UART_U1) ? UART_CHANNEL_U1 : UART_CHANNEL_U0; + + if (cfg->mux_mode == MUX_MODE_FRAME) { + uint16_t tx_free = uart_trans_tx_free(channel); + uint16_t payload_len; + if (tx_free <= 6u) { + return; + } + payload_len = available; + if (payload_len > APP_TCP_TO_UART_CHUNK_SIZE) { + payload_len = APP_TCP_TO_UART_CHUNK_SIZE; + } + if (payload_len > (uint16_t)(tx_free - 6u)) { + payload_len = (uint16_t)(tx_free - 6u); + } + if (payload_len == 0u) { + return; + } + payload_len = tcp_client_peek(i, buffer, payload_len); + if (payload_len == 0u) { + continue; + } + if (!App_SendTcpPayloadToUartMux(uart_index, src_id, dst_mask, buffer, payload_len)) { + return; + } + tcp_client_drop(i, payload_len); + } else { + uint16_t chunk = available; + uint16_t tx_free = uart_trans_tx_free(channel); + uint16_t written; + if (tx_free == 0u) { + return; + } + if (chunk > APP_TCP_TO_UART_CHUNK_SIZE) { + chunk = APP_TCP_TO_UART_CHUNK_SIZE; + } + if (chunk > tx_free) { + chunk = tx_free; + } + if (chunk == 0u) { + return; + } + chunk = tcp_client_peek(i, buffer, chunk); + if (chunk == 0u) { + continue; + } + written = App_SendTcpPayloadToUartRaw(uart_index, buffer, chunk); + if (written > 0u) { + tcp_client_drop(i, written); + } + if (written < chunk) { + return; + } } } } @@ -510,6 +637,7 @@ static void App_Poll(void) sys_check_timeouts(); App_StopLinksIfNeeded(); App_StartLinksIfNeeded(); + tcp_server_poll(); tcp_client_poll(); uart_trans_poll(); StackGuard_Check();