Skip to main content
Associate II
July 10, 2026
Solved

STM32C071 - usb fails to enumerate after jumping from system DFU / custom bootloader

  • July 10, 2026
  • 4 replies
  • 39 views
Hi everyone,I am working with the STM32C071 and experiencing problems with USB enumeration after my bootloader execution.I wrote a custom bootloader that performs checks (like CRC, metadata, etc.) and can also trigger the embedded STM32 DFU bootloader in System Memory using this method:void boot_jump_to_bootloader(void){    uint32_t i = 0;    void (*SysMemBootJump)(void);    uint32_t BootAddrC0 = 0x1FFF0000;    __disable_irq();    SysTick->CTRL = 0;    HAL_RCC_DeInit();    for (i = 0; i < 8; i++) {        if (i < (sizeof(NVIC->ICER) / sizeof(NVIC->ICER[0]))) {            NVIC->ICER[i] = 0xFFFFFFFF;            NVIC->ICPR[i] = 0xFFFFFFFF;        }    }        __enable_irq();    SysMemBootJump = (void (*)(void)) (*((uint32_t*) ((BootAddrC0 + 4))));    __set_MSP(*(uint32_t*) BootAddrC0);    SysMemBootJump();    while (1) { /* Code should never reach this loop */ }}After performing my bootloader-specific instructions, I jump to the main firmware application using this function:typedef void (*pFunction)(void);static void jump_to_address(uint32_t addr){    uint32_t appStack = *(uint32_t*)addr;    uint32_t appResetHandler = *(uint32_t*)(addr + 4);    pFunction appEntry = (pFunction)appResetHandler;    __disable_irq();    SysTick->CTRL = 0;    SysTick->LOAD = 0;    SysTick->VAL = 0;    SCB->VTOR = addr;    __set_MSP(appStack);    appEntry();}The issue is that after making the jump to the application, USB enumeration stops working entirely. In Windows Device Manager, it fails with Error 43 (CM_PROB_FAILED_POST_START).For reference, I have modified the .ld linker scripts for both the bootloader and the firmware as follows:FIRMWARE:MEMORY{  RAM (xrw)    : ORIGIN = 0x20000000, LENGTH = 24K  FLASH (rx)   : ORIGIN = 0x08005000, LENGTH = 44K}BOOTLOADER:MEMORY{  RAM (xrw)    : ORIGIN = 0x20000000, LENGTH = 24K  FLASH (rx)   : ORIGIN = 0x08000000, LENGTH = 16K}Here is my complete project memory layout and definitions:// Memory layout// 0x0800 0000// +---------------------------+// | Bootloader (16 KB)        | 0x0800 0000 - 0x0800 3FFF// +---------------------------+// | Metadata (4 KB)           | 0x0800 4000 - 0x0800 4FFF// +---------------------------+// | App A (44 KB)             | 0x0800 5000 - 0x0800 FFFF// +---------------------------+// | App B (44 KB)             | 0x0801 0000 - 0x0801 AFFF// +---------------------------+// END#define flash_a_size_addr       0x08004000#define flash_b_size_addr       0x08004008#define crc_a_addr              0x08004010#define crc_b_addr              0x08004018#define version_addr            0x08004020#define status_nb_addr          0x08004028#define magic_nb_addr           0x08004030#define magic_nb_default_value  0xDEADBEEF#define BOOTLOADER_START        0x08000000UL#define BOOTLOADER_SIZE         (16 * 1024UL)#define BOOTLOADER_END          (BOOTLOADER_START + BOOTLOADER_SIZE)#define METADATA_START          0x08004000UL#define METADATA_SIZE           (4 * 1024UL)#define METADATA_END            (METADATA_START + METADATA_SIZE)#define BANK_A_START            0x08005000UL#define BANK_A_SIZE             (44 * 1024UL)#define BANK_A_END              (BANK_A_START + BANK_A_SIZE)#define BANK_B_START            0x08010000UL#define BANK_B_SIZE             (44 * 1024UL)#define BANK_B_END              (BANK_B_START + BANK_B_SIZE)If the application runs directly from a power-on reset without the bootloader execution, the USB works flawlessly.I suspect this is caused either by active USB registers/peripherals left uncleaned by the DFU/Bootloader before the jump, or because of how the Cortex-M0+ handles the SCB->VTOR table relocation when transferring control.What is the recommended way to properly reset the USB subsystem and remap the vector table on the STM32C071 to prevent this enumeration failure?Any help would be highly appreciated. Thanks!
Best answer by krzysztof1

The problem was in jump to firmware function. As it turned out I missed __enable_irq(); so USB couldn’t send back descriptors.  

4 replies

Associate II
July 10, 2026

Sorry, for formatting …, so once again

Hi everyone,

I am working with the STM32C071 and experiencing problems with USB enumeration after my bootloader execution.

I wrote a custom bootloader that performs checks (like CRC, metadata, etc.) and can also trigger the embedded STM32 DFU bootloader in System Memory using this method:

void boot_jump_to_bootloader(void)
{
uint32_t i = 0;
void (*SysMemBootJump)(void);
uint32_t BootAddrC0 = 0x1FFF0000;

__disable_irq();
SysTick->CTRL = 0;
HAL_RCC_DeInit();

for (i = 0; i < 8; i++) {
if (i < (sizeof(NVIC->ICER) / sizeof(NVIC->ICER[0]))) {
NVIC->ICER[i] = 0xFFFFFFFF;
NVIC->ICPR[i] = 0xFFFFFFFF;
}
}

__enable_irq();
SysMemBootJump = (void (*)(void)) (*((uint32_t*) ((BootAddrC0 + 4))));
__set_MSP(*(uint32_t*) BootAddrC0);
SysMemBootJump();

while (1) { /* Code should never reach this loop */ }
}

After performing my bootloader-specific instructions, I jump to the main firmware application using this function:

typedef void (*pFunction)(void);

static void jump_to_address(uint32_t addr)
{
uint32_t appStack = *(uint32_t*)addr;
uint32_t appResetHandler = *(uint32_t*)(addr + 4);
pFunction appEntry = (pFunction)appResetHandler;

__disable_irq();

SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;

SCB->VTOR = addr;

__set_MSP(appStack);
appEntry();
}

The issue is that after making the jump to the application, USB enumeration stops working entirely. In Windows Device Manager, it fails with Error 43 (CM_PROB_FAILED_POST_START).

For reference, I have modified the .ld linker scripts for both the bootloader and the firmware as follows:

FIRMWARE:

MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 24K
FLASH (rx) : ORIGIN = 0x08005000, LENGTH = 44K
}

BOOTLOADER:

MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 24K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 16K
}

Here is my complete project memory layout and definitions:

// Memory layout
// 0x0800 0000
// +---------------------------+
// | Bootloader (16 KB) | 0x0800 0000 - 0x0800 3FFF
// +---------------------------+
// | Metadata (4 KB) | 0x0800 4000 - 0x0800 4FFF
// +---------------------------+
// | App A (44 KB) | 0x0800 5000 - 0x0800 FFFF
// +---------------------------+
// | App B (44 KB) | 0x0801 0000 - 0x0801 AFFF
// +---------------------------+
// END

#define flash_a_size_addr 0x08004000
#define flash_b_size_addr 0x08004008
#define crc_a_addr 0x08004010
#define crc_b_addr 0x08004018
#define version_addr 0x08004020
#define status_nb_addr 0x08004028
#define magic_nb_addr 0x08004030
#define magic_nb_default_value 0xDEADBEEF

#define BOOTLOADER_START 0x08000000UL
#define BOOTLOADER_SIZE (16 * 1024UL)
#define BOOTLOADER_END (BOOTLOADER_START + BOOTLOADER_SIZE)

#define METADATA_START 0x08004000UL
#define METADATA_SIZE (4 * 1024UL)
#define METADATA_END (METADATA_START + METADATA_SIZE)

#define BANK_A_START 0x08005000UL
#define BANK_A_SIZE (44 * 1024UL)
#define BANK_A_END (BANK_A_START + BANK_A_SIZE)

#define BANK_B_START 0x08010000UL
#define BANK_B_SIZE (44 * 1024UL)
#define BANK_B_END (BANK_B_START + BANK_B_SIZE)

If the application runs directly from a power-on reset without the bootloader execution, the USB works flawlessly.

I suspect this is caused either by active USB registers/peripherals left uncleaned by the DFU/Bootloader before the jump, or because of how the Cortex-M0+ handles the SCB->VTOR table relocation when transferring control.

What is the recommended way to properly reset the USB subsystem and remap the vector table on the STM32C071 to prevent this enumeration failure?

Any help would be highly appreciated. Thanks!

ST Technical Moderator
July 10, 2026

Hi ​@krzysztof1 

The failing enumeration seems to be caused by incomplete USB/clock/interrupt cleanup rather than linker offset or SCB->VTOR relocation. I suggest:

  • Disable interrupts / clear pending interrupts
  • Disable peripheral clocks before the jump
To give better visibility on the answered topics, please click on "Best answer" on the reply which solved your issue or answered your question.Best regards,FBL
Associate II
July 10, 2026

Hi ​@FBL ,

Thanks for the quick support.

I agree with you that this failure looks related to interrupts or peripheral cleanup. What makes it even more interesting is that my bootloader does not initialize USB at all. I only use a jump to the STM32 embedded bootloader, which detects the USB connection and enters DFU mode:

 

I checked your suggestions:

  • Disable interrupts / clear pending interrupts → still not working, same USB Error 43.
  • Disable peripheral clocks before the jump → still not working, same USB Error 43.

At this point I have no idea what else to try. I should also mention that my bootloader is intentionally kept as simple as possible. It does not configure USB, and even the clock configuration remains in its default state.

 

​​​​​​
At the moment my jump function looks like this:

static void jump_to_address(uint32_t addr)

{

uint32_t appStack = *(uint32_t *)addr;

uint32_t appResetHandler = *(uint32_t *)(addr + 4);

pFunction appEntry = (pFunction)appResetHandler;

 

(*(volatile uint32_t *)magic_nb_addr) = 0xDEADBEEF;

__disable_irq();

SysTick->CTRL = 0;

SysTick->LOAD = 0;

SysTick->VAL = 0;

 

for (uint32_t i = 0; i < 32; i++)

{

HAL_NVIC_DisableIRQ((IRQn_Type)i);

HAL_NVIC_ClearPendingIRQ((IRQn_Type)i);

}

HAL_RCC_DeInit();

SCB->VTOR = addr;

__DSB();

__ISB();

__set_MSP(appStack);

appEntry();

while (1){}

}

Associate II
July 10, 2026

I also noticed that my firmware (not bootloader) by default has set SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET in system_stm32c0xx.c where
FLASH_BASE ↔ 0x08000000
VECT_TAB_OFFSET ↔ 0x00000000
which is not correct because in my case it should be 
FLASH_BASE ↔ 0x08000000
VECT_TAB_OFFSET ↔ 0x00005000
Which is correct for my BANK offset, but vven this fix USB still not working with same error
 

krzysztof1AuthorBest answer
Associate II
July 10, 2026

The problem was in jump to firmware function. As it turned out I missed __enable_irq(); so USB couldn’t send back descriptors.