fix(uart): gate TCP forwarding by UART TX capacity

This commit is contained in:
2026-05-08 05:52:58 +08:00
parent 245d98f58e
commit 2679db4129
3 changed files with 158 additions and 21 deletions
+8
View File
@@ -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) {
+1
View File
@@ -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);
+143 -15
View File
@@ -38,6 +38,7 @@
#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,36 +299,160 @@ 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)) {
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)) {
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();