開發板:NanoPC-T4開發板eMMC:16GBLPDDR3:4GB顯示屏:15.6 HDMI介面顯示屏u-boot :2023.04 在前面我們已經介紹了編譯Rockchip官方提供的uboot源碼,並下載到開發板中進行測試運行。這一節我們嘗試下載最新的uboot版本試試,當前最新版本為2023 ...
----------------------------------------------------------------------------------------------------------------------------
開發板: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評估板的配置:
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=yView 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。
配置項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()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-sp