fix(uart): gate TCP forwarding by UART TX capacity
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
+149
-21
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user