2025-09-08 8:01 AM
I have written a custom bootloader that is running on a Nucleo-L433RC-P board.
The application uses USB CDC to call the bootloader and the bootloader uses USB DFU to download the application.
I wanted to use USB to call the custom bootloader, rather than having to use a physical switch on the BOOT0 pin to call the internal bootloader
I can successfully download a simple application which just flashes an LED using the USB DFU bootloader.
However, when I download my actual project, it appears to download successfully but does not run.
My actual project is more complicated and uses the following peripherals:
I used the following guide to write the custom bootloader and simple application...
The following web tool is used to download the application...
I have spent days trying to debug why my actual project will not work, yet the simple application does.
Now I am at a complete loss and don't know how to proceed.
The implementation is shown below.
Bootloader USB configuration...
Changes to bootloader linker script...
Bootloader main.c...
#include "main.h"
#include "usb_device.h"
typedef void (*pFunction)(void);
#define DFU_BOOT_FLAG 0xDEADBEEF
RTC_HandleTypeDef hrtc;
uint32_t dfu_boot_flag;
pFunction JumpToApplication;
uint32_t JumpAddress;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_RTC_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USB_DEVICE_Init();
MX_RTC_Init();
dfu_boot_flag = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR5);
if (dfu_boot_flag != DFU_BOOT_FLAG)
{
if (((*(__IO uint32_t*) USBD_DFU_APP_DEFAULT_ADD) & 0x2FFC0000) == 0x20000000)
{
JumpAddress = *(__IO uint32_t*) (USBD_DFU_APP_DEFAULT_ADD + 4);
JumpToApplication = (pFunction) JumpAddress;
__set_MSP(*(__IO uint32_t*) USBD_DFU_APP_DEFAULT_ADD);
JumpToApplication();
}
}
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR5, 0); // So next boot won't be affected
uint32_t now = 0, next_blink = 100;
while (1)
{
now = uwTick;
if (now >= next_blink)
{
HAL_GPIO_TogglePin(STATUS_LED_GPIO_Port, STATUS_LED_Pin);
next_blink = now + 100;
}
}
}
Changes to bootloader usbd_dfu_if.c....
Changes to bootloader usbd_dfu_if.h....
Changes to application linker script...
Simple application main.c...
#include "main.h"
#include "usb_device.h"
#define DFU_BOOT_FLAG 0xDEADBEEF
#define DFU_BOOT_REQ 0xAA
RTC_HandleTypeDef hrtc;uint32_t *dfu_boot_flag;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_RTC_Init(void);
int main(void)
{
uint32_t now = 0, next_blink = 1000;
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USB_DEVICE_Init();
MX_RTC_Init();
HAL_PWR_EnableBkUpAccess();
while (1)
{
now = uwTick;
if (now >= next_blink)
{
HAL_GPIO_TogglePin(STATUS_LED_GPIO_Port, STATUS_LED_Pin);
next_blink = now + 1000;
}
}
}
#define USB_RX_BUF_SIZE 512
volatile uint8_t usb_rx_buffer[USB_RX_BUF_SIZE];
volatile uint32_t usb_rx_count = 0; // number of bytes in buffer
void USB_CDC_RxHandler(uint8_t* Buf, uint32_t Len)
{
if ((usb_rx_count + Len) < USB_RX_BUF_SIZE)
{
memcpy((uint8_t *)&usb_rx_buffer[usb_rx_count], Buf, Len);
usb_rx_count += Len;
}
if (usb_rx_buffer[0] == DFU_BOOT_REQ)
{
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR5, DFU_BOOT_FLAG);
HAL_NVIC_SystemReset();
}
}
Changes to application system_stm32l4xx.c...
Changes to application usbd_cdc_if.c...
2025-09-09 11:00 AM
This is weird... I can't explain why it behaves this way.
If I recall correctly, one must make sure that the stack size is big enough when using USB. If it isn't, then you may see all sorts of strange beaviour.
Just in case it could be helpful, this is the setup of my USB port:
Heap and stack size, although I am not certain that the heap is being used:
2025-09-09 11:28 AM - edited 2025-09-09 11:35 AM
Thanks TDK, I did as you suggested and now the USB DFU device appears when the bootloader is called
while (1) {
now = uwTick;
if (now >= next_blink) {
HAL_GPIO_TogglePin(STATUS_LED_GPIO_Port, STATUS_LED_Pin);
next_blink = now + 100;
}
if (flgReqBootloader)
{
flgReqBootloader = 0;
JumpToBootloader();
}
void USB_CDC_RxHandler(uint8_t* Buf, uint32_t Len) { // accumulate incoming USB data into the buffer if ((usb_rx_count + Len) < USB_RX_BUF_SIZE) { memcpy((uint8_t *)&usb_rx_buffer[usb_rx_count], Buf, Len); usb_rx_count += Len; } if (usb_rx_buffer[0] == DFU_BOOT_REQ) { flgReqBootloader = 1; } }
However, when I try to flash a simple application .bin file (that just flashes an LED) I get the following errors...
The log shows the following...
19:21:21 : STM32CubeProgrammer API v2.20.0 | MacOS-64Bits
19:21:34 : USB speed : Full Speed (12MBit/s)
19:21:34 : Manuf. ID : STMicroelectronics
19:21:34 : Product ID : STM32 BOOTLOADER
19:21:34 : SN : 207C30AC5533
19:21:34 : DFU protocol: 1.1
19:21:34 : Board : --
19:21:34 : Device ID : 0x0435
19:21:34 : UPLOADING OPTION BYTES DATA ...
19:21:34 : Bank : 0x00
19:21:34 : Address : 0x1fff7800
19:21:34 : Size : 36 Bytes
19:21:34 : UPLOADING ...
19:21:34 : Size : 1024 Bytes
19:21:34 : Address : 0x8000000
19:21:34 : Read progress:
19:21:34 : Data read successfully
19:21:34 : Time elapsed during the read operation is: 00:00:00.031
19:22:00 : Opening and parsing file: STApplication.bin
19:22:00 : Memory Programming ...
19:22:00 : File : STApplication.bin
19:22:00 : Size : 6.13 KB
19:22:00 : Address : 0x08000000
19:22:00 : Download in Progress:
19:22:00 : File download complete
19:22:01 : Time elapsed during download operation: 00:00:00.086
19:22:01 : Verifying...
19:22:01 : Read progress:
19:22:01 : Error: Data mismatch found at address 0x08000004 (byte = 0x1D instead of 0x0D)
19:22:01 : Time elapsed during verifying operation: 00:00:00.057
19:22:01 : Error: Download verification failed
19:22:01 : RUNNING Program ...
19:22:01 : Address: : 0x08000000
19:22:01 : Start operation achieved successfully
19:22:01 : Warning: Connection to device 0x435 is lost
19:22:01 : Disconnected from device.
UPDATE;
Unticking "Skip flash erase before porgramming" fixed it...
So the simple application seems to work, now I need to implement it in my actual more complicated project.