04-09-2019 09:12 PM - edited 04-09-2019 09:17 PM
Hi,
We're developing an Ethernet steaming camera using Zynq-7010. The goal is to have LWIP sending out pixel data with UDP zero copy at the highest rate achievable on this device. I'm using the 1Gig ETH on PS side.
I have two tasks running on RTOS.
1. A controller task binding to a UDP port listening for commands
2. Pixel sender task. Upon VDMA complete IRQ trigger, send out the latest image frame.
Once VDMA and image sensor is activated, task 2 runs perfectly without glitch and without missing data. RTOS crash occurs when additional command packet is received by task 1 while task 2 is running. Below is a trimed down version of the code which can replicate the problem on LWIP 2.02 with XSDK2018.2
#include "lwipopts.h" #include "xil_printf.h" #include "FreeRTOS.h" #include "task.h" #include "lwip/netbuf.h" #include "lwip/api.h" #define THREAD_STACKSIZE 1024 u16_t echo_port = 9000; uint8_t packet_data[1024*48000]; xTaskHandle udp_send_task; u32_t packet_header[32768]; uint16_t pkt_count = 1; // Generate a sequence of predefined sequence for UDP void FillHeader(uint8_t frm_idx) { int i = 0; while (i < 32768) { packet_header[i] = i | (frm_idx << 16); i++; memset(packet_data + i * 1024, i & 0xFF, 1024); } } // Pixel data sender task void SendTestPattern(uint16_t buf_max) { FillHeader(0); struct netbuf * buf_head = netbuf_new(); struct netbuf * buf_data = netbuf_new(); struct netconn * netconn_inst = netconn_new(NETCONN_UDP); ip_addr_t ip_addr; ipaddr_aton("10.42.0.5", &ip_addr); netconn_connect(netconn_inst, &ip_addr, 8080); uint16_t pkt_count = 0; uint8_t count = 0; while (1) { while (netbuf_ref(buf_head, packet_header + pkt_count, 4) != ERR_OK) vTaskDelay(1); while (netbuf_ref(buf_data, packet_data + pkt_count * buf_max, buf_max) != ERR_OK) vTaskDelay(1); netbuf_chain(buf_head, buf_data); netconn_send(netconn_inst, buf_head); netbuf_free(buf_head); // Comment both netbuf_free() makes no difference netbuf_free(buf_data); if ((pkt_count & 0xFFFF) < 2118) pkt_count++; else { pkt_count = 0; count ++; //FillHeader(count); } } //Won't reach here netbuf_delete(buf_data); netconn_delete(netconn_inst); }
// Task 1, listening task. created in main.c from lwip rtos echo server void echo_application_thread() { struct netconn * netconn_inst = netconn_new(NETCONN_UDP); char net_res = netconn_bind(netconn_inst, IPADDR_ANY, 9000); if (net_res != ERR_OK) xil_printf("Failed"); struct netbuf * recv_buf = netbuf_new(); //netbuf_alloc(recv_buf, 1500); // Uncomment this line still crash uint8_t * recv_data_ptr; uint16_t recv_len; char connected = 0; while (netconn_recv(netconn_inst, &recv_buf) == ERR_OK) { if (netbuf_data(recv_buf, (void *) &recv_data_ptr, &recv_len) == ERR_OK) { // Crash after next line.
// recv_len would equal to my send length if (recv_len == 4 && strcmp((char *) recv_data_ptr, "SEND") == 0) { //netbuf_free(recv_buf); xTaskCreate(SendTestPattern, "PTG", 1024, 1454, 2, NULL); } netbuf_free(recv_buf); } } }
I used netcat to send command and tap using wireshark. At crash, the recv_len will not equal to the command packet length. Instead, it equals to buf_max of the sender task. I'm suspecting it's a memory corruption issue. I have added a vTaskPrint task to print stack water mark periodically and it's not a stack overflow issue at task 2 heavy load.
I have also attempted lwip_recvfrom in the task 1 and the crash behavior is the same. With both length and pointer corrupted.
Thanks!
04-18-2019 04:02 PM - edited 04-18-2019 05:25 PM
Bump
Update information:
I trace into LWIP and ethernet NIC is working properly. The p_buf from NIC shows the correct data and UDP length from host machine.
I'm suspecting something in the LWIP is wrong.