#include #include #include // gettimeofday #include #include #include #include #include #include #include #include #include #include #include #include #include /* 新增:clock_gettime / clock_nanosleep */ #include #include "serial.h" #include "uartinf.h" #include #define RECV_PORT 12000 // UDP接收端口 #define SEND_PORT 12001 // 发送端口(UART转NET) /* ===================== 网络帧协议定义 ===================== */ #define NET_FRAME_LEN 32 /* 收/发报文固定长度 */ #define NET_TAIL 0xBB /* 帧尾 */ #define PAYLOAD_LEN 30 /* 帧长度 byte0..29 */ #define BYTE_MODE 30 /* 接收帧 mode 字段偏移(0-4) */ #define BYTE_TAIL 31 /* 接收帧帧尾偏移 */ #define CHECKSUM_END 30 /* 校验和覆盖 byte0..byte30(含) */ #define NET_FRAME_MAX_LEN 256 /* recvfrom 缓冲大小 */ #define BYTE_NOSIG0 25 /* byte25 = 视频流0无信号标志(1=无信号,0=有信号) */ #define BYTE_NOSIG1 26 /* byte26 = 视频流1无信号标志(1=无信号,0=有信号) */ #define BYTE_RSSI1 28 /* 信号包=RSSI1;设备包=哨兵 */ #define BYTE_RSSI2 29 /* 信号包=RSSI2;设备包=哨兵 */ #define SIG_MARK 0x5A /* 设备包 byte28/29 哨兵值 */ #define SIGNAL_INTERVAL_MS 100 /* 独立信号包发送间隔(ms) */ #define FRAME_HEAD 0x11 /* 上行帧帧头(byte0),面板校验要求 */ #define FRAME_TAIL 0x22 /* 上行帧帧尾(byte30),面板校验要求 */ #define FRAME_HEAD_TX 0xAA /* 下行帧帧头(byte0),设备→面板 */ /* ===================== 共享内存 ===================== */ #define SHM_MSG_NAME "/video_switch" #define SHM_MODE_IDX 0 /* switch_mode -> shm[0](即 switch_video[0]) */ static int *shm_msg = NULL; static int *buffer_param = NULL; /* 新增:/param.txt 共享内存,供信号线程读 RSSI */ char _rx_data[200]; static int socket_descriptor; static struct sockaddr_in address; bool first = false; int socket_descriptor_recv; struct sockaddr_in address_recv; pthread_attr_t attr; pthread_t pkts_thread; /* 打开共享内存 /param.txt(由 lc6600_uart 进程写入 RSSI) */ static int *param_memory_open(void) { int fd = shm_open("/param.txt", O_RDWR, 0777); if (fd < 0) { fd = shm_open("/param.txt", O_RDWR | O_CREAT, 0777); if (fd < 0) { perror("shm_open /param.txt"); return NULL; } if (ftruncate(fd, 4096) == -1) { perror("ftruncate /param.txt"); return NULL; } } int *retval = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (retval == MAP_FAILED) { perror("mmap /param.txt"); return NULL; } return retval; } static int *switch_memory_open(void) { char buf[128]; int fd; sprintf(buf, SHM_MSG_NAME); fd = shm_open(buf, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); if(fd < 0) { perror("shm_open"); exit(1); } if (ftruncate(fd, 4096) == -1) { perror("ftruncate"); exit(1); } int *retval = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); return retval; } int init_net_recv(int port){ int i; struct timeval tv; bzero(&address_recv,sizeof(struct sockaddr_in)); address_recv.sin_family=AF_INET; address_recv.sin_addr.s_addr=htonl(INADDR_ANY); address_recv.sin_port=htons(port); socket_descriptor_recv=socket(AF_INET,SOCK_DGRAM,0);//IPV4 tv.tv_sec = 2; tv.tv_usec = 0; if (setsockopt(socket_descriptor_recv, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { printf("socket option SO_RCVTIMEO not support\n"); return -1; } if (bind(socket_descriptor_recv, (struct sockaddr *)&address_recv, sizeof(struct sockaddr_in)) < 0) { perror("bind"); exit(1); } return 0; } int udp_init(char *ip, int port){ bzero(&address,sizeof(address)); address.sin_family=AF_INET; address.sin_addr.s_addr=inet_addr(ip); address.sin_port=htons(port); socket_descriptor=socket(AF_INET,SOCK_DGRAM,0);//IPV4 return 0; } #if 0 void *net_recv(void *arg) { int i; struct sockaddr_in clientAddr; int len = sizeof(clientAddr); int ret; struct timeval tv; tv.tv_sec = 5; tv.tv_usec = 0; if (setsockopt(socket_descriptor_recv, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { printf("socket option SO_RCVTIMEO not support\n"); //return -1; } char buffer_cmd[200]; while(1){ i = recvfrom(socket_descriptor_recv, buffer_cmd, 200, 0, (struct sockaddr*)&clientAddr, &len); if(i>0){ uart_write_len(ROUTE_UART,buffer_cmd,i); } else{ printf(" time_out to receive data\n"); } } } #endif #if 1 void *net_recv(void *arg) { int i, k; struct sockaddr_in clientAddr; socklen_t len; struct timeval tv; char buffer_cmd[NET_FRAME_MAX_LEN]; char frame_out[NET_FRAME_MAX_LEN]; int sum; unsigned char checksum; tv.tv_sec = 5; tv.tv_usec = 0; if (setsockopt(socket_descriptor_recv, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) printf("socket option SO_RCVTIMEO not support\n"); while (1) { len = sizeof(clientAddr); /* 每次循环重置,recvfrom 会改写 len */ i = recvfrom(socket_descriptor_recv, buffer_cmd, NET_FRAME_MAX_LEN, 0, (struct sockaddr*)&clientAddr, &len); if (i <= 0) { printf(" time_out to receive data\n"); continue; } if (i != NET_FRAME_LEN) { printf("bad frame len=%d\n", i); continue; } /* 帧尾校验 */ if ((unsigned char)buffer_cmd[BYTE_TAIL] != NET_TAIL) { printf("bad tail=%02x\n", (unsigned char)buffer_cmd[BYTE_TAIL]); continue; } /* 解析 mode -> 写共享内存 */ if (shm_msg) { static int last_mode = -1; int mode = (unsigned char)buffer_cmd[BYTE_MODE]; if (mode <= 4) { if (mode != last_mode) { shm_msg[SHM_MODE_IDX] = mode; //写入共享内存 viode_switch last_mode = mode; printf("write shm: mode=%d\n", mode); } } else { printf("filed mode=%d\n", mode); } } /* 构造下行帧:byte0=0xAA 帧头,byte1..29 原样,byte30=0xBB 帧尾 */ frame_out[0] = FRAME_HEAD_TX; /* [0] 帧头 0xAA */ memcpy(frame_out + 1, buffer_cmd + 1, PAYLOAD_LEN - 1); /* [1..29] 原样 */ frame_out[PAYLOAD_LEN] = NET_TAIL; /* [30] 帧尾 0xBB */ /* 校验和 = byte0..byte30 求和取低8位,写入 byte31 */ sum = 0; for (k = 0; k <= CHECKSUM_END; k++) sum += (unsigned char)frame_out[k]; checksum = sum & 0xFF; frame_out[PAYLOAD_LEN + 1] = checksum; /* [31] 校验和 */ #if 0 /* 打印发出的包 */ printf(" send to uart %d bytes:", NET_FRAME_LEN); for (k = 0; k < NET_FRAME_LEN; k++) printf(" %02x", (unsigned char)frame_out[k]); printf("\n"); #endif uart_write_len(ROUTE_UART, frame_out, NET_FRAME_LEN); //发送给串口 } return NULL; } #endif /* 独立信号包线程:与串口收包完全解耦,固定 SIGNAL_INTERVAL_MS 周期发送。 * 用绝对时间 clock_nanosleep 对齐发送时刻,避免 sendto/printf 开销累积成漂移。 */ void *signal_send(void *arg) { char sig_frame[NET_FRAME_LEN]; struct timespec next; int k, sum; clock_gettime(CLOCK_MONOTONIC, &next); while (1) { memset(sig_frame, 0, NET_FRAME_LEN); sig_frame[0] = (char)FRAME_HEAD; /* byte0 = 0x11 */ /* byte25/26 = 视频流0/1无信号,byte27 = 布局开关(light_pwm_lvds 的 0x68 按键) */ sig_frame[BYTE_NOSIG0] = (shm_msg && shm_msg[2] == 0x55) ? 1 : 0; sig_frame[BYTE_NOSIG1] = (shm_msg && shm_msg[3] == 0x55) ? 1 : 0; sig_frame[27] = (shm_msg && shm_msg[1]) ? 1 : 0; printf("layout byte27 = %d\n", sig_frame[27]); if (buffer_param) { sig_frame[BYTE_RSSI1] = (char)buffer_param[1]; sig_frame[BYTE_RSSI2] = (char)buffer_param[2]; } sig_frame[PAYLOAD_LEN] = (char)FRAME_TAIL; /* byte30 = 0x22 */ sum = 0; for (k = 0; k <= CHECKSUM_END; k++) sum += (unsigned char)sig_frame[k]; sig_frame[CHECKSUM_END + 1] = (char)(sum & 0xFF); sendto(socket_descriptor, sig_frame, NET_FRAME_LEN, 0, (struct sockaddr *)&address, sizeof(address)); /* 下一个发送时刻 = 本次时刻 + 周期,与实际执行耗时无关 */ next.tv_nsec += (long)SIGNAL_INTERVAL_MS * 1000000L; while (next.tv_nsec >= 1000000000L) { next.tv_sec++; next.tv_nsec -= 1000000000L; } clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next, NULL); } return NULL; } int pthread_init() { int ret; pthread_t sig_thread; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); ret = pthread_create(&pkts_thread, &attr, net_recv, NULL); if(ret){ printf("create pthread1 error\n"); pthread_attr_destroy(&attr); return 1; } ret = pthread_create(&sig_thread, &attr, signal_send, NULL); if(ret){ printf("create pthread2 error\n"); pthread_attr_destroy(&attr); return 1; } pthread_attr_destroy(&attr); return 0; } int main (int argc, char *argv[]) { int n_read; int i; int count=0; char buffer_send[100]; int buffer_len; n_read = uart_init(ROUTE_UART, "/dev/ttyAMA4", 115200, 'N'); if(n_read <=0 ) { printf("open /dev/ttyAMA4 failed\n"); return -1; } // udp_init(argv[1], atoi(argv[2])); // init_net_recv(atoi(argv[3])); udp_init("127.0.0.1", SEND_PORT); // 发送目标:本机回环 12001 init_net_recv(RECV_PORT); // 接收:0.0.0.0:12000(INADDR_ANY) shm_msg = switch_memory_open(); buffer_param = param_memory_open(); if (pthread_init()) { printf("pthread_init failed\n"); return -1; } while(1){ n_read = uart_read(ROUTE_UART, _rx_data); if(n_read > 0 ){ int k, sum = 0; /* 收包校验:完整 32 字节帧,帧头 0x11、帧尾 0x22、byte31 校验和正确,否则丢弃 */ if (n_read < NET_FRAME_LEN) { printf("drop bad frame: len=%d\n", n_read); continue; } if ((unsigned char)_rx_data[0] != FRAME_HEAD || (unsigned char)_rx_data[CHECKSUM_END] != FRAME_TAIL) { printf("drop bad frame: head=%02x tail=%02x\n", (unsigned char)_rx_data[0], (unsigned char)_rx_data[CHECKSUM_END]); continue; } for (k = 0; k <= CHECKSUM_END; k++) sum += (unsigned char)_rx_data[k]; if ((unsigned char)_rx_data[31] != (sum & 0xFF)) { printf("drop bad frame: checksum=%02x expect=%02x\n", (unsigned char)_rx_data[31], (unsigned char)(sum & 0xFF)); continue; } /* byte28/29 固定哨兵值,RSSI 改由独立信号包承载 */ _rx_data[BYTE_RSSI1] = (char)SIG_MARK; _rx_data[BYTE_RSSI2] = (char)SIG_MARK; /* 和校验:byte0..byte30 求和取低 8 位,写入 byte31 */ sum = 0; for (k = 0; k <= CHECKSUM_END; k++) sum += (unsigned char)_rx_data[k]; _rx_data[31] = (char)(sum & 0xFF); sendto(socket_descriptor, _rx_data, NET_FRAME_LEN, 0, (struct sockaddr *)&address, sizeof(address)); } } }