Part Number: TMS320F28388D
Other Parts Discussed in Thread: C2000WARE
Hello TI Support Team,
We are using the C2000Ware v6.00.00.00 SDK on an F2838x device.
Note: The same issue exist in the latest SDK C2000Ware_26_00_00_00 also.
With reference to the issue reported earlier by another user:
We were getting the same issue(Ethernet Rx stops and it never recovers until a restart) in our system when we load our system with the heavy TCP load. (Consdering confidentiality of our ongoing development, we can not share our application/setup details for now).
There are mainly 2 reasons to post this here.
- Very first one is to share our findings with TI's team so that they can provide a permanent fix in the next SDK.
- Those who are still struggling in this issue and stuck in their developement, can use this workaround and continue their development.
So below are our observations:
- The problem starts when the ethernet Rx is heavily loaded and RX OVERFLOW interrupt is fired. Now in C2000Ware v6.00.00.00: TI has implemented handling of Rx over flow interrupts in the
Now in C2000Ware_26_00_00_00: TI has completely removed handling of Rx over flow interrupts in the Ethernet_genericISRCustom(). So there is PBUF_POOL exhaustion in this case, but still the Ethernet Rx and Tx is not working.Ethernet_genericISRCustom() where the Rx channel is init again and Rx descriptor tail pointer is upadted which does not seems to be a proper handling of Rx over flow interrupts. So the main reasons for Lwip memory exhaustion seems to be this Rx overflow interrupt handling. (
PBUF_POOLmemory exhaust) - We have done some low level debugging to know the Ethernet TX and RX DMA state, Tx and Rx interrupts counters after the Rx over flow interrupts. (with C2000Ware_26_00_00_00 ethernet driver).
C2000Ware_26_00_00_00: So after the RX OVERFLOW interrupt is fired, we have observed that the DMA Rx state machine goes into the suspend state and it never recovers from this state and Ethernet driver Tx stops after some time due to no available tx packet descriptors from the Lwip interface.
RCA for RX DMA goes into Suspend state: Rx interrupt is not fired from the ethernet module when the Rx overflow occurs. Due to this the ethernet Rx packets which are already processed by the DMA and handed over to the application are never seen to the application and never processed by the application and never given back to the DMA. (Because the whole Rx packet handling works based on the Rx interrupt)

RCA for Ethernet driver Tx Stops after some time: Tx interrupt is not fired from the ethernet module when the Rx overflow occurs. Due to this this, the driver sends the packet until the Tx packet FreeQ gets full (file: ports/c2000/netif/f2838xif.c: #define NUM_PACKET_DESC_TX_APPLICATION 20, TxPktFreeQ). After that the Tx stops as ethernet packet descriptors are not freed due to missing Tx interrupt and there are no Ethernet_Pkt_Desc available for Tx.
From the above analysis, it is clear that the main responsbile module for this whole problem is tx and rx interrupts which are not fired from the module when rx overflow occurs.
So for workaround, we have removed Tx and Rx packets handling based on the interrupts. We are continously polling Tx and Rx descriptors.
TI's reference implementation
if((uiISRsignal & RX_ISR_MASK) != 0)
{
//process Rx
Ethernet_removePacketsFromRxQueue(
(Ethernet_DescCh*)
&Ethernet_device_struct.dmaObj.rxDma[ETHERNET_DMA_CHANNEL_NUM_0],
ETHERNET_COMPLETION_NORMAL);
ETHERNET_DISABLE_INTERRUPTS();
CM_Eth_ISRsignal &= (~RX_ISR_MASK);
ETHERNET_ENABLE_INTERRUPTS();
}
if((uiISRsignal & TX_ISR_MASK) != 0)
{
//process tx
Ethernet_removePacketsFromTxQueue(
(Ethernet_DescCh*)
&Ethernet_device_struct.dmaObj.txDma[ETHERNET_DMA_CHANNEL_NUM_0],
ETHERNET_COMPLETION_NORMAL);
ETHERNET_DISABLE_INTERRUPTS();
CM_Eth_ISRsignal &= (~TX_ISR_MASK);
ETHERNET_ENABLE_INTERRUPTS();
}
Modification:
Just remove checks of uiISRsignal & RX_ISR_MASK and uiISRsignal & TX_ISR_MASK
if((1)
{
//process Rx
Ethernet_removePacketsFromRxQueue(
(Ethernet_DescCh*)
&Ethernet_device_struct.dmaObj.rxDma[ETHERNET_DMA_CHANNEL_NUM_0],
ETHERNET_COMPLETION_NORMAL);
}
if((1)
{
//process tx
Ethernet_removePacketsFromTxQueue(
(Ethernet_DescCh*)
&Ethernet_device_struct.dmaObj.txDma[ETHERNET_DMA_CHANNEL_NUM_0],
ETHERNET_COMPLETION_NORMAL);
}
Note: remove if(1), written here just for comparision with the reference implementation.
The workaround seems to be preety simple but we have spent many days in this low level debugging and finding the root cause.