Rockchip RK3399 – 移植uboot 2023.04

  • Rockchip RK3399 – 移植uboot 2023.04已关闭评论
  • 153 次浏览
  • A+
所属分类:linux技术
摘要

—————————————————————————————————————————-

----------------------------------------------------------------------------------------------------------------------------

开发板:NanoPC-T4开发板
eMMC:16GB
LPDDR3:4GB
显示屏:15.6 HDMI接口显示屏
u-boot :2023.04
----------------------------------------------------------------------------------------------------------------------------

在前面我们已经介绍了编译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评估板的配置:

Rockchip RK3399 - 移植uboot 2023.04Rockchip RK3399 - 移植uboot 2023.04

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

View Code

因此执行如下命令,生成.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。

Rockchip RK3399 - 移植uboot 2023.04

配置项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文件:

Rockchip RK3399 - 移植uboot 2023.04Rockchip RK3399 - 移植uboot 2023.04

#!/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, 'ttatf@%d {' % atf_index     print >> file, 'tttdescription = "ARM Trusted Firmware";'     print >> file, 'tttdata = /incbin/("%s");' % data     print >> file, 'ttttype = "firmware";'     print >> file, 'tttarch = "arm64";'     print >> file, 'tttos = "arm-trusted-firmware";'     print >> file, 'tttcompression = "none";'     print >> file, 'tttload = <0x%08x>;' % phy_addr     if atf_index == 1:         print >> file, 'tttentry = <0x%08x>;' % phy_addr     print >> file, 'ttthash {'     print >> file, 'ttttalgo = "sha256";'     print >> file, 'ttt};'     print >> file, 'tt};'     print >> file, ''  def append_fdt_node(file, dtbs):     """     Append FDT nodes.     """     cnt = 1     for dtb in dtbs:         dtname = os.path.basename(dtb)         print >> file, 'ttfdt {'         print >> file, 'tttdescription = "U-Boot device tree blob";'         print >> file, 'tttdata = /incbin/("u-boot.dtb");'         print >> file, 'ttttype = "flat_dt";'         print >> file, 'tttarch = "arm64";'         print >> file, 'tttcompression = "none";'         print >> file, 'ttthash {'         print >> file, 'ttttalgo = "sha256";'         print >> file, 'ttt};'         print >> file, 'tt};'         print >> file, ''         cnt = cnt + 1  def append_conf_section(file, cnt, dtname, atf_cnt):     print >> file, 'ttconfig {'     print >> file, 'tttdescription = "Rockchip armv8 with ATF";'     print >> file, 'tttrollback-index = <0x0>;'     print >> file, 'tttfirmware = "atf@1";'     print >> file, 'tttloadables = "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, 'tttfdt = "fdt";'     print >> file, 'tttsignature {'     print >> file, 'ttttalgo = "sha256,rsa2048";'     print >> file, 'ttttpadding = "pss";'     print >> file, 'ttttkey-name-hint = "dev";'     print >> file, 'ttttsign-images = "fdt", "firmware", "loadables";'     print >> file, 'ttt};'     print >> file, 'tt};'     print >> file, ''  def append_conf_node(file, dtbs, atf_cnt):     """     Append configeration nodes.     """     cnt = 1     print >> file, 'tconfigurations {'     print >> file, 'ttdefault = "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: %snfilesz: %08xnmemsz: %08xnoffset: %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()

View Code

拷贝命令过来:

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

3.1 u-boot.itd生成规则

这里我们需要生成FIT-uImage,对应的镜像文件名称为u-boot.itd,在顶层Makefile定义有:

ifdef U_BOOT_ITS u-boot.itb: u-boot-nodtb.bin                  $(if $(CONFIG_OF_SEPARATE)$(CONFIG_OF_EMBED)$(CONFIG_SANDBOX),dts/dt.dtb)                  $(if $(CONFIG_MULTI_DTB_FIT),$(FINAL_DTB_CONTAINER))                  $(U_BOOT_ITS) FORCE         $(call if_changed,mkfitimage)         $(BOARD_SIZE_CHECK) endif  ifneq ($(CONFIG_SPL_FIT_SOURCE),"")             // 方式1. 如果自己已经有u-boot.its,配置CONFIG_SPL_FIT_SOURCE=u-boot.its U_BOOT_ITS := u-boot.its $(U_BOOT_ITS): $(subst ",,$(CONFIG_SPL_FIT_SOURCE))         $(call if_changed,copy) else ifneq ($(CONFIG_USE_SPL_FIT_GENERATOR),)   // 方式2.  使用脚本生成 配置CONFIG_USE_SPL_FIT_GENERATOR=y U_BOOT_ITS := u-boot.its $(U_BOOT_ITS): $(U_BOOT_ITS_DEPS) FORCE         $(srctree)/$(CONFIG_SPL_FIT_GENERATOR)           $(patsubst %,arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST))) > $@           // 在$(patsubst %.c,%.o,$(dir) )中,patsubst把$(dir)中的变量符合后缀是.c的全部替换成.o endif endif

这里我们采用的配置CONFIG_SPL_FIT_GENERATOR的方式来生成u-boot.its,也就是我们在执行make menuconfig时配置的:

CONFIG_SPL_FIT_SOURCE="" CONFIG_USE_SPL_FIT_GENERATOR=y CONFIG_SPL_FIT_GENERATOR="arch/arm/mach-rockchip/make_fit_atf.py"

3.2 编译

行编译命令:

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文件内容如下:

Rockchip RK3399 - 移植uboot 2023.04Rockchip RK3399 - 移植uboot 2023.04

/*  * 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";                         };                 };          };   };

View Code

四、FIT uImage

我们在Mini2440之uboot移植流程之linux内核启动分析(六)中介绍过内核镜像包括多种格式,比如Legacy uImage、FIT uImage,这一节我们将学习制作FIT uImage,并将其烧录到开发板的eMMC第0x8000个扇区上。

4.1 编译内核

Rockchip RK3399 - linux内核移植我们介绍了linux内核5.2.8版本的编译,编译完成后会在arch/arm64/boot/文件夹下生成内核镜像文件,以及设备树dst/rockchip/xxx.dtb文件;

root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# ll arch/arm64/boot 总用量 44032 drwxr-xr-x  3 root root     4096 May 16 11:28 ./ drwxr-xr-x 14 root root     4096 May 16 11:15 ../ drwxr-xr-x 33 root root     4096 May 16 10:27 dts/ -rw-r--r--  1 root root       55 May 16 10:27 .gitignore -rw-r--r--  1 root root 33616384 May 16 11:27 Image -rw-r--r--  1 root root      134 May 16 11:27 .Image.cmd -rw-r--r--  1 root root 11617499 May 16 11:28 Image.gz -rw-r--r--  1 root root      101 May 16 11:28 .Image.gz.cmd -rw-r--r--  1 root root     1562 May 16 10:27 install.sh -rw-r--r--  1 root root      960 May 16 10:27 Makefile root@zhengyang:/work/sambashare/rk3399/linux-5.2.8/arch/arm64# cd arch/arm64/boot root@zhengyang:/work/sambashare/rk3399/linux-5.2.8/arch/arm64/boot# ls dts/rockchip/*rk3399*.dtb dts/rockchip/rk3399-evb.dtb              dts/rockchip/rk3399-gru-scarlet-kd.dtb  dts/rockchip/rk3399-rock960.dtb dts/rockchip/rk3399-ficus.dtb            dts/rockchip/rk3399-nanopc-t4.dtb       dts/rockchip/rk3399-rock-pi-4.dtb dts/rockchip/rk3399-firefly.dtb          dts/rockchip/rk3399-nanopi-m4.dtb       dts/rockchip/rk3399-rockpro64.dtb dts/rockchip/rk3399-gru-bob.dtb          dts/rockchip/rk3399-nanopi-neo4.dtb     dts/rockchip/rk3399-roc-pc.dtb dts/rockchip/rk3399-gru-kevin.dtb        dts/rockchip/rk3399-orangepi.dtb        dts/rockchip/rk3399-sapphire.dtb dts/rockchip/rk3399-gru-scarlet-inx.dtb  dts/rockchip/rk3399-puma-haikou.dtb     dts/rockchip/rk3399-sapphire-excavator.dtb

其中Image是内核镜像原生二进制文件,可以直接在芯片上运行的,由于Image文件较大,我们将Image压缩转换为zImage:

cat arch/arm64/boot/Image | gzip -n -f -9 > arch/arm64/boot/zImage

实际上Image.gz文件就是将Image文件通过gzip进行打包得到的。

4.2 创建its文件

因为mkimage是根据its文件中的描述来打包镜像生成itb文件(FIT uImage),所以首先需要制作一个its文件,在its文件中描述需要被打包的镜像,主要是kernel镜像,dtb文件,ramdisk镜像。 

我们创建一个kernel.its文件,内容如下:

/*  * Simple U-Boot uImage source file containing a single kernel and FDT blob  */ /dts-v1/;  / {         description = "Simple image with single Linux kernel and FDT blob";         #address-cells = <1>;          images {                  kernel {                         description = "Vanilla Linux kernel";                         data = /incbin/("Image.gz");                         type = "kernel";                         arch = "arm64";                         os = "linux";                         compression = "gzip";                         load = <0x20000000>;                         entry = <0x20000000>;                         hash-1 {                                 algo = "crc32";                         };                         hash-2 {                                 algo = "sha1";                         };                 };                 fdt {                         description = "Flattened Device Tree blob";                         data = /incbin/("rk3399-evb.dtb");                         type = "flat_dt";                         arch = "arm64";                         compression = "none";                         hash-1 {                                 algo = "crc32";                         };                         hash-2 {                                 algo = "sha1";                         };                 };                   ramdisk {                     description = "Ramdisk for project-x";                     data = /incbin/("ramdisk.gz");                     type = "ramdisk";                     arch = "arm64";                     os = "linux";                     load = <00000000>;                     entry = <00000000>;                     compression = "gzip";                     hash-1 {                         algo = "crc32";                    };               };         };         configurations {                 default = "conf-1";                 conf-1 {                         description = "Boot Linux kernel with FDT blob";                         kernel = "kernel";                         fdt = "fdt";                         ramdisk = "ramdisk";                 };         }; };

4.3 生成kernel.itb

FIT image 文件的编译过程很简单,这里我们需要将uboot路径下的mkimage工具拷贝过来,然后在命令行使用mkimage工具编译即可:

root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# cp ../u-boot-2023.04/tools/mkimage ./ root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# ./mkimage -f kernel.its kernel.itb

五、烧录测试

由于我们每次修改程序后,重新编译步骤比较麻烦,这里我们可以将这些步骤编写成一个shell脚本,这样每次执行就比较容易了。

5.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
make distclean
fi

然后给文件赋予可执行权限:

root@zhengyang:/work/sambashare/rk3399/u-boot-2023.04#  chmod +x build.sh

5.1.1 clean

执行如下命令进行清理:

root@zhengyang:/work/sambashare/rk3399/u-boot-2023.04#  ./build.sh clean

5.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 #

5.1.3 构建

执行如下命令进行uboot编译、生成idbloader.img、 u-boot.itb文件,并拷贝到rkdeveloptool目录下:

root@zhengyang:/work/sambashare/rk3399/u-boot-2023.04# ./build.sh

如果需要输出编译详情信息,追加V=1参数即可。

5.2 烧录uboot

烧录方法有两种:

  • 一种是基于Rockchip的官方烧录工具RKDevTool;官方RKDevTool是基于recovery模式实现的,如果板子带有recovery按键,可以使用这种方式;
  • 另外一种是在开发板上使用rkdeveloptool工具直接烧写eMMC;这里我们采用rkdeveloptool烧录的方式;
5.2.1 准备镜像

我们需按照之前的流程得到了idbloader.img、u-boot.itb文件,由于我们这里不进行内核和根文件系统的烧录,所以暂时不需要准备这俩。

按照Rockchip官方要求将idbloader.img烧录到eMMC的0x40扇区,u-boot.itb烧录到0x4000扇区。

我们需要将idbloader.img、u-boot.itb、kernel.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 ./

5.2.2 进入MASKROM升级模式

NanoPC-T4开发板如需进入MASKROM升级模式,需要进入如下操作:

  • 将开发板连接上电源,并且连接Type-C数据线到PC;
  • 按住BOOT键再长按Power键开机(保持按下BOOT键5秒以上),将强制进入MASKROM模式。

一般电脑识别到USB连接,都会发出声音。或者观察虚拟机右下角是否突然多个USB设备:右键点击链接;

Rockchip RK3399 - 移植uboot 2023.04

5.2.3 下载uboot

使用下载引导命令去使目标机器初始化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。

如果接上串口的话,执行完这一步可以看到如下输出信息:

Rockchip RK3399 - 移植uboot 2023.04Rockchip RK3399 - 移植uboot 2023.04

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

View Code

使用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命令的的,这里会直接启动内核。

5.3 测试u-boot

5.3.1 串口连接

使用准备好的USB转串口适配器和连接线(需另购),连接开发板:

引脚  开发板接口 USB转串口 
 1  GNC
VCC 5V 
UART2DBG_TX  RX
 UART2DBG_RX TX 

5.3.2 MobaXterm

这里我使用的串口调试工具是MobaXterm,选择串口端口,设置波特率为115200,8位数据位,1位停止位。

5.3.3 上电

给开发板上电,通过串口打印输出:

U-Boot TPL 2023.04 (May 21 2023 - 17:50:22) Channel 0: LPDDR3, 800MHz BW=32 Col=10 Bk=8 CS0 Row=15 CS1 Row=15 CS=2 Die BW=16 Size=2048MB Channel 1: LPDDR3, 800MHz BW=32 Col=10 Bk=8 CS0 Row=15 CS1 Row=15 CS=2 Die BW=16 Size=2048MB 256B stride Trying to boot from BOOTROM Returning to boot ROM...  U-Boot SPL 2023.04 (May 21 2023 - 17:50:22 +0800) Trying to boot from MMC2 spl_load_fit_image: Skip load 'atf@5': image size is 0! cannot find image node 'atf@6': -1 NOTICE:  BL31: v2.8(release):c194aa0 NOTICE:  BL31: Built : 19:26:54, May 11 2023   U-Boot 2023.04 (May 21 2023 - 17:50:25 +0800)  SoC: Rockchip rk3399 Reset cause: RST Model: Rockchip RK3399 Evaluation Board DRAM:  4 GiB (effective 3.9 GiB) Core:  254 devices, 27 uclasses, devicetree: separate MMC:   mmc@fe320000: 1, mmc@fe330000: 0 Loading Environment from MMC... OK In:    serial Out:   serial Err:   serial Model: Rockchip RK3399 Evaluation Board Net:   eth0: ethernet@fe300000 Hit any key to stop autoboot:  0

在倒计时执行完之前,按CTRL+C即可进入uboot命令行。

5.3.4 设置环境变量

这里我们这是本机和服务器的ip地址:

=> setenv ipaddr 192.168.0.105 => setenv serverip 192.168.0.200 => saveenv Saving Environment to MMC... Writing to MMC(0)... OK

5.3.5 mmc

查看mmc信息:

=> mmc info Device: mmc@fe330000 Manufacturer ID: 15 OEM: 0 Name: AJNB4R Bus Speed: 200000000 Mode: HS200 (200MHz) Rd Block Len: 512 MMC version 5.1 High Capacity: Yes Capacity: 14.6 GiB Bus Width: 8-bit Erase Group Size: 512 KiB HC WP Group Size: 8 MiB User Capacity: 14.6 GiB WRREL Boot Capacity: 4 MiB ENH RPMB Capacity: 4 MiB ENH Boot area 0 is not write protected Boot area 1 is not write protected

从上图中可以看到MMC设备版本为5.1, 14.6GiB(eMMC为16GB),速度为20000000Hz=200MHz, 8 位宽的总线。

5.4 烧录内核

5.4.1 下载kernel

我们将内核拷贝到tftp文件目录:

root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# cp kernel.itb /work/tftpboot/

接着通过uboot命令行将kernel.itb下载待内存地址0x10000000处:

=> tftp 0x10000000 kernel.itb ethernet@fe300000 Waiting for PHY auto negotiation to complete.... done Speed: 100, full duplex Using ethernet@fe300000 device TFTP from server 192.168.0.200; our IP address is 192.168.0.105 Filename 'kernel.itb'. Load address: 0x10000000 Loading: ##############T ##T #################################################          #################################################################          ###############################################################T ##T          #################################################################          #################################################################          #################################################################          #################################################################          ############T #T ################T #T ###################################          #################################################################          ################          184.6 KiB/s done Bytes transferred = 8822112 (869d60 hex)

通过mmc write命令将内核镜像烧录到eMMC第0x8000个扇区处:

=> mmc erase 0x8000 20000  MMC erase: dev # 0, block # 32768, count 131072 ... 131072 blocks erased: OK => mmc write 0x10000000 0x8000 20000  MMC write: dev # 0, block # 32768, count 131072 ... 131072 blocks written: OK

5.4.2 bootm启动内核

在uboot命令行运行bootm 0x10000000命令启动内核:

=> bootm 0x10000000 ## Loading kernel from FIT Image at 10000000 ...    Using 'conf-1' configuration    Trying 'kernel' kernel subimage      Description:  Vanilla Linux kernel      Type:         Kernel Image      Compression:  gzip compressed      Data Start:   0x100000e8      Data Size:    8637971 Bytes = 8.2 MiB      Architecture: AArch64      OS:           Linux      Load Address: 0x20000000      Entry Point:  0x20000000      Hash algo:    crc32      Hash value:   dfbd0f6d      Hash algo:    sha1      Hash value:   aad6af66fe5cef720c93e6ea8115c69093216105    Verifying Hash Integrity ... crc32+ sha1+ OK bootm_find_os images.os.load=0x20000000    # kernel.its文件中kernel节点配置的"load"属性 bootm_find_os images.ep=0x20000000         # kernel.its文件中kernel节点配置的"entry"属性 bootm_find_os images.os.image_start=0x100000e8  # Image.gz镜像文件在内存中的地址 ## Loading ramdisk from FIT Image at 10000000 ...    Using 'conf-1' configuration    Trying 'ramdisk' ramdisk subimage      Description:  Ramdisk for project-x      Type:         RAMDisk Image      Compression:  gzip compressed      Data Start:   0x10848a20      Data Size:    134661 Bytes = 131.5 KiB      Architecture: AArch64      OS:           Linux      Load Address: 0x00000000      Entry Point:  0x00000000      Hash algo:    crc32      Hash value:   649c78d3    Verifying Hash Integrity ... crc32+ OK WARNING: 'compression' nodes for ramdisks are deprecated, please fix your .its file! ## Loading fdt from FIT Image at 10000000 ...    Using 'conf-1' configuration    Trying 'fdt' fdt subimage      Description:  Flattened Device Tree blob      Type:         Flat Device Tree      Compression:  uncompressed      Data Start:   0x1083d024      Data Size:    47365 Bytes = 46.3 KiB      Architecture: AArch64      Hash algo:    crc32      Hash value:   2489ab59      Hash algo:    sha1      Hash value:   002b18a40044056ce9097742d3cf5f4480338521    Verifying Hash Integrity ... crc32+ sha1+ OK    Booting using the fdt blob at 0x1083d024 Working FDT set to 1083d024    Uncompressing Kernel Image    kernel loaded at 0x20000000, end = 0x213e9a00    bootm_load_os 0x20000000=0x91005a4d     # 加压缩之后得到Image镜像,并加载到0x20000000地址处    bootm_load_os 0x20000010=0x145c000    Loading Ramdisk to f45f0000, end f4610e05 ... OK    Loading Device Tree to 00000000f45e1000, end 00000000f45ef904 ... OK Working FDT set to f45e1000 ## Transferring control to Linux (at address 20000000)...  Starting kernel ...

上面的日志信息里,我打印了内存地址0x20000000、0x20000010处的数据,可以看到和Image镜像文件的内容是一样的。

Rockchip RK3399 - 移植uboot 2023.04

至少证明uboot已经成功解压了zImage,并将解压后的Image加载到了0x20000000地址处,只是在跳转到0x20000000处执行内核代码时卡住了。

5.4.3 启动卡在start kernel处理

假如想解决问题,就必须知道问题出现在了哪里,因此一般通过内核启动的时候打印的信息来定位问题产生的原因。

这里首先想到的是打开使能CONFIG_DEBUG_KMEMLEAK,执行make menuconfig配置内核、

Kernel hacking  --->       Memory Debugging  --->           [*]  Kernel memory leak detector

重新编译内核,再次将kernel.itb下载到开发板eMMC第0x8000个扇区上。

再次启动开发板然后看是否可以得到有效的提示信息,假如仍然不可以的话,那就你直接读取缓存 ,缓存的地址为 __log_buf其地址在system.map被标记出来,我们可以找到具体的位置。具体如下:

(1) 先去内核编译目录找到System.map文件。

(2) 接下来遭到System.map中__log_buf对应地址,执行:

root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# cat  ./System.map | grep -n  __log_buf 117061:ffff000011493358 b __log_buf

此时记住0x11493358这个数字。

(3) 设置uboot环境变量,在bootargs中加入kmemleak=on;

设置新的bootargs:

=> setenv bootargs earlyprintk earlycon=uart8250,mmio32,0xff1a0000,115200n8 console=ttyS2,115200n8 root=/dev/nfs rw nfsroot=192.168.0.200:/work/nfs_root/rootfs_rk3399 ip=192.168.0.105:192.168.0.200:192.168.0.1:255.255.255.0::eth0:off => saveenv Saving Environment to MMC... Writing to MMC(0)... OK

(4)  直接从eMMC第0x8000个扇区加载内核,启动内核,内核此时卡在Starting kernel …位置;

=> mmc read 0x10000000 0x8000 20000  MMC read: dev # 0, block # 32768, count 131072 ... 131072 blocks read: OK => bootm 0x10000000

(5)  重新启动系统(注意:不要断电启动,按下复位键即可),进入uboot命令行界面;

(6) 在命令行输入(数字是刚才得到的数字):

md 0x11493358

(7) 不停的敲击回车键,直到为全为0。

arm64和arm有点不太一样,待定.... ,在研究....

参考文章

[1] Rockchip参考官方移植

[2] Rockchip RK3399 - TPL/SPL方式加载uboot

[3] 嵌入式Linux之uboot源码make配置编译正向分析

[4]嵌入式ARM64 Linux内核FIT uimage方式启动