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
+472
View File
@@ -0,0 +1,472 @@
/**
* @file bs_connect_impl.c
* @brief 平台链路层实现:TCP/4G 连接、收发、4G 双 socket 分发
*
* - 联网参数从 t_sys_fix_cfg.s_net_cfg 读取
* - 4G 模式经 WH-GM5 模组,支持 socketA/B 分发
* - 以太网分支(u8_netType!=0)预留待补全
*/
#if EC200A_4G_EN
#include "plat_comm/4g_module/ec200a_4g.h"
#include "plat_comm/4g_module/ec200a_4g_cfg.h"
#endif
#if WH_GM5_EN
#include "plat_comm/4g_module/bs_wh_gm5.h"
#endif
#include "publicdata/publicdata.h"
#include "plat_comm/plat_comm_task.h"
#include "plat_comm/lwip_module/lwip_module.h"
#define BS_PRINTF_EN 1 //平台收发数据打印
ws_url_t url_info;
/**
* @brief 网口 TCP:关闭指定平台通道 socket
*/
void v_bs_eth_close_socket(U8_T u8_id)
{
if (s_bs_task_ctrl.s_bs_ctrl[u8_id].fd >= 0) {
lwip_tcp_close((int)s_bs_task_ctrl.s_bs_ctrl[u8_id].fd);
s_bs_task_ctrl.s_bs_ctrl[u8_id].fd = (S32_T)-1;
s_bs_task_ctrl.s_bs_ctrl[u8_id].u8_TCP_connect_flag = 0;
}
}
#if 1 //联网参数配置
/**
* ************************************************************************
* @brief - 4G模块联网参数获取
*
* @param[in] s_4g_para - 4G联网参数结构体
*
*
* @author jiankalka
* @date 2025-09-01
* ************************************************************************
*/
#if WH_GM5_EN
void v_get_4G_config_para(S_4G_CONFIG_PARA *s_4g_para)
{
SYS_FIX_CFG_T *t_sys_fix_cfg = &g_t_share_data.t_sys_fix_cfg;
memset(s_4g_para , 0 ,sizeof(S_4G_CONFIG_PARA));
//s_4g_para->socketA_IP = testIP;
s_4g_para->socketA_IP = t_sys_fix_cfg->s_net_cfg.u8_serverA_domain_name; //
s_4g_para->socketB_IP = t_sys_fix_cfg->s_net_cfg.u8_serverB_domain_name;
s_4g_para->u8_Sim_Type = t_sys_fix_cfg->s_net_cfg.u_net_comm_para.bits.bit_sim_anp_type;
s_4g_para->u8_socketB_en = t_sys_fix_cfg->s_net_cfg.u_net_comm_para.bits.bit_platB_en;
}
#endif /* WH_GM5_EN */
/**
* ************************************************************************
* @brief - 4G模块参数初始化
*
*
*
* @author jiankalka
* @date 2025-09-19
* ************************************************************************
*/
void v_bs_4G_data_init(void)
{
#if EC200A_4G_EN
{
S_4G_CONFIG_PARA s_4g_para;
SYS_FIX_CFG_T *t_sys_fix_cfg = &g_t_share_data.t_sys_fix_cfg;
memset(&s_4g_para, 0, sizeof(S_4G_CONFIG_PARA));
s_4g_para.socketA_IP = t_sys_fix_cfg->s_net_cfg.u8_serverA_domain_name;
s_4g_para.socketB_IP = t_sys_fix_cfg->s_net_cfg.u8_serverB_domain_name;
s_4g_para.u8_Sim_Type = t_sys_fix_cfg->s_net_cfg.u_net_comm_para.bits.bit_sim_anp_type;
s_4g_para.u8_socketB_en = t_sys_fix_cfg->s_net_cfg.u_net_comm_para.bits.bit_platB_en;
v_4g_data_init(&s_4g_para);
}
#endif /* EC200A_4G_EN */
#if WH_GM5_EN
{
S_4G_CONFIG_PARA s_4g_para;
v_get_4G_config_para(&s_4g_para);
v_wh_gm5_data_init(&s_4g_para);
}
#endif
}
/**
* ************************************************************************
* @brief - TCP 联网测试函数
*
*
* @return U8_T - 0未连接TCP 1已连接
*
* @author jiankalka
* @date 2025-08-29
* ************************************************************************
*/
U8_T u8_tcp_connect(U8_T u8_id)
{
U8_T u8_ret = 0;
if(s_bs_task_ctrl.s_bs_ctrl[u8_id].u8_netType == 0) //4G联网
{
#if WH_GM5_EN
// 无线模块WH_GM5初始化
if(s8_WH_GM5_init() == 0) //如果4g配置成功
{
if(s8_check_socket_LinkState(u8_id) >= 0) //查询网路连接状态
{
mSleep(100);
v_4g_uart_cache_clear(); //4G模块配置完毕 清除串口缓存区中的数据
return 1;
}
}
if(u8_ret == 0 && u32_safe_seconds_since(s_bs_task_ctrl.s_bs_ctrl[u8_id].ulong_restart_timer) > NUM_120) //120分钟 没连上 则重新连接
{
v_bs_4G_data_init(); //4G模块控制数据 初始化
s_bs_task_ctrl.s_bs_ctrl[u8_id].ulong_restart_timer = get_current_seconds();
}
#endif
#if EC200A_4G_EN
if(s8_ec200a_4g_init() == 0)
{
u8_ret = 1;
}
#endif
}
else //网线连接
{
}
return u8_ret;
}
#endif
#if WH_GM5_EN // WH-GM5 4G收发接口
/**
* ************************************************************************
* @brief - 4G模块多端口数据接收、用于多socket分端口接收、需要传入两平台接收处理函数接口
*
* @param[in] socketA_unPack - socketA 接收处理函数,不存在时赋值为NULL
* @param[in] socketB_unPack - socketB 接收处理函数,不存在时赋值为NULL
*
*
* @author jiankalka
* @date 2025-09-02
* ************************************************************************
*/
void v_4g_wh5_data_divide_recv(RecvUnpackHandler socketA_unPack, RecvUnpackHandler socketB_unPack)
{
// 静态缓冲区用于保存残包
static U8_T u8_recv_saveBuf[BS_RECV_BUF_LEN];
static U16_T u16_recv_saveLen = 0;
// 1. 数据合并:将新数据与静态缓冲区的残包合并
U16_T u16_totalLen = 0; // 总数据长度(静态缓冲区+新数据)
U16_T u16_rcvByteNum = 0; // 当前解析位置
U16_T u16_oneFrmLen = 0; // 完整帧长度
U16_T u16_dataLen = 0; // 数据域长度
U8_T frameType = 0; // 帧类型
U8_T flags = 0; // 标志位
U8_T* payloadStart = NULL; // 有效载荷起始位置
U16_T payloadLen = 0; // 有效载荷长度
U8_T u8_recvBuf[BS_RECV_BUF_LEN] = {0}; //接收数据缓存区
// 0. 获取串口数据
U16_T u16_recvLen = u16_usart_recv(COM_PORT_BS, u8_recvBuf, BS_RECV_BUF_LEN);
// 如果没有接收到数据,直接返回
if(u16_recvLen == 0) {
return;
}
// 计算新数据需要复制的长度(避免缓冲区溢出)
U16_T actualCopyLen = u16_recvLen;
if (u16_recv_saveLen + u16_recvLen > BS_RECV_BUF_LEN) {
// 缓冲区溢出处理:保留新数据,丢弃最旧的数据
U16_T overflowBytes = (u16_recv_saveLen + u16_recvLen) - BS_RECV_BUF_LEN;
// 移动现有数据,为新数据腾出空间
memmove(u8_recv_saveBuf, &u8_recv_saveBuf[overflowBytes],
u16_recv_saveLen - overflowBytes);
u16_recv_saveLen -= overflowBytes;
// 更新实际可复制长度
actualCopyLen = BS_RECV_BUF_LEN - u16_recv_saveLen;
}
// 追加新数据到静态缓冲区末尾
memcpy(u8_recv_saveBuf + u16_recv_saveLen, u8_recvBuf, actualCopyLen);
u16_recv_saveLen += actualCopyLen;
// 设置总数据长度
u16_totalLen = u16_recv_saveLen;
// 2. 主解析循环 - 处理完整帧
while (u16_totalLen >= 8)
{
// 帧头检查
if (u8_recv_saveBuf[u16_rcvByteNum] != 0xAA ||
u8_recv_saveBuf[u16_rcvByteNum+1] != 0xFD ||
u8_recv_saveBuf[u16_rcvByteNum+2] != 0x55)
{
// 帧头不匹配,移动搜索位置
u16_rcvByteNum++;
u16_totalLen--;
continue;
}
// 获取数据长度(大端格式)
u16_dataLen = (U16_T)((u8_recv_saveBuf[u16_rcvByteNum+3] << 8) |
u8_recv_saveBuf[u16_rcvByteNum+4]);
// 计算完整帧长度 = 头部(3) + 长度字段(2) + 元数据(3) + 数据长度
u16_oneFrmLen = 6 + u16_dataLen;
// 检查帧完整性
if (u16_oneFrmLen > u16_totalLen) {
// 残包处理:帧不完整,等待更多数据
break;
}
// 提取关键字段
frameType = u8_recv_saveBuf[u16_rcvByteNum + 5]; // 类型字段(0x61/0x62)
flags = u8_recv_saveBuf[u16_rcvByteNum + 6]; // 标志位
// 安全获取有效载荷(跳过帧头、长度字段和类型字段)
payloadStart = &u8_recv_saveBuf[u16_rcvByteNum + 7];
payloadLen = u16_dataLen - 2; // 减去类型和标志位
// 确保有效载`` 荷在缓冲区范围内
if ((payloadStart + payloadLen) > (u8_recv_saveBuf + BS_RECV_BUF_LEN)) {
// 缓冲区越界错误处理:重置缓冲区
u16_recv_saveLen = 0;
return;
}
// 处理网络返回数据
if ((flags & 0x80) == 0) {
if (frameType == 0x61 && socketA_unPack != NULL) {
// SOCKETA数据
socketA_unPack(0, payloadStart, payloadLen);
}
else if (frameType == 0x62 && socketB_unPack != NULL) {
// SOCKETB数据
socketB_unPack(1, payloadStart, payloadLen);
}
//测试打印
#if BS_PRINTF_EN
printf("--------------plat[%d] recv\r\n",frameType - 0x60);
for (int i = 0; i < u16_recvLen; i++)
{
printf("%02x ",u8_recvBuf[i]);
}
printf("\n---------------\r\n");
#endif
}
// 移动位置指针(处理完整帧)
u16_rcvByteNum += u16_oneFrmLen;
u16_totalLen -= u16_oneFrmLen;
}
// 3. 残包处理:保存剩余数据到静态缓冲区
if (u16_totalLen > 0) {
// 移动剩余数据到静态缓冲区开头
if (u16_rcvByteNum > 0) {
memmove(u8_recv_saveBuf, &u8_recv_saveBuf[u16_rcvByteNum], u16_totalLen);
}
u16_recv_saveLen = u16_totalLen;
} else {
// 没有剩余数据,重置静态缓冲区
u16_recv_saveLen = 0;
}
return;
}
/**
* ************************************************************************
* @brief - 4G 模块发送数据接口
*
* @param[in] u8_id - 发送接口ID 0代表不使能分发功能,直接透传发送 1代表像socketA发送数据 2代表像socketB发送数据
* @param[in] u8_sendBuf - 发送数据数组指针
* @param[in] u16_len - 发送数据长度
*
*
* @author jiankalka
* @date 2025-09-01
* ************************************************************************
*/
void v_4g_wh5_data_send(U8_T u8_id,U8_T *u8_sendBuf,U16_T u16_len)
{
U16_T len,u16_checkSum;
U8_T send_buf[10]={0};
if(u8_id == 0) //不使用套接字分发 直接发送数据
u16_usart_send(COM_PORT_BS, u8_sendBuf, u16_len);
else
{
//套接字分发组帧头
send_buf[0] = 0x55;
send_buf[1] = 0xFD;
send_buf[2] = 0xAA;
len = u16_len + 2;
send_buf[3] = (len >> 8) & 0xFF;
send_buf[4] = len & 0xFF;
send_buf[5] = 0x60 + u8_id; //SOCKETA为0x61,SOCKETB为0x62
send_buf[6] = 0;
//发送帧头
u16_usart_send(COM_PORT_BS, send_buf, 7);
//发送数据
u16_usart_send(COM_PORT_BS, u8_sendBuf, u16_len);
//计算校验合 发送数据+SOCKET序号
u16_checkSum = u16_crc_checksum(u8_sendBuf, u16_len);
u16_checkSum = u16_checkSum + send_buf[5];
send_buf[0] = u16_checkSum&0xFF;
u16_usart_send(COM_PORT_BS, send_buf, 1);
}
}
/**
* ************************************************************************
* @brief - 4G模块数据接收 接收原始数据 不进行分包解析
*
* @param[in] u8_recvBuf - 接收数据缓存数组
* @param[in] u16_len - 接受数组长度
*
* @return U16_T -
*
* @author jiankalka
* @date 2025-09-02
* ************************************************************************
*/
U16_T u16_4g_wh5_data_recv(U8_T *u8_recvBuf,U16_T u16_len)
{
U16_T u16_recvLen;
memset(u8_recvBuf , 0 , u16_len);
u16_recvLen = u16_usart_recv(COM_PORT_BS, u8_recvBuf, u16_len);
return u16_recvLen;
}
#endif
#if 1 //公共s收发函数接口
/**
* ************************************************************************
* @brief - 公共发送接口
*
* @param[in] u8_id - 平台位置 0-1
* @param[in] u8_sendBuf - 发送数据
* @param[in] u16_len - 发送数据长度
*
*
* @author jiankalka
* @date 2025-09-02
* ************************************************************************
*/
void v_bs_send(U8_T u8_id,U8_T *u8_sendBuf,U16_T u16_len)
{
if(s_bs_task_ctrl.s_bs_ctrl[u8_id].u8_netType == 0) //4G联网
{
#if WH_GM5_EN
if(s_bs_task_ctrl.u8_4g_dispense_en == 1) u8_id+=1; //分发使能 序号加一
v_4g_wh5_data_send(u8_id,u8_sendBuf,u16_len);
#endif
#if EC200A_4G_EN
if(s_bs_task_ctrl.u8_4g_dispense_en == 1) u8_id+=1;
#if EC200A_TCP_USE_TRANSPARENT_MODE
v_4g_send_data(u8_id,u8_sendBuf,u16_len);
#else
v_ec200a_tcp_app_send(u8_id,u8_sendBuf,u16_len);
#endif
#endif
}
else
{
}
mSleep(Plat_Send_Sleep);
s_bs_task_ctrl.u8_sendCnt++;
#if BS_PRINTF_EN
printf("\n--------------bs send\r\n");
for (int i = 0; i < u16_len; i++)
{
printf("%c",u8_sendBuf[i]);
}
printf("\r\n");
for (int i = 0; i < u16_len; i++)
{
printf("%02x ",u8_sendBuf[i]);
}
printf("\n---------------\r\n");
#endif
}
/**
* ************************************************************************
* @brief - 公共接收函数
*
* @param[in] u8_id - 平台位置 0-1
* @param[in] u8_recvBuf - 接收数据缓存地址
* @param[in] u16_len - 最大接收长度
*
* @return U16_T -
*
* @author jiankalka
* @date 2025-09-02
* ************************************************************************
*/
U16_T u16_bs_recv(U8_T u8_id,U8_T *u8_recvBuf,U16_T u16_len)
{
U16_T u16_recvLen = 0;
if(s_bs_task_ctrl.s_bs_ctrl[u8_id].u8_netType == 0) //4G联网
{
#if WH_GM5_EN
u16_recvLen = u16_usart_recv(COM_PORT_BS, u8_recvBuf, u16_len);
#endif
#if EC200A_4G_EN
u16_recvLen = u16_ec200a_tcp_app_recv(u8_recvBuf, u16_len);
#endif
}
else //以太网
{
// if(bs_task_ctrl_data.s_bs_ctrl[id].fd >= 0)
// u16_recvLen = eth_recv((int)bs_task_ctrl_data.s_bs_ctrl[id].fd, (char *)recvBuf, BS_RECV_BUF_LEN, 1);
}
#if BS_PRINTF_EN
if(u16_recvLen == 0) return u16_recvLen;
printf("\n--------------bs recv\r\n");
for (int i = 0; i < u16_recvLen; i++)
{
printf("%c",u8_recvBuf[i]);
}
printf("\r\n");
for (int i = 0; i < u16_recvLen; i++)
{
printf("%02x ",u8_recvBuf[i]);
}
printf("\n---------------\r\n");
#endif
return u16_recvLen;
}
#endif