cancel
Showing results for 
Search instead for 
Did you mean: 

lwip on CM4 STM32h745

RafaelS
Associate III

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.

1 ACCEPTED SOLUTION

Accepted Solutions
mƎALLEm
ST Employee

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

 

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

View solution in original post

3 REPLIES 3
mƎALLEm
ST Employee

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

 

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

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.

 

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.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.