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?AFAIK 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.
When designing my own board, what pins do I need to ensure I can connect to an external ST-Link programmer for MCU programming?For programming you need SWCLK, SWDIO, NRST and ground pins. This will allow programming and debugging.
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?
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?You 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.
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)
You 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.
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?You 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.
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)
Is there any recommended USB to UART chip , that is not Chinese and avilable easily on Digieky? A device that is straightforward for usage.Look 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.
AFAIK 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.You 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.
Additional 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).
AFAIK 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.
var = magic_number;
NVIC_SystemReset();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 */
}
#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 MCU
NVIC_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 boot
if ( (RCC->CSR & RCC_CSR_SFTRSTF) && BOOTLOADER_FLAG == BOOTLOADER_MAGIC )
{
// reset the trigger to prevent unwanted jump to bootloader later on
BOOTLOADER_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 on
BOOTLOADER_FLAG = 0x0;
// jump to _crt0_entry, as the overridden weak Reset_Handler normally would do
_crt0_entry();
}