This page explains how to use UART to update the boot device (SD card, e•MMC, NOR, NAND) with OpenSTLinux distribution.
1. UART as serial boot device[edit | edit source]
A UART instance can be used as a serial boot device if the selected UART is supported by :
- ROM code, with the PIN configuration
- TF-A device tree, including pincontrol
- U-Boot device tree, including pincontrol
On STM32 MPU STMicrolectronics boards, the UART used for console can be used as UART boot device.
OpenSTLinux distribution doesn't provide the flash memory layout (flashlayout) files required to use a UART as a serial boot device.
Refer to Using_STM32Programmer_over_UART chapter to see how to modify a flashlayout file to use the TF-A BL2 binary with UART support: tf-a-<board>-uart.stm32.
You can use this modified flashlayout as described in STM32CubeProgrammer article.
By default the baudrate used by STM32CubeProgrammer on UART is 115200 bit/s so the operations are very slow.
![]() |
the UART serial link is slower than USB, so it is NOT a recommended interface to program big files as a filesystem binaries. But if USB device is not available or not functional, the UART serial boot allows to load in DDR or to program the bootloaders, and use them to program the rest of the system with a faster interface as USB, ethernet... |
Refers to page:
- How_to_manually_update_bootloaders for example of U-Boot commands used to update the memory
- How to load U-Boot with STM32CubeProgrammer for command used to load U-Boot in DDR with STM32CubeProgrammer over UART.
Moreover the default UART baudrate can be increased if a higher UART frequency is supported by the hardware, for example on ST Microelectronics boards and with console on STLink you can increase it up to 1 Mbit/s:
- the selected baudrate is selected on host with the br option of STM32CubeProgrammer
- the UART baudrate is automatically detected by ROM code
- for bootloaders, the baudrate is defined during compilation:
- in your U-Boot board defconfig with the CONFIG_BAUDRATE flags
- for TF-A BL2 with compilation flage STM32MP_UART_BAUDRATE
2. Console and UART serial boot[edit | edit source]
When UART instance used for serial boot is the same than UART used for the bootloader consoles, useful for debug, these console are automatically deactivated.
As the console is not available when STM32CubeProgrammer other UART is used, the debug is done with GDB.
For STMicroelectronics boards for example, we have only one UART activated by default, used for console, and we have no console when STCubeProgrammer is used over this UART on STLink console.
See How to load U-Boot with STM32CubeProgrammer page for tips to restore console in U-Boot, when bootloader are loaded, and when the same UART instance is used.
But if you have a second UART available on you design and if you want a debug trace of boot-loaders during a serial UART boot, you can:
- either use a second UART instance available on the board and supported by ROM code for serial boot;
this UART instance need to be defined in U-Boot and in TF-A device tree to be used bystm32prog
command and the console is kept unchanged - either activate a second UART and select it as console in each boot-loader, the used console and early console must be identical in TF-A, OP-TEE and U-Boot:
- update
stdout-path
in thechosen
node of each device tree - when early debug is activated, update build configuration for the used uart instance because early console of each boot-loader assumed that UART configuration is done by previous stage
- for details more debug details, see the debug page of each boot-loaders
- update
For example, on STM32MP157x-EV1 a second UART is available on GPIO extension connector with:
- GND (Black) on pin 6 (GND)
- RXD (Yellow) on pin 8 (USART3_TX)
- TXD (Orange) on pin10 (USART3_RX)
Example of a device tree modification to change the console, when UART is present (here serial1) in device tree but not activated:
aliases { serial0 = &uart4; serial1 = &usart3; }; // change console to serial1 chosen { stdout-path = "serial1:115200n8"; }; // activate serial on GPIO connector &usart3 { status = "okay"; };
Example of a device tree modification to add a new UART instance, with replace console on serial0:
aliases { - serial0 = &usart2; + serial0 = &uart5; }; chosen { stdout-path = "serial0:115200n8"; }; +&uart5 { + pinctrl-names = "default"; + pinctrl-0 = <&uart5_pins_a>; + status = "okay"; +}; + +&pinctrl { + uart5_pins_a: uart5-0 { + pins1 { + pinmux = <STM32_PINMUX('G', 9, AF5)>; /* UART5_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = <STM32_PINMUX('G', 10, AF5)>; /* UART5_RX */ + bias-disable; + }; + }; +};
3. Examples[edit | edit source]
The next UART flashlayout examples on STM32MP157F-DK2 are based on the initial USB file "flashlayout_st-image-weston/optee/FlashLayout_sdcard_stm32mp157f-dk2-optee.tsv":
#Opt Id Name Type IP Offset Binary - 0x01 fsbl-boot Binary none 0x0 arm-trusted-firmware/tf-a-stm32mp157f-dk2-optee-programmer-usb.stm32 - 0x03 fip-boot FIP none 0x0 fip/fip-stm32mp157f-dk2-optee-programmer-usb.bin P 0x04 fsbl1 Binary mmc0 0x00004400 arm-trusted-firmware/tf-a-stm32mp157f-dk2-optee-sdcard.stm32 P 0x05 fsbl2 Binary mmc0 0x00044400 arm-trusted-firmware/tf-a-stm32mp157f-dk2-optee-sdcard.stm32 PD 0x06 metadata1 FWU_MDATA mmc0 0x00084400 arm-trusted-firmware/metadata.bin PD 0x07 metadata2 FWU_MDATA mmc0 0x000C4400 arm-trusted-firmware/metadata.bin P 0x08 fip-a FIP mmc0 0x00104400 fip/fip-stm32mp157f-dk2-optee-sdcard.bin PED 0x09 fip-b FIP mmc0 0x00504400 none PED 0x0A u-boot-env ENV mmc0 0x00904400 none P 0x10 bootfs System mmc0 0x00984400 st-image-bootfs-openstlinux-weston-stm32mp1.bootfs.ext4 P 0x11 vendorfs FileSystem mmc0 0x04984400 st-image-vendorfs-openstlinux-weston-stm32mp1.vendorfs.ext4 P 0x12 rootfs FileSystem mmc0 0x05984400 st-image-weston-openstlinux-weston-stm32mp1.rootfs.ext4 P 0x13 userfs FileSystem mmc0 0x105984400 st-image-userfs-openstlinux-weston-stm32mp1.userfs.ext4
Used with command:
STM32_Programmer_CLI -c port=usb1 -w FlashLayout_sdcard_stm32mp157f-dk2-optee.tsv
And the used UART port, on Linux is /dev/ttyACM0.
3.1. Load bootloaders in DDR[edit | edit source]
With default UART baudrate at 115200 bits/s, the U-Boot take up to 4 minutes for complete.
See page How_to_load_U-Boot_with_STM32CubeProgrammer for detail and the need changes in U-Boot to have console access.
In the flashlayout file, "tf-a-stm32mp157f-dk2-optee-programmer-usb.stm32" is replaced by "tf-a-stm32mp157f-dk2-optee-programmer-uart.stm32".
The modified file "FlashLayout_sdcard_stm32mp157f-dk2-optee_uart.tsv" iss:
#opt Id Name Type Device Offset Binary - 0x01 fsbl-boot Binary none 0x0 arm-trusted-firmware/tf-a-stm32mp157f-dk2-optee-programmer-uart.stm32 - 0x03 fip-boot FIP none 0x0 fip/fip-stm32mp157f-dk2-optee-programmer-usb.bin
And the command to load U-Boot is:
STM32_Programmer_CLI -c port=/dev/ttyACM0 -w flashlayout_st-image-weston/optee/FlashLayout_sdcard_stm32mp157f-dk2-optee_uart.tsv
3.2. Program bootloaders[edit | edit source]
If you want program the bootloaders on boot device with UART with STLink, it is recommended to change the baudrate at 1MB/s.
3.2.1. Update TF-A BL2[edit | edit source]
Recompile TF-A BL2 with compilation flag STM32MP_UART_BAUDRATE=1000000 and replace the OpenSTLinux file
- arm-trusted-firmware/tf-a-stm32mp157f-dk2-optee-programmer-uart.stm32
3.2.2. Update U-Boot in UART FIP[edit | edit source]
- update the U-Boot defconfig with
CONFIG_BAUDRATE=1000000
make stm32mp15_defconfig make DEVICE_TREE=stm32mp157f-dk2 all
- update FIP file with the U-Boot binary:
cp fip/fip-stm32mp157f-dk2-optee-programmer-usb.bin fip/fip-stm32mp157f-dk2-optee-programmer-uart.bin fiptool --verbose update --nt-fw u-boot-nodtb.bin --hw-config u-boot.dtb fip/fip-stm32mp157f-dk2-optee-programmer-uart.bin
3.2.3. Create UART flashlayout file[edit | edit source]
Found after this new UART file "FlashLayout_sdcard_stm32mp157f-dk2-optee_uart.tsv" using:
- the UART TF-A BL2 binary tf-a-stm32mp157f-dk2-optee-programmer-uart.stm32
- the updated FIP fip-stm32mp157f-dk2-optee-programmer-uart.bin
- use empty file system partitions to only program the bootloaders
#opt Id Name Type Device Offset Binary - 0x01 fsbl-boot Binary none 0x0 arm-trusted-firmware/tf-a-stm32mp157f-dk2-optee-programmer-uart.stm32 - 0x03 fip-boot FIP none 0x0 fip/fip-stm32mp157f-dk2-optee-programmer-uart.bin P 0x04 fsbl1 Binary mmc0 0x00004400 arm-trusted-firmware/tf-a-stm32mp157f-dk2-optee-sdcard.stm32 P 0x05 fsbl2 Binary mmc0 0x00044400 arm-trusted-firmware/tf-a-stm32mp157f-dk2-optee-sdcard.stm32 PD 0x06 metadata1 FWU_MDATA mmc0 0x00084400 arm-trusted-firmware/metadata.bin PD 0x07 metadata2 FWU_MDATA mmc0 0x000C4400 arm-trusted-firmware/metadata.bin P 0x08 fip-a FIP mmc0 0x00104400 fip/fip-stm32mp157f-dk2-optee-sdcard.bin PED 0x09 fip-b FIP mmc0 0x00504400 none PED 0x0A u-boot-env ENV mmc0 0x00904400 none PE 0x10 bootfs System mmc0 0x00984400 none PE 0x11 vendorfs FileSystem mmc0 0x04984400 none PE 0x12 rootfs FileSystem mmc0 0x05984400 none PE 0x13 userfs FileSystem mmc0 0x105984400 none
3.2.4. Program the board[edit | edit source]
![]() |
The USB cable must be disconnected before reset else ROM code select the USB device for serial boot. |
- Select serial boot on the board with BOOT pin and reset the board (the red LED is blinking until UART connection)
- On HOST execute the STM32CubeProgrammer command:
STM32_Programmer_CLI -c port=/dev/ttyACM0 br=1000000 -w flashlayout_st-image-weston/optee/FlashLayout_sdcard_stm32mp157f-dk2-optee_uart.tsv
- Select the correct boot mode and reboot the board.
The bootloaders are executed up to U-Boot console, ready to update the partitions needed by Linux kernel boot (see How_to_manually_update_bootloaders for examples).