lwip-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lwip-users] lwIP replies ping request with reply of an earlier requ


From: Mark Lakata
Subject: Re: [lwip-users] lwIP replies ping request with reply of an earlier request (packages out off sync)
Date: Thu, 19 Sep 2013 13:02:18 -0700
User-agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20130801 Thunderbird/17.0.8

The STM32F4xx demo driver code is very poorly written and has a poor interrupt handler. It doesn't actually lose packets, but if multiple packets arrive within a short time, only the first packet is given to LWIP, and the rest of the packets stay in the queue until another packet arrives much later.

Please search the lwip-users email archives for the subject "STM32 RBUS (Receive Buffer Unavailable) bit set after    debugger break" where this was discussed (Sep 2012, last year). I think the code that Seba posted below is from that discussion.

-Mark Lakata

-
On 9/19/2013 2:45 AM, address@hidden wrote:
There is a mistake in the management of RBUS flag with STM32 & FreeRTOS. When you put a breakpint and stop your program on debug mode, the RBUS flag is not correctly reset, so when you continue your program all the ping request will be slow down.


Try this (in ethernetif.c):

/**
 * Should allocate a pbuf and transfer the bytes of the incoming
 * packet from the interface into the pbuf.
 *
 * @param netif the lwip network interface structure for this ethernetif
 * @return a pbuf filled with the received packet (including MAC header)
 *         NULL on memory error
 */
static struct pbuf * low_level_input(struct netif *netif)
{
  (void)(netif);
  struct pbuf *p, *q;
  u16_t len;
  u32 l=0,i =0;
  FrameTypeDef frame;
  u8 *buffer;
  volatile ETH_DMADESCTypeDef *DMARxNextDesc;

  p = NULL;

  /* Get received frame */
  frame = ETH_Get_Received_Frame_interrupt();

  if (frame.descriptor && frame.buffer) {
  /* check that frame has no error */
  if ((frame.descriptor->Status & ETH_DMARxDesc_ES) == (u32)RESET)
  {

    /* Obtain the size of the packet and put it into the "len" variable. */
    len = frame.length;
    buffer = (u8 *)frame.buffer;

    /* We allocate a pbuf chain of pbufs from the pool. */
    p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);

    /* Copy received frame from ethernet driver buffer to stack buffer */
    if (p != NULL)
    {
      for (q = p; q != NULL; q = q->next)
      {
        memcpy((u8_t*)q->payload, (u8_t*)&buffer[l], q->len);
        l = l + q->len;
      }
    }
  }

  /* Release descriptors to DMA */
  /* Check if received frame with multiple DMA buffer segments */
  if (DMA_RX_FRAME_infos->Seg_Count > 1)
  {
    DMARxNextDesc = DMA_RX_FRAME_infos->FS_Rx_Desc;
  }
  else
  {
    DMARxNextDesc = frame.descriptor;
  }

  /* Set Own bit in Rx descriptors: gives the buffers back to DMA */
  for (i=0; i<DMA_RX_FRAME_infos->Seg_Count; i++)
  {
    DMARxNextDesc->Status = ETH_DMARxDesc_OWN;
    DMARxNextDesc = (ETH_DMADESCTypeDef *)(DMARxNextDesc->Buffer2NextDescAddr);
  }

  /* Clear Segment_Count */
  DMA_RX_FRAME_infos->Seg_Count =0;


  /* When Rx Buffer unavailable flag is set: clear it and resume reception */
  //if ((ETH->DMASR & ETH_DMASR_RBUS) != (u32)RESET)
  //{
    /* Clear RBUS ETHERNET DMA flag */
    //ETH->DMASR = ETH_DMASR_RBUS;

    /* Resume DMA reception */
    //ETH->DMARPDR = 0;
  //}
  }
  return p;
}

static void ethernet_watchdog(void) {

   // u32 temp;
    /* When Rx Buffer unavailable flag is set: clear it and resume reception */
    if ((ETH->DMASR & ETH_DMASR_RBUS) != (u32)RESET)
    {
        /* Clear RBUS ETHERNET DMA flag */
        //ETH_DMAClearITPendingBit(ETH_DMA_IT_RBU | ETH_DMA_IT_AIS);
        //temp = ETH->DMASR;

        ETH->DMASR = ETH_DMASR_RBUS;


        /* Resume DMA reception. The register doesn't care what you write to it. */
        ETH->DMARPDR = 0;
    }
}

/**
 * This function is the ethernetif_input task, it is processed when a packet
 * is ready to be read from the interface. It uses the function low_level_input()
 * that should handle the actual reception of bytes from the network
 * interface. Then the type of the received packet is determined and
 * the appropriate input function is called.
 *
 * @param netif the lwip network interface structure for this ethernetif
 */
void ethernetif_input( void * pvParameters )
{
  (void)pvParameters;
  struct pbuf *p;

  for( ;; )
  {
    if (xSemaphoreTake( s_xSemaphore, emacBLOCK_TIME_WAITING_FOR_INPUT)==pdTRUE)
    {

       while ((p = low_level_input( s_pxNetIf )) != 0) {
          if (p != 0) {
              if (ERR_OK != s_pxNetIf->input( p, s_pxNetIf))
              {
                pbuf_free(p);
                p=NULL;
              }
          }
        }
    }
    ethernet_watchdog();
  }
}

----- Mail original -----
De: "George Ruinelli" <address@hidden>
À: "Mailing list for lwIP users" <address@hidden>
Envoyé: Jeudi 19 Septembre 2013 11:32:09
Objet: Re: [lwip-users] lwIP replies ping request with reply of an earlier request (packages out off sync)

Thank you for your quick reply!

What would I have to look for?
I see that the RBUS flag is only used in low_level_input().

BTW:
Up to yesterday we used lwIP 1.4.0 but updated to 1.4.1 without improvements in that issue.

George Ruinelli

Kistler Instrumente AG
Eulachstrasse 22, 8408 Winterthur, Switzerland
Direct+41 52 2241 257, Main Office+41 52 224 11 11
address@hidden, www.kistler.com
_______________________________________________
lwip-users mailing list
address@hidden
https://lists.nongnu.org/mailman/listinfo/lwip-users

_______________________________________________
lwip-users mailing list
address@hidden
https://lists.nongnu.org/mailman/listinfo/lwip-users


reply via email to

[Prev in Thread] Current Thread [Next in Thread]