feat: save stable CH390 bridge baseline

This commit is contained in:
2026-04-04 02:48:21 +08:00
parent 6f4ba247a4
commit d5b2506269
18 changed files with 2146 additions and 1621 deletions
+103 -96
View File
@@ -1,12 +1,12 @@
/**
* @file tcp_server.c
* @brief lwIP RAW TCP server for the UART2 bridge.
* @brief Indexed lwIP RAW TCP server manager.
*/
#include "tcp_server.h"
#include "lwip/pbuf.h"
#include "lwip/tcp.h"
#include "../Drivers/LwIP/src/include/lwip/pbuf.h"
#include "../Drivers/LwIP/src/include/lwip/tcp.h"
#include "SEGGER_RTT.h"
@@ -18,11 +18,12 @@ typedef struct {
uint8_t rx_ring[TCP_SERVER_RX_BUFFER_SIZE];
uint16_t rx_head;
uint16_t rx_tail;
tcp_server_config_t config;
uint8_t index;
tcp_server_instance_config_t config;
tcp_server_status_t status;
} tcp_server_ctx_t;
static tcp_server_ctx_t g_server;
static tcp_server_ctx_t g_servers[TCP_SERVER_INSTANCE_COUNT];
static uint16_t ring_free(uint16_t head, uint16_t tail, uint16_t size)
{
@@ -34,13 +35,18 @@ static err_t tcp_server_on_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p,
tcp_server_ctx_t *ctx = (tcp_server_ctx_t *)arg;
struct pbuf *q;
if (ctx == NULL) {
if (p != NULL) {
pbuf_free(p);
}
return ERR_ARG;
}
if (err != ERR_OK) {
if (p != NULL) {
pbuf_free(p);
}
return err;
}
if (p == NULL) {
tcp_arg(pcb, NULL);
tcp_recv(pcb, NULL);
@@ -50,8 +56,7 @@ static err_t tcp_server_on_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p,
tcp_abort(pcb);
}
ctx->client_pcb = NULL;
ctx->status.state = TCP_SERVER_STATE_LISTENING;
SEGGER_RTT_WriteString(0, "TCP server peer disconnected\r\n");
ctx->status.state = ctx->config.enabled ? TCP_SERVER_STATE_LISTENING : TCP_SERVER_STATE_IDLE;
return ERR_OK;
}
@@ -77,28 +82,31 @@ static err_t tcp_server_on_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
tcp_server_ctx_t *ctx = (tcp_server_ctx_t *)arg;
(void)pcb;
ctx->status.tx_bytes += len;
if (ctx != NULL) {
ctx->status.tx_bytes += len;
}
return ERR_OK;
}
static void tcp_server_on_err(void *arg, err_t err)
{
tcp_server_ctx_t *ctx = (tcp_server_ctx_t *)arg;
(void)err;
if (ctx == NULL) {
return;
}
ctx->client_pcb = NULL;
ctx->status.state = TCP_SERVER_STATE_LISTENING;
ctx->status.state = ctx->config.enabled ? TCP_SERVER_STATE_LISTENING : TCP_SERVER_STATE_IDLE;
ctx->status.errors++;
SEGGER_RTT_printf(0, "TCP server connection error=%d\r\n", (int)err);
SEGGER_RTT_printf(0, "TCP server[%u] connection error=%d\r\n", ctx->index, (int)err);
}
static err_t tcp_server_on_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
{
tcp_server_ctx_t *ctx = (tcp_server_ctx_t *)arg;
if (err != ERR_OK) {
return err;
if (ctx == NULL || err != ERR_OK) {
return (ctx == NULL) ? ERR_ARG : err;
}
if (ctx->client_pcb != NULL) {
tcp_abort(newpcb);
return ERR_ABRT;
@@ -107,10 +115,7 @@ static err_t tcp_server_on_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
ctx->client_pcb = newpcb;
ctx->status.state = TCP_SERVER_STATE_CONNECTED;
ctx->status.connections++;
SEGGER_RTT_WriteString(0, "TCP server client connected\r\n");
tcp_nagle_disable(newpcb);
tcp_arg(newpcb, ctx);
tcp_recv(newpcb, tcp_server_on_recv);
tcp_sent(newpcb, tcp_server_on_sent);
@@ -118,149 +123,151 @@ static err_t tcp_server_on_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
return ERR_OK;
}
int tcp_server_init(const tcp_server_config_t *config)
int tcp_server_init_all(void)
{
memset(&g_server, 0, sizeof(g_server));
g_server.config.port = TCP_SERVER_DEFAULT_PORT;
g_server.config.auto_reconnect = true;
g_server.status.state = TCP_SERVER_STATE_IDLE;
if (config != NULL) {
g_server.config = *config;
memset(g_servers, 0, sizeof(g_servers));
for (uint8_t i = 0; i < TCP_SERVER_INSTANCE_COUNT; ++i) {
g_servers[i].index = i;
g_servers[i].status.state = TCP_SERVER_STATE_IDLE;
}
return 0;
}
int tcp_server_start(void)
int tcp_server_config(uint8_t instance, const tcp_server_instance_config_t *config)
{
if (instance >= TCP_SERVER_INSTANCE_COUNT || config == NULL) {
return -1;
}
g_servers[instance].config = *config;
return 0;
}
int tcp_server_start(uint8_t instance)
{
struct tcp_pcb *pcb;
err_t err;
tcp_server_ctx_t *ctx;
if (g_server.listen_pcb != NULL) {
if (instance >= TCP_SERVER_INSTANCE_COUNT) {
return -1;
}
ctx = &g_servers[instance];
if (!ctx->config.enabled) {
ctx->status.state = TCP_SERVER_STATE_IDLE;
return 0;
}
if (ctx->listen_pcb != NULL) {
return 0;
}
pcb = tcp_new_ip_type(IPADDR_TYPE_V4);
if (pcb == NULL) {
g_server.status.errors++;
ctx->status.errors++;
return -1;
}
err = tcp_bind(pcb, IP_ANY_TYPE, g_server.config.port);
err = tcp_bind(pcb, IP_ANY_TYPE, ctx->config.port);
if (err != ERR_OK) {
tcp_abort(pcb);
g_server.status.errors++;
ctx->status.errors++;
return -1;
}
g_server.listen_pcb = tcp_listen_with_backlog(pcb, 1);
if (g_server.listen_pcb == NULL) {
g_server.status.errors++;
ctx->listen_pcb = tcp_listen_with_backlog(pcb, 1);
if (ctx->listen_pcb == NULL) {
ctx->status.errors++;
return -1;
}
tcp_arg(g_server.listen_pcb, &g_server);
tcp_accept(g_server.listen_pcb, tcp_server_on_accept);
g_server.status.state = TCP_SERVER_STATE_LISTENING;
SEGGER_RTT_printf(0, "TCP server listening on %u\r\n", g_server.config.port);
tcp_arg(ctx->listen_pcb, ctx);
tcp_accept(ctx->listen_pcb, tcp_server_on_accept);
ctx->status.state = TCP_SERVER_STATE_LISTENING;
return 0;
}
int tcp_server_stop(void)
int tcp_server_stop(uint8_t instance)
{
if (g_server.client_pcb != NULL) {
tcp_arg(g_server.client_pcb, NULL);
tcp_recv(g_server.client_pcb, NULL);
tcp_sent(g_server.client_pcb, NULL);
tcp_err(g_server.client_pcb, NULL);
tcp_abort(g_server.client_pcb);
g_server.client_pcb = NULL;
tcp_server_ctx_t *ctx;
if (instance >= TCP_SERVER_INSTANCE_COUNT) {
return -1;
}
ctx = &g_servers[instance];
if (ctx->client_pcb != NULL) {
tcp_arg(ctx->client_pcb, NULL);
tcp_recv(ctx->client_pcb, NULL);
tcp_sent(ctx->client_pcb, NULL);
tcp_err(ctx->client_pcb, NULL);
tcp_abort(ctx->client_pcb);
ctx->client_pcb = NULL;
}
if (ctx->listen_pcb != NULL) {
tcp_arg(ctx->listen_pcb, NULL);
tcp_accept(ctx->listen_pcb, NULL);
tcp_close(ctx->listen_pcb);
ctx->listen_pcb = NULL;
}
if (g_server.listen_pcb != NULL) {
tcp_arg(g_server.listen_pcb, NULL);
tcp_accept(g_server.listen_pcb, NULL);
tcp_close(g_server.listen_pcb);
g_server.listen_pcb = NULL;
}
g_server.status.state = TCP_SERVER_STATE_IDLE;
ctx->status.state = TCP_SERVER_STATE_IDLE;
ctx->rx_head = 0u;
ctx->rx_tail = 0u;
return 0;
}
int tcp_server_send(const uint8_t *data, uint16_t len)
int tcp_server_send(uint8_t instance, const uint8_t *data, uint16_t len)
{
err_t err;
tcp_server_ctx_t *ctx;
if (g_server.client_pcb == NULL || data == NULL || len == 0u) {
if (instance >= TCP_SERVER_INSTANCE_COUNT || data == NULL || len == 0u) {
return -1;
}
if ((g_server.client_pcb->flags & TF_RXCLOSED) != 0u) {
g_server.status.errors++;
ctx = &g_servers[instance];
if (ctx->client_pcb == NULL) {
return -1;
}
if (tcp_sndbuf(g_server.client_pcb) < len) {
if (tcp_sndbuf(ctx->client_pcb) < len) {
return 0;
}
err = tcp_write(g_server.client_pcb, data, len, TCP_WRITE_FLAG_COPY);
err = tcp_write(ctx->client_pcb, data, len, TCP_WRITE_FLAG_COPY);
if (err != ERR_OK) {
g_server.status.errors++;
ctx->status.errors++;
return -1;
}
err = tcp_output(g_server.client_pcb);
err = tcp_output(ctx->client_pcb);
if (err != ERR_OK) {
g_server.status.errors++;
ctx->status.errors++;
return -1;
}
return (int)len;
}
int tcp_server_recv(uint8_t *data, uint16_t max_len, uint32_t timeout_ms)
int tcp_server_recv(uint8_t instance, uint8_t *data, uint16_t max_len)
{
uint16_t copied = 0u;
(void)timeout_ms;
tcp_server_ctx_t *ctx;
if (data == NULL || max_len == 0u) {
if (instance >= TCP_SERVER_INSTANCE_COUNT || data == NULL || max_len == 0u) {
return -1;
}
while (copied < max_len && g_server.rx_tail != g_server.rx_head) {
data[copied++] = g_server.rx_ring[g_server.rx_tail];
g_server.rx_tail = (uint16_t)((g_server.rx_tail + 1u) % TCP_SERVER_RX_BUFFER_SIZE);
ctx = &g_servers[instance];
while (copied < max_len && ctx->rx_tail != ctx->rx_head) {
data[copied++] = ctx->rx_ring[ctx->rx_tail];
ctx->rx_tail = (uint16_t)((ctx->rx_tail + 1u) % TCP_SERVER_RX_BUFFER_SIZE);
}
return (int)copied;
}
bool tcp_server_is_connected(void)
bool tcp_server_is_connected(uint8_t instance)
{
return g_server.client_pcb != NULL;
return (instance < TCP_SERVER_INSTANCE_COUNT) && (g_servers[instance].client_pcb != NULL);
}
void tcp_server_get_status(tcp_server_status_t *status)
void tcp_server_get_status(uint8_t instance, tcp_server_status_t *status)
{
if (status != NULL) {
*status = g_server.status;
if (instance < TCP_SERVER_INSTANCE_COUNT && status != NULL) {
*status = g_servers[instance].status;
}
}
void *tcp_server_get_rx_stream(void)
{
return NULL;
}
void *tcp_server_get_tx_stream(void)
{
return NULL;
}
void tcp_server_task(void *argument)
{
(void)argument;
}