2025-09-01 6:26 AM - last edited on 2025-09-02 4:00 AM by mƎALLEm
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.
When checking the line located at this address and commenting that line which is this
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
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);
}
Solved! Go to Solution.
2025-09-04 3:06 AM
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.
2025-09-02 3:51 AM
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.
2025-09-02 7:56 AM - edited 2025-09-02 7:58 AM
> 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.
2025-09-02 8:14 AM
Hello @Zainulabedeen
Did you relocate the vector table offset address in systemInit().
2025-09-03 5:58 AM
I bypassed the SystemInit() function in the application, since the system was already initialized by the bootloader. Before jumping from the bootloader, I also relocated the vector table to SDRAM.
The reason for skipping SystemInit() in the application was that running it again caused crashes, as mentioned earlier. Because both the bootloader and application use the same clock configuration, there was no need to re-run SystemInit() in the application.
Here is my jump code:
static void jump_to_application(uint32_t address)
{
// Disable D/I Caches
SCB_DisableICache();
SCB_DisableDCache();
delay_us(50000);
__disable_irq();
for (uint8_t i = 0; i < 8; i++)
{
NVIC->ICER[i] = 0xFFFFFFFF;
}
for (uint8_t i = 0; i < 8; i++)
{
NVIC->ICPR[i] = 0xFFFFFFFF;
}
RCC->APB2RSTR |= RCC_APB2RSTR_SYSCFGRST;
RCC->APB2RSTR &= ~(RCC_APB2RSTR_SYSCFGRST);
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
SCB->VTOR = address;
SysTick->CTRL = 0x00;
SysTick->LOAD = 0x00;
SysTick->VAL = 0x00;
JumpToApp(address);
}
I’d appreciate a review of my setup to check if there are any mistakes.
I tried adding __enable_irq() at the very start of main() (before HAL_Init()), as suggested by @Pavel A. However, in this case the code never reached HAL_Delay(). Instead, it started making unexpected jumps around HAL_InitTick() and HAL_RCC_GetClockConfig(), and never progressed past HAL_Init(). It did, however, enter TIM6_DAC_IRQHandler(), which shows that interrupts were running correctly.
I’m using Timer 6 as the system timebase since I’m running an RTOS.
Can someone help me understand why this behavior occurs? Should I only enable interrupts after HAL_Init()? When I disable global interrupts before jumping from the bootloader, the code goes past HAL_Init() and into the HAL_Delay() I added. The issue with HAL_Delay() not working was simply because I had disabled global interrupts earlier.
FYI: @Pavel A.
2025-09-03 2:18 PM
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).
2025-09-04 3:06 AM
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.
2025-09-04 2:08 PM
Set a breakpoint in TIM6_DAC_IRQHandler. Does it break there?