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