cancel
Showing results for 
Search instead for 
Did you mean: 

NUCLEO-H753ZI - SBSFU seems to not jump correctly on my user app (Watchdog reset error)

KLedi.2
Associate II

Hello,

I want to implement my own UserApp (just a blinking LED for the moment but it will implement FreeRTOS and LwIP in future) on Nucleo-H753ZI. I followed Youtube tutorials for SBSFU especially Security Part6 - 04 Experience SBSFU benefits. Then, I managed to run successfully the SBSFU example like in Security Part6 - 02 Building the SBSFU.

I made my linker script like this:

/* Entry Point */
ENTRY(Reset_Handler)
 
/* Highest address of the user mode stack */
_estack = ORIGIN(RAM_D1) + LENGTH(RAM_D1);	/* end of "RAM_D1" Ram type memory */
 
_Min_Heap_Size = 0x200 ;	/* required amount of heap  */
_Min_Stack_Size = 0x800 ;	/* required amount of stack */
 
/* Memories definition */
MEMORY
{
  ITCMRAM    (xrw)    : ORIGIN = 0x00000000,   LENGTH = 64K
  RAM_D1    (xrw)    : ORIGIN = 0x24000000,   LENGTH = 512K
  RAM_D2    (xrw)    : ORIGIN = 0x30000000,   LENGTH = 288K
  RAM_D3    (xrw)    : ORIGIN = 0x38000000,   LENGTH = 64K
  ISR_VECTOR (rx)   : ORIGIN = 0x8020000 + 0x400, LENGTH = 0x400
  FLASH    (rx)    : ORIGIN = 0x8020000 + 0x800,   LENGTH = 0x8100000 - 0x8020800
}
 
/* Sections */
SECTIONS
{
  /* The startup code into "FLASH" Rom type memory */
  .isr_vector :
  {
    . = ALIGN(8);
    KEEP(*(.isr_vector)) /* Startup code */
    FILL(0);
    . = ORIGIN(ISR_VECTOR) + LENGTH(ISR_VECTOR) - 1;
    BYTE(0)
    . = ALIGN(8);
  } >ISR_VECTOR
  
  /* The program code and other data into "FLASH" Rom type memory */
  .text :
  {
    . = ALIGN(8);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)
 
    KEEP (*(.init))
    KEEP (*(.fini))
 
    . = ALIGN(8);
    _etext = .;        /* define a global symbols at end of code */
  } >FLASH
 
  /* Constant data into "FLASH" Rom type memory */
  .rodata :
  {
    . = ALIGN(8);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    . = ALIGN(8);
  } >FLASH
 
  .ARM.extab   : {
    . = ALIGN(8);
    *(.ARM.extab* .gnu.linkonce.armextab.*)
    . = ALIGN(8);
  } >FLASH
 
  .ARM : {
    . = ALIGN(8);
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
    . = ALIGN(8);
  } >FLASH
 
  .preinit_array     :
  {
    . = ALIGN(8);
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
    . = ALIGN(8);
  } >FLASH
 
  .init_array :
  {
    . = ALIGN(8);
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
    . = ALIGN(8);
  } >FLASH
 
  .fini_array :
  {
    . = ALIGN(8);
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
    . = ALIGN(8);
  } >FLASH
 
  /* Used by the startup to initialize data */
  _sidata = LOADADDR(.data);
 
  /* Initialized data sections into "RAM_D1" Ram type memory */
  .data :
  {
    . = ALIGN(8);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */
    /**(.RamFunc)*/        /* .RamFunc sections */
    /**(.RamFunc*)*/       /* .RamFunc* sections */
 
    . = ALIGN(8);
    _edata = .;        /* define a global symbol at data end */
 
  } >RAM_D1 AT> FLASH
  
   /* Extra ROM section (last one) to make sure the binary size is a multiple of the AES block size (16 bytes) and H7 flash writing unit (32 bytes)*/
  .align32 :
  {
    . = . + 1;         /* _edata=. is aligned on 8 bytes so could be aligned on 32 bytes: add 1 byte gap */
    . = ALIGN(32) - 1; /* increment the location counter until next 32 bytes aligned address (-1 byte)   */
    BYTE(0);           /* allocate 1 byte (value is 0) to be a multiple of 32 bytes                      */
  } > FLASH
 
  /* Uninitialized data section into "RAM_D1" Ram type memory */
  . = 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_D1
 
  /* User_heap_stack section, used to check that there is enough "RAM_D1" Ram  type memory left */
  ._user_heap_stack :
  {
    . = ALIGN(8);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  } >RAM_D1
 
  /* Remove information from the compiler libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }
 
  .ARM.attributes 0 : { *(.ARM.attributes) }
}

I also defined VECT_TAB_OFFSET in system_stm32h7xx.c like this:

#define VECT_TAB_OFFSET  0x08020400

Here my main function:

int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MPU Configuration--------------------------------------------------------*/
  MPU_Config();
 
  /* Enable I-Cache---------------------------------------------------------*/
  SCB_EnableICache();
 
  /* Enable D-Cache---------------------------------------------------------*/
  SCB_EnableDCache();
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ETH_Init();
  MX_SPI1_Init();
  /* USER CODE BEGIN 2 */
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
	  IWDG1->KR = IWDG_KEY_RELOAD;
	  HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
	  HAL_Delay(50);
  }
  /* USER CODE END 3 */
}

I manage to build the binary with the SBSFU and my app. SBSFU accepts my app and try to run it until Watchdog reset error. The LED never blinks. Then, it seems that SBSFU jump to my app does not work as I expect.

Regards

Kevyn

7 REPLIES 7
Jocelyn RICARD
ST Employee

Hi Kevyn,

I don't see obvious reason for your issue from your code.

I guess you didn't change the slots mapping.

I would suggest deactivating the protections in the app_sfu.h and check with debugger what happens.

Best regards

Jocelyn

KLedi.2
Associate II

Hello Jocelyn,

Thank you for your answer and your help.

If I remove Ethernet connectivity it is working ! Same thing, if I remove MPU protection from app_sfu.h. It seems then there is a conflict between Ethernet connectivity and MPU protection.

Here my Ethernet connectivity configuration:

0693W000008z500QAA.png 

0693W000008z4lHQAQ.png0693W000008z51cQAA.pngHave you any idea of the reason of the conflict ? Thank you.

Regards

Kevyn

Hello!

have you solved this issue? I am facing the same problem with the ethernet and watchdog reset!

Thanks

Hello

Yes, I have solved this issue. I did several things to make it works.

Firstly, I moved MPU_Config and the Cache activation on USER CODE 2

/* USER CODE BEGIN 2 */  
  MPU_Config();
  SCB_EnableICache();
  SCB_EnableDCache();
/* USER CODE END 2 */

I also disabled ICache and DCache in sfu_mpu_isolation.c

#if defined(SFU_MPU_PROTECT_ENABLE)
      SCB_InvalidateICache();
      SCB_CleanDCache();
      SCB_DisableICache();
      SCB_DisableDCache();
#endif /* SFU_MPU_PROTECT_ENABLE */

And I have this MPU Config in my app for LwIP on SRAM2

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 = 0x30040000;
  MPU_InitStruct.Size = MPU_REGION_SIZE_256B;
  MPU_InitStruct.SubRegionDisable = 0x0;
  MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
  MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
  MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
  MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
  MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
  MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
 
  HAL_MPU_ConfigRegion(&MPU_InitStruct);
  /** Initializes and configures the Region and the memory to be protected
  */
  MPU_InitStruct.Enable = MPU_REGION_ENABLE;
  MPU_InitStruct.Number = MPU_REGION_NUMBER1;
  MPU_InitStruct.BaseAddress = 0x30044000;
  MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;
  MPU_InitStruct.SubRegionDisable = 0x0;
  MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
  MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
  MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
  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);
 
  MPU_InitStruct.Enable = MPU_REGION_DISABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER2;
 
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
 
  MPU_InitStruct.Enable = MPU_REGION_DISABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER3;
 
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
 
    MPU_InitStruct.Enable = MPU_REGION_DISABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER4;
 
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
 
    MPU_InitStruct.Enable = MPU_REGION_DISABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER5;
 
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
 
    MPU_InitStruct.Enable = MPU_REGION_DISABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER6;
 
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
 
    MPU_InitStruct.Enable = MPU_REGION_DISABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER7;
 
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
 
    MPU_InitStruct.Enable = MPU_REGION_DISABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER8;
 
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
 
    MPU_InitStruct.Enable = MPU_REGION_DISABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER9;
 
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
 
    MPU_InitStruct.Enable = MPU_REGION_DISABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER10;
 
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
 
    MPU_InitStruct.Enable = MPU_REGION_DISABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER11;
 
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
 
    MPU_InitStruct.Enable = MPU_REGION_DISABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER12;
 
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
 
    MPU_InitStruct.Enable = MPU_REGION_DISABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER13;
 
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
 
    MPU_InitStruct.Enable = MPU_REGION_DISABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER14;
 
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
 
    MPU_InitStruct.Enable = MPU_REGION_DISABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER15;
 
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
  /* Enables the MPU */
  HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

I imagine there is a better way to do it (not sure that everything is required to make it works) but it works for me. I hope it will help you.

Regards

Kevyn

Hello!

thank you for your information, but your solution unfortunately has not solved my issue, I have seen that before these changes if you had disabled the MPU protection in app_sfu.h the board is functioning even though the ethernet is on; this is not valid for me so maybe there is something different that breaks the FW.

I have created a dedicated thread if you want to see more details

Thanks!

alister
Lead

>I made my linker script like this

These are not stopping this code from working. Just areas for improvement.

  • Line 2. Your boot code doesn't use this. It pulls the entry point from the app's reset vector and jumps there. Its vector table is its API to the boot code. Its source code populated the reset vector as Reset_Handler. This ENTRY does nothing useful and should be removed.
  • Line 27. This ALIGN should not be required. Why would the ISR_VECTOR memory region be incorrect?
  • Line 131 Assigning the output location counter (.) here is mostly harmless, but useless. If the previous output section to RAM_DA had left its location aligned less than 4, and ignoring that the linker may ensure output sections are appropriately aligned, then _sbss would be aligned that. This ALIGN should be immediately before _sbss's assignment at line 135.

>I also defined VECT_TAB_OFFSET in system_stm32h7xx.c like this

Another area for improvement.

Your linker script describes where things are located.

Add a symbol in your .isr_vector output section immediately before its loading the .isr_vector input section:

isr_vector_start = .

Then declare that and use its address in your .c:

extern uint32_t isr_vector_start;

#define VECT_TAB_OFFSET ((uint32_t)&isr_vector_start)

>Here my main function

That should be fine.

>Yes, I have solved this issue. I did several things to make it works.

I cannot see the root cause of the problem from your changes.

Perhaps post the boot source code that launches your app.

Without your changes, does the app work if you load and execute it the debugger, i.e. without the SBSFU? To test that decisively, erase your boot code's sector in STM32CubeProgrammer before debugging the app.

>And I have this MPU Config in my app for LwIP on SRAM2

Post the value your SBSFU configures the MPU_CTRL register.

See https://developer.arm.com/documentation/dui0646/c/cortex-m7-peripherals/optional-memory-protection-unit/updating-an-mpu-region or ST's PM0253. A region should be disabled before writing new settings if it has been previously configured.

Also note MPU registers are accessible in privileged mode only.

Hello! is the Ethernet workin after these changes?