Is it caused by some wrong with STM32 ETH DMA? It's the error handling code
in RT-Thread STM32F107 ETH driver:
/* interrupt service routine for ETH */
void ETH_IRQHandler(void)
{
...
if ((status & ETH_DMA_IT_RBU) != (u32)RESET)
{
ETH_ResumeDMAReception();
ETH->DMASR = (u32)ETH_DMA_IT_RBU;
}
if ((status & ETH_DMA_IT_TBU) != (u32)RESET)
{
ETH_ResumeDMATransmission();
ETH->DMASR = (u32)ETH_DMA_IT_TBU;
}
...
}
Regards,
Bernard Xiong
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RT-Thread - An open source RTOS from China.
http://en.rt-thread.org
http://www.rt-thread.org
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2012/5/11 vincent cui <[email protected]>
> Hi all:****
>
> ** **
>
> I found root cause now , it is ST CORTEX M3 DMA problem when receive a
> large of file..****
>
> I trace the code, after lwIP performance is down, the Rx Buffer
> unavailable flag is always set. It means that DMA is in unknown status..**
> **
>
> ** **
>
> It should be enthernet driver problem ..anyone know how to fix ? thank you
> ****
>
> ** **
>
> ** **
>
> 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;****
>
> ****
>
> /* Get received frame */****
>
> frame = ETH_Get_Received_Frame_interrupt();****
>
> ****
>
> /* 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) ****
>
> {****
>
> printf(" RX buffer unavailable flag set \n");****
>
> /* Clear RBUS ETHERNET DMA flag */****
>
> ETH->DMASR = ETH_DMASR_RBUS;****
>
> ****
>
> /* Resume DMA reception */****
>
> ETH->DMARPDR = 0;****
>
> ** **
>
> }****
>
> return p;****
>
> }****
>
> ** **
>
> ** **
>
> ** **
>
> *From:* [email protected] [mailto:
> [email protected]] *On Behalf Of *vincent
> cui
> *Sent:* 2012年5月11日 13:24
>
> *To:* Mailing list for lwIP users
> *Subject:* Re: [lwip-users] lwip performance goes down if running with
> FreeRTOS****
>
> ** **
>
> *Hi :*
>
> * *
>
> *I found it maybe enthernet driver problem. Cortex m3 use DMA channel to
> receive and send data. And also, it link*
>
> *Receive and send buffer as chain to speed up. The default ETH_TXBUFNB
> value is 5, when I change it to 1. The lwip*
>
> *Performance is stable,but not fast as same as ETH_TXBUFNB == 5.*
>
> *In enthernet interrupt handler, it will check input frame and give
> semaphore and force task witch, then, ethernetif_input take the semaphore*
>
> *To handle the receive packet.*
>
> * *
>
> *Why lWIP performance goes down when ETH_TXBUFNB is 5 ?*
>
> * *
>
> * *
>
> *static void low_level_init(struct netif *netif)*
>
> *{*
>
> * uint32_t i;*
>
> * uint8_t mac_buffer[8];*
>
> * *
>
> * /* set netif MAC hardware address length */*
>
> * netif->hwaddr_len = ETHARP_HWADDR_LEN;*
>
> * *
>
> * /* set netif MAC hardware address */*
>
> * *
>
> * pdu_mac_init(mac_buffer);*
>
> * *
>
> * netif->hwaddr[0] = mac_buffer[0];*
>
> * netif->hwaddr[1] = mac_buffer[1];*
>
> * netif->hwaddr[2] = mac_buffer[2];*
>
> * netif->hwaddr[3] = mac_buffer[3];*
>
> * netif->hwaddr[4] = mac_buffer[4];*
>
> * netif->hwaddr[5] = mac_buffer[5];*
>
> * *
>
> * /* set netif maximum transfer unit */*
>
> * netif->mtu = 1500;*
>
> * *
>
> * /* Accept broadcast address and ARP traffic */*
>
> * netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;*
>
> * *
>
> * s_pxNetIf =netif;*
>
> * *
>
> * /* create binary semaphore used for informing ethernetif of frame
> reception */*
>
> * if (s_xSemaphore == NULL)*
>
> * {*
>
> * s_xSemaphore= xSemaphoreCreateCounting(32,0);*
>
> * }*
>
> * *
>
> * /* initialize MAC address in ethernet MAC */ *
>
> * ETH_MACAddressConfig(ETH_MAC_Address0, netif->hwaddr); *
>
> * *
>
> * /* Initialize Tx Descriptors list: Chain Mode */*
>
> * ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);*
>
> * /* Initialize Rx Descriptors list: Chain Mode */*
>
> * ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);*
>
> * *
>
> * /* Enable Ethernet Rx interrrupt */*
>
> * { *
>
> * for(i=0; i<ETH_RXBUFNB; i++)*
>
> * {*
>
> * ETH_DMARxDescReceiveITConfig(&DMARxDscrTab[i], ENABLE);*
>
> * }*
>
> * }*
>
> * *
>
> *#ifdef CHECKSUM_GEN_ICMP*
>
> * /* Enable the checksum insertion for the Tx frames */*
>
> * {*
>
> * for(i=0; i<ETH_TXBUFNB; i++)*
>
> * {*
>
> * ETH_DMATxDescChecksumInsertionConfig(&DMATxDscrTab[i],
> ETH_DMATxDesc_ChecksumTCPUDPICMPFull);*
>
> * }*
>
> * } *
>
> *#endif*
>
> * *
>
> * /* create the task that handles the ETH_MAC */*
>
> * xTaskCreate(ethernetif_input, (signed char*) "Eth_if",
> netifINTERFACE_TASK_STACK_SIZE, NULL,*
>
> * netifINTERFACE_TASK_PRIORITY,NULL);*
>
> * *
>
> * /* Enable MAC and DMA transmission and reception */*
>
> * ETH_Start(); *
>
> *}*
>
> * *
>
> * *
>
> *void ETH_IRQHandler(void)*
>
> *{*
>
> * portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;*
>
> * *
>
> * /* Frame received */*
>
> * if ( ETH_GetDMAFlagStatus(ETH_DMA_FLAG_R) == SET) *
>
> * {*
>
> * /* Give the semaphore to wakeup LwIP task */*
>
> * *
>
> * xSemaphoreGiveFromISR( s_xSemaphore, &xHigherPriorityTaskWoken ); *
>
> * }*
>
> * *
>
> * /* Clear the interrupt flags. */*
>
> * /* Clear the Eth DMA Rx IT pending bits */*
>
> * ETH_DMAClearITPendingBit(ETH_DMA_IT_R);*
>
> * ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS);*
>
> * *
>
> * /* Switch tasks if necessary. */ *
>
> * if( xHigherPriorityTaskWoken != pdFALSE )*
>
> * {*
>
> * *
>
> * portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );*
>
> * }*
>
> * *
>
> *}*
>
> * *
>
> *void ethernetif_input( void * pvParameters )*
>
> *{*
>
> * struct pbuf *p;*
>
> * *
>
> * for( ;; )*
>
> * {*
>
> * if (xSemaphoreTake( s_xSemaphore,
> emacBLOCK_TIME_WAITING_FOR_INPUT)==pdTRUE)*
>
> * {*
>
> * p = low_level_input( s_pxNetIf );*
>
> * if (ERR_OK != s_pxNetIf->input( p, s_pxNetIf))*
>
> * {*
>
> * pbuf_free(p);*
>
> * p=NULL;*
>
> * }*
>
> * }*
>
> * }*
>
> *} *
>
> * *
>
> ** **
>
> *From:* [email protected] [mailto:
> [email protected]] *On Behalf Of *vincent
> cui
> *Sent:* 2012年5月11日 8:20
> *To:* Mailing list for lwIP users
> *Subject:* Re: [lwip-users] lwip performance goes down if running with
> FreeRTOS****
>
> ** **
>
> Hi :****
>
> ****
>
> When lwIP performance goes to down, I capture the TCP packet as attached
> files. ****
>
> I also extend PBUF_POOL_BUFSIZE to enough size. It seems no use.****
>
> Anyone can give any help ?****
>
> ****
>
> Vincent ****
>
> ****
>
> *From:* [email protected] [mailto:
> [email protected]] *On Behalf Of *vincent
> cui
> *Sent:* 2012年5月10日 21:01
> *To:* Mailing list for lwIP users
> *Subject:* [lwip-users] lwip performance goes down if running with
> FreeRTOS****
>
> ****
>
> Hi: ****
>
> ****
>
> I found a odd strange in Cortex M3, running LWIP1.4.0 + FreeRTOS.****
>
> I write a TCP server to accept large file, the code works well if running
> in LWIP standalone. The performance is high and stable.****
>
> But when I create the task in FreeRTOS, the whole LWIP performance goes to
> down after the task accept file for a while****
>
> ****
>
> It seems that switch task in FreeRTOS cause it down, but I don’t know how
> to bypass. I even try to “define LWIP_TCP_CORE_LOCKING’****
>
> To disable TCP task switch, but still got same result . ****
>
> ****
>
> Anyone can give help ?****
>
> ****
>
> ****
>
> vincent****
>
> ****
>
> ****
>
> _______________________________________________
> lwip-users mailing list
> [email protected]
> https://lists.nongnu.org/mailman/listinfo/lwip-users
>
_______________________________________________
lwip-users mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/lwip-users