Skip to main content
KMill
Senior
January 9, 2025
Solved

CubeIDE generates wrong/hard-fault parameters for LWiP on Nucleo-F746ZG

  • January 9, 2025
  • 4 replies
  • 2872 views

Steps to reproduce:

Start a new STM32 Project in STM32CubeIDE v1.17.0
Select NUCLEO-F746ZG board, and initailize all peripherals.
Now in the IOC editor, under Middleware select LwIP and enable it.
Set the PHY to LAN8742 in the "Platform Settings" tab.
On the Key Options tab set NO_SYS to OS Not Used.
In General Settings tab, disable DHCP, disable the TCP module and enable UDP.
Go back to Key Options tab and note that the "LWIP_RAM_HEAP_POINTER" is set to 0x30004000
Save, Build an run the project in debug mode.

The code will hard-fault during MX_LWiP_Init() because the RAM HEAP POINTER is wrong.

Now open the file at LWIP/Target/lwipopts.h
Note that at approximately line 58/59 there is:

 

 

 

 

/*----- Default Value for F7/H7 devices: 0x30044000 -----*/
#define LWIP_RAM_HEAP_POINTER 0x30004000

 

 

 

 

FIrst of all the comment doesn't match the value given, and even if you change the value given to the same as the comment (this is an F7 device after all) the code will still hard-fault.

If you comment out the #define the code will now build and run, but the number of ETH_RX_BUFFER_CNT buffers you can set in the IOC editor is very limited.

Also, if you make any changes at all to anything in the IOC editor, this line will get put back i and your code will hard-fault again.

 

Best answer by Sarra.S

Hello @KMill@OWLchan, and @z0ki 

Thank you all for your contributions, after discussion with dedicated team: 

The “LwIP_HTTP_Server_Netconn_RTOS” example provided for the NUCLEO-F746ZG board is setting LWIP_RAM_HEAP_POINTER to the value of 0x20048000 which is correct because: 

(LWIP_RAM_HEAP_POINTER + MEM_SIZE) <= (SRAM1_BASE + SRAM1_SIZE)

  • LWIP_RAM_HEAP_POINTER    = 0x20048000 (from the file lwipopts.h generated by CubeMX in our case)
  • MEM_SIZE                 = (16*1024) /* 0x4000 */  (from the file lwipopts.h generated by CubeMX in our case)
  • SRAM1_BASE               = 0x20001000 (from the RM or from file stm32f746xx.h)
  • SRAM1_SIZE               = (240*1024) /* 0x3C000 */  (from the RM or from file stm32f746xx.h)

So, the computing formula should be:

LWIP_RAM_HEAP_POINTER=(SRAM1_BASE + SRAM1_SIZE - MEM_SIZE)=( 0x20001000 + 0x3C000 + 0x4000)= 0x20048000

Minimal value is 1600 (from the lwIP mw opt.h file)

Max value for F7 is (SRAM1_BASE + SRAM1_SIZE – STACK_SIZE – HEAP_SIZE)

Max value for H7 is (D2_AHBSRAM_BASE + D2_AHBSRAM_SIZE – M4_STACK_SIZE – M4_HEAP_SIZE).

4 replies

ST Employee
January 9, 2025

Hello @KMill, you are right 

The default value causes a Hardfault as the address is in a reserved region:

SarraS_0-1736433773036.png

I'm creating an internal ticket to correct this (Internal ticket number: 200083) 

OWLchan
Associate III
January 10, 2025

thanks for saving my day, I'm using STM32CubeMX version '6.13.0' to generate code and got the error as you said above, I wonder if ST has fixed that error or has a guide because it's very inconvenient every time I generate code again.

and one thing I just discovered is that previous versions of STM32CubeMX don't seem to generate anything similar to #define LWIP_RAM_HEAP_POINTER 0x30004000

Screenshot 2025-01-10 150757.png

 


UPDATE: I found a way to fix this problem, just change the address of LWIP_RAM_HEAP_POINTER to sram
Screenshot 2025-01-10 153448.png

 

KMill
KMillAuthor
Senior
January 10, 2025

I too changed the value in that field to 0x20010000 (sram) but I was not confident in the fix, having drilled through the macros that LWiP uses.

As far as I could figure out, if LWIP_RAM_HEAP_POINTER is not defined, it will just allocate space for a variable of the required size, plus alignment. Thus leaving it up to the compiler to allocate scalar storage space from the heap. However if I define this to be the start of ram (where the heap would normally grow from) how do I know that there is nothing else using that location, or that the compiler hasn't alreay allocated space at that address?

Clearly I could be mis-reading this, but to me it looks like an arbitrarily chosen ram pointer, which the compiler would not be aware of. Please tell me I'm wrong so that I can have confidence in this!

OWLchan
Associate III
January 10, 2025

your comment is right but that is actually what is going on, i looked a little at :

 

 

 lwip_init();

 

 

it seems that function is using malloc to allocate memory on sram and using mutex to handle:

 

 

void
mem_init(void)
{
 struct mem *mem;

 LWIP_ASSERT("Sanity check alignment",
 (SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT - 1)) == 0);

 /* align the heap */
 ram = (u8_t *)LWIP_MEM_ALIGN(LWIP_RAM_HEAP_POINTER);
 /* initialize the start of the heap */
 mem = (struct mem *)(void *)ram;
 mem->next = MEM_SIZE_ALIGNED;
 mem->prev = 0;
 mem->used = 0;
 /* initialize the end of the heap */
 ram_end = ptr_to_mem(MEM_SIZE_ALIGNED);
 ram_end->used = 1;
 ram_end->next = MEM_SIZE_ALIGNED;
 ram_end->prev = MEM_SIZE_ALIGNED;
 MEM_SANITY();

 /* initialize the lowest-free pointer to the start of the heap */
 lfree = (struct mem *)(void *)ram;

 MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED);

 if (sys_mutex_new(&mem_mutex) != ERR_OK) {
 LWIP_ASSERT("failed to create mem_mutex", 0);
 }
}

 

 

my hypothesis is that allocating ram using pointer is only possible on F7|H7 line because they have MPU mechanism. not sure if i am right but they say this helps prevent fragmentation and is faster than heap:

/**
 * @file
 * Dynamic memory manager
 *
 * This is a lightweight replacement for the standard C library malloc().
 *
 * If you want to use the standard C library malloc() instead, define
 * MEM_LIBC_MALLOC to 1 in your lwipopts.h
 *
 * To let mem_malloc() use pools (prevents fragmentation and is much faster than
 * a heap but might waste some memory), define MEM_USE_POOLS to 1, define
 * MEMP_USE_CUSTOM_POOLS to 1 and create a file "lwippools.h" that includes a list
 * of pools like this (more pools can be added between _START and _END):
 *
 * Define three pools with sizes 256, 512, and 1512 bytes
 * LWIP_MALLOC_MEMPOOL_START
 * LWIP_MALLOC_MEMPOOL(20, 256)
 * LWIP_MALLOC_MEMPOOL(10, 512)
 * LWIP_MALLOC_MEMPOOL(5, 1512)
 * LWIP_MALLOC_MEMPOOL_END
 */

 

Explorer II
January 10, 2025

ahhh I can't believe it, thank you so much @KMill for opening this post! I'm new to STM32 and spent 2 days searching for the error! 

I searched for "ethernet hard fault" and "F767ZI hard fault" but nothing showed up, until I dug so deep that I discovered the fault myself and then found this post.

Is it somehow possible to make the post show when searching  "ethernet hard fault" and "F767ZI hard fault" (sth like a knowledge post) or sth like this in order to avoid other people having to spent this much time as well? 

Sarra.SBest answer
ST Employee
January 13, 2025

Hello @KMill@OWLchan, and @z0ki 

Thank you all for your contributions, after discussion with dedicated team: 

The “LwIP_HTTP_Server_Netconn_RTOS” example provided for the NUCLEO-F746ZG board is setting LWIP_RAM_HEAP_POINTER to the value of 0x20048000 which is correct because: 

(LWIP_RAM_HEAP_POINTER + MEM_SIZE) <= (SRAM1_BASE + SRAM1_SIZE)

  • LWIP_RAM_HEAP_POINTER    = 0x20048000 (from the file lwipopts.h generated by CubeMX in our case)
  • MEM_SIZE                 = (16*1024) /* 0x4000 */  (from the file lwipopts.h generated by CubeMX in our case)
  • SRAM1_BASE               = 0x20001000 (from the RM or from file stm32f746xx.h)
  • SRAM1_SIZE               = (240*1024) /* 0x3C000 */  (from the RM or from file stm32f746xx.h)

So, the computing formula should be:

LWIP_RAM_HEAP_POINTER=(SRAM1_BASE + SRAM1_SIZE - MEM_SIZE)=( 0x20001000 + 0x3C000 + 0x4000)= 0x20048000

Minimal value is 1600 (from the lwIP mw opt.h file)

Max value for F7 is (SRAM1_BASE + SRAM1_SIZE – STACK_SIZE – HEAP_SIZE)

Max value for H7 is (D2_AHBSRAM_BASE + D2_AHBSRAM_SIZE – M4_STACK_SIZE – M4_HEAP_SIZE).

KMill
KMillAuthor
Senior
January 13, 2025

@Sarra.S Thank you for this detailed response!