UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Visitor okanbozkurt
Visitor
360 Views
Registered: ‎12-25-2018

LWIP BinarySemaphore usage problem and bug report

Jump to solution

Hi to all,

I have been working on MicroBlaze with FreeRTOS Lwip Echo Server example. I use lwip in "Socket API" mode. But default project settings and configurations do not work properly. I start ping to FPGA and pings stop for a while. I started debug to code. I realized that this problem is derived from "Binary Semaphore" usage in "xemacif_recv_handler" function.

Let me explain problem step by step:

1. A packet is received from Emaclite within "xemacif_recv_handler()" interrupt funtion.

2. Packet is written to receive queue.

3. Binary Semaphore is given

After scheduler works , xemacif_input_thread takes the Binary Semaphore and read only one incoming packet from queue. Packet processing stuff  goes on... and then xemacif_input_thread starts waiting the binary semaphore again.

But, if more packets are received from Emaclite before scheduler works(it means two packets arrived nearly at same time and xemacif_input_thread did not work yet), then the above steps are repeated except 3rd step. Because binary semaphore is already given. But length of receive queue became 2. So it will cause an event lost.

After scheduler works xemac_input_thread takes the binary semaphore which is given by interrupt handler. And only one incoming packet is processed due to one binary semaphore. But now one packet is still waiting in receive queue. Because binary semaphore is given once however incoming packets keep writting to receive queue all time. So, counting of coming packets accumulating slowly.

I think that it would be better to use counting semaphore instead of binary semaphore in xemacif_recv_handler().

How can I solve this problem? Using counting semaphore enough? Do you have any idea?

Thanks...

 

-------------- Packet Processing Thread--------------------

#if !NO_SYS
/*
* The input thread calls lwIP to process any received packets.
* This thread waits until a packet is received (sem_rx_data_available),
* and then calls xemacif_input which processes 1 packet at a time.
*/
void
xemacif_input_thread(struct netif *netif)
{
struct xemac_s *emac = (struct xemac_s *)netif->state;
while (1) {
/* sleep until there are packets to process
* This semaphore is set by the packet receive interrupt
* routine.
*/
sys_sem_wait(&emac->sem_rx_data_available); //Semaphore is waiting...

/* move all received packets to lwIP */
xemacif_input(netif); // Only one Packet is read from queue 
}
}
#endif

--------------------------------------------------------------------

 

-------------- Packet Received Interrupt--------------------

static void
xemacif_recv_handler(void *arg) {
struct xemac_s *xemac = (struct xemac_s *)(arg);
xemacliteif_s *xemacliteif = (xemacliteif_s *)(xemac->state);
XEmacLite *instance = xemacliteif->instance;
struct pbuf *p;
int len = 0;
struct xtopology_t *xtopologyp = &xtopology[xemac->topology_index];

#ifdef OS_IS_FREERTOS
xInsideISR++;
#endif

#if XLWIP_CONFIG_INCLUDE_EMACLITE_ON_ZYNQ == 1
#else
XIntc_AckIntr(xtopologyp->intc_baseaddr, 1 << xtopologyp->intc_emac_intr);
#endif
p = pbuf_alloc(PBUF_RAW, XEL_MAX_FRAME_SIZE, PBUF_POOL);
if (!p)
{
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.drop++;
#endif
/* receive and just ignore the frame.
* we need to receive the frame because otherwise emaclite will
* not generate any other interrupts since it cannot receive,
* and we do not actively poll the emaclite
*/
XEmacLite_Recv(instance, xemac_tx_frame);
#ifdef OS_IS_FREERTOS
xInsideISR--;
#endif
return;
}

/* receive the packet */
len = XEmacLite_Recv(instance, p->payload); // receive the packet from EmacLite

if (len == 0)
{
#if LINK_STATS
lwip_stats.link.drop++;
#endif
pbuf_free(p);
#ifdef OS_IS_FREERTOS
xInsideISR--;
#endif
return;
}

/* store it in the receive queue, where it'll be processed by xemacif input thread */
if (pq_enqueue(xemacliteif->recv_q, (void*)p) < 0)  //Write packet to queue
{
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.drop++;
#endif
pbuf_free(p);
#ifdef OS_IS_FREERTOS
xInsideISR--;
#endif
return;
}

#if !NO_SYS
sys_sem_signal(&xemac->sem_rx_data_available); // Semaphore is given
#endif
#ifdef OS_IS_FREERTOS
xInsideISR--;
#endif
}

---------------------------------------------------------------------

0 Kudos
1 Solution

Accepted Solutions
Highlighted
Explorer
Explorer
264 Views
Registered: ‎07-14-2014

Re: LWIP BinarySemaphore usage problem and bug report

Jump to solution

Hi,

I hit upon the same problem while running the xemac lite. I modified my code to do the following:

 

xemacif_input_thread(struct netif *netif)
{
	struct xemac_s *emac = (struct xemac_s *)netif->state;
	xemacliteif_s *xemacliteif = (xemacliteif_s *)(emac->state);
	extern u32 B2BPacketsProc;

	int packets_to_process = 0;
	while (1) {
		/* sleep until there are packets to process
		 * This semaphore is set by the packet receive interrupt
		 * routine.
		 */
		sys_sem_wait(&emac->sem_rx_data_available);

		// find out how many packets are in the queue
		packets_to_process = pq_qlength(xemacliteif->recv_q);

		/* move all received packets to lwIP */
		while(packets_to_process)
		{
		xemacif_input(netif);
		packets_to_process--;
	        }
	}
}

The original code was causing all sorts of problems (as you found out) when IP packets arrive with a very small time between them.

This was the only way I could get my system to remain stable and working for long periods.

I also agree it should be fixed in the drivers

Regards

Simon

0 Kudos
2 Replies
Highlighted
Explorer
Explorer
265 Views
Registered: ‎07-14-2014

Re: LWIP BinarySemaphore usage problem and bug report

Jump to solution

Hi,

I hit upon the same problem while running the xemac lite. I modified my code to do the following:

 

xemacif_input_thread(struct netif *netif)
{
	struct xemac_s *emac = (struct xemac_s *)netif->state;
	xemacliteif_s *xemacliteif = (xemacliteif_s *)(emac->state);
	extern u32 B2BPacketsProc;

	int packets_to_process = 0;
	while (1) {
		/* sleep until there are packets to process
		 * This semaphore is set by the packet receive interrupt
		 * routine.
		 */
		sys_sem_wait(&emac->sem_rx_data_available);

		// find out how many packets are in the queue
		packets_to_process = pq_qlength(xemacliteif->recv_q);

		/* move all received packets to lwIP */
		while(packets_to_process)
		{
		xemacif_input(netif);
		packets_to_process--;
	        }
	}
}

The original code was causing all sorts of problems (as you found out) when IP packets arrive with a very small time between them.

This was the only way I could get my system to remain stable and working for long periods.

I also agree it should be fixed in the drivers

Regards

Simon

0 Kudos
Visitor okanbozkurt
Visitor
250 Views
Registered: ‎12-25-2018

Re: LWIP BinarySemaphore usage problem and bug report

Jump to solution

Thank you for your answer. When no one answered, I started to think that I have only person which have this problem :)

I did same modification like yours. It works well.

As a second way, I removed semaphore in xemacif_input_thread() and add "taskEnter_Critical" macros somewheres in drivers, but in this way thread always works. Less efficient way but also works well

 

0 Kudos