2019-06-17 03:04 AM
Hello,
I have a few questions regarding the system memory bootloader on STM32 cortex-M products (especially STM32F446, though other parts as well).
1) Is there no timeout to get out of the bootloader if no communication is detected?
I mean, the system boot is activated by tying the BOOTx pins to the proper voltage, then the bootloader executes, but no one is transmitting anything on any of the interfaces (UART, SPI, etc.).
Will the bootloader keep waiting forever?
Can it be exited by applying different voltages on the BOOTx pins?
Is the only way out that of transmitting a GO instruction via one of the available interfaces?
2) How should I connect the unused interfaces?
For instance, I want to use CAN2 for the firmware update. However, the bootloader will also listen to various USARTs, SPIs, I2Cs, etc.
Do their pins need to be tied to some voltage (e.g. pullups on I2C SDA, pullup on USART RX) to prevent spurious data being received, or will the bootloader initialize all the pins appropriately?
3) What if I have other hardware connected to the pins of unused interfaces?
For instance, if I don't want to use USART1, and I guarantee that nothing will be transmitted to USART1_RX, will USART1_TX still be configured as output while the bootloader is executing?
4) Are there utilities provided by ST to perform a firmware update from a PC?
I know that there's the "Flash loader demonstrator" (https://www.st.com/en/development-tools/flasher-stm32.html#), but as far as I can tell it only supports the USART bootloader protocol.
I would need a utility working with CAN instead (through a USB-to-CAN hardware adapter).
2019-06-17 03:59 AM
To 1.:
AFAIK, no. It would not make sense if there is no application yet.
Or, even with an application in Flash, the system BL was specifically entered by user manipulation. It is his decision to terminate/restart.
To 2. & 3.:
If you can guarantee not undesired communication which would provoke misbehaviour, just leave it as it is.
But yes, the system BL would configure outputs of checked channels (like UART Tx) regardless of your actual schematics.
To 4.:
At least for CAN, not that I'm aware of. AFAIK the STLink Utility supports UARTs in Nucleo boards via VCP.
I think there are no standard (pure) CAN protocols really suitable for BL use, I know only of proprietary one's.
UDS would be a more complex CAN-based and standardized protocol that supports firmware updates.
2019-06-17 07:38 AM
The system boot loader is sensitive to inputs on multiple interfaces, and these need to be quiet for it to recognize the one you want to use. AN2606 enumerates the pins of interest as I recall. Putting a GPS receiver on the USART interfaces used by the loader, for example, will prevent access by other means.
It is designed as production/de-bricking type loader, and has no specific familiarity with your board design or component choices.
You really should write your own loader, using several of the first flash sectors to store it, and have it implement the functionality you need for user updates, and to validate your app placed deeper into the flash memory.
2019-06-17 07:40 AM
STM32 Cube Programmer replaces several of the older tools, and supports CAN in some fashion, but might be limited to specific drivers/dongles
https://www.st.com/en/development-tools/stm32cubeprog.html
2021-01-13 02:11 AM
The STM32 Cube programmer, at least version 2.5.0 does not have any option to upgrade by CAN pins
2021-01-13 03:33 AM
In case you need the CAN bootloader too, here's what I did.
I used ST's standard bootloader.
Developing your own bootloader gives you more flexibility (both in hardware and software), but it's additional work, and it has drawbacks:
1) you need an additional step in production to flash the bootloader itself, unless you flash bootloader and application together; anyway, you need a non-CAN interface for programming, whereas with the default bootloader you don't (except for developing and debugging, of course)
2) the bootloader might get corrupted (unless you fiddle with option bytes, for protection), whereas the default bootloader is always there
I had to be careful not to use peripherals in a way that would conflict with the bootloader.
In particular, since I had to use a serial port that's also used by the bootloader, I used hardware pullups; otherwise, the bootloader would sometimes pick up noise on that port.
This would effectively lock it, because once the bootloader senses some communication on a port, it stops listening to other ports. So, it would receive garbage data on the floating serial pins and stop listening to the CAN pins.
At least, this is what I experienced. Maybe it also depends on the specific ports, with some kind of priority.
Before using my custom board (mounting an STM32F446RETx), I tested the bootloader communication on the Nucleo-64 board (https://www.st.com/en/evaluation-tools/nucleo-f446re.html)
This is the behavior I saw for each relevant pin.
It seems that the bootloader uses pullups for some pins, while others seem to be cyclically initialized (as if polling them, and then putting them back to their reset state; they are marked as '?').
It might also be that all of them are initialized periodically, but I just didn't see them floating.
PA9 (?): USART1_TX CN10.21 / CN5.1 (D8)
PA10 (?): USART1_RX CN10.33 / CN9.3 (D2)
PB10 (?): USART3_TX CN10.25 / CN9.7 (D6)
PB11 (doesn't exist): USART3_RX
PC11 (pullup): USART3_RX CN7.2
PC10 (pullup): USART3_TX CN7.1
PB5 (pullup): CAN2_RX CN10.29 / CN9.5 (D4)
PB13 (pullup): CAN2_TX CN10.30
PB6 (?): I2C1_SCL CN10.17 / CN5.3 (D10)
PB9 (?): I2C1_SDA CN10.5 / CN5.9 (D14)
PF1 (doesn't exist): I2C2_SCL
PF0 (doesn't exist): I2C2_SDA
PA8 (?): I2C3_SCL
PC9 (?): I2C3_SDA
PA7 (no): SPI1_MOSI
PA6 (pullup): SPI1_MISO
PA5 (no): SPI1_SCK
PA4 (no): SPI1_NSS
PB15 (no): SPI2_MOSI
PB14 (pullup): SPI2_MISO
PC7 (no): SPI2_SCK
PB12 (no): SPI2_NSS
PE14 (doesn't exist): SPI4_MOSI
PE13 (doesn't exist): SPI4_MISO
PE12 (doesn't exist): SPI4_SCK
PE11 (doesn't exist): SPI4_NSS
PA11 (no): USB_DM
PA12 (pullup): USB_DP
PB4 (pullup): ???
PC13 (pullup): ???
PA15 (pullup): ???
PA13 (pullup): JTAG
I used PB13+PB5 for CAN, and PA9+PA10 for UART (the one that had garbage data problems); this is a debug UART, but I also tried to communicate to the bootloader using it, and it works (for this you can just use the STM32 Cube Programmer).
For the CAN firmware upgrade, I used the 'canprog' utility:
https://pypi.org/project/canprog/
https://github.com/marcinbor85/can-prog
This requires you to use Linux, and a compatible USB-to-CAN adapter. "Compatible" means that it supports the slcan protocol, so that 'canprog' can use standard linux drivers.
One such adapter is "USBtin": https://www.fischl.de/usbtin/
Upgrading this way is quite slow (maybe 100KiB/minute); I don't know what's the bottleneck here: the bus, the bootloader, the adapter, or 'canprog'.
Anyway, it was enough for me.
If you find better alternatives, let me know.
If you need more details about using linux+canprog+usbtin, I can tell you.