cancel
Showing results for 
Search instead for 
Did you mean: 

lwip ping 2 times

Daming Liu
Associate II
Posted on June 30, 2017 at 04:39

Hi,

I use CubeMX 4.21.0 to generate FreeRTOS+LWIP code on STM32F746GZ Nucleo board. The problem is when I ping the board, It will reply after pinging 2 times. See below capture:

0690X00000607ZMQAY.png0690X00000607ZHQAY.png

Did anybody ever meet this problem?

5 REPLIES 5
Zt Liu
Senior III
Posted on June 30, 2017 at 07:40

Do they have same gateway?

Posted on June 30, 2017 at 11:25

Same Gateway. 

I traced the code and foud the problem may be in function HAL_ETH_TransmitFrame() which called by low_level_output(). I could see the ICMP pack was copied to heth buffer in memory view. But the pack didn't be sent after running function  

HAL_ETH_TransmitFrame(), and will be sent after call HAL_ETH_TransmitFrame() again by another pack.

I will check DMA part of 746GZ to see where's the reason.

Posted on July 05, 2017 at 09:02

I found the problem. It's in 'Resume DMA transmission' part code in function

HAL_ETH_TransmitFrame():

  if (((heth->Instance)->DMASR & ETH_DMASR_TBUS) != (uint32_t)RESET)

{

/* Clear TBUS ETHERNET DMA flag */

(heth->Instance)->DMASR = ETH_DMASR_TBUS;

/* Resume DMA transmission*/

(heth->Instance)->DMATPDR = 0;

dprintf('DMASR=0X%08X; TxDescriptor addr= 0X%08X; 0X%08X\r\n', (heth->Instance)->DMASR, (heth->Instance)->DMACHTDR, (uint32_t)heth->TxDesc);

Register 

DMATPDR: ' Bits 31:0 TPD: Transmit poll demand

When these bits are written with any value, the DMA reads the current descriptor pointed to

by the ETH_DMACHTDR register. If that descriptor is not available (owned by Host),

transmission returns to the Suspend state and ETH_DMASR register bit 2 is asserted. If the

descriptor is available, transmission resumes.'

The problem is ETH_DMACHTDR  update on time(maybe not, cause printf also take time) by print it when ping delay over time occur. If It's update on time, then tx descriptor should be available(owned by DMA), But the result is it's unabailable . so the ping reply would delay untill next packet sent

DMASR=0X00360400; TxDescriptor addr= 0X20019E30; 0X20019E50

icmp_input: ping

DMASR=0X00360400; TxDescriptor addr= 0X20019E50; 0X20019E70

icmp_input: ping

DMASR=0X00360400; TxDescriptor addr= 0X20019E70; 0X20019E10

icmp_input: ping

DMASR=0X00660404; TxDescriptor addr= 0X20019E10; 0X20019E30

icmp_input: ping

DMASR=0X00360400; TxDescriptor addr= 0X20019E10; 0X20019E50

icmp_input: ping

DMASR=0X00360400; TxDescriptor addr= 0X20019E50; 0X20019E70

icmp_input: ping

DMASR=0X00360400; TxDescriptor addr= 0X20019E70; 0X20019E10

The conclude is there's confilict betweenDMASR=0X00660404 and DMACHTDR = 0X20019E10; My new question is when registerDMACHTDR is updated by DMA?

Posted on November 21, 2017 at 02:59

Did you find a solution to this problem?  I have the same problem and don't want to waste too much time if you already know the answer.  Thanks for sharing.

Posted on November 28, 2017 at 20:11

This solution worked for me. I found it on this forum:

https://community.st.com/0D50X00009XkgffSAB

Basically, just add '

__DSB();

' just before the check when Tx Buffer is unavailable.

@

https://community.st.com/0D50X00009XkgffSAB#comment-168645

on

https://community.st.com/0D50X00009XkgffSAB#comment-170221

diff --git a/fw/controller/system/src/stm32f7-hal/stm32f7xx_hal_eth.c b/fw/controller/system/src/stm32f7-hal/stm32f7xx_hal_eth.cindex 527ed.07eeba0 100644--- a/fw/controller/system/src/stm32f7-hal/stm32f7xx_hal_eth.c+++ b/fw/controller/system/src/stm32f7-hal/stm32f7xx_hal_eth.c@@ -752,7 +752,12 @@ HAL_StatusTypeDef HAL_ETH_TransmitFrame(ETH_HandleTypeDef *heth, uint32_t FrameL heth->TxDesc = (ETH_DMADescTypeDef *)(heth->TxDesc->Buffer2NextDescAddr); } }-++ /* DNIL: Sync here before moving on. Otherwise we seem to have intermittent issues with stores to+ * TxDesc->Status register not reaching the DMA engine.+ */+ __DSB();+ /* When Tx Buffer unavailable flag is set: clear it and resume transmission */ if (((heth->Instance)->DMASR & ETH_DMASR_TBUS) != (uint32_t)RESET) {