在前面我们已经介绍了编译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
进入到u-boot文件夹里,这就是我们需要的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 <dt_name> [<dt_name> [<dt_name] ...] """ import os import sys import getopt # pip install pyelftools from elftools.elf.elffile import ELFFile from elftools.elf.sections import SymbolTableSection from elftools.elf.segments import Segment, InterpSegment, NoteSegment ELF_SEG_P_TYPE='p_type' ELF_SEG_P_PADDR='p_paddr' ELF_SEG_P_VADDR='p_vaddr' ELF_SEG_P_OFFSET='p_offset' ELF_SEG_P_FILESZ='p_filesz' ELF_SEG_P_MEMSZ='p_memsz' DT_HEADER="""/* * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd * * Minimal dts for a SPL FIT image payload. * * SPDX-License-Identifier: GPL-2.0+ X11 */ /dts-v1/; / { description = "Configuration to load ATF before U-Boot"; #address-cells = <1>; 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 == 1) print >> fit_file, DT_HEADER % p_paddr with open(bl31_file_name) as bl31_file: bl31 = ELFFile(bl31_file) for i in range(bl31.num_segments()): seg = bl31.get_segment(i) if ('PT_LOAD' == seg.__getitem__(ELF_SEG_P_TYPE)): paddr = seg.__getitem__(ELF_SEG_P_PADDR) p= seg.__getitem__(ELF_SEG_P_PADDR) append_atf_node(fit_file, i+1, paddr) atf_cnt = i+1 append_fdt_node(fit_file, dtbs_file_name) print >> fit_file, '%s' % DT_IMAGES_NODE_END append_conf_node(fit_file, dtbs_file_name, atf_cnt) print >> fit_file, '%s' % DT_END if fit_file_name != sys.stdout: fit_file.close() def generate_atf_binary(bl31_file_name): with open(bl31_file_name) as bl31_file: bl31 = ELFFile(bl31_file) num = bl31.num_segments() for i in range(num): seg = bl31.get_segment(i) if ('PT_LOAD' == seg.__getitem__(ELF_SEG_P_TYPE)): paddr = seg.__getitem__(ELF_SEG_P_PADDR) file_name = 'bl31_0x%08x.bin' % paddr with open(file_name, "wb") as atf: atf.write(seg.data()); def get_bl31_segments_info(bl31_file_name): """ Get load offset, physical offset, file size from bl31 elf file program headers. """ with open(bl31_file_name) as bl31_file: bl31 = ELFFile(bl31_file) num = bl31.num_segments() print 'Number of Segments : %d' % bl31.num_segments() for i in range(num): print 'Segment %d' % i seg = bl31.get_segment(i) ptype = seg[ELF_SEG_P_TYPE] poffset = seg[ELF_SEG_P_OFFSET] pmemsz = seg[ELF_SEG_P_MEMSZ] pfilesz = seg[ELF_SEG_P_FILESZ] print 'type: %s\nfilesz: %08x\nmemsz: %08x\noffset: %08x' % (ptype, pfilesz, pmemsz, poffset) paddr = seg[ELF_SEG_P_PADDR] print 'paddr: %08x' % paddr def main(): uboot_elf="./u-boot" bl31_elf="./bl31.elf" FIT_ITS=sys.stdout opts, args = getopt.getopt(sys.argv[1:], "o:u:b:h") for opt, val in opts: if opt == "-o": FIT_ITS=val elif opt == "-u": uboot_elf=val elif opt == "-b": bl31_elf=val elif opt == "-h": print __doc__ sys.exit(2) dtbs = args #get_bl31_segments_info("u-boot") #get_bl31_segments_info("bl31.elf") generate_atf_fit_dts(FIT_ITS, bl31_elf, uboot_elf, dtbs) generate_atf_binary(bl31_elf); if __name__ == "__main__": main()
这里我直接拷贝过来:
root@zhengyang:/work/sambashare/rk3399/u-boot-2023.04# cp ../u-boot/arch/arm/mach-rockchip/make_fit_atf.py ./arch/arm/mach-rockchip/
1.2.4 配置uboot启动倒计时
如果在uboot启动倒计时结束之前,没有按下任何键,将会执行那么将执行也就是bootcmd中配置中的命令,bootcmd中保存着默认的启动命令。
(5) delay in seconds before automatically booting
保存文件,输入文件名为evb-rk3399_defconfig ,在当前路径下生成evb-rk3399_defconfig ,存档:
root@zhengyang:/work/sambashare/rk3399/u-boot# mv evb-rk3399_defconfig ./configs/
注意:如果需要配置生效,需要使用make distclean清除之前的配置,重新执行配置命令。
1.3 编译uboot
执行make命令,生成u-boot文件:
root@zhengyang:/work/sambashare/rk3399/u-boot# make ARCH=arm CROSS_COMPILE=arm-linux-
然后出现了如下错误:
binman: Filename 'atf-bl31' not found in input path (.,.,./board/rockchip/evb_rk3399,arch/arm/dts) (cwd='/work/sambashare/rk3399/u-boot-2023.04')
大致意思就是缺少了bl31.elf文件,我们将Rockchip RK3399 - TPL/SPL方式加载uboot章节制作的bl31.elf拷贝到uboot根目录下:
root@zhengyang:/work/sambashare/rk3399/u-boot-2023.04# cp /work/sambashare/rk3399/arm-trusted-firmware/build/rk3399/release/bl31/bl31.elf ./ root@zhengyang:/work/sambashare/rk3399/u-boot-2023.04# cp bl31.elf atf-bl31
重新编译,可以看到在 ./spl、./tpl目录下生成镜像文件:
root@zhengyang:/work/sambashare/rk3399/u-boot-2023.04# ls tpl/u-boot* tpl/u-boot.cfg tpl/u-boot-tpl tpl/u-boot-tpl.dtb tpl/u-boot-tpl.map tpl/u-boot-tpl.sym tpl/u-boot-spl.lds tpl/u-boot-tpl.bin tpl/u-boot-tpl-dtb.bin tpl/u-boot-tpl-nodtb.bin root@zhengyang:/work/sambashare/rk3399/u-boot-2023.04# ls spl/u-boot* spl/u-boot.cfg spl/u-boot-spl.bin spl/u-boot-spl-dtb.bin spl/u-boot-spl.map spl/u-boot-spl.sym spl/u-boot-spl spl/u-boot-spl.dtb spl/u-boot-spl.lds spl/u-boot-spl-nodtb.bin
二、idbloader.img
我们基于uboot源码编译出TPL/SPL,其中TPL负责实现DDR初始化,TPL初始化结束之后会回跳到BootROM程序,BootROM程序继续加载SPL,SPL加载u-boot.itb文件,然后跳转到uboor执行。
idbloader.img是由tpl/u-boot-tpl.bin和spl/u-boot-spl.bin文件生成,这里我们需要使用到tools目录下的mkimage工具。
2.1 tpl/u-boot-tpl.bin
在u-boot目录下执行:
root@zhengyang:/work/sambashare/rk3399/u-boot-2023.04# tools/mkimage -n rk3399 -T rksd -d tpl/u-boot-tpl.bin idbloader.img Image Type: Rockchip RK33 (SD/MMC) boot image Init Data Size: 53248 bytes
其中:
- -n rk3399将镜像文件的名称设置为"rk3399";
- -T rksd将映像类型指定为Rockchip SD卡启动映像;
- -d tpl/u-boot-tpl.bin将生成的TPL镜像文件"tpl/u-boot-tpl.bin"指定为输入文件,而idbloader.img则指定为输出文件。
生成idbloader.img文件:
root@zhengyang:/work/sambashare/rk3399/u-boot-2023.04# ll idbloader.img -rw-r--r-- 1 root root 55296 May 21 17:12 idbloader.img
2.2 spl/u-boot-spl.bin
将spl/u-boot-spl.bin合并到idbloader.img:
root@zhengyang:/work/sambashare/rk3399/u-boot-2023.04# cat spl/u-boot-spl.bin >> idbloader.img root@zhengyang:/work/sambashare/rk3399/u-boot-2023.04# ll idbloader.img -rw-r--r-- 1 root root 143866 May 21 17:13 idbloader.img
三、u-boot.idb
执行编译命令:
root@zhengyang:/work/sambashare/rk3399/u-boot-2023.04# make u-boot.itb ARCH=arm CROSS_COMPILE=arm-linux- UPD include/generated/timestamp_autogenerated.h ENVC include/generated/env.txt ENVP include/generated/env.in ENVT include/generated/environment.h CC cmd/version.o AR cmd/built-in.o CC env/common.o AR env/built-in.o CC lib/efi_loader/dtbdump.o LD lib/efi_loader/dtbdump_efi.so OBJCOPY lib/efi_loader/dtbdump.efi CC lib/efi_loader/initrddump.o LD lib/efi_loader/initrddump_efi.so OBJCOPY lib/efi_loader/initrddump.efi LD u-boot OBJCOPY u-boot-nodtb.bin RELOC u-boot-nodtb.bin ./"arch/arm/mach-rockchip/make_fit_atf.py" \ arch/arm/dts/rk3399-evb.dtb > u-boot.its MKIMAGE u-boot.itb
编译完成在当前路径下生成u-boot.its、u-boot.itb文件。
root@zhengyang:/work/sambashare/rk3399/u-boot-2023.04# ll u-boot.it* -rw-r--r-- 1 root root 974224 May 21 17:14 u-boot.itb -rw-r--r-- 1 root root 2423 May 21 17:14 u-boot.its
其中u-boot.its文件内容如下:
/* * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd * * Minimal dts for a SPL FIT image payload. * * SPDX-License-Identifier: GPL-2.0+ X11 */ /dts-v1/; / { description = "Configuration to load ATF before U-Boot"; #address-cells = <1>; images { uboot { description = "U-Boot (64-bit)"; data = /incbin/("u-boot-nodtb.bin"); type = "standalone"; os = "U-Boot"; arch = "arm64"; compression = "none"; load = <0x00200000>; hash { algo = "sha256"; }; }; atf@1 { description = "ARM Trusted Firmware"; data = /incbin/("bl31_0x00040000.bin"); type = "firmware"; arch = "arm64"; os = "arm-trusted-firmware"; compression = "none"; load = <0x00040000>; entry = <0x00040000>; hash { algo = "sha256"; }; }; atf@2 { description = "ARM Trusted Firmware"; data = /incbin/("bl31_0xff3b0000.bin"); type = "firmware"; arch = "arm64"; os = "arm-trusted-firmware"; compression = "none"; load = <0xff3b0000>; hash { algo = "sha256"; }; }; atf@3 { description = "ARM Trusted Firmware"; data = /incbin/("bl31_0xff8c0000.bin"); type = "firmware"; arch = "arm64"; os = "arm-trusted-firmware"; compression = "none"; load = <0xff8c0000>; hash { algo = "sha256"; }; }; atf@4 { description = "ARM Trusted Firmware"; data = /incbin/("bl31_0xff8c1000.bin"); type = "firmware"; arch = "arm64"; os = "arm-trusted-firmware"; compression = "none"; load = <0xff8c1000>; hash { algo = "sha256"; }; }; atf@5 { description = "ARM Trusted Firmware"; data = /incbin/("bl31_0xff8c2000.bin"); type = "firmware"; arch = "arm64"; os = "arm-trusted-firmware"; compression = "none"; load = <0xff8c2000>; hash { algo = "sha256"; }; }; fdt { description = "U-Boot device tree blob"; data = /incbin/("u-boot.dtb"); type = "flat_dt"; arch = "arm64"; compression = "none"; hash { algo = "sha256"; }; }; }; configurations { default = "config"; config { description = "Rockchip armv8 with ATF"; rollback-index = <0x0>; firmware = "atf@1"; loadables = "uboot", "atf@2" , "atf@3" , "atf@4" , "atf@5" , "atf@6" ; fdt = "fdt"; signature { algo = "sha256,rsa2048"; padding = "pss"; key-name-hint = "dev"; sign-images = "fdt", "firmware", "loadables"; }; }; }; };
四、烧录测试
由于我们每次修改程序后,重新编译步骤比较麻烦,这里我们可以将这步骤编写成一个sheell脚本,这样每次执行就比较容易了。
4.1 自动构建脚本
在uboot根目录下创建一个build.sh文件:
#!/bin/bash # 接收第一个参数 支持 ''|'config'|'clean' step=$1 # 接收 V=1 支持编译输出详细信息 V=$2 cmd=${V%=*} if [[ ${cmd} = 'V' ]]; then V=${V#*=} fi if [[ ${step} == "config" ]];then echo '----------------config evb-rk3399_defconfig------- -------------' make evb-rk3399_defconfig V=${V} fi if [[ -z ${step} ]];then echo "---------------1. compile uboot-------------------------------- " make ARCH=arm CROSS_COMPILE=arm-linux- V=${V} echo "---------------2. mkimahe idbloader----------------------------" tools/mkimage -n rk3399 -T rksd -d tpl/u-boot-tpl.bin idbloader.img cat spl/u-boot-spl.bin >> idbloader.img echo "---------------3. make itb-------------------------------------" make u-boot.itb ARCH=arm CROSS_COMPILE=arm-linux- cp ./u-boot.itb ../rkdeveloptool cp ./idbloader.img ../rkdeveloptool fi if [[ ${step} == "clean" ]];then echo "-----------------clean-----------------------------------------" make clean fi
然后给文件赋予可执行权限:
root@zhengyang:/work/sambashare/rk3399/u-boot-2023.04# chmod +x build.sh
4.1.1 clean
执行如下命令进行清理:
root@zhengyang:/work/sambashare/rk3399/u-boot-2023.04# ./build.sh clean
4.1.2 配置
执行如下命令进行uboot配置:
root@zhengyang:/work/sambashare/rk3399/u-boot# ./build.sh config ----------------config evb-rk3399_defconfig------- ------------- HOSTCC scripts/basic/fixdep HOSTCC scripts/kconfig/conf.o HOSTCC scripts/kconfig/zconf.tab.o HOSTLD scripts/kconfig/conf # # configuration written to .config #
4.1.2 构建
执行如下命令进行uboot编译、生成idbloader.img、 u-boot.itb文件,并拷贝到rkdeveloptool目录下:
root@zhengyang:/work/sambashare/rk3399/u-boot-2023.04# ./build.sh
如果需要输出编译详情信息,追加V=1参数即可。
4.2、烧录
烧录方法有两种:
- 一种是基于Rockchip的官方烧录工具RKDevTool;官方RKDevTool是基于recovery模式实现的,如果板子带有recovery按键,可以使用这种方式;
- 另外一种是在开发板上使用rkdeveloptool工具直接烧写eMMC;这里我们采用rkdeveloptool烧录的方式;
4.2.1 准备镜像
我们需按照之前的流程得到了idbloader.img、u-boot.itb文件,由于我们这里不进行内核和根文件系统的烧录,所以暂时不需要准备这俩。
按照Rockchip官方要求将idbloader.img烧录到eMMC的0x40扇区,u-boot.itb烧录到0x4000扇区。
我们需要将idbloader.img、u-boot.itb拷贝到rkdeveloptool路径下:
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# cp ../u-boot-2023.04/u-boot.itb ./ root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# cp ../u-boot-2023.04/idbloader.img ./
4.2.2 进入MASKROM升级模式
NanoPC-T4开发板如需进入MASKROM升级模式,需要进入如下操作:
- 将开发板连接上电源,并且连接Type-C数据线到PC;
- 按住BOOT键再长按Power键开机(保持按下BOOT键5秒以上),将强制进入MASKROM模式。
一般电脑识别到USB连接,都会发出声音。或者观察虚拟机右下角是否突然多个USB设备:右键点击链接;
4.2.3 烧录
使用下载引导命令去使目标机器初始化DDR与运行usbplug(初始化DDR的原因是由于升级需要很大的内存,所以需要使用到DDR);
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# rkdeveloptool db rk3399_loader_v1.27.126.bin Downloading bootloader succeeded.
由于BootROM启动会将rk3399_loader_v1.27.126.bin将在到内部SRAM中,然后跳转到ddr.bin代码进行DDR的初始化,ddr.bin执行之后会回跳到BootROM程序,BootROM程序继续加载usbplug.bin,由usbplug.bin完成程序的下载以及烧录到eMMC。
如果接上串口的话,执行完这一步可以看到如下输出信息:
DDR Version 1.27 20211018 In Channel 0: LPDDR3, 800MHz CS = 0 MR0=0x58 MR1=0x58 MR2=0x58 MR3=0x58 MR4=0x2 MR5=0x1 MR6=0x5 MR7=0x0 MR8=0x1F MR9=0x1F MR10=0x1F MR11=0x1F MR12=0x1F MR13=0x1F MR14=0x1F MR15=0x1F MR16=0x1F CS = 1 MR0=0x58 MR1=0x58 MR2=0x58 MR3=0x58 MR4=0x2 MR5=0x1 MR6=0x5 MR7=0x0 MR8=0x1F MR9=0x1F MR10=0x1F MR11=0x1F MR12=0x1F MR13=0x1F MR14=0x1F MR15=0x1F MR16=0x1F Bus Width=32 Col=10 Bank=8 Row=15/15 CS=2 Die Bus-Width=32 Size=2048MB Channel 1: LPDDR3, 800MHz CS = 0 MR0=0x58 MR1=0x58 MR2=0x58 MR3=0x58 MR4=0x2 MR5=0x1 MR6=0x5 MR7=0x0 MR8=0x1F MR9=0x1F MR10=0x1F MR11=0x1F MR12=0x1F MR13=0x1F MR14=0x1F MR15=0x1F MR16=0x1F CS = 1 MR0=0x58 MR1=0x58 MR2=0x58 MR3=0x58 MR4=0x2 MR5=0x1 MR6=0x5 MR7=0x0 MR8=0x1F MR9=0x1F MR10=0x1F MR11=0x1F MR12=0x1F MR13=0x1F MR14=0x1F MR15=0x1F MR16=0x1F Bus Width=32 Col=10 Bank=8 Row=15/15 CS=2 Die Bus-Width=32 Size=2048MB 256B stride ch 0 ddrconfig = 0x101, ddrsize = 0x2020 ch 1 ddrconfig = 0x101, ddrsize = 0x2020 pmugrf_os_reg[2] = 0x3AA0DAA0, stride = 0xD OUT Boot1 Release Time: Jun 2 2020 15:02:17, version: 1.26 CPUId = 0x0 SdmmcInit=2 0 BootCapSize=100000 UserCapSize=14910MB FwPartOffset=2000 , 100000 UsbBoot ...73858 powerOn 86071
使用wl命令烧写镜像到目标机器的eMMC,需要注意的是访问DDR所需的所有其他命令都应在使用db命令之后才能使用;
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# rkdeveloptool wl 0x40 idbloader.img Write LBA from file (100%) root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# rkdeveloptool wl 0x4000 u-boot.itb Write LBA from file (100%)
在烧写镜像完成后使用rd命令重启目标机器:
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# rkdeveloptool rd Reset Device OK.
需要注意的是:如果这个时候你也烧录了内核程序,执行完rd命令后是无法进入uboot命令的的,这里会直接启动内核。
参考文章
[1] Rockchip参考官方移植