cancel
Showing results for 
Search instead for 
Did you mean: 

[bug fixes] STM32H7 Ethernet

alister
Lead

@Amel NASRI​, @ranran​, @Piranha​, @Harrold​, @Pavel A.​ 

V2 of my fixes and improvements to H7_FW V1.5.0/V1.6.0 Ethernet...

Changes include

  • Decoupling receive buffers from receive descriptors so buffers may be held any length time without choking receive.
  • Optionally queuing transmit, so transmit doesn't need to block until complete.
  • Many bug fixes.

Find full details and source in the attached zip. V1 was posted to another developer's question. Please post any questions about V2 here.

97 REPLIES 97

I dind't rename them. But just made the example document easier to rewrite...

ADunc.1
Senior

From some testing I have been doing today I found some potential improvements on transmit. I believe alister mentioned in his documentation that transmit was not a priority, and actually for my application is not so important either.

Rather than calling HAL_Transmit when not using a tx queue, calling HAL_TransmitIT, waiting on an event and signalling from the interrupt callback seems to yield better performance (the mechanism is already there for the tx queue). When doing load testing it seemed that the application was spending significant time spinning in HAL_transmit and potentially starving other (particularly the lwip) thread.

However, this may not be the case for infrequent transmission of small packets rather than frequent transmission of large packets. Some testing with setting/clearing a port pin on entry/exit to the transmit function may be required to quantify the difference exactly.

Personally I would not run this driver without the transmit queue as that yields a 41-51MBps improvement in my application and has little impact on memory footprint.

Just thought I would open it up for discussion...

Tx-queuing, using HAL_ETH_Transmit_IT, is enabled as default. Are you sure you'd ported all of ethernetif.c?

It's controlled by the ETH_TX_QUEUE_ENABLE macro.

Take care, non-blocking transmit (tx-queuing) is only safe if you know your app won't change a pbuf (or its buffer) after it's been transmitted.

There is an option in CubeMX (not) to "Delete previously generated files when not re-generated". Did you try it to keep the files?

>There is an option in CubeMX (not) to "Delete previously generated files when not re-generated". Did you try it to keep the files?

That won't help. Its tool-tip says "After a configuration change, some previously generated files may not be needed anymore. Select the checkbox to force their deletion at next code generation."

It is untidy to change HAL files, then move them and, by stealth, change the compiler search order, etc, etc.

But the method is conventional. It's for problems like this that the GCC compiler's include path search order is changeable and that Eclipse can exclude files.

I did try that option, but it turns out it always deletes files that are not meant to be in the folder. That's why you need to place them in another folder. It doesn't seem to delete folders, or maybe it doesn't delete anything outside the Src/Inc folders.

I tried with/without tx queue and blocking/non blocking transmit with tx queue disabled. The fully blocking option did not work well, and not a good design practice to use blocking/polling functions unless absolutely necessary. This application has four different nefifs, plus a heap of other stuff going on so needs to stay responsive.

Transmit with interrupt is still a better option for no queue than a blocking transmit. Neither option prevents another thread from modifying the buffer, both options prevent the lwip tcp thread from modifying the buffer as it is blocked either way. I am running with the queue enabled as want to keep the lwip thread running to service the other netifs.

AFAIK, there is no way my application can modify the buffers. But I do remember reading somewhere that lwip may modify them in certain cases. Maybe TCP segmentation, or transmit failure. I cant remember where I saw that though.

>I tried with/without tx queue and blocking/non blocking transmit with tx queue disabled

With tx-queue is for non-blocking. Without tx-queue is for blocking.

>blocking option did not work well, and not a good design

Non-blocking tx is _atypical_ implementation.

The low_level_output doesn't do the tx directly. It offloads the tx to the MAC via DMA.

In an earlier post you'd mentioned seening "41-51MBps" (that's bits/s) improvement with tx-queuing. That's like 10x more improvement that I saw (with my one interface).

> This application has four different nefifs

Yes, and this explains your large observed tx improvement with tx-queuing.

The low_level_output is executed by lwIP's tcpip_thread. The tx-queuing is a small improvement to its tx. But a big improvement to everything else the stack does, and especially for you because of those other interfaces.

> Transmit with interrupt is still a better option for no queue than a blocking transmit.

Without tx-queueing, HAL_ETH_Transmit_IT returns some 10s of microseconds that are lost by HAL_ETH_Transmit waiting for the DMA to complete. But that time doesn't help tcpip_thread. Only tx-queuing unblocks tcpip_thread.

>want to keep the lwip thread running to service the other netifs

Yes.

>I do remember reading somewhere that lwip may modify them in certain cases

https://lists.nongnu.org/archive/html/lwip-devel/2015-10/msg00077.html

ASar
Associate II

Hello,

I have also used your code. It works very well ( 94Mbit send/rcv). But i have one problem i can not resolve. 

After reset uC or first connect rj45 to PC i got max transfert. But when i reconnect RJ45 the transfer slow down ( <500kbps). In debug i get message "memp_malloc: out of memory in pool TCPIP_MSG_INPKT".

After disconnect function RxBuffFree is called, so the rx buffers should be empty.

What can be wrong ?

>i get message "memp_malloc: out of memory in pool TCPIP_MSG_INPKT".

MEMP_TCPIP_MSG_INPKT is lwIP's container for received packets. What's MEMP_NUM_TCPIP_MSG_INPKT?

>After disconnect function RxBuffFree is called

You're calling HAL_ETH_DeInit or HAL_ETH_Stop? You shouldn't need to. Or what's calling RxBuffFree?