Skip to main content
Graduate
March 25, 2025
Solved

lwip on CM4 STM32h745

  • March 25, 2025
  • 1 reply
  • 778 views

Hello, 

I am trying to setup the CM4 core with lwip+mbedtls working. Actually I get this code working on CM7 but I need to migrate it to CM4. When I run the code the CM4 get a ard fault interrupt. Debuging I can see that this happens in HAL_MPU_Enable in the line SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;

I thing that this happens because a wrong configuration of memories and/or MPU. I'm not familiar with memory management in microcontrollers and I'm feeling lost.

The MPU configuration is:

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

 /* Disables the MPU */
 HAL_MPU_Disable();

 /** Initializes and configures the Region and the memory to be protected
 */
 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);

 /** Initializes and configures the Region and the memory to be protected
 */
 MPU_InitStruct.Number = MPU_REGION_NUMBER1;
 MPU_InitStruct.BaseAddress = 0x10020000;
 MPU_InitStruct.Size = MPU_REGION_SIZE_128KB;
 MPU_InitStruct.SubRegionDisable = 0x0;
 MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
 MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;

 HAL_MPU_ConfigRegion(&MPU_InitStruct);

 /** Initializes and configures the Region and the memory to be protected
 */
 MPU_InitStruct.Number = MPU_REGION_NUMBER2;
 MPU_InitStruct.BaseAddress = 0x10040000;
 MPU_InitStruct.Size = MPU_REGION_SIZE_512B;
 MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
 MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
 MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
 MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;

 HAL_MPU_ConfigRegion(&MPU_InitStruct);
 /* Enables the MPU */
 HAL_MPU_Enable(MPU_HFNMI_PRIVDEF_NONE);

}

And the STM32H745XIHX_FLASH.ld file:

/* Entry Point */
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */

/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08100000, LENGTH = 1024K
RAM_D2 (xrw) : ORIGIN = 0x10000000, LENGTH = 288K
}
..............
..............
 .data :
 {
 . = ALIGN(4);
 _sdata = .; /* create a global symbol at data start */
 *(.data) /* .data sections */
 *(.data*) /* .data* sections */
 *(.RamFunc) /* .RamFunc sections */
 *(.RamFunc*) /* .RamFunc* sections */

 . = ALIGN(4);
 _edata = .; /* define a global symbol at data end */
 } >RAM AT> FLASH


 /* Uninitialized data section */
 . = ALIGN(4);
 .bss :
 {
 /* This is used by the startup in order to initialize the .bss section */
 _sbss = .; /* define a global symbol at bss start */
 __bss_start__ = _sbss;
 *(.bss)
 *(.bss*)
 *(COMMON)

 . = ALIGN(4);
 _ebss = .; /* define a global symbol at bss end */
 __bss_end__ = _ebss;
 } >RAM

 /* User_heap_stack section, used to check that there is enough RAM left */
 ._user_heap_stack :
 {
 . = ALIGN(8);
 PROVIDE ( end = . );
 PROVIDE ( _end = . );
 . = . + _Min_Heap_Size;
 . = . + _Min_Stack_Size;
 . = ALIGN(8);
 } >RAM

.lwip_sec (NOLOAD) :
 {
 . = ABSOLUTE(0x10040000);
 *(.RxDecripSection)

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

 . = ABSOLUTE(0x10040200);
 *(.Rx_PoolSection)
 } >RAM_D2

 

Please help.

    This topic has been closed for replies.
    Best answer by mƎALLEm

    Hello,

    1- I think the MPU you shared belongs to the Cortex-M7 which has no effects on Cortex-M4 memory attributes as each core has its own MPU. And no need for MPU configuration for CM4 side for LWIP as there is no cache.

    2- Another thing regarding your linker file:

    RAM_D2 (xrw) : ORIGIN = 0x10000000, LENGTH = 288K

    You set the region RAM_D2 to the sum of the SRAM1, SRAM2 and SRAM3 sizes but you are using SRAM3 for the Ethernet stuff! It could be an overlap between the stack and the Ethernet data. So set RAM_D2 size to 256K and leave SRAM3 for LWIP:

    RAM_D2 (xrw) : ORIGIN = 0x10000000, LENGTH = 256K

     

    1 reply

    mƎALLEmAnswer
    Technical Moderator
    March 25, 2025

    Hello,

    1- I think the MPU you shared belongs to the Cortex-M7 which has no effects on Cortex-M4 memory attributes as each core has its own MPU. And no need for MPU configuration for CM4 side for LWIP as there is no cache.

    2- Another thing regarding your linker file:

    RAM_D2 (xrw) : ORIGIN = 0x10000000, LENGTH = 288K

    You set the region RAM_D2 to the sum of the SRAM1, SRAM2 and SRAM3 sizes but you are using SRAM3 for the Ethernet stuff! It could be an overlap between the stack and the Ethernet data. So set RAM_D2 size to 256K and leave SRAM3 for LWIP:

    RAM_D2 (xrw) : ORIGIN = 0x10000000, LENGTH = 256K

     

    RafaelSAuthor
    Graduate
    March 25, 2025

    Thank you @mƎALLEm. !

    1.- I actually thought I would have to copy the MPU configuration from CM7 to CM4, adapting the addresses. I disabled the MPU on CM4, and now the HardFault no longer occurs. I realize that I haven't fully understood the purpose of the MPU. Could you recommend me a document to help me understand it better?

    2.-  I don't understand why the memory configuration was changed from 288K to 256K. What I had understood is that memory that is not defined in the .ld file won't be used by the compiler. Is that correct? Or perhaps it is left undefined here so that it remains available for CM7?

     

    Best regards.

     

    Technical Moderator
    March 25, 2025

    Hello,

    1. I suggesr two documents:

    - AN4839 "Level 1 cache on stm32f7 series and stm32h7 series"

    -  AN4838 "Introduction to memory protection unit management on STM32 MCUs"

    2. "What I had understood is that memory that is not defined in the .ld file won't be used by the compiler. Is that correct?"

    That's correct. But in your linker file SRAM3 is defined in RAM_D2:

    SRAM1 (128kB) + SRAM2 (128kB) + SRAM3 (32kB) = 288kB which is the size declared in your linker file for RAM_D2 starting from the base address of SRAM1. And you are using SRAM3 for ETH descriptors which induced to an overlap between the data (stack etc..) and the ETH decriptor.

    mALLEm_0-1742932336075.png

    That's why you need to keep SRAM1 + SRAM2 i.e. 256kB for the application (RW data for CM4) and SRAM3 for LWIP i.e. 32kB.

    Hope it's clear now.