Last edited one month ago

How to configure U-Boot for your board

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

This page explains how to configure the U-Boot source for your board.

Many existing ressources [1] [2] explain the porting of U-Boot on a new board. This article only provides basic guidelines for STM32 Arm® Cortex® MPUs More info.png.

To summarize, you need to configure U-Boot for your <VENDOR> <BOARD> with the following steps:

  1. Add your board device tree: arch/arm/dts/<board>.dts and <board>-u-boot.dtsi.
  2. Create your own board support directory: board/<vendor>/<board>.
  3. Add TARGET_<VENDOR> _<BOARD> in Kconfig.
  4. Create your board defconfig: defconfig/<board>_defconfig.
  5. Add your configuration file : include/configs/<board>.h.

1. Device tree[edit | edit source]

Add the board device tree files <board>.dts and <board>-u-boot.dtsi in arch/arm/dts , following the steps below:

  • Copy the Linux kernel device tree in the directory arch/arm/dts : <board>.dts.

E.g for STM32MP13x lines More info.png

 dtb-$(CONFIG_STM32MP13X) += \
 	<STM32MP13 board>.dtb

E.g for STM32MP15x lines More info.png

 dtb-$(CONFIG_STM32MP15X) += \
 	<STM32MP15 board>.dtb 

E.g for STM32MP21x lines More info.png

 dtb-$(CONFIG_STM32MP21X) += \
 	<STM32MP21 board>.dtb

E.g for STM32MP25x lines More info.png

 dtb-$(CONFIG_STM32MP23X) += \
 	<STM32MP23 board>.dtb

E.g for STM32MP25x lines More info.png

 dtb-$(CONFIG_STM32MP25X) += \
 	<STM32MP25 board>.dtb

At this point you can use the generic STM32 MPU defconfig with the STMicroelectronics board directory, but with your board device tree.

The board-specific features are not correctly managed, but should be sufficient for a simple board derived from STMicroelectronics designs.

You can use the STMicroelectronics code with your device tree as follows:

E.g for STM32MP13x lines More info.png

  make stm32mp13_defconfig
  make DEVICE_TREE=<STM32MP13 board> all

E.g for STM32MP15x lines More info.png

  make stm32mp15_defconfig
  make DEVICE_TREE=<STM32MP15 board> all

E.g for STM32MP21x lines More info.png

  make stm32mp21_defconfig
  make DEVICE_TREE=<STM32MP21 board> all

E.g for STM32MP23x lines More info.png

  make stm32mp23_defconfig
  make DEVICE_TREE=<STM32MP23 board> all

E.g for STM32MP25x lines More info.png

  make stm32mp25_defconfig
  make DEVICE_TREE=<STM32MP25 board> all

The next steps are required if the STMicroelectronics generic board does not comply with all of the expected behavioral aspects for your board (for example MAC address not located in OTP, specific PMIC, specific boot command).

1.1. Console[edit | edit source]

The U-Boot console use stdout-path defined in the chosen node of the Linux kernel device tree as described in the Linux kernel binding[3].

As the console is used before relocation, you must add the flags bootph-all for each associated nodes (and sub-nodes).

For example in device tree from kernel = <board>.dts:

 / {
 	...
 	chosen {
 		stdout-path = " serial0:115200n8";
 	  };
 	aliases {
 		serial0 = &uart4;
 	};
 	...
 };
 ...
 &uart4 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart4_pins_a>;
 	status = "okay";
 };

And in the U-Boot add-on file = <board>-u-boot.dtsi:

 &uart4 {
 	bootph-all;
 };
 
 &uart4_pins_a {
 	bootph-all;
 	pins1 {
 		bootph-all;
 	};
 	pins2 {
 		bootph-all;
 	};
 };

The variable baudrate, initialized with CONFIG_BAUDRATE value, is used to configure the desired baud rate; the default value is 115200 bauds.

An early DEBUG trace, before the device tree parsing, can be also activated with CONFIG_DEBUG_UART and board_debug_uart_init() (see U-Boot-How to debug page for details).

1.2. Config node[edit | edit source]

Some properties in the 'config' node are also used to dynamically configure the U-Boot behavior in the board device tree as follows:

  • Generic U-Boot configuration: doc/device-tree-bindings/config.txt
    • u-boot,mmc-env-partition = name of partition used to save U-Boot environment
    • u-boot,boot-led = name of boot-progress indicator LED
    • u-boot,error-led = name of error indicator LED (only for STM32MP1 series)
  • Some STMicroelectronics properties only for STM32MP1 series, managed in board/st/stm32mp1/stm32mp1.c :
    • st,adc_usb_pd = ADC channels used to check USB power supply
    • st,stm32prog-gpios = GPIO used to force STM32CubeProgrammer mode
    • st,fastboot-gpios = GPIO used to force Android Fastboot mode only

These parameters are managed in U-Boot generic code or in STMicroelectronics board code (board/st/stm32mp1/stm32mp1.c or board/st/stm32mp2/stm32mp2.c ) in line with LEDs and buttons on STM32 MPU boards; they can only be used if your board reuses the associated code.

E.g for STM32MP15x lines More info.png, in arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi , the properties are:

   	config {
   		u-boot,boot-led = "heartbeat";
   		u-boot,error-led = "error";
   		u-boot,mmc-env-partition = "u-boot-env";
   		st,adc_usb_pd = <&adc1 18>, <&adc1 19>;
   		st,fastboot-gpios = <&gpioa 13 GPIO_ACTIVE_LOW>;
   		st,stm32prog-gpios = <&gpioa 14 GPIO_ACTIVE_LOW>;
   	};

1.3. USB node[edit | edit source]

1.3.1. On STM32MP1 series and STM32MP21x lines More info.png[edit | edit source]

The U-Boot drivers for USB OTG internal peripheral, with the compatible st,stm32mp15-hsotg, does not have a full OTG support with USB host and USB device detection; to avoid issue only the gadget driver is used in STM32 MPU boards with drivers/usb/gadget/dwc2_udc_otg.c activated by CONFIG_USB_GADGET_DWC2_OTG; the host driver drivers/usb/host/dwc2.c is not activated with CONFIG_USB_DWC2.

Warning white.png Warning
If you want to activate the HOST driver with CONFIG_USB_DWC2 configuration, the VBUS protection needs to be implemented in you board code to protect the USB power line, avoiding to power up the VBUS when USB HOST is connected on USB OTG port.

Moreover, as only one driver for the same node for OTG internal peripheral must be activated or only the first one will bind in U-Boot , the USB device driver, with CONFIG_USB_GADGET_DWC2_OTG, must be deactivated when you activate the USB HOST driver with CONFIG_USB_DWC2.

Two methods exist to support USB OTG in U-Boot device tree:

  1. Two U-Boot specific properties are added to support the possible USB connection of ID pin and VBUS on the board (method used in ecosystem release ≤ v5.1.0 ):
    • u-boot,force-b-session-valid: This property forces USB B session (by deactivating the detection with ID pin) and deactivates VBus sensing. It is used when all these features are managed by the board.
    • u-boot,force-vbus-detection: This property forces Vbus sensing when u-boot,force-b-session-valid is used (typically when the ID pin is not correctly managed).
  2. Alternately the generic USB properties can be used to force the usb role switch (recommended on STM32MP21x lines More info.png)
    • usb-role-switch: Add usb-role-switch property to OTG controller node, it indicates that the device is capable of assigning the USB data role (USB host or USB device).
    • role-switch-default-mode: Add role-switch-default-mode = "host" or "peripheral" according to dr_mode, it forces corresponding valid session in OTG driver

See Linux Generic USB OTG Controller binding file (Documentation/devicetree/bindings/usb/usb-drd.yaml ) for USB properties description such as dr_mode, usb-role-switch, role-switch-default-mode...

Examples of USB configuration in <board>-u-boot.dtsi:

  • B session forced as device mode, USB ID pin not used and VBus sensing deactivated:
 &usbotg_hs {
 	u-boot,force-b-session-valid;
 	dr_mode = "peripheral";
 };
  • B session and VBus sensing forced (deactived by default with "force-b-session-valid")
 &usbotg_hs {
 	u-boot,force-b-session-valid;
 	u-boot,force-vbus-detection;
 	dr_mode = "peripheral";
 };
  • usb role switch and usb default mode
&usbotg_hs {
       dr_mode = "peripheral";                          /* could be "host", see USB generic bindings */
       usb-role-switch;                                 /* see USB generic bindings */
       role-switch-default-mode = "peripheral";         /* could be "host", see USB generic bindings */
};

1.3.2. On STM32MP23x lines More info.png and STM32MP25x lines More info.png[edit | edit source]

The U-Boot drivers for the USB3DR internal peripheral, with the st,stm32mp25-dwc3 compatible, only supports the peripheral mode. E.g. only the gadget driver (drivers/usb/dwc3/gadget.c ) is used in STM32 MPU boards. It is activated by CONFIG_USB_DWC3_GADGET. Full Dual-Role support with automatic USB host and USB device detection isn't supported.

Warning white.png Warning
If the end user wants to activate the HOST configuration, the VBUS protection needs to be implemented in the board code to protect the USB power line, avoiding to power up the VBUS when another USB HOST is connected on USB3DR port, and providing a valid USB VBUS supply on the connector (for the device to be connected). The operation of HOST and DEVICE configuration is mutually exclusive using USB3DR internal peripheral registers.

Examples of USB configuration in <board>-u-boot.dtsi:

  • USB3DR forced as device mode:
&usb3dr {
	dwc3: usb@48300000 {
		maximum-speed = "high-speed";
		dr_mode = "peripheral";
	};
};

2. Board subdirectory[edit | edit source]

Create your own board support subdirectory = board/<vendor>/<board> and add a Makefile file.

You can add any source files needed for your board.

In this Makefile, you can compile the STMicroelectronics files (in board/st/stm32mp1 or in board/st/common) or just copy them as starting point then modify them.

For example board/dhelectronics/dh_stm32mp1/Makefile uses STMicroelectronics board files in ../../st/stm32mp1 directory and local file "board.c"

 ifdef CONFIG_SPL_BUILD
 obj-y += ../../st/stm32mp1/spl.o
 endif

 obj-y += ../../st/stm32mp1/board.o board.o

3. Kconfig[edit | edit source]

You need to support your board in Kconfig with a new configuration flag: TARGET_<VENDOR>_<BOARD>

This flag will replace the flags for STMicroelectronics boards support TARGET_ST_<BOARD> used in our defconfig.

  • TARGET_ST_STM32MP13X
  • TARGET_ST_STM32MP15X
  • TARGET_ST_STM32MP21X
  • TARGET_ST_STM32MP23X
  • TARGET_ST_STM32MP25X

3.1. Arch Kconfig: arch/arm/mach-stm32mp/Kconfig [edit | edit source]

  1. Add new CONFIG_TARGET_<VENDOR>_<BOARD> and for this new option, select the required CONFIG_
  2. Include your board Kconfig (source "board/<vendor>/<board>/Kconfig") in the SoC Konfig file

With the minal SoC options CONFIG to select and Kconfig file to modified :

E.g for STM32MP15x lines More info.png, the file arch/arm/mach-stm32mp/Kconfig.15x is modified:

 if STM32MP15x
 
 [...]
 choice
 	prompt "STM32MP15x board select"
 	optional
   
   [...]
   
   config TARGET_<VENDOR>_<BOARD>
   	bool "<vendor> <board> board"
   	select STM32MP15x
   	help
 		target the <vendor> <board> board with SOC STM32MP15x
 		managed by board/<vendor>/<board>
 
 endchoice
 
 [...]
 source "board/st/stm32mp1/Kconfig"
 source "board/dhelectronics/dh_stm32mp1/Kconfig"
 source "board/<vendor>/<board>/Kconfig"
  
 endif

3.2. Board Kconfig: board/<vendor>/<board>/Kconfig[edit | edit source]

The mininimal content of this file is:

 if TARGET_<VENDOR>_<BOARD>
 
 config SYS_BOARD
 	default "<board>"
 
 config SYS_VENDOR
 	default "<vendor>"
 
 config SYS_CONFIG_NAME
 	default "<config>"
 endif

For example see board/dhelectronics/dh_stm32mp1/Kconfig .

SYS_CONFIG_NAME selects the used configuration file: include/configs/SYS_CONFIG_NAME.h.

4. Defconfig[edit | edit source]

Add a new defconfig for your board in configs .

  • copy the correct defconfig to your "<vendor>_<board>_defconfig" (configs/stm32mp13_defconfig , configs/stm32mp15_defconfig , configs/stm32mp25_defconfig )
  • select your new defconfig: make <vendor>_<board>_defconfig
  • use make menuconfig to change your defconfig
    • remove the STMicroelectronics board config (CONFIG_TARGET_ST_STM32MP13X, CONFIG_TARGET_ST_STM32MP15X, CONFIG_TARGET_ST_STM32MP25X)
    • add CONFIG_TARGET_<VENDOR>_<BOARD>
    • change CONFIG_DEFAULT_DEVICE_TREE to the name of the board device tree: "<board>"
  • save the updated defconfig: make savedefconfig
  • verify and copy the file "defconfig" in configs/<vendor>_<board>_defconfig

For example see the file configs/stm32mp15_dhcom_basic_defconfig .

5. Configuration file[edit | edit source]

The configuration file is the include file in include/configs directory selected in Makefile.autoconf by CONFIG_SYS_CONFIG_NAME.

This file defines the CONFIG_ flags of the boards that are not defined with Kconfig.

For example, in this configuration file, you can choose the initial U-Boot environment through CONFIG_EXTRA_ENV_SETTINGS, including the boot command.

A generic configuration file is provided for each family:

For STMicroelectronics boards in OpenSTLinux, some configuration (bootcmd) are modified with CONFIG_SYS_CONFIG_NAME =

These STMicroelectronics configuration files can be:

  • either used in your project without modification through CONFIG_SYS_CONFIG_NAME = a file in the list:
    • "stm32mp13_common.h" or "stm32mp13_st_common.h"
    • "stm32mp15_common.h" or " stm32mp15_st_common.h"
    • "stm32mp21_common.h" or " stm32mp21_st_common.h"
    • "stm32mp23_common.h" or " stm32mp23_st_common.h"
    • "stm32mp25_common.h" or " stm32mp25_st_common.h"
  • included in your board configuration file (e.g. #include "stm32mp13_common.h") before to override them or
  • used a starting point for your configuration file (copy and update it).

6. Configuration example[edit | edit source]

6.1. MTD partitions[edit | edit source]

In U-Boot, all the mtd fixed partitions are managed in U-Boot device tree based on the binding defined in Linux kernel file Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml .

For example in arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi with:

&flash0 {
	partitions {
		compatible = "fixed-partitions";
		#address-cells = <1>;
		#size-cells = <1>;

		partition@0 {
			label = "fsbl1";
			reg = <0x00000000 0x00040000>;
		};
		partition@40000 {
			label = "fsbl2";
			reg = <0x00040000 0x00040000>;
		};
		partition@80000 {
			label = "metadata1";
			reg = <0x00080000 0x00040000>;
		};
		partition@c0000 {
			label = "metadata2";
			reg = <0x000c0000 0x00040000>;
		};
		partition@100000 {
			label = "fip-a";
			reg = <0x00100000 0x00400000>;
		};
		partition@500000 {
			label = "fip-b";
			reg = <0x00500000 0x00400000>;
		};
		partition@900000 {
			label = "u-boot-env";
			reg = <0x00900000 0x00080000>;
		};
		partition@980000 {
			label = "nor-user";
			reg = <0x00980000 0x03680000>;
		};
	};
};
&nand {
	partitions {
		compatible = "fixed-partitions";
		#address-cells = <1>;
		#size-cells = <1>;

		partition@0 {
			label = "fsbl1";
			reg = <0x00000000 0x00080000>;
		};
		partition@80000 {
			label = "fsbl2";
			reg = <0x00080000 0x00080000>;
		};
		partition@100000 {
			label = "metadata1";
			reg = <0x00100000 0x00080000>;
		};
		partition@180000 {
			label = "metadata2";
			reg = <0x00180000 0x00080000>;
		};
		partition@200000 {
			label = "fip-a1";
			reg = <0x00200000 0x00400000>;
		};
		partition@600000 {
			label = "fip-a2";
			reg = <0x00600000 0x00400000>;
		};
		partition@a00000 {
			label = "fip-b1";
			reg = <0x00a00000 0x00400000>;
		};
		partition@e00000 {
			label = "fip-b2";
			reg = <0x00e00000 0x00400000>;
		};
		partition@1200000 {
			label = "UBI";
			reg = <0x01200000 0x3ee00000>;
		};
	};
};

The customer can modify the MTD in U-Boot device tree for its board.

Warning white.png Warning
Other U-Boot configurations depend on the offset of MTD partition.

E.g for STM32MP1 series, the offset of U-Boot ENV in NOR named "u-boot-env" is align with

  • CONFIG_ENV_SECT_SIZE 0x40000, aligned with the maximum supported erase block for NOR, 256 Kbytes
  • CONFIG_ENV_OFFSET 0x900000, offset of ENV partition in NOR
  • CONFIG_ENV_OFFSET_REDUND 0x940000, offset of the second 'sector' in the ENV partition

U-Boot dynamically update the Linux® kernel device tree with these information with call fdt_copy_fixed_partitions() under CONFIG_OF_BOARD_SETUP in ft_board_setup() in board/st/stm32mp1/stm32mp1.c or board/st/stm32mp2/stm32mp2.c .

This device tree update enables the alignment of MTD configuration between U-Boot and Linux, and avoids STM32CubeProgrammer support issues as the MTD partition sizes has to be aligned with Flashlayout.

To define the MTD partitions in Linux device tree, no more call fdt_copy_fixed_partitions() in your board code or deactivate CONFIG_OF_BOARD_SETUP in the customer defconfig. However this might result in misalignment with U-Boot.

For information, you can also define the MTD configuration directly through this U-Boot configuration

  • CONFIG_MTDPARTS_DEFAULT and CONFIG_MTDIDS_DEFAULT
  • or by directly setting variable CONFIG_EXTRA_ENV_SETTINGS in your board configuration file:
    • mtdparts="mtdparts=nand0:2m(fsbl),4m(fip1),4m(fip2),-(UBI)"
    • mtdids="nand0=nand0"

This corresponds to a generic U-Boot configuration (see U-Boot documentation for additional details).

6.2. U-Boot memory mapping[edit | edit source]

The memory used by U-Boot is defined by several configurations.

6.2.1. Before relocation[edit | edit source]

Configuration is defined by Kconfig defines:

  • CONFIG_TEXT_BASE: Load Address of U-Boot, aligned with TF-A configuration (see STM32MP_BL33_BASE in TF-A FW config)
  • CONFIG_CUSTOM_SYS_INIT_SP_ADDR: Start for stack (reverse order)
  • CONFIG_PRE_CON_BUF_ADDR and CONFIG_PRE_CON_BUF_SZ (4096): PreConsole buffer
  • CONFIG_BOOTSTAGE_STASH_ADDR: bootstage stash buffer for SPL
  • CONFIG_SYS_MALLOC_F_LEN: reserved memory for alloc in STACK

For STM32MP1 series, the beginning of the DDR is mapped, limited by CONFIG_DDR_CACHEABLE_SIZE to avoid overlapping with OP-TEE reserved memory, and used by U-Boot.

For STM32MP2 series, the beginning of the DDR, before CONFIG_TEXT_BASE is NOT mapped, this memory is secured by OP-TEE and used by the secured world of the co-processor.

If you change the default configurations in your board defconfig file, you need to avoid overlap, particularly for stack and OP-TEE. The default values, used for STMicroelectronics boards, are defined:

Address Comment Config
C3000000 Bootstage CONFIG_BOOTSTAGE_STASH_ADDR
C0800000 PreConsole CONFIG_PRE_CON_BUF_ADDR + CONFIG_PRE_CON_BUF_SZ
C0400000 start for stack CONFIG_CUSTOM_SYS_INIT_SP_ADDR including CONFIG_SYS_MALLOC_F_LEN
C0000000 Load Address of U-Boot CONFIG_TEXT_BASE
Address Comment Config
C3000000 Bootstage CONFIG_BOOTSTAGE_STASH_ADDR
C02FF000 PreConsole CONFIG_PRE_CON_BUF_ADDR + CONFIG_PRE_CON_BUF_SZ
C0100000 Load Address of U-Boot CONFIG_TEXT_BASE
C0100000
C0000000
Stack (reverse order) CONFIG_CUSTOM_SYS_INIT_SP_ADDR including CONFIG_SYS_MALLOC_F_LEN,
limited by start of DDR
Address Comment Config
0x87000000 Bootstage CONFIG_BOOTSTAGE_STASH_ADDR
0x84800000 PreConsole CONFIG_PRE_CON_BUF_ADDR + CONFIG_PRE_CON_BUF_SZ
0x90000000 start for stack CONFIG_CUSTOM_SYS_INIT_SP_ADDR including CONFIG_SYS_MALLOC_F_LEN
0x84000000 Load Address of U-Boot, after OP-TEE and secure memory CONFIG_TEXT_BASE

6.2.2. After relocation[edit | edit source]

U-Boot is reloaded at the end of the DDR, where it found enough available memory to its code and other reserved memory in common/board_r.c , e.g CONFIG_SYS_MALLOC_LEN and framebuffer.

This relocation address can be checked with bdinfo command in U-Boot console.

The DDR size is retrieved by U-Boot:

  • for STM32MP1 series, from DDRCTRL configuration with ADDRMAP1-6 registers in RAM driver (see stm32mp1_ddr_size() in drivers/ram/stm32mp1/stm32mp1_ram.c )
  • for STM32MP2 series, without RAM driver, from the device tree

The reserved-memory nodes present in its device tree are preserved by U-Boot (see board_get_usable_ram_top() in arch/arm/mach-stm32mp/dram_init.c ).

To avoid U-Boot violation access, the secure memory used OP-TEE needs to be aligned with OP-TEE reserved memory nodes in U-Boot device tree for your board device tree, for example arch/arm/dts/stm32mp135f-dk.dts :

 optee@de000000 {
 	reg = <0xde000000 0x2000000>;
 	no-map;
 };

The beginning of DDR is used by U-Boot commands (bootm or booti for example) and scripts (DISTRO) as defined with variables in U-Boot environment or config:

For STM32MP1 series:

  • CONFIG_SYS_LOAD_ADDR=0xc2000000, used by some U-Boot commands.
  • kernel_addr_r=0xc2000000
  • fdt_addr_r=0xc4000000
  • scriptaddr=0xc4100000
  • pxefile_addr_r=0xc4200000
  • fdtoverlay_addr_r=0xc4300000
  • ramdisk_addr_r=0xc4400000

For STM32MP2 series

  • CONFIG_SYS_LOAD_ADDR=0x84000000, used by some U-Boot commands.
  • kernel_comp_addr_r=0x84000000, used by booti command during decompression of Image.gz
  • kernel_comp_size=0x04000000, used by booti command, max size of Image.gz
  • kernel_addr_r=0x8a000000, load address of Image / Image.gz and address of decompressed image
  • fdt_addr_r=0x90000000
  • scriptaddr=0x90100000
  • pxefile_addr_r=0x90200000
  • fdtoverlay_addr_r=0x90300000
  • ramdisk_addr_r=0x90400000

These default values, define in generic configuration files, allow to load 32MB (for STM32MP1 series) / 96MB (for STM32MP2 series) kernel or FIT (uncompressed/compressed), 1MB device tree file (fdt), 1MB script, 1MB pxe file and 1MB for overlay file and the ramdisk at the end.
For STM32MP1 series the kernel is loaded (from uImage) at its final location, normally 0xC0000000, by the bootm command.
For STM32MP2 series the kernel is executed in place by the booti command, at 0x8a000000, after possible decompression.

You can change these value in the configuration file of your board to allow bigger files or optimized loading address, e.g. without relocation (device tree with fdt_high=0xFFFFFFFF or RAMDISK with initrd_high=0xffffffff) or load kernel at a final location (see zImage in arm/booting.html).

See U-Boot documentation (usage/environment.html) for details on these variables fdt_high and initrd_high.

7. References[edit | edit source]