Skip to main content
Graduate II
September 1, 2025
Solved

Jumping and executing application code from SDRAM.

  • September 1, 2025
  • 3 replies
  • 612 views

Hello all, 

MCU: STM32H733ZG

I am facing issue as i am trying to jump from bootloader to the Application code which is located in the SDRAM. In the bootloader stage when the MCU receives the binary from OTA it is stored inside the External Flash. After receiving the binary image and storing it inside the External Flash, the image is copied from External Flash inside the SDRAM and then jumps to the application code. When it jumps to the application code, i open disassembly view and it starts running instructions stored inside the SDRAM until it reaches a specific address `0xC000150E` which is inside the `SystemInit` function. After calling the instruction at this address the disassembly closes up and a text of can not read register at `0xDEADBEE` appears.

image_2025-09-01_182022793.png

When checking the line located at this address and commenting that line which is this Screenshot 2025-09-01 171447.png

the problem persists at the same address of `0xC000150E` even though the previous line was commented out. It always crashes at this address. Kindly someone suggest what could be the issue? Why it always crash at this exact address.

Here is the disassembly before and after commenting that line

Zainulabedeen_0-1756732330890.png

Zainulabedeen_0-1756742697584.png

 

Here is my MPU configurations:

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 = 0x24000000;
 MPU_InitStruct.Size = MPU_REGION_SIZE_128KB;
 MPU_InitStruct.SubRegionDisable = 0x0;
 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_CACHEABLE;

 HAL_MPU_ConfigRegion(&MPU_InitStruct);

 /** Initializes and configures the Region and the memory to be protected
 */
 MPU_InitStruct.Number = MPU_REGION_NUMBER2;
 MPU_InitStruct.Size = MPU_REGION_SIZE_256B;
 MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
 MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;

 HAL_MPU_ConfigRegion(&MPU_InitStruct);

 /* Region 4: External Flash (OCTOSPI, 0x90080000 - 0x907FFFFF) now with Full Access (readable & writable)
 * This area is removed from Region 0 to apply the desired access rights here.
 */
 MPU_InitStruct.Enable = MPU_REGION_ENABLE;
 MPU_InitStruct.BaseAddress = 0x90000000;
 MPU_InitStruct.Size = MPU_REGION_SIZE_8MB;
 MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; // Read/Write access
 MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
 MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
 MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
 MPU_InitStruct.Number = MPU_REGION_NUMBER4;
 MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
 MPU_InitStruct.SubRegionDisable = 0x00;
 MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; // If XIP (code execution) is desired; otherwise MPU_INSTRUCTION_ACCESS_DISABLE
 HAL_MPU_ConfigRegion(&MPU_InitStruct);

 /* Configure the MPU attributes for SDRAM */
 MPU_InitStruct.Enable = MPU_REGION_ENABLE;
 MPU_InitStruct.BaseAddress = 0xC0000000; // Start address of SDRAM Bank 1
 MPU_InitStruct.Size = MPU_REGION_SIZE_8MB; // SDRAM size
 MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
 MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
 MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; // Currently MPU_ACCESS_CACHEABLE causes incorrect data
 MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
 MPU_InitStruct.Number = MPU_REGION_NUMBER3; // MPU region number
 MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
 MPU_InitStruct.SubRegionDisable = 0x00;
 MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
 HAL_MPU_ConfigRegion(&MPU_InitStruct);

 /* Enables the MPU */
 HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}

 

    This topic has been closed for replies.
    Best answer by Zainulabedeen

    I resolved it.

    I just needed to call 

    __enable_irq(); 

    after system SystemClock_Config(); in the application and it start working.

     

    One question, it seems if i configure something from the bootloader i can use inside my application even though i skip the HAL_Init(), SystemClock_Config()and all other peripheral initialization given that i configured it inside the bootloader. I can even toggle GPIO if i initialize it inside the Bootloader but then HAL_Delay() or anything related to timer does not work then. Can someone explain me why?

    Thanks a lot.

    3 replies

    Graduate II
    September 2, 2025

    Update i was able to execute from the SDRAM after commenting the Application SystemInit().

    But now the HAL_Delay() don't work however the configured peripherals works.

    Can someone explain why and how to fix it or systemInit is failing.

     

    I will be grateful Thanks.

    Super User
    September 2, 2025

     i was able to execute from the SDRAM after commenting the Application SystemInit().

    Very good.

    But now the HAL_Delay() don't work

    Maybe because the SystemInit() sets the interrupt vectors base address but it is no longer called.

    Set the address directly in your app main():

     extern int g_pfnVectors; /* defined in GCC startup_xxx.s */
     SCB->VTOR = (uint32_t)(uintptr_t)&g_pfnVectors;

    Or even better: copy the vectors from the app image in SDRAM to the internal SRAM (ITCRAM) for best performance.

    Super User
    September 3, 2025

    Be careful not to disturb the FMC, which is used for the SDRAM.

    Before JumpToApp (line 29) stop in the debugger and look at your app code in SDRAM (disassembly or dump): does it look sane?

    I tried adding __enable_irq() ... as suggested by @pavel A

    Sorry, I haven't suggested that. I've suggested to copy the vectors to the internal RAM (and point the VTOR there, of course)

     Should I only enable interrupts after HAL_Init()?

    No, because HAL_Init can call HAL_Delay, which won't work with disabled interrupts (unless you implement it without the tick interrupt).

     

    ZainulabedeenAuthorAnswer
    Graduate II
    September 4, 2025

    I resolved it.

    I just needed to call 

    __enable_irq(); 

    after system SystemClock_Config(); in the application and it start working.

     

    One question, it seems if i configure something from the bootloader i can use inside my application even though i skip the HAL_Init(), SystemClock_Config()and all other peripheral initialization given that i configured it inside the bootloader. I can even toggle GPIO if i initialize it inside the Bootloader but then HAL_Delay() or anything related to timer does not work then. Can someone explain me why?

    Thanks a lot.

    Super User
    September 4, 2025

    Set a breakpoint in TIM6_DAC_IRQHandler. Does it break there?