cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H723VGT6 + ETH + LWIP: Error pbuf_alloc and ETH DMAErrorCode 0x4080

phamtutailtvm
Associate II

Post edited by ST moderator to be inline with the community rules especially with the code sharing. In next time please use </> button to paste your code. Please read this post: How to insert source code.

Hi all,

I am working with STM32H723VGT6, using ETH and SPI4.

I have configured Ethernet following this ST Community guide:
https://community.st.com/t5/stm32-mcus/how-to-create-a-project-for-stm32h7-with-ethernet-and-lwip-stack/ta-p/49308

When I follow the instructions exactly, I noticed that memp_memory_RX_POOL_base is located at 0x24000000.

Current problem

When running my program, the crash occurs at:

struct pbuf *q;
q = pbuf_alloc(PBUF_TRANSPORT, length, PBUF_RAM);

Inside pbuf_alloc, in the case PBUF_RAM:

p = (struct pbuf *)mem_malloc(alloc_len);

 

In mem_malloc, the program fails at:

/* Scan through the heap searching for a free block that is big enough */
for (ptr = mem_to_ptr(lfree); ptr < MEM_SIZE_ALIGNED - size;
ptr = ptr_to_mem(ptr)->next) {
mem = ptr_to_mem(ptr);
}

Although mem is allocated with the LWIP heap pointer address successfully, at the same time, ETH->DMAErrorCode reports 0x4080.

What I have configured

  • I have set up MPU regions for DMA descriptors and LWIP RAM heap.

  • RX pool is located in D1 SRAM (0x24000000).

  • DMA descriptors are in D2 SRAM (0x30000000 onwards).

  • LWIP RAM heap pointer for TX buffers is set correctly in D2 SRAM.

Observations

  • The crash seems related to mem_malloc scanning the heap, possibly because of DMA or MPU configuration.

  • ETH DMA fails immediately with code 0x4080 when trying to allocate pbuf.

Files attached

  • main.c with MPU configuration

  • Screenshots showing memory map and error

  • Other relevant configuration

Questions  

  1. Is it safe to locate memp_memory_RX_POOL_base in D1 SRAM (0x24000000) on STM32H723?

  2. Should RX pool be moved to D2 SRAM, even if only 32 KB is available? How to divide RX descriptors, RX pool, and TX heap safely?

  3. Are there known issues with mem_malloc + pbuf_alloc when using D1 SRAM + DMA ETH on H723?

Any guidance or suggestions will be highly appreciated!

Thanks,

z7022415138318_53a4ba9ef2a8800c838796943092a048.jpg

z7022403546046_2400ad221a721cad087ab732fae8b8da.jpg

z7022405348900_284cad205d7a6ee56e6b91a70d6989ca.jpg

z7022406758162_ce3601a00c2d406fbcddef932d4bfdee.jpg

z7022408559660_beeb34be33d51a1390d129f00e20d067.jpg

z7022414328393_290b6b67e8b28a3feac63785e9170180.jpg

4 REPLIES 4
STackPointer64
ST Employee

Hello, and welcome to ST community!

Have you ensured that the memory sections for the descriptors and memory pool are properly configured in the linker file? Also, please verify that the address of the LwIP heap pointer in your lwipopts.h aligns with your configuration. Additionally, could you attach a screenshot of the call stack when the HardFault occurs?

Best regards,

To improve visibility of answered topics, please click 'Accept as Solution' on the reply that resolved your issue or answered your question.

Hello,

I have checked the addresses of the related buffers:

DMARxDscrTab: 0x30000000
DMATxDscrTab: 0x30000100
memp_memory_RX_POOL_base: 0x24003460

In lwipopts.h I configured:

#define LWIP_RAM_HEAP_POINTER 0x30000200
#define MEM_SIZE 32232

For the MPU configuration, I am using the following setup:

void MPU_Config(void)
{
MPU_Region_InitTypeDef MPU_InitStruct = {0};

HAL_MPU_Disable();

// Region 0: default no access //
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.BaseAddress = 0x0;
MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
MPU_InitStruct.SubRegionDisable = 0x87;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);

// Region 1: descriptors in D2 SRAM //
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.BaseAddress = 0x30000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_32KB;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);

// Region 2: small buffer region //
MPU_InitStruct.Number = MPU_REGION_NUMBER2;
MPU_InitStruct.Size = MPU_REGION_SIZE_512B;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);

// Region 3: D1 SRAM (disabled in current config) //
MPU_InitStruct.Number = MPU_REGION_NUMBER3;
MPU_InitStruct.BaseAddress = 0x24000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_32KB;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
//HAL_MPU_ConfigRegion(&MPU_InitStruct);

HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}

When I set a breakpoint inside HAL_ETH_ReadData, the execution reaches HAL_ETH_RxLinkCallback but then fails with a DMAErrorCode.
If I do not set any breakpoint, there is no error, but the board does not respond to pings.

From Wireshark, I can see that the PC sends ARP requests to the STM32, but the STM32 does not reply.

My LWIP network configuration is as follows:

IP_ADDRESS: 192.168.1.198
NETMASK: 255.255.255.0
GATEWAY: 192.168.1.1

On my PC I am using:
IP_ADDRESS: 192.168.1.68
NETMASK: 255.255.255.0
GATEWAY: 192.168.1.1

The firewall on the PC is disabled.

In the main loop I call the following:

while (1)
{
ethernetif_input(&gnetif);
sys_check_timeouts();
}

Could you please advise if there is anything wrong with the current MPU or memory configuration, or if additional steps are required for proper Ethernet RX/TX operation?

Best regards,

phamtutailtvm_0-1758167995290.png

phamtutailtvm_1-1758168186164.png

 

I would like to add my linker script configuration. In this file I assigned the addresses for RxDecripSection and TxDecripSection.

I also added in D1 RAM

. = ALIGN(32);
*(.Rx_PoolSection)
LCE
Principal II

I don't know about the absolute.

I do it this way (also on H723 / H733), with only one descriptor section for both RX & TX:

...

0/* internal */
	SRAXI_D1(xrw)		: ORIGIN = 0x24000000, LENGTH = 320K
	SRAM1_D2(xrw)		: ORIGIN = 0x30000000, LENGTH = 16K
	SRAM2_D2(xrw)		: ORIGIN = 0x30004000, LENGTH = 16K
	SRAM4_D3(xrw)		: ORIGIN = 0x38000000, LENGTH = 16K			

...

/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* ethernet descriptor section */
/* MUST be in RAM_D2 */

	.EthDescrSection (NOLOAD):
	{
		. = ALIGN(4);
		*(.EthDescrSection)
		*(.EthDescrSection*)
		. = ALIGN(4);
	} >SRAM1_D2

Then I like to use some macros to place the descriptors there in the *.c file:

somewhere in main.h:
/* alignment */
#define __ATT_PACKED				__attribute__((packed))
#define __ATT_ALIGN4				__attribute__((aligned(4)))
#define __ATT_ALIGN8				__attribute__((aligned(8)))
#define __ATT_ALIGN16				__attribute__((aligned(16)))

/* RAM sections
 *	as defined in linker file *.ld
 *		make sure that the peripheral using the variables
 *		can access this memory section / domain
 */
#define __ATT_SECT_RAMD1		__attribute__((section(".RamD1Section")))
#define __ATT_SECT_NOINIT		__attribute__((section(".NoInitSection")))

#define __ATT_SECT_A2IPCTL		__attribute__((section(".A2IpCtlSection")))
#define __ATT_SECT_C2IPCTL		__attribute__((section(".C2IpCtlSection")))
#define __ATT_SECT_A2IPBUFX		__attribute__((section(".A2IpBufExtSection")))

#define __ATT_SECT_LWIPPOOL		__attribute__((section(".LwipPoolSection")))
#define __ATT_SECT_LWIPHEAP		__attribute__((section(".LwipHeapSection")))

#define __ATT_SECT_ETHTXBUF		__attribute__((section(".EthTxBufSection")))
#define __ATT_SECT_ETHDESCR		__attribute__((section(".EthDescrSection")))

... and finally:

/* DESCRIPTOR lists:
 * 		DESC0 .. DESC7 (status, control, addresses, PTP timestamp)
 * 		aligned
 * 		in dedicated RAM section (see linker script)
 */
/* TX */
__ATT_SECT_ETHDESCR __ATT_ALIGN4 EthDmaDescr_t DmaTxDescriptors[ETH_TX_DESC_CNT];
/* RX */
__ATT_SECT_ETHDESCR __ATT_ALIGN4 EthDmaDescr_t DmaRxDescriptors[ETH_RX_DESC_CNT];

 

Anyway, it looks more like you don't free the RX buffers fast enough / at all.

I'd first try to increase the RX buffer pool, install some counters and debug info where I'm at.

And look for any buffers which might "hang" somewhere without getting free.

 

PS: each time I see "Decrip" it gives me the crips -er, creeps I mean.
Just because some years ago an ST guy forgot the "s", everybody's keeping that. Makes me rather think of decryption than descriptor.