Initial commit: CCU621_M firmware project with BLE debug link support.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-08 17:28:36 +08:00
commit 9ceb218f80
1597 changed files with 724159 additions and 0 deletions
+621
View File
@@ -0,0 +1,621 @@
/**
* @file debug_link.c
* @brief 调试链路层实现(comm_link_ctx + TCP Socket + comm_link 分发)
*/
#include "debug_link.h"
#include "tcp_protocol.h"
#include "publicdata/public_define.h"
#include "lwip/sockets.h"
#include "lwip/netdb.h"
#include <string.h>
#include <stdio.h>
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "app_fatfs/fatfs_init.h"
#if BLE_DEBUG_EN
#include "ble_link/fc41d_ble.h"
#endif
#if TCP_DEBUG_EN
/* =============================================================================
* 会话上下文(原 comm_link_ctx.c
* ============================================================================= */
static comm_link_ctx_t s_comm_link_ctx;
comm_link_ctx_t *comm_link_ctx_get(void)
{
return &s_comm_link_ctx;
}
comm_link_session_t *comm_link_session(void)
{
return &s_comm_link_ctx.session;
}
void comm_link_ctx_reset_session(void)
{
comm_link_type_t saved_type = s_comm_link_ctx.session.type;
memset(&s_comm_link_ctx.session, 0, sizeof(s_comm_link_ctx.session));
s_comm_link_ctx.session.type = saved_type;
}
void comm_link_ctx_reset_all(void)
{
memset(&s_comm_link_ctx, 0, sizeof(s_comm_link_ctx));
}
/* =============================================================================
* TCP Socket 后端(原 tcp_server_socket.c,本文件内 static
* ============================================================================= */
#ifndef AF_INET
#define AF_INET 2
#endif
#ifndef SOCK_STREAM
#define SOCK_STREAM 1
#endif
#ifndef SOL_SOCKET
#define SOL_SOCKET 0xFFF
#endif
#ifndef SO_REUSEADDR
#define SO_REUSEADDR 0x0004
#endif
#ifndef INADDR_ANY
#define INADDR_ANY 0x00000000
#endif
#ifndef F_GETFL
#define F_GETFL 3
#endif
#ifndef F_SETFL
#define F_SETFL 4
#endif
#ifndef O_NONBLOCK
#define O_NONBLOCK 0x0004
#endif
#ifndef EWOULDBLOCK
#define EWOULDBLOCK 11
#endif
#ifndef EAGAIN
#define EAGAIN 11
#endif
#ifndef ECONNRESET
#define ECONNRESET 104
#endif
#ifndef EPIPE
#define EPIPE 32
#endif
#ifndef ECONNABORTED
#define ECONNABORTED 103
#endif
#ifndef ETIMEDOUT
#define ETIMEDOUT 110
#endif
#ifndef ENETDOWN
#define ENETDOWN 100
#endif
#ifndef ENETUNREACH
#define ENETUNREACH 101
#endif
#ifndef EHOSTUNREACH
#define EHOSTUNREACH 113
#endif
#ifndef errno
extern int errno;
#endif
#define TCP_LOCAL_PORT TCP_DEBUG_PORT
#define MAX_CLIENTS TCP_DEBUG_MAX_CLIENTS
typedef struct {
int server_socket;
int client_socket;
uint8_t is_client_connected;
struct sockaddr_in client_addr;
} tcp_socket_server_t;
static tcp_socket_server_t socket_server = {
.server_socket = -1,
.client_socket = -1,
.is_client_connected = 0,
};
static SemaphoreHandle_t socket_mutex = NULL;
static int tcp_socket_create_server(void)
{
int sock;
struct sockaddr_in server_addr;
int opt = 1;
sock = lwip_socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
TCP_PRINT("Failed to create socket: %d\r\n", sock);
return -1;
}
lwip_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(TCP_LOCAL_PORT);
if (lwip_bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
TCP_PRINT("Failed to bind socket to port %d\r\n", TCP_LOCAL_PORT);
lwip_close(sock);
return -1;
}
if (lwip_listen(sock, MAX_CLIENTS) < 0) {
TCP_PRINT("Failed to listen on socket\r\n");
lwip_close(sock);
return -1;
}
{
int flags = lwip_fcntl(sock, F_GETFL, 0);
lwip_fcntl(sock, F_SETFL, flags | O_NONBLOCK);
}
TCP_PRINT("TCP server socket created on port %d\r\n", TCP_LOCAL_PORT);
return sock;
}
static int tcp_socket_init(void)
{
socket_mutex = xSemaphoreCreateMutex();
if (socket_mutex == NULL) {
TCP_PRINT("Failed to create socket mutex\r\n");
return -1;
}
socket_server.server_socket = tcp_socket_create_server();
if (socket_server.server_socket < 0) {
vSemaphoreDelete(socket_mutex);
socket_mutex = NULL;
return -1;
}
socket_server.client_socket = -1;
socket_server.is_client_connected = 0;
TCP_PRINT("Socket server initialized successfully\r\n");
return 0;
}
static int tcp_socket_accept_client(void)
{
struct sockaddr_in client_addr;
socklen_t addr_len = sizeof(client_addr);
int new_sock;
if (socket_server.server_socket < 0) {
return -1;
}
if (socket_mutex != NULL) {
xSemaphoreTake(socket_mutex, portMAX_DELAY);
}
new_sock = lwip_accept(socket_server.server_socket,
(struct sockaddr *)&client_addr, &addr_len);
if (new_sock >= 0) {
if (socket_server.is_client_connected) {
TCP_PRINT("Rejecting new connection - already have a client\r\n");
lwip_close(new_sock);
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
}
return 0;
}
{
int flags = lwip_fcntl(new_sock, F_GETFL, 0);
lwip_fcntl(new_sock, F_SETFL, flags | O_NONBLOCK);
}
socket_server.client_socket = new_sock;
socket_server.is_client_connected = 1;
memcpy(&socket_server.client_addr, &client_addr, sizeof(client_addr));
TCP_PRINT("Client connected from %s:%d\r\n",
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
}
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
}
return (new_sock >= 0) ? 1 : 0;
}
static int tcp_socket_receive_data(uint8_t *buffer, uint32_t buffer_size)
{
int received;
if (buffer == NULL || buffer_size == 0U) {
return -1;
}
if (socket_mutex != NULL) {
xSemaphoreTake(socket_mutex, portMAX_DELAY);
}
if (!socket_server.is_client_connected || socket_server.client_socket < 0) {
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
}
return -1;
}
received = lwip_recv(socket_server.client_socket, buffer, buffer_size, 0);
if (received > 0) {
TCP_PRINT("Received %d bytes from client\r\n", received);
} else if (received == 0) {
TCP_PRINT("Client disconnected\r\n");
lwip_close(socket_server.client_socket);
socket_server.client_socket = -1;
socket_server.is_client_connected = 0;
received = -1;
#if FATFS_EN
fatfs_set_write_disable_flag(FATFS_WRITE_DISABLE_TCP_DEBUG, 0);
#endif
} else {
int err = errno;
if (err != EWOULDBLOCK && err != EAGAIN) {
TCP_PRINT("Socket receive error: %d\r\n", err);
if (err == ECONNRESET || err == EPIPE || err == ECONNABORTED ||
err == ETIMEDOUT || err == ENETDOWN || err == ENETUNREACH ||
err == EHOSTUNREACH) {
TCP_PRINT("Connection error detected, closing socket\r\n");
lwip_close(socket_server.client_socket);
socket_server.client_socket = -1;
socket_server.is_client_connected = 0;
#if FATFS_EN
fatfs_set_write_disable_flag(FATFS_WRITE_DISABLE_TCP_DEBUG, 0);
#endif
}
received = -1;
} else {
received = 0;
}
}
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
}
return received;
}
static int tcp_socket_send_data(const uint8_t *data, uint32_t len)
{
int sent;
if (data == NULL || len == 0U) {
return -1;
}
if (socket_mutex != NULL) {
xSemaphoreTake(socket_mutex, portMAX_DELAY);
}
if (!socket_server.is_client_connected || socket_server.client_socket < 0) {
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
}
return -1;
}
sent = lwip_send(socket_server.client_socket, data, len, 0);
if (sent > 0) {
TCP_PRINT("Sent %d bytes to client\r\n", sent);
} else {
TCP_PRINT("Failed to send data: %d\r\n", sent);
if (sent < 0) {
int err = errno;
if (err == ECONNRESET || err == EPIPE) {
TCP_PRINT("Connection broken, closing socket\r\n");
lwip_close(socket_server.client_socket);
socket_server.client_socket = -1;
socket_server.is_client_connected = 0;
}
}
}
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
}
return sent;
}
static int tcp_socket_is_client_connected(void)
{
int connected;
if (socket_mutex != NULL) {
xSemaphoreTake(socket_mutex, portMAX_DELAY);
}
connected = socket_server.is_client_connected;
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
}
return connected;
}
static void tcp_socket_close_client(void)
{
if (socket_mutex != NULL) {
xSemaphoreTake(socket_mutex, portMAX_DELAY);
}
if (socket_server.client_socket >= 0) {
lwip_close(socket_server.client_socket);
socket_server.client_socket = -1;
}
socket_server.is_client_connected = 0;
#if FATFS_EN
fatfs_set_write_disable_flag(FATFS_WRITE_DISABLE_TCP_DEBUG, 0);
#endif
TCP_PRINT("Client connection closed\r\n");
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
}
}
static void tcp_socket_close_server(void)
{
if (socket_mutex != NULL) {
xSemaphoreTake(socket_mutex, portMAX_DELAY);
}
if (socket_server.client_socket >= 0) {
lwip_close(socket_server.client_socket);
socket_server.client_socket = -1;
}
if (socket_server.server_socket >= 0) {
lwip_close(socket_server.server_socket);
socket_server.server_socket = -1;
}
socket_server.is_client_connected = 0;
#if FATFS_EN
fatfs_set_write_disable_flag(FATFS_WRITE_DISABLE_TCP_DEBUG, 0);
#endif
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
vSemaphoreDelete(socket_mutex);
socket_mutex = NULL;
}
TCP_PRINT("Socket server closed\r\n");
}
static int tcp_socket_get_client_ip(char *ip_buffer, uint32_t buffer_size)
{
const char *ip_str;
if (ip_buffer == NULL || buffer_size == 0U) {
return -1;
}
if (socket_mutex != NULL) {
xSemaphoreTake(socket_mutex, portMAX_DELAY);
}
if (!socket_server.is_client_connected) {
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
}
return -1;
}
ip_str = inet_ntoa(socket_server.client_addr.sin_addr);
if (ip_str != NULL) {
strncpy(ip_buffer, ip_str, buffer_size - 1U);
ip_buffer[buffer_size - 1U] = '\0';
} else {
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
}
return -1;
}
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
}
return 0;
}
/* =============================================================================
* comm_link 分发(原 comm_link.c
* ============================================================================= */
#define SESS (comm_link_session())
static uint8_t comm_link_using_ble(void)
{
#if BLE_DEBUG_EN
return (SESS->type == COMM_LINK_BLE) ? 1U : 0U;
#else
return 0U;
#endif
}
void comm_link_set_type(comm_link_type_t type)
{
SESS->type = type;
}
comm_link_type_t comm_link_get_type(void)
{
return SESS->type;
}
comm_link_type_t comm_link_type_from_dip(void)
{
#if BLE_DEBUG_EN
return ble_link_is_bt_mode() ? COMM_LINK_BLE : COMM_LINK_TCP;
#else
return COMM_LINK_TCP;
#endif
}
int comm_link_start(void)
{
if (comm_link_using_ble() != 0U) {
#if BLE_DEBUG_EN
return comm_link_ble_start();
#endif
}
return tcp_socket_init();
}
void comm_link_stop(void)
{
if (comm_link_using_ble() != 0U) {
#if BLE_DEBUG_EN
comm_link_ble_stop();
#endif
return;
}
tcp_socket_close_server();
}
void comm_link_process(void)
{
#if BLE_DEBUG_EN
if (comm_link_using_ble() != 0U) {
comm_link_ble_process();
}
#endif
}
int comm_link_accept_client(void)
{
if (comm_link_using_ble() != 0U) {
return 0;
}
return tcp_socket_accept_client();
}
int comm_link_is_client_connected(void)
{
if (comm_link_using_ble() != 0U) {
#if BLE_DEBUG_EN
return comm_link_ble_is_client_connected();
#endif
return 0;
}
return tcp_socket_is_client_connected();
}
void comm_link_close_client(void)
{
if (comm_link_using_ble() != 0U) {
#if BLE_DEBUG_EN
comm_link_ble_close_client();
#endif
return;
}
tcp_socket_close_client();
}
int comm_link_receive_data(uint8_t *buffer, uint32_t buffer_size)
{
if (comm_link_using_ble() != 0U) {
#if BLE_DEBUG_EN
return comm_link_ble_receive_data(buffer, buffer_size);
#endif
return 0;
}
return tcp_socket_receive_data(buffer, buffer_size);
}
int comm_link_send_data(const uint8_t *data, uint32_t len)
{
if (comm_link_using_ble() != 0U) {
#if BLE_DEBUG_EN
return comm_link_ble_send_data(data, len);
#endif
return -1;
}
return tcp_socket_send_data(data, len);
}
int comm_link_get_peer_info(char *buf, uint32_t buf_size)
{
if ((buf == NULL) || (buf_size == 0U)) {
return -1;
}
if (SESS->peer_info[0] != '\0') {
(void)snprintf(buf, buf_size, "%s", SESS->peer_info);
return 0;
}
if (comm_link_using_ble() != 0U) {
#if BLE_DEBUG_EN
return comm_link_ble_get_peer_info(buf, buf_size);
#endif
}
return tcp_socket_get_client_ip(buf, buf_size);
}
#else /* TCP_DEBUG_EN */
comm_link_ctx_t *comm_link_ctx_get(void) { return NULL; }
comm_link_session_t *comm_link_session(void) { return NULL; }
void comm_link_ctx_reset_session(void) { }
void comm_link_ctx_reset_all(void) { }
void comm_link_set_type(comm_link_type_t type) { (void)type; }
comm_link_type_t comm_link_get_type(void) { return COMM_LINK_TCP; }
comm_link_type_t comm_link_type_from_dip(void) { return COMM_LINK_TCP; }
int comm_link_start(void) { return -1; }
void comm_link_stop(void) { }
void comm_link_process(void) { }
int comm_link_accept_client(void) { return -1; }
int comm_link_is_client_connected(void) { return 0; }
void comm_link_close_client(void) { }
int comm_link_receive_data(uint8_t *buffer, uint32_t buffer_size)
{
(void)buffer;
(void)buffer_size;
return -1;
}
int comm_link_send_data(const uint8_t *data, uint32_t len)
{
(void)data;
(void)len;
return -1;
}
int comm_link_get_peer_info(char *buf, uint32_t buf_size)
{
(void)buf;
(void)buf_size;
return -1;
}
#endif /* TCP_DEBUG_EN */