LWIP 1.4.1, FreeRTOS, STM32F4, ze by vitezstvi?

Jaroslav Buchta jaroslav.buchta na hascomp.cz
Úterý Listopad 5 21:13:12 CET 2013


Tak zaver - fakt to bylo spatnym nastavenim priorit preruseni, diky za 
tip uz nevim komu ;-)
Uz to 30h jede s intenzivni komunikaci bez chyby, ale 128kB pameti je 
fakt rozumne minimum pro LWIP a FreeRTOS.


Dne 22.10.2013 6:36, Jaroslav Buchta napsal(a):
> Tak jsem nakonec byl nucen system bufferu a deskriprotu DMA pochopit, 
> neni to tak slozite ;-)
> Tech pricin nefunkce bylo vice najednou, zejmena se jednalo o 
> promeskani ISR, kdy se zpozdovalo zpracovani prichozich paketu, to 
> zachranuje uprava fce low_level_input, ktera zpracuje paket po nejakem 
> casovem limitu i bez nahozeni semaforu:
>
>  void ethernetif_input( void * pvParameters )
> {
>   struct pbuf *p;
>   int32_t bSmallDelay = pdFALSE;
>   for( ;; )
>   {
>     xSemaphoreTake( s_xSemaphore, bSmallDelay ? 10 : 
> emacBLOCK_TIME_WAITING_FOR_INPUT);
>     {
>       //TXDBGMSG("PKT R START");
>       if (ETH_CheckFrameReceived())
>       {
>           TXDBGMSG("PKT R START");
>           p = low_level_input( s_pxNetIf );
>           LedSetRx();
>           if (ERR_OK != s_pxNetIf->input( p, s_pxNetIf))
>           {
>             TXDBGMSG("PKT R ERROR");
>             pbuf_free(p);
>             p=NULL;
>           }
>           TXDBGMSG("PKT R FINISH");
>           bSmallDelay = pdTRUE;
>       }
>       else
>       {
>           bSmallDelay = pdFALSE;
>       }
>     }
>   }
> }
>
> to while co jsem mel predtim nebylo idealni, sice zajistilo zpracovani 
> vsech cekajicich paketu najednou, ale tento task ma nejvyssi prioritu 
> a zase nepustil k procesoru nic jineho...
>
> A pak je potreba zakazat optimalizaci globalne nebo pro funkce, ktere 
> operuji s DMA deskriptory - jinak to zmeni posloupnost prikazu zapisu 
> ruzne do pameti a dela to divy... Ja to udelal takto u nasledujicich fci:
>
> static struct pbuf * low_level_input(struct netif *netif) 
> __attribute__((optimize("-O0")));
> static err_t low_level_output(struct netif *netif, struct pbuf *p) 
> __attribute__((optimize("-O0")));
> uint32_t ETH_Prepare_Transmit_Descriptors(u16 
> FrameLength)__attribute__((optimize("-O0")));
> uint32_t ETH_Prepare_Transmit_Descriptors(u16 
> FrameLength)__attribute__((optimize("-O0")));
> FrameTypeDef ETH_Get_Received_Frame(void) 
> __attribute__((optimize("-O0")));
>
> Tak snad to nekdy nekomu pomuze, uz to bezi asi 30 hodin pod 
> intenzivni komunikaci bez problemu.
>
>
> Dne 19.10.2013 21:58, Jaroslav Buchta napsal(a):
>> 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;
>> }
>>
>>
>>
>> ---------------------------------------------------------------------------------------------------------------------------------------------- 
>>
>>
>> _______________________________________________
>> HW-list mailing list  -  sponsored by www.HW.cz
>> Hw-list na list.hw.cz
>> http://list.hw.cz/mailman/listinfo/hw-list
>
> _______________________________________________
> HW-list mailing list  -  sponsored by www.HW.cz
> Hw-list na list.hw.cz
> http://list.hw.cz/mailman/listinfo/hw-list



Další informace o konferenci Hw-list