cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Contributor
Contributor
586 Views
Registered: ‎03-11-2016

LWIP crash RTOS at high TX bandwidth using UDP netconn

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!

0 Kudos
1 Reply
Highlighted
Contributor
Contributor
524 Views
Registered: ‎03-11-2016

Re: LWIP crash RTOS at high TX bandwidth using UDP netconn

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.

0 Kudos