STM32C011F6 I²C Bootloader Jump from Application — NACK on SYNC
Dear STMicroelectronics Support Team,
I am currently working with the STM32C011F6 microcontroller and attempting to enter the built-in system bootloader via software from my application. My goal is to flash the device over I²C from an external processor (RFSoC running Linux), without toggling the BOOT0 or RESET pins.
I followed the STM32 application notes AN2606 and AN4221 closely and implemented the bootloader jump using the standard approach:
1. Disabling all interrupts (NVIC->ICER / ICPR)
2. De-initializing peripherals (HAL_DeInit, HAL_RCC_DeInit)
3. Stopping SysTick
4. Setting the MSP from address 0x1FFF0000
5. Jumping to the bootloader reset handler at 0x1FFF0004
From the external I²C master, I send the `0x7F` SYNC byte, and I **consistently receive a NACK (0x1F)** instead of the expected ACK (0x79). I confirmed the I²C lines (PA9 and PA10), 100kHz speed, correct pull-ups, and that the STM32 is not held in reset or debug mode. I also verified that the bootloader jump function is being called properly by printing debug messages over UART before the jump.
I suspect the STM32 is not correctly initializing the bootloader I²C peripheral or is exiting bootloader mode prematurely, even though I send the SYNC immediately after the jump.
Could you please help confirm:
- Whether STM32C011F6 supports jumping to system bootloader (0x1FFF0000) from application for I²C?
- Are there additional steps or constraints (option bytes, flash size, peripheral clock resets, etc.) specific to the C0 series that may be preventing I²C bootloader activation via software?
- Any known limitations or errata for bootloader use in STM32C011F6?
This is the function I used to jump from application to STM32 system bootloader.
void jump_to_bootloader(void)
{
__disable_irq();
for (int i = 0; i < sizeof(NVIC->ICER) / sizeof(NVIC->ICER[0]); i++) {
NVIC->ICER[i] = 0xFFFFFFFF;
NVIC->ICPR[i] = 0xFFFFFFFF;
}
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
HAL_RCC_DeInit();
HAL_DeInit();
__HAL_RCC_GPIOA_CLK_DISABLE();
__HAL_RCC_GPIOB_CLK_DISABLE();
__HAL_RCC_GPIOC_CLK_DISABLE();
__HAL_RCC_I2C1_CLK_DISABLE();
__HAL_RCC_USART1_CLK_DISABLE();
uint32_t bootloader_msp = *(volatile uint32_t *)0x1FFF0000;
uint32_t bootloader_reset = *(volatile uint32_t *)(0x1FFF0000 + 4);
void (*bootloader_entry)(void) = (void (*)(void))bootloader_reset;
__set_MSP(bootloader_msp);
bootloader_entry();
while (1);
}
Thank you for your support.
Best regards,
Anees A.
