LWIP 1.4.1, FreeRTOS, STM32F4, ze by vitezstvi?

Jaroslav Buchta jaroslav.buchta na hascomp.cz
Úterý Říjen 22 06:36:26 CEST 2013


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



Další informace o konferenci Hw-list