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 .
To summarize, you need to configure U-Boot for your <VENDOR> <BOARD> with the following steps:
- Add your board device tree: arch/arm/dts/<board>.dts and <board>-u-boot.dtsi.
- Create your own board support directory: board/<vendor>/<board>.
- Add TARGET_<VENDOR> _<BOARD> in Kconfig.
- Create your board defconfig: defconfig/<board>_defconfig.
- 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.
- Update arch/arm/dts/Makefile to compile your device tree:
dtb-$(CONFIG_STM32MP13X) += \
<STM32MP13 board>.dtb
dtb-$(CONFIG_STM32MP15X) += \
<STM32MP15 board>.dtb
dtb-$(CONFIG_STM32MP21X) += \
<STM32MP21 board>.dtb
dtb-$(CONFIG_STM32MP23X) += \
<STM32MP23 board>.dtb
dtb-$(CONFIG_STM32MP25X) += \
<STM32MP25 board>.dtb
- Add a U-Boot addon device tree for your board in the arch/arm/dts directory: <board>-u-boot.dtsi
This file is automatically included during <board>.dts processing.
It includes the <STM32MP series>-u-boot.dtsi file provided by STMicroelectronics in arch/arm/dts/ (stm32mp13-u-boot.dtsi , stm32mp15-scmi-u-boot.dtsi , stm32mp25-u-boot.dtsi ) and add all the properties on nodes needed by U-Boot (added nodes, config nodes and bootph-all or bootph-pre-ram attributes as described in U-Boot overview, device tree).
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:
make stm32mp13_defconfig make DEVICE_TREE=<STM32MP13 board> all
make stm32mp15_defconfig make DEVICE_TREE=<STM32MP15 board> all
make stm32mp21_defconfig make DEVICE_TREE=<STM32MP21 board> all
make stm32mp23_defconfig make DEVICE_TREE=<STM32MP23 board> all
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 , 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 [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.
Two methods exist to support USB OTG in U-Boot device tree:
- 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).
- Alternately the generic USB properties can be used to force the usb role switch (recommended on STM32MP21x lines )
- 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 and STM32MP25x lines [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.
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]
- Add new CONFIG_TARGET_<VENDOR>_<BOARD> and for this new option, select the required CONFIG_
- 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 :
- for STM32MP13x lines : CONFIG_STM32MP13X and arch/arm/mach-stm32mp/Kconfig.13x
- for STM32MP15x lines : CONFIG_STM32MP15X and arch/arm/mach-stm32mp/Kconfig.15x
- for STM32MP21x lines : CONFIG_STM32MP21X and arch/arm/mach-stm32mp/Kconfig.21x
- for STM32MP23x lines : CONFIG_STM32MP23X and arch/arm/mach-stm32mp/Kconfig.23x
- for STM32MP25x lines : CONFIG_STM32MP25X and arch/arm/mach-stm32mp/Kconfig.25x
E.g for STM32MP15x lines , 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:
- STM32MP13x lines : include/configs/stm32mp13_common.h
- STM32MP15x lines : include/configs/stm32mp15_common.h
- STM32MP21x lines : include/configs/stm32mp21_common.h
- STM32MP23x lines : include/configs/stm32mp23_common.h
- STM32MP25x lines : include/configs/stm32mp25_common.h
For STMicroelectronics boards in OpenSTLinux, some configuration (bootcmd) are modified with CONFIG_SYS_CONFIG_NAME =
- STM32MP13x lines : stm32mp13_st_common and the configuration file is include/configs/stm32mp13_st_common.h
- STM32MP15x lines : stm32mp15_st_common and the configuration file is include/configs/stm32mp15_st_common.h
- STM32MP21x lines : stm32mp21_st_common and the configuration file is include/configs/stm32mp25_st_common.h
- STM32MP23x lines : stm32mp23_st_common and the configuration file is include/configs/stm32mp25_st_common.h
- STM32MP25x lines : stm32mp25_st_common and the configuration file is include/configs/stm32mp25_st_common.h
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.
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:
- for STM32MP13x lines , in arch/arm/mach-stm32mp/Kconfig.13x or in defconfig file :
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 |
- for STM32MP15x lines , in arch/arm/mach-stm32mp/Kconfig.15x or in defconfig file :
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 |
- for STM32MP21x lines , in arch/arm/mach-stm32mp/Kconfig.21x or in defconfig file
for STM32MP23x lines , in arch/arm/mach-stm32mp/Kconfig.23x or in defconfig file
for STM32MP25x lines , in arch/arm/mach-stm32mp/Kconfig.25x or in defconfig file :
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]
- ↑ https://archive.fosdem.org/2018/schedule/event/state_of_the_art_uboot/attachments/slides/2051/export/events/attachments/state_of_the_art_uboot/slides/2051/fosdem_2018_u_boot.pdf
- ↑ https://elinux.org/images/2/2a/Schulz-how-to-support-new-board-u-boot-linux.pdf
- ↑ dtschema/schemas/chosen.yaml the Linux kernel binding for chosen node