LWIP 1.4.1, FreeRTOS, kdepak, nejde...

Jaroslav Buchta jaroslav.buchta na hascomp.cz
Sobota Říjen 19 21:58:17 CEST 2013


Ha uz to asi mam, ono se nejak rozhodi poradi a odpovedi na pakety n to 
odesila az pri  prijmu paketu n+x, takze to vypada treba takhle

No.     Time           Source                Destination Protocol Length 
Info
      11 14.408727000   192.168.0.29          192.168.0.9 ICMP     
74     Echo (ping) request  id=0x0001, seq=9691/56101, ttl=128 (reply in 21)
      15 19.390221000   192.168.0.29          192.168.0.9 ICMP     
74     Echo (ping) request  id=0x0001, seq=9692/56357, ttl=128 (reply in 24)
      16 21.434476000   192.168.0.29          192.168.0.9 ICMP     
74     Echo (ping) request  id=0x0001, seq=9693/56613, ttl=128 (reply in 27)
      17 24.901624000   192.168.0.29          192.168.0.9 ICMP     
74     Echo (ping) request  id=0x0001, seq=9694/56869, ttl=128 (reply in 29)
      20 27.210004000   192.168.0.29          192.168.0.9 ICMP     
74     Echo (ping) request  id=0x0001, seq=9695/57125, ttl=128 (reply in 31)
      21 27.211617000   192.168.0.9           192.168.0.29 ICMP     
74     Echo (ping) reply    id=0x0001, seq=9691/56101, ttl=255 (request 
in 11)
      23 30.030601000   192.168.0.29          192.168.0.9 ICMP     
74     Echo (ping) request  id=0x0001, seq=9696/57381, ttl=128 (reply in 33)
      24 30.032255000   192.168.0.9           192.168.0.29 ICMP     
74     Echo (ping) reply    id=0x0001, seq=9692/56357, ttl=255 (request 
in 15)
      26 33.399941000   192.168.0.29          192.168.0.9 ICMP     
74     Echo (ping) request  id=0x0001, seq=9697/57637, ttl=128 (reply in 35)
      27 33.401526000   192.168.0.9           192.168.0.29 ICMP     
74     Echo (ping) reply    id=0x0001, seq=9693/56613, ttl=255 (request 
in 16)
      28 37.627961000   192.168.0.29          192.168.0.9 ICMP     
74     Echo (ping) request  id=0x0001, seq=9698/57893, ttl=128 (reply in 37)
      29 37.629555000   192.168.0.9           192.168.0.29 ICMP     
74     Echo (ping) reply    id=0x0001, seq=9694/56869, ttl=255 (request 
in 17)
      31 38.191036000   192.168.0.9           192.168.0.29 ICMP     
74     Echo (ping) reply    id=0x0001, seq=9695/57125, ttl=255 (request 
in 20)
      33 39.191060000   192.168.0.9           192.168.0.29 ICMP     
74     Echo (ping) reply    id=0x0001, seq=9696/57381, ttl=255 (request 
in 23)
      34 40.171452000   192.168.0.29          192.168.0.9 ICMP     
74     Echo (ping) request  id=0x0001, seq=9699/58149, ttl=128 (reply in 49)
      35 40.173069000   192.168.0.9           192.168.0.29 ICMP     
74     Echo (ping) reply    id=0x0001, seq=9697/57637, ttl=255 (request 
in 26)
      37 40.191099000   192.168.0.9           192.168.0.29 ICMP     
74     Echo (ping) reply    id=0x0001, seq=9698/57893, ttl=255 (request 
in 28)
      49 60.374202000   192.168.0.9           192.168.0.29 ICMP     
74     Echo (ping) reply    id=0x0001, seq=9699/58149, ttl=255 (request 
in 34)

Problem je zda se v tom, ze funkce ISR inkrementuje semafor a extra task 
na nej ceka a zpracuje presne stejny pocet paketu, takze pokud dojde k 
promeskani jednoho preruseni, tak se zacne zpracovani paketu zpozdovat 
(mam aktualne 5 prijimacich bufferu)
Tomu se da tezko zabranit u slozitejsiho systemu, cili reseni vidim v 
tom, ze pri obsluze ISR zpracuju vsechny pakety ktere jsou k dispozici 
(semafor by se asi nahradil mutexem)
Vyzkousel jsem modifikaci a pokud se nekdo vyzna v praci Eth. MAC a DMA 
u STM32F4xxx tak se prosim podivejte, jestli je to takto korektne a co 
pripadne upravit, nerad bych se ted snazil ten ukrutny system registru, 
deskriptoru a bufferu pochopit... Takhle to zda se funguje OK:

ISR na prijem je beze zmeny:
   if ( ETH_GetDMAFlagStatus(ETH_DMA_FLAG_R) == SET)
   {
     /* Give the semaphore to wakeup LwIP task */
     xSemaphoreGiveFromISR( s_xSemaphore, &xHigherPriorityTaskWoken );
     ETH_DMAClearITPendingBit(ETH_DMA_IT_R);
   }

Zmena je v tasku pro cekani na semafor a zpracovani paketu, 
zakomentovana cast na konci je puvodni text

   for( ;; )
   {
     if (xSemaphoreTake( s_xSemaphore, 
emacBLOCK_TIME_WAITING_FOR_INPUT)==pdTRUE)
     {
       while (ETH_CheckFrameReceived())
       {
           p = low_level_input( s_pxNetIf );
           if (ERR_OK != s_pxNetIf->input( p, s_pxNetIf))
           {
             pbuf_free(p);
             p=NULL;
           }
           TXDBGMSG("PKT R FINISH");
       }



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

A ve fci  low_level_input jsem upravil jen radek s
frame = ETH_Get_Received_Frame();    //puvodne 
ETH_Get_Received_Frame_interrupt

No a ted je otazka, jestli zbytek funkce nedela neco spatne, kdyz se 
zmenila funkce pro cteni frame... Prikladam komplet:

static struct pbuf * low_level_input(struct netif *netif)
{
   struct pbuf *p, *q;
   u16_t len;
   uint32_t l=0,i =0;
   FrameTypeDef frame;
   u8 *buffer;
   __IO ETH_DMADESCTypeDef *DMARxNextDesc;

   p = NULL;

//    STM32F4_Discovery_LEDToggle(LEDO);
   /* Get received frame */
     frame = ETH_Get_Received_Frame();//terrupt();

   /* check that frame has no error */
   if ((frame.descriptor->Status & ETH_DMARxDesc_ES) == (uint32_t)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;
}



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



Další informace o konferenci Hw-list