Last edited 2 weeks 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.

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. Using serial boot on UART console[edit | edit source]

To use STM33CubeProgrammer on UART serial console, you must:

  • Modify the flashlayout tsv file to use the specific fsbl binary dedicated to use UART serial by adapting only the fsbl-boot binary
  • Prepare the board by putting the board on programming mode and power-on/reset the board; the red led is blinking
  • Launch the process with the tool STM32Programmer and the adapted flashlayout TSV file with UART serial binary

See the last chapter for complete examples.

Information
If you have adapted OP-TEE and U-Boot to use a different UART serial, you need to adapt also the fip-boot binary

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. See the next chapter to debug tips.

Warning
if the programming doesn't work, doesn't start or the red led is not blinking you need to verify if a USB device cable is connected on the board (USB2 OTG or USB3 DRD).

If it is the case, the ROM code start the serial boot on USB with DFU; you need to remove this USB cable to perform a UART Serial flash.

STM32CubeProgrammer provides the list of different interfaces available with option -l, including the USB DFU devices present if a USB cable with DFU support is unfortunately connected to the board.

STM32_Programmer_CLI -l 
     -------------------------------------------------------------------
                       STM32CubeProgrammer v2.22.0                  
     -------------------------------------------------------------------
=====  DFU Interface   =====
Total number of available STM32 device in DFU mode: 1
 Device Index           : USB1
 USB Bus Number         : 003
 USB Address Number     : 004
 Product ID             : DFU in HS Mode @Device ID /0x501, @Revision ID /0x1003
 Serial number          : 003D000B3232511538303631
 Firmware version       : 0x0110
 Device ID              : 0x0501
=====  UART Interface  =====
Total number of serial ports available: xx
...
Board Name  : STM32MP135F-DK
ST-LINK SN: 001200284741500420383733
Port: ttyACM0
Location: /dev/ttyACM0
Description: STLINK-V3
Manufacturer: STMicroelectronics
..
Board Name  : STM32MP135F-DK
ST-LINK SN: 001200284741500420383733
Port: ttyACM1
Location: /dev/ttyACM1
Description: STLINK-V3
Manufacturer: STMicroelectronics
..
Port: ttyUSB1
Location: /dev/ttyUSB1
Description: CP2102 USB to UART Bridge Controller
Manufacturer: Silicon Labs

On STMicroelectronics boards

  • the UART for console is provided with an embedded ST-LINK on a dedicated USB connector (Type-C or micro-B), available with a ttyACM device on Linux PC
    except for STM32MP215F-DK on which the functionality is available via specific connectors (see STM32MP215x-DKx board overview for details).
  • for boards with a connector USB Type-C common for Power in and for ST-Link, as STM32MP257F-DK , the PC must be connected on USB Type-C port with Power Delivery support with USB Type-C/Type-C cable.

3. Debug[edit | edit source]

As the UART console is not available when STM32CubeProgrammer on UART is used, the debug is done with GDB when the only one UART instance is available.

See How to load U-Boot with STM32CubeProgrammer page for tips to restore console in U-Boot when boot-loader are loaded and STM32CubeProgrammer is no more used.

For STMicroelectronics boards, we have only one UART activated by default, used for console and provided by embedded ST-Link for most of STMicroelectronics boards, thus we have no console when STCubeProgrammer is used over this UART on board this console.


3.1. Add a second console[edit | edit source]

If you have a second UART available on your design, you can use it for a debug trace of boot-loaders during a serial UART boot.

In this case, the board use one UART instance of STM32CubeProgrammer and one instance for the console when the seconde UART is configured:

  • either use the second UART instance available on the board is 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 in boot-loaders
  • either activate and select the second UART 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

3.2. Example of debug console activation[edit | edit source]

As 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)

The device tree modification to change the console, when UART is present (here serial1) in device tree but not activated is:

aliases {
	serial0 = &uart4;
	serial1 = &usart3;
};

// change console to serial1
chosen {
	stdout-path = "serial1:115200n8";
};

// activate serial on GPIO connector
&usart3 {
	status = "okay";
};

The device tree modification to add a new UART instance, with replace console on serial0 is:

	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;
+		};
+	};
+};

4. 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.

4.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

If you have adapted OP-TEE and U-Boot to use a different UART serial, you need to adapt also the fip-boot binary.

4.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.

4.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

4.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

4.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

4.2.4. Program the board[edit | edit source]

  • 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).