/* * lwip_util.c * * Created on: 2025年7月29日 * Author: wulianwei */ #include "nim_config.h" #include "device/console.h" #include "hal/nim_ethernet.h" #include "lwiplib.h" #include "lwipopts.h" #include #define TCP_POLL_INTERVAL 4 #define MAX_SIZE 4096 static err_t tcp_accept_handle(void *arg, struct tcp_pcb *pcb, err_t err); static err_t tcp_recv_handle(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); static void tcp_close_conn(struct tcp_pcb *pcb); err_t tcp_send_data(struct tcp_pcb *pcb, struct pbuf *p); err_t queue_send_data(struct pbuf *p); static struct udp_pcb *gui_udp_pcb; static struct tcp_pcb *tcp_server_pcb; static struct tcp_pcb *cur_conn = NULL; // 当前连接 static unsigned int ipAddr = 0; void init_ip(void); void lwip_device_init(void) { EthernetInit(); //以太网外设配置 init_ip(); //udp_bind(gui_udp_pcb, IP_ADDR_ANY, 3000); } void init_ip(void) { unsigned char macArray[6] = MAC_ADDRESS; unsigned int retry_count = 0; while (ipAddr == 0) { #if STATIC_IP_ADDRESS ipAddr = lwIPInit(0, macArray, STATIC_IP_ADDRESS, STATIC_NET_MASK, 0, IPADDR_USE_STATIC); #else ipAddr = lwIPInit(0, macArray, 0, 0, 0, IPADDR_USE_DHCP); #endif if (retry_count++ > 5) { ConsolePrintf("lwIPInit failed!.\r\n\r\n"); break; } } ConsolePrintf("lwIP HostIP:%d.%d.%d.%d\n", (ipAddr >> (0 * 8)) & 0xFF, (ipAddr >> (1 * 8)) & 0xFF, (ipAddr >> (2 * 8)) & 0xFF, (ipAddr >> (3 * 8)) & 0xFF); if (ipAddr != 0) { if (gui_udp_pcb == NULL) { gui_udp_pcb = udp_new(); lwip_udp_connect(gui_udp_pcb, UI_IP_ADDRESS, UI_UDP_PORT); } if (tcp_server_pcb == NULL) { tcp_server_pcb = tcp_new(); lwip_tcp_init(TCP_SERVER_PORT); } } } /** * tcp 服务初始化 */ err_t lwip_tcp_init(int port) { err_t err; //struct tcp_pcb *pcb; if (tcp_server_pcb == NULL) { ConsolePuts("tcp new 空间不足", -1); return ERR_MEM; // 内存不足 } err = tcp_bind(tcp_server_pcb, IP_ADDR_ANY, port); if (err != ERR_OK) { ConsolePuts("tcp 绑定断开失败", -1); return err; } tcp_server_pcb = tcp_listen(tcp_server_pcb); if (tcp_server_pcb == NULL) { ConsolePuts("tcp 监听失败", -1); } /* initialize callback arg and accept callback */ tcp_arg(tcp_server_pcb, NULL); tcp_accept(tcp_server_pcb, tcp_accept_handle); return ERR_OK; } // 连接错误回调(可选) static void tcp_server_conn_err(void *arg, err_t err) { ConsolePrintf("TCP 连接错误:%s\n", lwip_strerr(err)); } /** * 链接监听函数. */ static err_t tcp_accept_handle(void *arg, struct tcp_pcb *pcb, err_t err) { LWIP_UNUSED_ARG(err); LWIP_UNUSED_ARG(arg); tcp_setprio(pcb, TCP_PRIO_MAX); /* Set up the various callback functions */ tcp_recv(pcb, tcp_recv_handle); tcp_err(pcb, tcp_server_conn_err); tcp_poll(pcb, NULL, TCP_POLL_INTERVAL); tcp_sent(pcb, NULL); return ERR_OK; } /** * 接收数据处理函数. */ static err_t tcp_recv_handle(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) { LWIP_UNUSED_ARG(arg); LWIP_UNUSED_ARG(err); err_t err_send; if (p != NULL) { /* Inform TCP that we have taken the data. */ tcp_recved(pcb, p->tot_len); } if ((err != ERR_OK)) { /* error or closed by other side */ if (p != NULL) { pbuf_free(p); } tcp_close_conn(pcb); return ERR_OK; } cur_conn = pcb; //tcp_send_data(pcb ,p); if (p != NULL) { err_send = queue_send_data(p); } return err_send; } /** * 关闭远程连接. */ static void tcp_close_conn(struct tcp_pcb *pcb) { ConsolePuts("tcp close", -1); tcp_recv(pcb, NULL); tcp_close(pcb); /* closing succeeded */ tcp_arg(pcb, NULL); tcp_sent(pcb, NULL); } /** * 发送数据 */ err_t tcp_send_data(struct tcp_pcb *pcb, struct pbuf *p) { unsigned char mydata[MAX_SIZE]; err_t err = ERR_OK; char *data; unsigned int cnt = 0, j, i; unsigned int len, tot_len; struct pbuf *temp = p; tot_len = p->tot_len; /** * traverse pbuf chain and store payload * of each pbuf into buffer */ do { data = (char*) p->payload; len = p->len; for (i = 0, j = 0; i < len; i++, j++, cnt++) { if (cnt >= MAX_SIZE) break; mydata[cnt] = data[j]; } p = p->next; } while (p != NULL); /* free pbuf's */ pbuf_free(temp); /** *send the data in buffer over network with * tcp header attached */ err = tcp_write(pcb, mydata, tot_len, TCP_WRITE_FLAG_COPY); return err; } void lwip_tcp_send_gui(unsigned char *data, int len) { tcp_write(cur_conn, data, len, TCP_WRITE_FLAG_COPY); tcp_output(cur_conn); } /** * 发送数据到USB */ err_t queue_send_data(struct pbuf *p) { struct pbuf *temp = p; unsigned int len = 0; do { char *data = (char*) p->payload; len = p->len; ConsolePuts("\r\ntcp rec data:\r\n", -1); if (len > 0) { ConsolePutsHexStr(data, len); enqueueFromEthernet(data, len); } p = p->next; } while (p != NULL); pbuf_free(temp); return ERR_OK; } /** * udp 链接 */ void lwip_udp_connect(struct udp_pcb *pcb, unsigned int ip, int port) { struct ip_addr ip_dst; ip_dst.addr = htonl(ip); udp_connect(pcb, &ip_dst, port); } /** * udp 发送 */ void lwip_udp_send(struct udp_pcb *pcb, unsigned char *data, int len) { struct pbuf *pbuf = pbuf_alloc(PBUF_TRANSPORT, len + sizeof(struct pbuf), PBUF_REF); pbuf->payload = data; udp_send(pcb, pbuf); pbuf_free(pbuf); } /** * udp 发送 */ void lwip_udp_sendto(struct udp_pcb *pcb, unsigned int ip, int port, unsigned char *data, int len) { struct ip_addr ip_dst; ip_dst.addr = htonl(ip); struct pbuf *pbuf = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct pbuf), PBUF_REF); pbuf->payload = data; udp_sendto(pcb, pbuf, &ip_dst, port); pbuf_free(pbuf); } /** * udp 向gui发送数据 */ void lwip_udp_send_gui(unsigned char *data, int len) { struct pbuf *pbuf = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_REF); pbuf->payload = data; udp_send(gui_udp_pcb, pbuf); pbuf_free(pbuf); } /** * udp 向gui发送数据 * data 浮点数据指针, flen 数据数量, channelFlag 有效通道 */ void lwip_udp_send_gui_signal(float *data, int flen, char channelFlag) { unsigned char head[8] = { 'T', 'R', 1, 3, 1, 1 }; int clen = sizeof(float) * flen; int head_len = sizeof(head); int total_len = head_len + 1 + clen; head[6] = total_len >> 8; head[7] = total_len; unsigned char *fdata = malloc(total_len); memcpy(fdata, &head, head_len); fdata[head_len] = channelFlag; memcpy(fdata + head_len + 1, data, clen); struct pbuf *pbuf = pbuf_alloc(PBUF_TRANSPORT, total_len, PBUF_REF); pbuf->payload = fdata; udp_send(gui_udp_pcb, pbuf); pbuf_free(pbuf); free(fdata); } /** * udp 向gui发送数据 * data 浮点数据指针, len 数据数量, channelFlag 有效通道 */ void lwip_udp_send_gui_signal2(float *data1, float *data2, float *data3, float *data4, char channelFlag, int len) { unsigned char head[8] = { 'T', 'R', 1, 3, 1, 1 }; int clen = sizeof(float) * len * 4; int head_len = sizeof(head); int total_len = head_len + 1 + clen; head[6] = total_len >> 8; head[7] = total_len; unsigned char *const fdata = malloc(total_len); memcpy(fdata, &head, head_len); fdata[head_len] = channelFlag; unsigned char *cp = fdata + head_len + 1; int i = 0; for (i = 0; i < len; i++) { memcpy(cp + (i * sizeof(float) * 4), data1++, sizeof(float)); memcpy(cp + (i * sizeof(float) * 4) + 4, data2++, sizeof(float)); memcpy(cp + (i * sizeof(float) * 4) + 8, data3++, sizeof(float)); memcpy(cp + (i * sizeof(float) * 4) + 12, data4++, sizeof(float)); } struct pbuf *pbuf = pbuf_alloc(PBUF_TRANSPORT, total_len, PBUF_REF); pbuf->payload = fdata; // ConsolePuts("signal data:\n", -1); // ConsolePutsHexStr(pbuf->payload, total_len); udp_send(gui_udp_pcb, pbuf); pbuf_free(pbuf); free(fdata); } /** * udp 向波形模拟器VOFA发送数据 单通道 * data 要发送的数据,len float数组长度 */ void lwip_udp_send_vofa(float *data, int len) { int i = 0; char tail[4] = { 0x00, 0x00, 0x80, 0x7f }; int flen = (sizeof(float) + 4) * len; unsigned char *fdata = malloc(flen); for (i = 0; i < len; i++) { memcpy(fdata + (i * (sizeof(float) + 4)), data, sizeof(float)); memcpy(fdata + (i * (sizeof(float) + 4)) + 4, tail, sizeof(tail)); data++; } struct pbuf *pbuf = pbuf_alloc(PBUF_TRANSPORT, flen, PBUF_REF); pbuf->payload = fdata; ConsolePuts("signal data2:\n", -1); ConsolePutsHexStr(pbuf->payload, flen); //udp_send(gui_udp_pcb, pbuf); pbuf_free(pbuf); free(fdata); } /** * udp 向波形模拟器VOFA发送数据 双通道 * data1 要发送的通道1数据,data1 要发送的通道2数据,len float数组长度 */ void lwip_udp_send_vofa2(float *data1, float *data2, int len) { ConsolePuts("lwip send data", -1); int i = 0; char tail[4] = { 0x00, 0x00, 0x80, 0x7f }; int flen = (sizeof(float) * 2 + 4) * len; unsigned char *fdata = malloc(flen); for (i = 0; i < len; i++) { memcpy(fdata + (i * (sizeof(float) * 2 + 4)), data1, sizeof(float)); memcpy(fdata + (i * (sizeof(float) * 2 + 4)) + 4, data2, sizeof(float)); memcpy(fdata + (i * (sizeof(float) * 2 + 4)) + 8, tail, sizeof(tail)); data1++; data2++; } struct pbuf *pbuf = pbuf_alloc(PBUF_TRANSPORT, flen, PBUF_REF); pbuf->payload = fdata; udp_send(gui_udp_pcb, pbuf); pbuf_free(pbuf); free(fdata); } /** * udp 向波形模拟器VOFA发送数据 四通道 * data1 要发送的通道1数据,data1 要发送的通道2数据,len float数组长度 */ void lwip_udp_send_vofa4(float *data1, float *data2, float *data3, float *data4, int len) { int i = 0; char tail[4] = { 0x00, 0x00, 0x80, 0x7f }; int flen = (sizeof(float) * 4 + 4) * len; unsigned char *fdata = malloc(flen); for (i = 0; i < len; i++) { memcpy(fdata + (i * (sizeof(float) * 4 + 4)), data1, sizeof(float)); memcpy(fdata + (i * (sizeof(float) * 4 + 4)) + 4, data2, sizeof(float)); memcpy(fdata + (i * (sizeof(float) * 4 + 4)) + 8, data3, sizeof(float)); memcpy(fdata + (i * (sizeof(float) * 4 + 4)) + 12, data4,sizeof(float)); memcpy(fdata + (i * (sizeof(float) * 4 + 4)) + 16, tail, sizeof(tail)); data1++; data2++; data3++; data4++; } struct pbuf *pbuf = pbuf_alloc(PBUF_TRANSPORT, flen, PBUF_REF); pbuf->payload = fdata; // ConsolePuts("\nsignal data2:\n", -1); // ConsolePutsHexStr(pbuf->payload, flen); udp_send(gui_udp_pcb, pbuf); pbuf_free(pbuf); free(fdata); }