FreeRTOS+TCP for STM32H7?

Sorry Hein, but we’ve completely given up on ST. One project with hardware is on hold (we will probably respin with NXP uC), ST disqualified for a couple pending projects (including one with some light prototyping already done on ST), and for two products underway we’re using NXP. We have to get products out the door, and can’t afford the time, money, and aggravation of rewriting all the ST low-level code and drivers. Not to mention the extreme aggravation of dealing with their clowns pretending support.

Sorry I can’t help, Good luck!
Best Regards, Dave

Hi Dave, thanks for your response.
I have decided to get on with the HAL library as it is, and change it my self until it works.
The FreeRTOS+TCP driver is working now.

ST Electronics makes great hardware, I have applied their STM32F[04] in several projects.
But I also noticed that their hardware-support libraries (HAL) need more attention. Some engineers keep on using ST’s good-old Standard Peripheral Library. That was less fancy, but it worked well.

I will soon create a PR for the network interface for STM32H7xx.

The FreeRTOS+TCP network interface for STM32H7xx is now available for testing!

I submitted it on Github freertos/freertos.

The driver shows a very high performance, both when receiving and/or sending packets.

Hi Hein,

Sorry, I am quite late to this party. Myself having an H743 nucleo here. The H7 Ethernet driver from ST is extremely buggy, a lot of people have been crying out aloud on the ST forum.

Alister on the ST forum, seems to have a driver well debugged fixing all of ST’s H7 ethernet driver bugs.

ST does not seem to want those changes unfortunately and it is such a shame!
You could probably have a look at Alister’s fixes and or the bugs that he found with ST’s driver.

I would like to test your changes. Where and how to get into the testing mode is what I would like to hear from you.

Cheers,

Manu

@htibosch

Hi Hein,

I forgot the link to the forum thread. Here it is

https://community.st.com/s/question/0D50X0000C6eNNSSQ2/bug-fixes-stm32h7-ethernet

Cheers,

Manu

Hi manu, thanks for that link. I had seen it already.

I used a copy of ST’s driver and worked on it until I was satisfied with it.

I took the original stm32h7xx_hal_eth.c to start with, and renamed it to stm32hxx_hal_eth.c ( leaving out the ‘7’ ).
It is a simplified version, and I think that it will work well.
Regards,

1 Like

@htibosch

Hi Hein,

How should the MPU be configured? I just read Ethernet not working on STM32H7x3 article and the MPU settings seems to be very critical.

How should the MPU be configured?

I did not configure it at all.

I had stumbled on the same article.

Like I wrote in the readme.md, I created a section called “.ram3_data” in:

RAM3 (xrw)      : ORIGIN = 0x24000000, LENGTH = 512K

All memory that is shared with DMA is allocated in mentioned section.

Ok, thanks for the quick reply. Do you happen to have an example project which you could share?

It is a quick-and-dirty project full of little tests and try-outs.
I will share it in a private message.

Hello Hein,

I had stumbled on the same article.

Like I wrote in the readme.md, I created a section called “.ram3_data” in:

RAM3 (xrw)      : ORIGIN = 0x24000000, LENGTH = 512K

All memory that is shared with DMA is allocated in mentioned section.

A small issue here:

SRAM @location 0x24000000 is in the D1 domain.

One needs to locate the Ethernet stuff in D2 domain SRAM
ie in either SRAM1, SRAM2 or SRAM3. and not in D1 AXI SRAM.

That’s what I understand; I could have misunderstood though.
For clarification, I checked the datasheet, just now:
Datasheet STM32H742xI/G STM32H743xI/G
Document no: DS12110 Rev 7, Page#33/357
Fig 4: Ethernet is connected to

  1. D2 SRAM1 128kb
  2. D2 SRAM2 128kb
  3. D2 SRAM3 32kb

That led me to wonder, how it worked for you. Looking deeper,
I see that D2 domain is connected to the 64bit D1 domain through
a bridge (D2toD1 AHB bridge).

That likely creates double bus traffic and chokes the AHB bridge ?

The 64 bit bus is connecting all other peripherals to the stack
through this bridge. If the Ethernet peripheral hogs this bridge,
it could like create a minute temporary denial of service to the
DTCM or the AXI SRAM ?

Maybe this could explain a memory unreliability issue you
mentioned someplace ?

ST recommends that Ethernet descriptors and friends “should” be
in the D2 domain.

Regarding the MPU configuration, the MPU creates a
DCache free zone, from what I understand.
In short, if you disable DCache() then you would not require to use
a MPU configuration. I guess that’s what you have done.

Which is okay atm for test purposes, but disabling DCache completely
causes a significant performance drop.
(For example, when I was testing with LWIP, with DCache disabled and
enabling debug messages, caused quite a significant load, which caused
TCP packets to timeout)

I think the best would be to move Ethernet stuff from D1 to D2.

Thanks,

Manu

I am glad to see that I am not the only one who gets confused by ST’s documentation.

I suppose that you also found : https://community.st.com/s/article/FAQ-DMA-is-not-working-on-STM32H7-devices ?

It shows this picture:

Yes I am sure that ETH works perfectly when I locate all DMA memories here:

RAM3 (xrw)      : ORIGIN = 0x24000000, LENGTH = 512K

There is even confusion about the names “RAM3”. Have you seen this:

The memory at 0x24000000 has a size of 512 KB and it is called AXI SRAM
"SRAM3 has a differente address: 0x30040000 with a size of 128 KB.

Looking at the picture, it is indeed a long way from AXI to ETH, indeed through the D2toD1 AHB bridge.

Regards,
Hein

Hi Hein,

I am glad to see that I am not the only one who gets confused by ST’s documentation.

Definitely, looking at my own condition, it will be injustice to say that you are the only one. This is one of the reasons, why I wrote previously: to preserve my sanity, I do write some comments and definitions, just to make sure that I am fully functional. :wink:

I suppose that you also found : DMA is not working on STM32H7 devices - STMicroelectronics Community ?

Honestly, I did. Previously on this very same forum myself had a discussion with someone else too …

It shows this picture:

Yes I am sure that ETH works perfectly when I locate all DMA memories here:

RAM3 (xrw)      : ORIGIN = 0x24000000, LENGTH = 512K

The missing part: AXI_SRAM != SRAM3
SRAM1 (D2), SRAM2 (D2), SRAM3 (D2), SRAM4 (D3)
while AXI_SRAM (D1)
The different Domains have different clock speeds too …

There is even confusion about the names “RAM3”. Have you seen this:

The memory at 0x24000000 has a size of 512 KB and it is called AXI SRAM
"SRAM3 has a differente address: 0x30040000 with a size of 128 KB.

SRAM3 length = 0x30047fff - 0x30040000 = 0x7fff = 32kB
AXI_SRAM length = 0x2407ffff - 0x24000000 = 0x7ffff = (524,287) 511kB

SRAM3 is always at 0x30040000, the documents anywhere it says, otherwise ?
(I am unable to see that. If so, it would be even more confusion)

Looking at the picture, it is indeed a long way from AXI to ETH, indeed through the D2toD1 AHB bridge.

Indeed.

I do keep myself a small definition comment set to keep myself a bit stable:
The comments from the datasheet itself. I think yesterday night, poring over, I saw on the ST forum also someone having a similar question about abusing the bridge.

The only problem, is when you use it in a real world scenario, when one finds that there seems to be that data at this location not appearing (Just like how you got late to office, due to a traffic congestion. You did appear at work, but you got delayed. But it would be easy for some to think that you did not appear for work!). But alas, that data got blocked on the bus, because there was some data transmitted on the Ethernet. At a later stage, that would be a very weird and hard to fix bug. Someone hops along, complaining to ST, chip is buggy, when I do this, data does not appear in memory, maybe memory has holes or something like that. It would be a painful issue for anyone to get a foothold on to. Better documentation, always does help. But what to do… (You ask for more, maybe they will say tomorrow, we are not going to give you any docs. This issue I had faced many times with driver development for peripherals in another lifetime. My simple prayer is that vendors do things in a positive mindset and not otherwise)

For convenience sake, I add it in here.

/**
 * STM32H743 Memory layout
 * ----------------------------------------
 * 0x20000000 - 0x2001FFFF	DTCM-RAM	<- Stack & Heap @(Size: 0x1ffff = 131071, 128kB)
 * 0x20020000 - 0x23FFFFFF	Reserved
 * 0x24000000 - 0x2407FFFF	AXI SRAM	<- Current IRAM2 @(Size: 0x7ffff, 524287, 511kB)
 * 0x24080000 - 0x2FFFFFFF	Reserved
 * 0x30000000 - 0x3001FFFF	SRAM1		<- (Size: 0x1ffff, 131,071, 128kB)
 * 0x30020000 - 0x3003FFFF	SRAM2		<- (Size: 0x1ffff, 131,071, 128kB)
 * 0x30040000 - 0x30047FFF	SRAM3		<- Current Rx/Tx Descriptors, Rx buffers (Size: 32767, 128kB)
 * 0x30048000 - 0x37FFFFFF	Reserved
 * 0x38000000 - 0x3800FFFF	SRAM4		<- (Size: 0xffff, 65535, 64kB)
 * 0x38010000 - 0x387FFFFF	Reserved
 * 0x38800000 - 0x38800FFF	Backup SRAM	<- NVRAM (Size: 0xfff, 4095, 4kB)
 * 0x38801000 - 0x3FFFFFFF	Reserved
 */
#define DTCM_RAM_beg		0x20000000	/* TCM RAM, for critical data/stk/heap; eg: ISR's */
#define DTCM_RAM_end		0x2001ffff
#define DTCM_RAM_siz		0x1ffff		/* 131,071 bytes */

#define D1_SRAM_AXI_beg		0x24000000	/* D1 domain */
#define D1_SRAM_AXI_end		0x2407ffff
#define D1_SRAM_AXI_siz		0x7ffff		/* 524,287 bytes */

#define D2_SRAM1_beg		0x30000000	/* D2 domain */
#define D2_SRAM1_end		0x3001ffff
#define D2_SRAM1_siz		0x1ffff		/* 131,071 bytes */

#define D2_SRAM2_beg		0x30020000	/* D2 domain */
#define D2_SRAM2_end		0x3003ffff
#define D2_SRAM2_siz		0x1ffff		/* 131,071 bytes */

#define D2_SRAM3_beg		0x30040000	/* D2 domain */
#define D2_SRAM3_end		0x30047fff
#define D2_SRAM3_siz		0x07fff		/*  32,767 bytes */

#define D3_SRAM4_beg		0x38000000	/* D3 domain */
#define D3_SRAM4_end		0x3800ffff
#define D3_SRAM4_siz		0x0ffff		/*  65,535 bytes */

#define SRAM4			(D3_SRAM4_siz + 1)
#define SRAM3			(D2_SRAM3_siz + 1)
#define SRAM2			(D2_SRAM2_siz + 1)
#define SRAM1			(D2_SRAM1_siz + 1)
#define SRAM_AXI		(D1_SRAM_AXI_siz + 1)

Thanks,

Manu

Thanks, Hein for all the good work. I struggled along the way had to butcher your repo. But I would like to share with the community the implementation on a Nucleo-H745ZI https://github.com/Huizies/NUCLEO-H745ZI-FreeRTOS-TPCIP.git

It uses the following for the LD Flash
/* Modification start */
.lwip_sec (NOLOAD) : {
. = ABSOLUTE(0x30040000);
*(.RxDecripSection)

. = ABSOLUTE(0x30040060);
*(.TxDecripSection)

. = ABSOLUTE(0x30040200);
*(.RxArraySection)

. = ABSOLUTE(0x30042000);
*(.TxArraySection) 

} >RAM_D2

/* Modification end */

Hi Heinrich,

Nice to see, you got it booted up well. Cheers!

Had a quick look, saw a small issue.
The linker scripts says this:

RAM_D1 (xrw)      : ORIGIN = 0x24000000, LENGTH = 512K
RAM_D2 (xrw)      : ORIGIN = 0x30000000, LENGTH = 288K
RAM_D3 (xrw)      : ORIGIN = 0x38000000, LENGTH = 64K

From what it “appears to be obvious” to me, RAM_D2 is a sum of D2_SRAM1 (128k), D2_SRAM2 (128k), D2_SRAM3 (32k) 128+128+32 =288k, which looks fine.

But, D2_SRAM1, D2_SRAM2, D2_SRAM3 are all independent, within the D2 domain.
ie, They have their own independent Clocks from AHB2:

If you enable all 3 clocks all the time, identically; Then everything is alright. But if one does think that it is one single memory location, enables only a single clock, this could likely entail long hours of debugging. This could be a pain.

In the belief that, I am looking at it correctly;
I think better would be to have it as 3 separate memories themselves, rather than as a single memory region, which would otherwise cause confusion to someone who is not careful enough ?
(As it is, the H7 is complex enough, making a variation to the documentation would be even more confusing.)

Just my thoughts. I do not want to sound a bit rude and short live your success-happiness moment, but thought that it would be in the best interest of all.

Thanks,

Manu

Hi Manu,

When you are right you are right. I have updated the git to reflect this. I used bits and pieces from the web and mainly from the NUCLEO-H743ZI LwIP_HTTP_Server_Netconn_RTOS example. I do not understand why STM does not have better documentation or comments in their code.

But thanks!

For this and the SAME70 thread: Are the most up to date drivers in the FreeRTOS+TCP Git repo? Where can we document the valuable information contained in these threads - do we also have demos in the Git repo for others to reference in the future?

Are the most up to date drivers in the FreeRTOS+TCP Git repo?

Yes, they are in Github freertos/freertos
The STM32Hx driver is still in PR #256

Where can we document the valuable information contained in
these threads

As for the drivers, I have started adding a readme.md to the new drivers. Those files should contain the information that we have gathered in this forum.

do we also have demos in the Git repo for others to reference
in the future?

I/we have testing projects for every driver. Those are mostly Makefile projects and they do some integration testing.
I have not yet found enough time to clean up those projects and put them somewhere on Github.

For the STM32H7xx I used a projects that was initially created by Cube.

Hi Heinrich,

You are not the only one and alone, finding the documentation a bit terse at some places, while it explains something to a level of confusion. Some days, I’ve had splitting headaches, trying to get a proper foothold on the logic. If you ask Hein, I bet he will also likely say something similar.

I am happy that you found my comments useful.

Thanks,

Manu

Hi all,

This is very exciting, as I am trying to run the FreeRTOS+TCP stack on a STM32H743 Nucleo board (firmware dev testing for a PCB).

I’ve been having trouble with figuring out how a full project is supposed to be structured, as I can’t really find any full examples online (even the project posted above doesn’t seem to have a main that I can look at to see what is called).

This is my attempt at initializing the TCP stack, but I don’t see the device in ARP and cannot ping it.

Here is my main():

// Initialize GPIOs for Ethernet here
FreeRTOS_IPInit( ucIPAddress,
                 ucNetMask,
                 ucGatewayAddress,
                 ucDNSServerAddress,
                 ucMACAddress );
vTaskStartScheduler();
for(;;) {}

Any help would be much appreciated. I’m very new to the FreeRTOS ecosystem so I’m not 100% familiar with the intricacies.

Thank you