Last edited one week ago

How to use UART as serial boot device with STM32CubeProgrammer

Applicable for STM32MP13x lines, STM32MP15x lines, STM32MP21x lines, STM32MP23x lines, STM32MP25x lines


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 :

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.

Info white.png Information
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:

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 by stm32prog 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 the chosen 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
      • TF-A (for early and crash console some parameters have to be hard-coded)
      • OP-TEE (set CFG_STM32_EARLY_CONSOLE_UART, early console initialization is based on TF-A configuration)
      • U-Boot

For example, on STM32MP157x-EV1 a second UART is available on GPIO extension connector with:

STM32MP157x-EV1-uart-connection.jpg
  • 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 More info green.png 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]

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]

Info white.png Information
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).