2026-05-29 2:57 AM - last edited on 2026-06-01 4:45 AM by FBL
Hello all!
Actually i am trying to use USB DFU mode of STM32H533RE Nucleo board.
I can able to enter DFU mode by using BOOT0 pin but the intention is to do software method of entering into USB DFU. After doing a lot of research on web and using some AI tools below is the code i got.
For the better understanding:
I am using USB CDC and whenever it recevies DFU over USB i am calling this function to enter to DFU mode.
void JumpToUSB_DFU(void)
{
/* Called from main() BEFORE HAL_Init() — after a software reset where
* Enter_DFU_Bootloader() already cleanly stopped USB and waited 300 ms.
* After SYSRESET: all peripherals are reset, hpcd_USB_DRD_FS.Instance = NULL. */
/* 1. Disable all interrupts globally */
__disable_irq();
/* 2. Disable ICACHE directly via register — MUST be done BEFORE disabling SysTick.
* ICACHE state persists through software reset. If we call HAL_ICACHE_Disable()
* after SysTick is off, it hangs in a HAL_GetTick() timeout loop forever. */
ICACHE->CR &= ~ICACHE_CR_EN;
/* Wait for ICACHE to go idle using a simple poll (no SysTick needed) */
uint32_t icache_timeout = 0x00FFFFFFUL;
while ((ICACHE->SR & ICACHE_SR_BUSYF) && (icache_timeout-- > 0)) { __NOP(); }
/* 3. Disable SysTick timer */
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
/* 4. Clear all pending NVIC interrupt requests */
for (uint8_t i = 0; i < 8; i++) {
NVIC->ICER[i] = 0xFFFFFFFF;
NVIC->ICPR[i] = 0xFFFFFFFF;
}
/* -----------------------------------------------------------------------
* 5. CRITICAL: Enable VDDUSB power domain for the bootloader.
* After SYSRESET, PWR_USBSCR.USB33DEN resets to 0 (disabled).
* The STM32H533 ROM bootloader does NOT enable this itself.
* Without VDDUSB, the USB transceiver has no power and USB DFU
* silently fails to enumerate — this is the most common failure mode.
* HAL_PWREx_EnableVddUSB() just sets one register bit; safe here.
* ----------------------------------------------------------------------- */
HAL_PWREx_EnableVddUSB();
/* Short NOP delay for the USB 3.3V supply to stabilize (~100 us @ 64 MHz) */
for (volatile uint32_t i = 0; i < 6400UL; i++) { __NOP(); }
/* -----------------------------------------------------------------------
* 6. CRITICAL: Ensure HSI48 is ON and stable.
* The bootloader needs HSI48 for its CRS-synchronized USB clock.
* After SYSRESET it may be OFF; turn it on and wait for lock.
* ----------------------------------------------------------------------- */
SET_BIT(RCC->CR, RCC_CR_HSI48ON);
uint32_t hsi48_timeout = 200000UL;
while (!(RCC->CR & RCC_CR_HSI48RDY) && (hsi48_timeout-- > 0U)) { __NOP(); }
/* 7. Find the bootloader base address automatically.
* The exact System Memory base for STM32H533 is not reliably defined in
* all HAL versions (varies between 0x0BF80000, 0x0BF90000, 0x0BF97000).
* We scan the 0x0BF80000 - 0x0BFA0000 range for a valid vector table. */
uint32_t bootloader_base = 0;
uint32_t bootloader_sp = 0;
uint32_t bootloader_pc = 0;
for (uint32_t addr = 0x0BF80000UL; addr < 0x0BFA0000UL; addr += 0x1000UL)
{
uint32_t sp = *((volatile uint32_t*)addr);
uint32_t pc = *((volatile uint32_t*)(addr + 4));
/* Valid Vector Table signature:
* 1. SP points inside SRAM (STM32H533 RAM is 0x20000000 to 0x20044000)
* 2. PC points somewhere inside the ROM bootloader memory itself */
if ((sp >= 0x20000000UL) && (sp <= 0x20050000UL) &&
(pc > addr) && (pc < (addr + 0x10000UL)))
{
bootloader_base = addr;
bootloader_sp = sp;
bootloader_pc = pc;
break;
}
}
if (bootloader_base == 0)
{
/* Bootloader not found. Reboot to app to avoid hard fault. */
HAL_NVIC_SystemReset();
while (1);
}
/* 8. Small NOP delay (~100 ms at ~64 MHz HSI) — ensures host USB stack
* has fully processed the prior disconnect before DFU re-enumerates. */
for (volatile uint32_t i = 0; i < 6400000UL; i++) { __NOP(); }
/* 9. CRITICAL: Clear Reset Flags!
* If the ROM bootloader sees the Software Reset flag (SFTRSTF) in RCC->RSR,
* it assumes a fault occurred and immediately jumps back to Flash.
* We must clear it so the bootloader acts like it was a fresh power-on. */
RCC->RSR |= RCC_RSR_RMVF;
/* 10. Set the Vector Table Offset Register to System Memory */
SCB->VTOR = bootloader_base;
__DSB(); /* Data Sync Barrier — ensure VTOR write completes before jump */
__ISB(); /* Instruction Sync Barrier — flush pipeline */
/* 11. Set Main Stack Pointer and branch to bootloader Reset Handler */
__asm volatile (
"msr msp, %0\n\t"
"bx %1\n\t"
:
: "r" (bootloader_sp),
"r" (bootloader_pc)
: "memory"
);
/* The CPU should never reach this point */
while (1);
}
But it is not going into DFU mode at all.
It is just resetting the board. What am I missing here? If someone has faced the same issue, it would be great to help me resolve this
2026-06-01 4:44 AM
Hi @Sumanth_M_N
Thank you for sharing your DFU implementation details. Before we proceed, I need to clarify an important architectural point:
Your code attempts to jump to the ROM bootloader ( also called System Memory at 0x0BF97000)
This approach is not suitable when BOOT0 is held HIGH during reset, as it directs the STM32H533 to execute ST's internal bootloader which cannot be customized.
So if you want to use custom DFU, you need to keep boot0 OFF and trigger DFU entry via CDC command;
Which development framework do you prefer or do you have any constraints like using USBX or stm32h5-classic-coremw? Do you have flexibility to choose? Do you need to implement trustzone?
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.
We’re moving the ST Community to a new platform to give you a better and more reliable community experience.