2022-03-10 06:40 AM
I have been able to use the below function to enter the bootloader from the Application and successfully flash a new firmware from the UART interface.
/**
* @brief Resets the microcontroller entering into the embedded bootloader
* to allow for upgrading the application's firmware
* @param run Safety variable
* @arg @ref TRUE To enable execution of the bootloader
* @retval None
*/
void Bootloader_Start(uint32_t run) {
void (*SysMemBootJump)(void);
/**
* Set system memory address.
*
* For STM32F072, system memory is on 0x1FFF C800
* For other families, check AN2606 document table 155 with descriptions of memory addresses
*/
volatile uint32_t addr = 0x1FFFC800;
if (run == TRUE)
{
// De-initialize all peripherals configured for this Application
HAL_TIM_Base_DeInit(&htim1);
HAL_TIM_Base_DeInit(&htim6);
HAL_TIM_Base_DeInit(&htim7);
HAL_TIM_Base_DeInit(&htim14);
HAL_TIM_PWM_DeInit(&htim15);
HAL_TIM_Base_DeInit(&htim15);
HAL_CRC_DeInit(&hcrc);
HAL_NVIC_DisableIRQ(DMA1_Channel1_IRQn);
HAL_NVIC_DisableIRQ(DMA1_Channel2_3_IRQn);
HAL_NVIC_DisableIRQ(DMA1_Channel4_5_6_7_IRQn);
HAL_DMA_DeInit(&hdma_memtomem_dma1_channel2);
HAL_PCD_DeInit(&hpcd_USB_FS);
HAL_UART_DeInit(&huart2);
HAL_UART_DeInit(&huart1);
HAL_ADC_DeInit(&hadc);
// Disable GPIO interrupts
HAL_NVIC_DisableIRQ(EXTI0_1_IRQn);
HAL_NVIC_DisableIRQ(EXTI2_3_IRQn);
HAL_NVIC_DisableIRQ(EXTI4_15_IRQn);
// Disable RCC, set it to default (after reset) settings
// Internal clock, no PLL, etc.
HAL_RCC_DeInit();
// Disable SysTick timer and reset it to default values
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
// Disable all interrupts
__disable_irq();
// Remap system memory to address 0x0000 0000 in address space
__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
// Set jump memory location for system memory
// Use address with 4 bytes offset which specifies jump location where program starts
SysMemBootJump = (void (*)(void)) (*((uint32_t *)(addr + 4)));
/**
* Set main stack pointer.
* This step must be done last otherwise local variables in this function
* don't have proper value since stack pointer is located on different position
*
* Set direct address location which specifies stack pointer in SRAM location
*/
__set_MSP(*(uint32_t *)addr);
/**
* Call our function to jump to set location
* This will start system memory execution
*/
SysMemBootJump();
}
}
However, in this new application, I require to use the USB interface for flashing the firmware. This application implements a USB CDC, so I modified the above code as follows:
void Bootloader_Start(uint32_t run) {
void (*SysMemBootJump)(void);
/**
* Set system memory address.
*
* For STM32F072, system memory is on 0x1FFF C800
* For other families, check AN2606 document table 155 with descriptions of memory addresses
*/
volatile uint32_t addr = 0x1FFFC800;
if (run == TRUE)
{
// De-initialize all peripherals configured for this Application
HAL_TIM_Base_DeInit(&htim6);
HAL_TIM_Base_DeInit(&htim7);
USBD_DeInit(&hUsbDeviceFS);
// Disable RCC, set it to default (after reset) settings
// Internal clock, no PLL, etc.
HAL_RCC_DeInit();
// Disable SysTick timer and reset it to default values
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
// Disable all interrupts
__disable_irq();
// Remap system memory to address 0x0000 0000 in address space
__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
// Set jump memory location for system memory
// Use address with 4 bytes offset which specifies jump location where program starts
SysMemBootJump = (void (*)(void)) (*((uint32_t *)(addr + 4)));
/**
* Set main stack pointer.
* This step must be done last otherwise local variables in this function
* don't have proper value since stack pointer is located on different position
*
* Set direct address location which specifies stack pointer in SRAM location
*/
__set_MSP(*(uint32_t *)addr);
/**
* Call our function to jump to set location
* This will start system memory execution
*/
SysMemBootJump();
}
}
When running this function microcontroller does disconnect from the computer, but it never loads the DFU, and the computer shows unknown device, so I am not able to see it listed on the SMT32CubeProgrammer.
Am I missing something?
Thanks in advance for your support.
2022-03-10 07:11 AM
> __disable_irq()
Don't do this. The DFU bootloader requires interrupts to be enabled.
If it still doesn't work, the problem likely that the chip is not in its default reset state. Consider setting a magic flag, resetting, and jumping to the bootloader immediately after startup. This will circumvent issues during deinitialization.
2022-03-15 08:36 AM
Thanks!
Removing the line that disables the interrupts worked. Now the STM32CubeProgrammer is able to detect the DFU device. However when connecting to it, it says the Read Protection is enabled. After connecting with the "Read Unprotect (MCU) option ticked", it says it disabled the protection. Then after disconnecting and reconnecting it gives the same error back...
Any ideas? I flashed the firmware in debugger mode for testing purposes. But I also tried in Run mode and kept the STLink disconnected.
Thanks again for your support!
2022-03-15 11:22 AM
I also tried as suggested, setting up a flag to run the Bootloader_Start function after reset just before the initialization of peripherals begin.
But I still get the same issue. The STM32CubeProgrammer is able to connect but says the device is read protected:
And when connecting with the "Read Unprotect (MCU)" option enabled, then I'm asked for confirmation to disable.
After confirmation, I get that it is disabled successfully:
But then when I try to Download a new firmware I get the same warning saying it is under Read out protection:
Is there a way to disable this RDP during runtime before I call the Bootloader function?
Thanks for your time and input.
2022-03-16 08:54 AM
Thanks!
Removing the line that disables the interrupts worked. Now the STM32CubeProgrammer is able to detect the DFU device. However when connecting to it, it says the Read Protection is enabled. After connecting with the "Read Unprotect (MCU) option ticked", it says it disabled the protection. Then after disconnecting and reconnecting it gives the same error back...
Any ideas? I flashed the firmware in debugger mode for testing purposes. But I also tried in Run mode and kept the ST-Link disconnected.
Thanks again for your support!
2022-03-16 09:02 AM
Not really. I believe removing RDP requires a chip erase/reset and I'm not sure how the DFU would handle that. I don't have much experience using the DFU bootloader.
Why not just keep RDP off during development?
2022-03-16 11:38 AM
As a matter of fact, the RDP is not being turned on by the time of loading the firmware. For some reason, the way the DFU bootloader is being executed is what is causing it to say RDP is on...