Board Bringup
This document provides guidance for board bring-up in IoT Yocto.
Before starting software bring-up, please verify the hardware status of the board. The following hardware components and interfaces should be inspected according to your board design:
Power source & voltage
Clock frequency
Voltage in different outputs
LEDs status
Check Boot ROM
Connect the board to serial port (UART0
) and start serial communication using a baud rate of 115200
.
If the board is well powered, ROM code logs should appear in the serial interface from UART0
port.
If not, please check whether the hardware is well powered or a powering problem has occurred. The following is an example of Boot ROM log for MT8395:
F0: 102B 0000
F3: 1006 0033 [0200]
F3: 4001 00E0 [0200]
F3: 0000 0000
V0: 0000 0000 [0001]
00: 0000 0000
BP: 0C00 0241 [0000]
G0: 1190 0000
EC: 0080 0000 [0000]
S7: 0000 0000 [0000]
T0: 0000 01AA [100F]
Jump to BL
Different SoC have different Boot ROM log, but the format should be similar.
Create New Yocto Layer
After confirming the SoC is well powered, you can now create new software configurations
for your board. To do so, you need to add new layers
on top of the meta-mediatek-bsp
and meta-rity
layers provided by IoT Yocto.
Download IoT Yocto layers by referring to Get Started with IoT Yocto.
Create a
meta-<board_name>
layer with the following basic architecture:meta-<board_name> ├── conf │ ├── machine │ │ └── <machine_name>.conf # an MACHINE identifier for your board │ ├── layer.conf # │ ├── local.conf.sample # example configuration for users of your board │ └── bblayers.conf.sample # the layers you'd like to include by default │ ├── recipes-bsp │ ├── libdram │ │ ├── files/ # patches to add board support │ │ ├── libdram-lk.bbappend # apply patches to libdram-lk.bb │ │ └── libdram.bbappend # symlink to add the patches to libdram.bb │ │ │ └── u-boot │ ├── files/ # patches to add board support │ └── u-boot_%.bbappend # add device-tree and config patches │ ├── recipes-kernel │ └── linux-mtk │ ├── files/ # patches to add device-tree kernel modification and configuration │ └── linux-mtk_%.bbappend # apply the patches to linux kernel │ ├── recipes-core │ └── wic └── custom.wks.in # Partitioning
Each recipe could extend or override the definition of existing BSP and RITY layers.
Add New Machine Configuration
For board bring-up, it usually involves adding a new machine configuration to specify the following configurations:
DRAM configuration
U-Boot device driver and configuration
Kernel device driver and configuration
Boot process configuration
Additional Yocto package and image customization
In meta-<board_name>/conf/machine
, add a <machine_name>.conf file. The content should be:
Include SoC-recipe include files. For example,
require conf/machine/include/mtxxxx.inc
You can refer to existing board configurations in
meta-mediatek-bsp
layer to know which include files that should be used.For example,
conf/machine/genio-1200-evk.conf
provides configuration for the Genio 1200-EVK which uses eMMC storage by default.conf/machine/genio-1200-evk-ufs.conf
provides configuration for UFS boot and storage configurations for Genio 1200 EVK configured for UFS storage.
Set
LIBDRAM_BOARD_NAME
, See Libdram configurationSet kernel device-tree:
KERNEL_DEVICETREE
, See Kernel device treeSet u-boot configuration:
UBOOT_MACHINE
, See U-boot device treeSet OP-TEE DRAM size:
OPTEE_DRAM_SIZE
, See OP-TEE DRAM size configurationSet overrides via
MACHINEOVERRIDES
variable.Add machine and distro features using
DISTRO_FEATURES_append
andMACHINE_FEATURES_append
.
The following sections show how to achieve this by modifying different recipes.
libdram Configuration
Note
Only MT8365 (Genio 350) requires modification to libdram
. For other SoCs, please skip this section.
Important
Modifying DRAM component requires proprietary software
libdram
from MediaTek. You need to get the source code from MediaTek partners and distributors.The DRAM driver will determine the bank size and bank number based on the voltage of the AUXIN1 pin. Please refer to the hardware design notice and reference design document for guidance, and set the AUXIN1 pin to the correct voltage.
Important
The libdram is used by the bl2 and the download agent(lk). If you make modifications to the source code locally, you need to modify both the libdram
and libdram-lk
.
Using the following commands to obtain the source code.
devtool modify libdram
devtool modify libdram-lk
And also you need to modify both build/workspace/sources/libdram/
and build/workspace/sources/libdram-lk/
. Then rebuild rity-demo-image
and lk
.
In libdram/boards/<board_name>
, add a meson.build
file that contains the reference for DDR configuration:
https://gitlab.com/mediatek/aiot/nda/libdram
libdram
├── board
│ └── <board_name>
│ └── meson.build
├── src
│ └── mtxxxx
│ ├── ddr
│ │ └── <ddr_type>.cfg
│ └── driver
│
└── tools
In meson.build
:
SoC = 'mtxxxx'
ddr = [
'<ddr_type>',
]
MediaTek supports different DDR type and provide some default configurations(refer to libdram/src/<SOC>/ddr
: https://gitlab.com/mediatek/aiot/nda/libdram/-/tree/main/src).
Please select the ddrtype_default.cfg base on your DDR type.
Please define the DDR type you are using and comment out other types.
#add_project_arguments('-DCOMBO_LPDDR3_178BALL', language: 'c') add_project_arguments('-DCOMBO_LPDDR4', language: 'c') #add_project_arguments('-DCOMBO_PCDDR3_32BIT', language: 'c') #add_project_arguments('-DCOMBO_PCDDR4_32BIT', language: 'c')
Patch the modified libdram sources as a libdram patch file.
After adding a new machine in IoT Yocto project (refer to Add New Machine Configuration), set LIBDRAM_BOARD_NAME in machine configuration file.
meta-mediatek-bsp
└─── conf
└── machine
└── <board_name>.cfg
...
# libdram
LIBDRAM_BOARD_NAME = "<board_name>"
...
Add the libdram patch file to meta-<board_name>/recipes-bsp/libdram/files/.
Add the patch PATH to SRC_URI variable in libdram-lk.bbappend.
Add symbolic link to libdram.bbappend.
meta-<board_name>
├── recipes-bsp
│ ├── libdram
│ │ ├── files/ # patches to add board support
│ │ ├── libdram-lk.bbappend # apply patches to libdram-lk.bb
│ │ └── libdram.bbappend # symbolic link to add the patches to libdram.bb
... ...
U-Boot configuration
U-Boot Device tree
Add the device tree to u-boot/arch/arm/dts/<mtxxxx-board_name>.dts.
u-boot
└── arch
└── arm
└── dts
└── <mtxxxx-board_name>.dts
Include the SoC device tree : mtxxxx.dtsi.
Refer to already existing device tree with the same SoC.
Configure emmc : frequency, bus-width …
Configure DDR size :
It is not mandatory to change the default DDR size in u-boot device tree since u-boot only need few MB of memory at most and does not need to use the whole DDR.
memory@40000000 {
device_type = "memory";
reg = <0 0x40000000 0 0x80000000>;
} ;
0 0x40000000 is the address of the DDR in memory coded in 64 Bits, meaning that 0x0000000040000000 is the actual DDR address. This value should not be changed.
0 0x80000000 is the RAM size. In this example, it refers to 2GB of RAM.
reg = <0 0x40000000 1 0x00000000>; # meaning '0x0000000100000000'.
Add <mtxxxx-board_name>.dtb to u-boot/arch/arm/dts/Makefile.
...
dtb-$(CONFIG_ARCH_MEDIATEK) += \
<mtxxxx-board_name>.dtb
...
Patch u-boot sources and add the patch to meta-<board_name>/recipes-bsp/u-boot/files/.
Add the patch PATH to SRC_URI variable in meta-<board_name>/recipes-bsp/u-boot/u-boot_%.bbappend.
meta-<board_name>
├──recipes-bsp
│ └── u-boot
│ ├── files/ # patches to add board support
│ └── u-boot_%.bbappend # add device-tree and config patches
...
U-Boot Machine Configuration
Use already existing SoC-matching defconfig if no changes are to be added (jump to step 4).
Create a <mtxxxx_board_defconfig> that contains u-boot configuration in /configs
u-boot
└── configs
└── <mtxxxx_board_defconfig>
Patch u-boot sources and add the patch to meta-<board_name>/recipes-bsp/u-boot/files/.
Add the patch PATH to SRC_URI variable in meta-<board_name>/recipes-bsp/u-boot/u-boot_%.bbappend.
meta-<board_name>
├──recipes-bsp
│ └── u-boot
│ ├── files/ # patches to add board support
│ └── u-boot_%.bbappend # add device-tree and config patches
Set UBOOT_MACHINE variable in <machine_name>.conf
meta-<board_name>
├── conf
│ ├── machine
│ │ └── <machine_name>.conf #
│ ├── layer.conf #
│ ├── local.conf.sample #
│ └── bblayers.conf.sample #
...
UBOOT_MACHINE = "mtxxxx_board_defconfig"
OP-TEE configuration
OP-TEE DRAM Size Configuration
Use already existing SoC-matching machine config if no changes are to be added (jump to step 4).
Important
The OP-TEE DRAM size must be equal to the DRAM size configured in kernel device tree.
(Optional) If the DRAM size is large than 4GB, set
CFG_CORE_ARM64_PA_BITS,36
in <OP-TEE>/core/arch/arm/plat-mediatek/conf.mk.
optee-os
└── core
└── arch
└── arm
└── plat-mediatek
└── conf.mk
ifeq ($(PLATFORM_FLAVOR),<platform_name>)
$(call force,CFG_CORE_ARM64_PA_BITS,36)
endif
Patch optee-os sources and add the patch to meta-<board_name>/recipes-security/optee-os/files/.
Add the patch PATH to SRC_URI variable in meta-<board_name>/recipes-security/optee-os/optee-os_%.bbappend.
meta-<board_name>
├──recipes-security
│ └── optee-os
│ ├── files/ # patches to add board support
│ └── optee-os_%.bbappend # add DRAM PA bits patch
Set
OPTEE_DRAM_SIZE
variable in <machine_name>.conf
meta-<board_name>
├── conf
│ ├── machine
│ │ └── <machine_name>.conf #
│ ├── layer.conf #
│ ├── local.conf.sample #
│ └── bblayers.conf.sample #
...
OPTEE_DRAM_SIZE = "0x80000000" # meaning '0x000000080000000'.
OPTEE_DRAM_SIZE = "0x200000000" # meaning '0x0000000200000000'.
Kernel Configurations
Kernel Device Tree
Kernel device tree should be added to arch/arm64/boot/dts/mediatek/
in kernel source tree.
Create a device tree file
<mtxxxx-board_name>.dts
Refer to already existing device tree with the same SoC
Include necessary
.dtsi
file and configure RAM size
memory@40000000 {
device_type = "memory";
reg = <0 0x40000000 0 0x80000000>;
};
Do pin muxing and emmc configuration, such as frequency.
Add
<mtxxxx-board_name>.dtb
toarch/arm64/boot/dts/mediatek/Makefile
dtb-$(CONFIG_ARCH_MEDIATEK) += <mtxxxx-board_name>.dtb
Patch kernel sources and add the patch to meta-<board_name>/recipes-kernel/linux-mtk/files/.
Add the patch path to SRC_URI variable in meta-<board_name>/recipes-kernel/linux-mtk/linux-mtk_%.bbappend.
meta-<board_name>
├── recipes-kernel
│ └── linux-mtk
│ ├── files/ # patches to add device-tree kernel modification and configuration
│ └── linux-mtk_%.bbappend # apply the patches to linux kernel
Kernel Configuration
The kernel configuration used by yocto is a merge of the Linux ARM64 defconfig in arch/arm64/configs/defconfig and config fragments that can be found in recipes-kernel/linux-mtk/files.
Note
Please refer to Add extra kernel configuration and Kernel Development in order to add extra kernel configuration.
Yocto and Image customization
Add new prebuilt so/ko for drivers
In recipes-kernel/, create <module_name>/src folder and add <module_name>.ko.
Create a recipe file <recipe_name>.bb in meta-<board_name>/recipes-kernel/<module_name>/ in order to add the module to SRC_URI variable.
meta-<board_name>
├── recipes-kernel
│ ├── linux-mtk
│ │ ├── files/ # patches to add device-tree kernel modification and configuration
│ │ └── linux-mtk_%.bbappend # apply the patches to linux kernel
│ │
│ └── <module_name>
│ ├── src/
│ │ └── <module_name>.ko
│ │
│ └── <recipe_name>.bb
...
An example of what the recipe may look like:
SUMMARY = "Example of how to add prebuilt module"
DESCRIPTION = "${SUMMARY}"
FILESEXTRAPATHS:prepend := "${THISDIR}/src:"
inherit linux-kernel-base
S = "${WORKDIR}"
SRC_URI = "file://<module_name>.ko\"
S = "${WORKDIR}"
do_install() {
install -m 755 ${S}/<module_name>.ko
}
Add extra kernel configuration
In order to add extra kernel configuration:
Add new <board>.cfg in meta-<board_name>/recipes-kernel/linux-mtk/files/.
Create linux-mtk_%.bbappend in meta-<board_name>/recipes-kernel/linux-mtk/.
meta-<board_name>
├── recipes-kernel
│ └── linux-mtk
│ ├── files/ # config files and patches to add device-tree kernel modification and configuration
│ │ └── <board>.cfg
│ └── linux-mtk_%.bbappend # apply the patches to linux kernel
...
Append <board>.cfg to SRC_URI variable in linux-mtk_%.bbappend.
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
SRC_URI:append = " \
file://<board>.cfg \
"
Layer configuration
Detailed explanation is given in Create your own layer section.
Add the created layer to
meta-<board_name>/conf/bblayers.conf.sample
.
# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly
POKY_BBLAYERS_CONF_VERSION = "2"
BBPATH = "${TOPDIR}"
BBFILES ?= ""
BBLAYERS ?= " \
##OEROOT##/meta \
##OEROOT##/meta-poky \
##OEROOT##/meta-yocto-bsp \
##OEROOT##/../meta-arm/meta-arm \
##OEROOT##/../meta-arm/meta-arm-toolchain \
##OEROOT##/../meta-mediatek-bsp \
##OEROOT##/../meta-openembedded/meta-oe \
##OEROOT##/../meta-openembedded/meta-python \
##OEROOT##/../meta-rity/meta \
##OEROOT##/../meta-rity/meta-rity-bringup \
##OEROOT##/../meta-<board_name> \
"
Add meta-<board_name>/conf/layer.conf file and set layer information, priority, dependency …
# We have a conf and classes directory, add to BBPATH
BBPATH .= ":${LAYERDIR}"
# We have recipes-* directories, add to BBFILES
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend"
BBFILE_COLLECTIONS += "<board_name>"
BBFILE_PATTERN:<board_name> = "^${LAYERDIR}/"
BBFILE_PRIORITY:<board_name> = "12"
# This should only be incremented on significant changes that will
# cause compatibility issues with other layers
LAYERVERSION:<board_name> = "1"
LAYERDEPENDS:<board_name> = ""
# Yocto 3.1, codename: Dunfell (LTS)
# Yocto 3.2, codename: Gatesgarth (Stable)
# Yocto 3.3, codename: Hardknott (Stable)
LAYERSERIES_COMPAT:<board_name> = "dunfell"
Adjust storage partition
Add custom.wks.in to meta-<board_name>/wic/.
meta-<board_name>
└── wic
└── custom.wks.in # Partitioning
Add the wks file to meta-<board_name>/conf/local.conf.sample
WKS_FILE:forcevariable = "custom.wks.in"
An example of image partitioning :
# SHORT-description: Create an image for MediaTek SoC based boards
# long-description: Creates a partitioned image for MediaTek SoC based boards.
bootloader --ptable gpt --timeout=0
part --source rawcopy --sourceparams="file=fip.bin" --part-name bootloaders --align 512 --fixed-size 4M
part --source rawcopy --sourceparams="file=fitImage" --part-name kernel --size 15M
part / --source rootfs --fstype=ext4 --label rootfs --part-name rootfs --part-type B921B045-1DF0-41C3-AF44-4C6F280D3FAE --active --exclude-path=home/
part /home --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/home --fstype=ext4 --label home --part-name home --part-type 933AC7E1-2EB4-4F13-B844-0E14E2AEF915 --use-uuid --size ${IMAGE_HOME_SIZE} --mkfs-extraopts "-b ${WIC_BLOCK_SIZE}"
Note
Memory reserved regions
The size of memory reserved regions used by IoT Yocto SDK is not mandatory to be changed. The memory mapping for MT8395(Genio 1200), MT8390(Genio 700) and MT8365(Genio 350) are shown as follows:
For example if you would like to adjust the TF-A(BL31) start address and size, you could find the definition in trusted-firmware-a source and dts:
platform_def.h for MT8395(Genio 1200) :
#define TZRAM_BASE (0x54600000)
#define TZRAM_SIZE (0x00200000)
mt8195-demo.dts for MT8395(Genio 1200) :
bl31_secmon_reserved: secmon@54600000 {
no-map;
reg = <0 0x54600000 0x0 0x200000>;
};
For example if you would like to adjust the OP-TEE(BL32), you could find the definition in trusted-firmware-a source, dts and machine configurations in meta-mediatek-bsp layer:
platform_def.h for MT8395(Genio 1200) :
#define BL32_BASE (0x43200000)
#define BL32_LIMIT (0x00c00000)
mt8195-demo.dts for MT8395(Genio 1200) :
optee_reserved: optee@43200000 {
no-map;
reg = <0 0x43200000 0 0x00c00000>;
};
mediatek-common.inc for MT8395(Genio 1200) :
OPTEE_TZDRAM_START ?= "0x43200000"
OPTEE_TZDRAM_SIZE ?= "0x00c00000"
You might need to change the memory reserved regions to fit the kernel size changes during development. The default memory address for Genio 1200, Genio 700 and Genio 350 are aligned to 0x64000000, but this is not mandatory and can be adjusted to fit the size of your kernel. The default configuration of IoT Yocto allows kernel to be relocated. If you would like to adjust the Linux Kernel, you could find the definition in meta-mediatek-bsp layer:
mediatek-common.inc for MT8395(Genio 1200) :
UBOOT_ENTRYPOINT = "0x64000000"
UBOOT_LOADADDRESS = "0x64000000"
When the kernel size is too big, the error messages could happen as follows:
ERROR: reserving fdt memory region failed (addr=43200000 size=c00000 flags=4)
Note
Testing Memory Region Configuration
If you’ve updated the resered region settings in board DTS or in bootloader, we recommend you to check for the consistency of memory region settings between bootloader and kernel.
Therefore, you should run the kernel memtest after any memory configuration update. To run kernel memtest, you can:
Make sure the kernel config
CONFIG_MEMTEST=y
is set to enabeld.Add a kernel boot commandline parameter
memtest=1
. You can do this in U-Boot console, or use thefw_setenv
utility:fw_setenv bootargs "memtest=1" reboot
Reboot the system, and during kernel startup, a kernel message
early_memtest
should appear:[ 0.000000] early_memtest: # of tests: 2 [ 0.000000] 0x0000000040000000 - 0x0000000043200000 pattern ffffffffffffffff [ 0.000000] 0x0000000043e00000 - 0x0000000050000000 pattern ffffffffffffffff [ 0.000000] 0x0000000052900000 - 0x0000000053000000 pattern ffffffffffffffff [ 0.000000] 0x0000000054400000 - 0x0000000054600000 pattern ffffffffffffffff [ 0.000000] 0x0000000054800000 - 0x0000000060000000 pattern ffffffffffffffff
If you see
bad mem addr
, then this might indicate an incorrect DRAM configuration, or mismatched memory region between bootloader and kernel:[ 0.000000] ffffffffffffffff bad mem addr 0x0000000054800740 - 0x0000000054800780 reserved [ 0.000000] ffffffffffffffff bad mem addr 0x00000000548009c0 - 0x0000000054800a00 reserved [ 0.000000] ffffffffffffffff bad mem addr 0x0000000054800fc0 - 0x0000000054801000 reserved [ 0.000000] ffffffffffffffff bad mem addr 0x0000000054801540 - 0x0000000054801580 reserved [ 0.000000] ffffffffffffffff bad mem addr 0x0000000054801740 - 0x0000000054801780 reserved [ 0.000000] ffffffffffffffff bad mem addr 0x0000000054801880 - 0x00000000548018c0 reserved
Boot process (systemd) customization
Enable Systemd
Add the following lines to enable systemd by default:
meta-<board_name>
├── conf
│ ├── machine
│ │ └── <machine_name>.conf #
│ ├── layer.conf #
│ ├── local.conf.sample #
│ └── bblayers.conf.sample #
DISTRO_FEATURES_append = " systemd"
DISTRO_FEATURES_BACKFILL_CONSIDERED += "sysvinit"
VIRTUAL-RUNTIME_init_manager = "systemd"
VIRTUAL-RUNTIME_initscripts = "systemd-compat-units"
Add Systemd Services File
Create meta-<board_name>/recipes-core/systemd/files
Add service files <service_name>,service to /files
Add systemd_%.bbappend recipe to integrate the service to systemd configuration.
meta-<board_name>
├── recipes-core
│ └── systemd
│ ├── files/
│ │ └── <service_name>.service
│ └── systemd_%.bbappend
...
Hardware documentation
Please refer to MediaTek Online or request hardware documentation from your MediaTek contact window.