2026-05-29 2:57 AM - last edited on 2026-05-29 12:36 PM by mƎALLEm
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