STM32 Bootloader questions - Page 1
Forum section: electronics / general

author: Sariel
author_rank: Regular Contributor
timestamp: October 27, 2024, 03:18:29 pm
content: Hello,I’m planning to create my own custom STM32 board instead of using external development boards like the Nucleo boards. I’m considering the STM32L476RG and would like to use the Nucleo (NUCLEO-L476RG) schematic as a starting point for my design.My goal is to simplify the layout by omitting the onboard ST-Link device, opting instead to program the MCU with an external ST-Link V2 programmer.From what I understand, all bare STM32 devices purchased (via Digi-Key or other vendors) come with the bootloader pre-installed, correct?According to application note AN2606, the bootloader enables downloading the application program to the internal flash memory using one of the available serial interfaces (like USART, CAN, USB, I2C, or SPI).However, in the Nucleo schematic, I see that the ST-Link devices program the main MCU via the SWD interface. The documentation mentions that I can remove the ST-Link part of the PCB and connect jumper wires from CN6 to the MCU portion.This leads me to conclude that programming through the ST-Link is done via the SWD interface, rather than the methods outlined in AN2606. How do these two methods relate?When designing my own board, what pins do I need to ensure I can connect to an external ST-Link programmer for MCU programming?Additionally, what is the purpose of the RX/TX pins? Are they solely for debugging purposes?Thank you for your help!

author: tellurium
author_rank: Frequent Contributor
timestamp: October 27, 2024, 04:00:30 pm
content: You can take a look at the existing schematics of some simple board, like black pill:https://stm32-base.org/boards/STM32F411CEU6-WeAct-Black-Pill-V2.0.htmlThe schematic file is linked from a resources section.Since all STM32 MCUs have a built-in boot loader in ROM, you don't really need an st-link to reflash it.Although it is a good idea to break out SWDIO / SWCLK pins anyway, for live debugging. Like the black pill board above. They break out SWDIO, SWCLK, GND and VCC for the st-link, and that's exactly what you need to do for the st-link support.If you want to reflash your STM32 using a built-in bootloader, you need to break out UART1 pins (usually PA9/PA10), BOOT0 pin, and RESET.

author: nctnico
author_rank: Super Contributor
timestamp: October 27, 2024, 04:15:27 pm
content: Quote from: Sariel on October 27, 2024, 03:18:29 pmAFAIK the bootloader is for programming only. This can be handy to use through a USB to UART converter and do automated programming / testing in a production line. First program the firmware through the serial port and once the firmware is running, the serial port can be used to configure & test the product. The actual serial protocol used for the configure & test step can be defined freely as this is a function of the firmware and not the bootloader.Typically field updates are easier to do through a bootloader + serial port compared to using an SWD programmer board.QuoteFor programming you need SWCLK, SWDIO, NRST and ground pins. This will allow programming and debugging.

author: Sariel
author_rank: Regular Contributor
timestamp: October 27, 2024, 04:51:08 pm
content: Thank you all for your responses. I've gained some clarity, but I'm still a bit confused.If I want to upload new programs to the device using the default bootloader without reflashing the MCU from scratch, which interface should I use: SWD or UART?I’m a bit puzzled because, on the Nucleo board, after cutting the ST-Link section, I noticed there's no connection through the RX/TX pins.So how does programming work? Is it done solely through the SWCLK and SWDIO pins?The bootloader documentation doesn’t mention the option to download the application program via the SWD interface.

author: nctnico
author_rank: Super Contributor
timestamp: October 27, 2024, 05:00:33 pm
content: You have to seperate things:1) SWD is a hardware interface (kind of like JTAG but with much less pins). This controls the internals of the microcontroller directly. This allows to access the internal flash as well (if it is not read / write protected)2) Bootloader is a software interface. This is a program stored in ROM which is executed at startup. If a specific pin is set, the bootloader doesn't start running the program from flash but halts and waits for commands on the serial port (or whatever interface is selected).

author: Siwastaja
author_rank: Super Contributor
timestamp: October 27, 2024, 05:06:33 pm
content: And also, ST's bootloader is not a bootloader. They just misused a term. It's a programming interface just like any else - just implemented in software code but being non-eraseable it's "as if" it was a hardware interface.Bootloader then means a piece of code which loads your application - boots it, possibly offering some extra features like a firmware update mechanism over whatever interface you want to use, data integrity checks etc. You can use one if you wish, write your own, or not use one at all.ST's "bootloader" allows programming through UART or similar which is sometimes handy, but SWD dongle like ST/LINK is not expensive and offers more (e.g. debugging). But if your board exposes the UART pins shared by the ST's bootloader, then it's not a bad idea to also expose the BOOT0 pin to a jumper or pushbutton or something so you can run the ST's bootloader if you so wish, even if you normally would use SWD.

author: Sariel
author_rank: Regular Contributor
timestamp: October 27, 2024, 05:26:00 pm
content: Thank you for your answers! I understand now.I noticed in the Nucleo schematic that the ST-Link section is also connected to the MCU via the SWO and MCO lines.What are the functions of these lines? Are they critical?I apologize for asking what may seem like basic questions; I'm primarily an Analog/RF designer and am gradually learning about hardware for embedded systems (I’ve already moved beyond the Arduino stage).

author: langwadt
author_rank: Super Contributor
timestamp: October 27, 2024, 05:49:54 pm
content: Quote from: Sariel on October 27, 2024, 05:26:00 pmfor debug all you need is SWCLK and SWDIO. SWO is for an extra communication channel that can be used sorta like a uartMCO is connected on the Nucleo board because on those the debugger supplies the clock to the cpu

author: Sariel
author_rank: Regular Contributor
timestamp: October 27, 2024, 06:42:40 pm
content: To program the STM32, I need SWDIO, SWCLK, GND, NRST (though not all boards expose this pin), and VDD, right? (all these 5 pins)If I want to add serial communication to the PC for entering parameters into the MCU via a serial monitor, what’s the simplest way to do this with STM32?On Arduino boards, I use USB to UART chips along with the Serial Monitor in the Arduino IDE. How can I achieve something similar with STM32? (easiest method)

author: asmi
author_rank: Super Contributor
timestamp: October 28, 2024, 02:59:20 pm
content: Quote from: Sariel on October 27, 2024, 06:42:40 pmYou can do the same thing with STM32 - connect USB/UART bridge to any of STM32's UART/LPUART/USART ports, and you're good to go. That's by far the easiest way. Alternatively, if your MCU has USB support, you can connect USB port and implement USB COM port device in software. Advantage of that approach is that you won't need a bridge IC, the disadvantage is that the USB stack will take quite a bit of flash space and will consume some CPU resources, potentially impacting your main application.

author: Siwastaja
author_rank: Super Contributor
timestamp: October 28, 2024, 03:47:48 pm
content: Quote from: asmi on October 28, 2024, 02:59:20 pmAdditional benefit is that you can re-flash the STM32 this way through the same UART you would use as your application data link, using the ST's "bootloader". All you need is a jumper or pushbutton on BOOT0 pin to run the ST's bootloader code instead of your own application. Hold the BOOT0 button while applying power (or pushing reset button connected to NRST) and then you can flash through UART. Such option might come in handy even if you plan to normally use SWD for programming.Just read the appnote regarding the bootloader carefully to be sure which pins the bootloader uses for UART programming, if there are many pins (multiple UARTs and/or alternative pin mappings).

author: Sariel
author_rank: Regular Contributor
timestamp: October 29, 2024, 06:50:57 am
content: Quote from: asmi on October 28, 2024, 02:59:20 pmIs there any recommended USB to UART chip , that is not Chinese and avilable easily on Digieky? A device that is straightforward for usage.

author: fchk
author_rank: Frequent Contributor
timestamp: October 29, 2024, 08:38:36 am
content: FTDI is always. good. Don't use the FT232 because of the risk of counterfeits. The newer FT230/231/234 don't have clones. If you use a FT2232 you can use port 0 for JTAG and port 1 for UART.Or: use a STLINKV3-MODS.https://www.digikey.com/en/products/detail/stmicroelectronics/stlink-v3mods/11610874This is a STLINK with additional Debug UART designed for soldering onto a controller board. Very convenient and not too expensive.

author: asmi
author_rank: Super Contributor
timestamp: October 29, 2024, 12:34:47 pm
content: Quote from: Sariel on October 29, 2024, 06:50:57 amLook at FTDI's FT-X series, it includes a full range of interfaces, for UART I would recommend FT234XD or FT230X, both of them are very simple to integrate into your designs, the difference being amount of GPIOs available, which can be used for many functions like blinking a LED on RX/TX, VBUS sense (for self-powered configurations), clock outputs, sleep, BCD and other things.

author: nctnico
author_rank: Super Contributor
timestamp: October 29, 2024, 12:43:00 pm
content: Quote from: Siwastaja on October 28, 2024, 03:47:48 pmAFAIK there is also a way to enter the bootloader through software on some STM32s. One of my customers uses that feature to put their product into firmware update mode without having to implement their own bootloader and not needing external reset / boot mode pins. There are some caveats though as needing to pre-initialise the chip to near reset conditions as the ROM bootloader doesn't do a full initialisation of the UART.

author: voltsandjolts
author_rank: Unknown
timestamp: October 29, 2024, 01:07:28 pm
content: Quote from: nctnico on October 29, 2024, 12:43:00 pmYeh, I do that, just jump to the bootloader after a reset.From deep in the app code I set a RAM variable to a magic_number then reset the MCU withCode:var = magic_number;NVIC_SystemReset();Then early in main, jump to the bootloader:Code:if (var == magic_number){/* Jump to the STM32 built-in bootloader.* This is done early in main() so we don't have to de-init everything before jumping to the bootloader.* See ST app note AN2606 for bootloader details.*/SET_BIT(RCC->CSR, RCC_CSR_RMVF); /* clear reset type flags */var = 0;/* don't loop back here again at next boot *//* set stack pointer to the value at bootloader start address */__set_MSP(*((uint32_t *)(0x1FF00000)));/* jump to @bootloader + 4 */((void (*)(void))(*((uint32_t *)(0x1FF00004))))();/* never get here */}The RAM var needs to be noinit of course.

author: radar_macgyver
author_rank: Frequent Contributor
timestamp: October 29, 2024, 03:51:23 pm
content: Same can also be done by hooking the Reset vector, which apparently is needed on some STM32s. I tried doing this in main on an STM32L152 and it would not work until I moved it over to the Reset() handler. Also, the address that one jumps to is different between different STM32 families. From my code, I call bootloader_jump() when needed, and call bootloader_clear_flags() at the top of main().Rather than using the hardcoded address for BOOTLOADER_FLAG, you could also define a variable and put it in a special segment that you define in your memory map at a fixed location, and is also noinit.Code:#define SYSTEM_MEMORY_ADDRESS 0x1FF00000//#define SYSTEM_MEMORY_ADDRESS 0x1FFFC800#define BOOTLOADER_MAGIC 0xDEADBEEF#define BOOTLOADER_FLAG *((uint32_t *)0x20003FF0)uint32_t rcc_csr_copy;void bootloader_clear_flags(void){/* Make a copy of the CSR and clear reset flags */rcc_csr_copy = RCC->CSR;RCC->CSR |= RCC_CSR_RMVF;}void bootloader_jump(void){BOOTLOADER_FLAG = BOOTLOADER_MAGIC;// Soft-Reset the MCUNVIC_SystemReset();return;}// defined in os/common/startup/ARMCMx/compilers/GCC/crt0_v6m.S__attribute__((naked)) void _crt0_entry(void);// overrides the weak symbol in vector.S__attribute__((naked)) __attribute__((__used__)) void Reset_Handler(void){// check reset reason in RCC_CSR register: must be soft reset for jump to bootloader// also bootloader magic code must be set// this combination ensures that no stray jumps to bootloader can happen due to random values in ram on bootif ( (RCC->CSR & RCC_CSR_SFTRSTF) && BOOTLOADER_FLAG == BOOTLOADER_MAGIC ){// reset the trigger to prevent unwanted jump to bootloader later onBOOTLOADER_FLAG = 0x0;register void (*BootloaderStartAddr)(void);BootloaderStartAddr = (void (*)(void)) (*((uint32_t *) ((SYSTEM_MEMORY_ADDRESS + 4))));// Initialize the stack pointer for the bootloader__set_MSP(*(__IO uint32_t*) SYSTEM_MEMORY_ADDRESS);BootloaderStartAddr();}// reset the trigger to prevent unwanted jump to bootloader later onBOOTLOADER_FLAG = 0x0;// jump to _crt0_entry, as the overridden weak Reset_Handler normally would do_crt0_entry();}