----------------------------------------------------------------------------------------------------------------------------开发板 :NanoPC-T4开发板eMMC :16GBLPDDR3:4GB显示屏 :15.6 HDMI接口显示屏u-boot :2023.04linux :6.3----------------------------------------------------------------------------------------------------------------------------
在前面我们已经介绍了编译Rockchip官方提供的uboot源码,并下载到开发板中进行测试运行。这一节我们尝试下载最新的uboot版本试试,当前最新版本为2023.04。
一、uboot
1.1 下载源码
u-boot软件包下载网站:https://ftp.denx.de/pub/u-boot/。
DENX相关的网站:http://www.denx.de/re/DPLG.html。
u-boot git仓库:https://gitlab.denx.de/u-boot/u-boot。
我们在ubuntu运行如下命令:
root@zhengyang:/work/sambashare/rk3399# wget https://ftp.denx.de/pub/u-boot/u-boot-2023.04.tar.bz2
解压:
root@zhengyang:/work/sambashare/rk3399# tar -jxf u-boot-2023.04.tar.bz2
进入到uboot文件夹里,这就是我们需要的uboot的源码了:
root@zhengyang:/work/sambashare/rk3399# cd u-boot-2023.04
root@zhengyang:/work/sambashare/rk3399/u-boot-2023.04# ll
总用量 484
drwxrwxr-x 25 root root 4096 Apr 4 04:38 ./
drwxr-xr-x 14 root root 4096 May 21 15:22 ../
drwxrwxr-x 2 root root 4096 Apr 4 04:38 api/
drwxrwxr-x 14 root root 4096 Apr 4 04:38 arch/
-rw-rw-r-- 1 root root 21095 Apr 4 04:38 .azure-pipelines.yml
drwxrwxr-x 177 root root 4096 Apr 4 04:38 board/
drwxrwxr-x 2 root root 4096 Apr 4 04:38 boot/
-rw-rw-r-- 1 root root 814 Apr 4 04:38 .checkpatch.conf
drwxrwxr-x 10 root root 4096 Apr 4 04:38 cmd/
drwxrwxr-x 5 root root 4096 Apr 4 04:38 common/
-rw-rw-r-- 1 root root 2180 Apr 4 04:38 config.mk
drwxrwxr-x 2 root root 57344 Apr 4 04:38 configs/
drwxrwxr-x 2 root root 4096 Apr 4 04:38 disk/
drwxrwxr-x 20 root root 4096 Apr 4 04:38 doc/
drwxrwxr-x 74 root root 4096 Apr 4 04:38 drivers/
drwxrwxr-x 2 root root 4096 Apr 4 04:38 dts/
drwxrwxr-x 2 root root 4096 Apr 4 04:38 env/
drwxrwxr-x 4 root root 4096 Apr 4 04:38 examples/
drwxrwxr-x 15 root root 4096 Apr 4 04:38 fs/
-rw-rw-r-- 1 root root 44 Apr 4 04:38 .get_maintainer.conf
-rw-rw-r-- 1 root root 207 Apr 4 04:38 .gitattributes
drwxrwxr-x 2 root root 4096 Apr 4 04:38 .github/
-rw-rw-r-- 1 root root 1115 Apr 4 04:38 .gitignore
-rw-rw-r-- 1 root root 14133 Apr 4 04:38 .gitlab-ci.yml
drwxrwxr-x 36 root root 20480 Apr 4 04:38 include/
-rw-rw-r-- 1 root root 783 Apr 4 04:38 Kbuild
-rw-rw-r-- 1 root root 20750 Apr 4 04:38 Kconfig
drwxrwxr-x 24 root root 4096 Apr 4 04:38 lib/
drwxrwxr-x 2 root root 4096 Apr 4 04:38 Licenses/
-rw-rw-r-- 1 root root 4022 Apr 4 04:38 .mailmap
-rw-rw-r-- 1 root root 42030 Apr 4 04:38 MAINTAINERS
-rw-rw-r-- 1 root root 81547 Apr 4 04:38 Makefile
drwxrwxr-x 2 root root 4096 Apr 4 04:38 net/
drwxrwxr-x 5 root root 4096 Apr 4 04:38 post/
-rw-rw-r-- 1 root root 94985 Apr 4 04:38 README
-rw-rw-r-- 1 root root 491 Apr 4 04:38 .readthedocs.yml
drwxrwxr-x 6 root root 4096 Apr 4 04:38 scripts/
drwxrwxr-x 17 root root 4096 Apr 4 04:38 test/
drwxrwxr-x 15 root root 4096 Apr 4 04:38 tools/
1.2 配置uboot
uboot的编译分为两步:配置、编译。单板的默认配置在configs目录下,这里我们直接选择configs/evb-rk3399_defconfig,这是Rockchip评估板的配置:
CONFIG_ARM=y
CONFIG_SKIP_LOWLEVEL_INIT=y
CONFIG_COUNTER_FREQUENCY=24000000
CONFIG_ARCH_ROCKCHIP=y
CONFIG_TEXT_BASE=0x00200000
CONFIG_NR_DRAM_BANKS=1
CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x300000
CONFIG_ENV_OFFSET=0x3F8000
CONFIG_DEFAULT_DEVICE_TREE="rk3399-evb"
CONFIG_DM_RESET=y
CONFIG_ROCKCHIP_RK3399=y
CONFIG_TARGET_EVB_RK3399=y
CONFIG_SPL_STACK=0x400000
CONFIG_DEBUG_UART_BASE=0xFF1A0000
CONFIG_DEBUG_UART_CLOCK=24000000
CONFIG_SYS_LOAD_ADDR=0x800800
CONFIG_DEBUG_UART=y
CONFIG_DEFAULT_FDT_FILE="rockchip/rk3399-evb.dtb"
CONFIG_DISPLAY_BOARDINFO_LATE=y
CONFIG_SPL_MAX_SIZE=0x2e000
CONFIG_SPL_PAD_TO=0x7f8000
CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
CONFIG_SPL_BSS_START_ADDR=0x400000
CONFIG_SPL_BSS_MAX_SIZE=0x2000
# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
CONFIG_SPL_STACK_R=y
CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x10000
CONFIG_TPL=y
CONFIG_CMD_BOOTZ=y
CONFIG_CMD_GPT=y
CONFIG_CMD_MMC=y
CONFIG_CMD_USB=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_CMD_TIME=y
CONFIG_SPL_OF_CONTROL=y
CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
CONFIG_ENV_IS_IN_MMC=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_ROCKCHIP_GPIO=y
CONFIG_SYS_I2C_ROCKCHIP=y
CONFIG_MISC=y
CONFIG_MMC_HS400_SUPPORT=y
CONFIG_MMC_DW=y
CONFIG_MMC_DW_ROCKCHIP=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_SDMA=y
CONFIG_MMC_SDHCI_ROCKCHIP=y
CONFIG_SF_DEFAULT_SPEED=20000000
CONFIG_ETH_DESIGNWARE=y
CONFIG_GMAC_ROCKCHIP=y
CONFIG_PHY_ROCKCHIP_INNO_USB2=y
CONFIG_PHY_ROCKCHIP_TYPEC=y
CONFIG_PMIC_RK8XX=y
CONFIG_REGULATOR_PWM=y
CONFIG_REGULATOR_RK8XX=y
CONFIG_PWM_ROCKCHIP=y
CONFIG_DM_RNG=y
CONFIG_RNG_ROCKCHIP=y
CONFIG_BAUDRATE=1500000
CONFIG_DEBUG_UART_SHIFT=2
CONFIG_SYS_NS16550_MEM32=y
CONFIG_SYSRESET=y
CONFIG_USB=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_XHCI_DWC3=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_GENERIC=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_GENERIC=y
CONFIG_USB_HOST_ETHER=y
CONFIG_USB_ETHER_ASIX=y
CONFIG_USB_ETHER_ASIX88179=y
CONFIG_USB_ETHER_MCS7830=y
CONFIG_USB_ETHER_RTL8152=y
CONFIG_USB_ETHER_SMSC95XX=y
CONFIG_VIDEO=y
# CONFIG_VIDEO_BPP8 is not set
CONFIG_DISPLAY=y
CONFIG_VIDEO_ROCKCHIP=y
CONFIG_VIDEO_ROCKCHIP_MAX_YRES=1200
CONFIG_DISPLAY_ROCKCHIP_MIPI=y
CONFIG_SPL_TINY_MEMSET=y
CONFIG_ERRNO_STR=y
因此执行如下命令,生成.config文件:
root@zhengyang:/work/sambashare/rk3399/u-boot-2023.04# make evb-rk3399_defconfig V=1
接着我们需要执行make menuconfig做一些配置。
1.2.1 配置串口波特率
uboot中默认的调试串口波特率是1500000,有很多的调试终端不支持1.5M的波特率,我们可以把波特率重新配置下;
Device Drivers --->
Serial --->
(115200) Default baudrate
注意:波特率数值如果无法删除,按CTRL+回车键尝试。如果配置为1500000,后面测试时串口输出内容一部分正常,偶尔出现乱码,考虑是串口波特率太高不稳定造成的,降低波特率到115200尝试。
这里我更改为了115200,之前烧录Rockchip官方uboot时设置为1500000一点问题都没有,但是uboot官方代码设置为1500000竟然出现乱码,看样uboot官方对RK3399支持并不是很好。
1.2.2 配置eMMC
为什么要去配置eMMC呢?这个是因为我使用默认配置,编译后的uboot下载到开发板出现了无法对eMMC进行读写的问题,并且输出了如下错误:
sdhci_transfer_data: Error detected in status(0x208000)
然后我去比对了当前版本uboot和Rockchip官方(Rockchip RK3399 - TPL/SPL方式加载uboot)提供的uboot单板配置configs/evb-rk3399_defconfig的差异,发现当前版本默认开启了以下配置:
CONFIG_MMC_HS400_SUPPORT=y # 多出了这个
CONFIG_MMC_DW=y
CONFIG_MMC_DW_ROCKCHIP=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_SDMA=y # 多出了这个
那CONFIG_MMC_HS400_SUPPOR、CONFIG_MMC_SDHCI_SDMA是什么呢?
CONFIG_MMC_HS400_SUPPORT 是一个配置选项,用于支持嵌入式设备中的高速 MMC(Multimedia Card)/SD(Secure Digital)卡,默认情况下未启用。
启用这个选项可以让MMC/SD卡在HS400模式下运行,从而提高读写速度,但是需要确保硬件上支持 HS400 模式,并且芯片厂商提供了对应的驱动程序。如果硬件不支持或驱动程序不可用,则启用此选项将会导致系统无法正常启动。
既然我们已经明白了该配置项的作用,那我们就要看一下我们的eMMC芯片是否支持HS400模式,这里用的开发板板载的eMMC型号为:KLMAG2WEMB-B031,找到芯片的datasheet有关HS400 mode的信息,具体定位到EXT_CSD第196个字节DEVICE_TYPE,其值为0x57;可以看到eMMC工作在HS400模式时,电压要求为1.8V。
配置项CONFIG_MMC_SDHCI_SDMA用于启用SD/SDIO/MMC 主机控制器使用 DMA 方式进行数据传输。
这里我们暂且将CONFIG_MMC_HS400_SUPPORT,CONFIG_MMC_SDHCI_SDMA配置关掉:
Device Drivers --->
MMC Host controller Support --->
[ ] MMC debugging
[ ] enable HS400 support
[ ] Support IO voltage configuration
[ ] Support SDHCI SDMA
如果想查看eMMC读写命令信息,可以打开MMC debuging。
1.2.3 配置FIT
Boot options --->
Boot images --->
[*] Use a script to generate the .its script
(arch/arm/mach-rockchip/make_fit_atf.py) .its file generator script for U-Boot FIT image
我们之前介绍过在生成u-boot.itb文件时,需要执行如下命令:
tools/mkimage -f u-boot.its u-boot.itb
mkimage将its文件以及对应的image data file,打包成一个itb文件,也就是uboot可以识别的image file(FIT-uImage)。
因为mkimage是根据its文件中的描述来打包镜像生成itb文件(FIT-uImage),所以首先需要制作一个its文件,在its文件中描述需要被打包的镜像,主要是bl31.bin,dtb文件,u-boot-nodtb.bin。
这里我们需要使用到arch/arm/mach-rockchip/make_fit_atf.py文件,这个是从Rockchip官网uboot下拷贝过来的,内容如下,这是一个python脚本,主要就是生成一个u-boot.its文件:#!/usr/bin/env python2
"""
A script to generate FIT image source for rockchip boards
with ARM Trusted Firmware
and multiple device trees (given on the command line)
usage: $0 [ [;
images {
uboot {
description = "U-Boot (64-bit)";
data = /incbin/("u-boot-nodtb.bin");
type = "standalone";
os = "U-Boot";
arch = "arm64";
compression = "none";
load = <0x%08x>;
hash {
algo = "sha256";
};
};
"""
DT_IMAGES_NODE_END="""
};
"""
DT_END="""
};
"""
def append_atf_node(file, atf_index, phy_addr):
"""
Append ATF DT node to input FIT dts file.
"""
data = 'bl31_0x%08x.bin' % phy_addr
print >> file, '\t\tatf@%d {
' % atf_index
print >> file, '\t\t\tdescription = \"ARM Trusted Firmware\";'
print >> file, '\t\t\tdata = /incbin/("%s");' % data
print >> file, '\t\t\ttype = "firmware";'
print >> file, '\t\t\tarch = "arm64";'
print >> file, '\t\t\tos = "arm-trusted-firmware";'
print >> file, '\t\t\tcompression = "none";'
print >> file, '\t\t\tload = <0x%08x>;' % phy_addr
if atf_index == 1:
print >> file, '\t\t\tentry = <0x%08x>;' % phy_addr
print >> file, '\t\t\thash {
'
print >> file, '\t\t\t\talgo = "sha256";'
print >> file, '\t\t\t};'
print >> file, '\t\t};'
print >> file, ''
def append_fdt_node(file, dtbs):
"""
Append FDT nodes.
"""
cnt = 1
for dtb in dtbs:
dtname = os.path.basename(dtb)
print >> file, '\t\tfdt {
'
print >> file, '\t\t\tdescription = "U-Boot device tree blob";'
print >> file, '\t\t\tdata = /incbin/("u-boot.dtb");'
print >> file, '\t\t\ttype = "flat_dt";'
print >> file, '\t\t\tarch = "arm64";'
print >> file, '\t\t\tcompression = "none";'
print >> file, '\t\t\thash {
'
print >> file, '\t\t\t\talgo = "sha256";'
print >> file, '\t\t\t};'
print >> file, '\t\t};'
print >> file, ''
cnt = cnt + 1
def append_conf_section(file, cnt, dtname, atf_cnt):
print >> file, '\t\tconfig {
'
print >> file, '\t\t\tdescription = "Rockchip armv8 with ATF";'
print >> file, '\t\t\trollback-index = <0x0>;'
print >> file, '\t\t\tfirmware = "atf@1";'
print >> file, '\t\t\tloadables = "uboot",',
for i in range(1, atf_cnt):
print >> file, '"atf@%d"' % (i+1),
if i != (atf_cnt - 1):
print >> file, ',',
else:
print >> file, ';'
print >> file, '\t\t\tfdt = "fdt";'
print >> file, '\t\t\tsignature {
'
print >> file, '\t\t\t\talgo = "sha256,rsa2048";'
print >> file, '\t\t\t\tpadding = "pss";'
print >> file, '\t\t\t\tkey-name-hint = "dev";'
print >> file, '\t\t\t\tsign-images = "fdt", "firmware", "loadables";'
print >> file, '\t\t\t};'
print >> file, '\t\t};'
print >> file, ''
def append_conf_node(file, dtbs, atf_cnt):
"""
Append configeration nodes.
"""
cnt = 1
print >> file, '\tconfigurations {
'
print >> file, '\t\tdefault = "config";'
for dtb in dtbs:
dtname = os.path.basename(dtb)
append_conf_section(file, cnt, dtname, atf_cnt)
cnt = cnt + 1
print >> file, '\t};'
print >> file, ''
def generate_atf_fit_dts(fit_file_name, bl31_file_name, uboot_file_name, dtbs_file_name):
"""
Generate FIT script for ATF image.
"""
if fit_file_name != sys.stdout:
fit_file = open(fit_file_name, "wb")
else:
fit_file = sys.stdout
num_load_seg = 0
p_paddr = 0xFFFFFFFF
with open(uboot_file_name) as uboot_file:
uboot = ELFFile(uboot_file)
for i in range(uboot.num_segments()):
seg = uboot.get_segment(i)
if ('PT_LOAD' == seg.__getitem__(ELF_SEG_P_TYPE)):
p_paddr = seg.__getitem__(ELF_SEG_P_PADDR)
num_load_seg = num_load_seg + 1
assert (p_paddr != 0xFFFFFFFF and num_load_seg ==