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