Rockchip RK3399 - 官方固件方式加载uboot
----------------------------------------------------------------------------------------------------------------------------
开发板 :NanoPC-T4开发板
eMMC :16GB
LPDDR3:4GB
显示屏 :15.6英寸HDMI接口显示屏
u-boot :2017.09
----------------------------------------------------------------------------------------------------------------------------
NanoPC-T4开发板,主控芯片是Rockchip RK3399,big.LITTLE大小核架构,双Cortex-A72大核(up to 2.0GHz) + 四Cortex-A53小核结构(up to 1.5GHz);Cortex-A72处理器是Armv8-A架构下的一款高性能、低功耗的处理器。
我们接着上一节,介绍Rockchip处理器启动支持的两种引导方式:
- TPL/SPL加载:使用Rockchip官方提供的TPL/SPL U-boot(就是我们上面说的小的uboot),该方式完全开源;
- 官方固件加载:使用Rockchip idbLoader,来自Rockchip rkbin项目的Rockchip DDR初始化bin和miniloader bin,该方式不开源;
这一节我们将介绍采用官方固件方式,如何编译源码以及烧录程序到eMMC,从而完成uboot的启动。
一、idbloader.img
我们基于Rockchip rkbin官方给的ddr.bin、miniloader.bin来构建rk3399_loader_v1.27.126.bin。
- ddr.bin:等价于我们之前说的TPL,用于初始化DDR;
- miniloader.bin:Rockchip修改的一个bootloader,等价于我们之前说的SPL,用于加载uboot;
1.1 下载rkbin
我们可以在Rockchip的github上下载到Rockchip rkbin项目,如下所示:
root@zhengyang:/work/sambashare/rk3399# git clone https://github.com/rockchip-linux/rkbin.git --depth 1
1.2 合并
在rkbin根目录下执行如下命令:
root@zhengyang:/work/sambashare/rk3399# cd rkbin/ root@zhengyang:/work/sambashare/rk3399/rkbin# tools/mkimage -n rk3399 -T rksd -d bin/rk33/rk3399_ddr_800MHz_v1.27.bin idbloader.img Image Type: Rockchip RK33 (SD/MMC) boot image Init Data Size: 153600 bytes root@zhengyang:/work/sambashare/rk3399/rkbin# cat bin/rk33/rk3399_miniloader_v1.26.bin >> idbloader.img root@zhengyang:/work/sambashare/rk3399/rkbin# ll idbloader.img -rw-r--r-- 1 root root 239900 5月 15 20:47 idbloader.img
二、u-boot.img
使用Rockchip miniloader的idbloader时,需要将u-boot.bin通过tools/loaderimage转换为可加载的miniloader格式。
2.1 编译uboot
关于uboot的编译在上一篇博客中已经介绍的很详细了,这里不再重复介绍了,具体参考Rockchip RK3399- TPL/SPL方式加载uboot。
编译完成,在在uboot根录下生成文件有:root@zhengyang:/work/sambashare/rk3399/u-boot# ll u-boot* Sys* -rw-r--r-- 1 root root 153740 5月 14 10:30 System.map -rwxr-xr-x 1 root root 6872736 5月 14 10:30 u-boot* -rw-r--r-- 1 root root 931504 5月 14 10:30 u-boot.bin -rw-r--r-- 1 root root 15808 5月 14 10:30 u-boot.cfg -rw-r--r-- 1 root root 9996 5月 14 10:30 u-boot.cfg.configs -rw-r--r-- 1 root root 51685 5月 14 10:30 u-boot.dtb # 设备树 -rw-r--r-- 1 root root 931501 5月 14 10:30 u-boot-dtb.bin # 等同u-boot.bin -rw-r--r-- 1 root root 932864 5月 14 10:30 u-boot-dtb.img # 等同u-boot.img -rw-r--r-- 1 root root 932864 5月 14 10:30 u-boot.img -rw-r--r-- 1 root root 1304 5月 14 10:30 u-boot.lds -rw-r--r-- 1 root root 800454 5月 14 10:30 u-boot.map -rwxr-xr-x 1 root root 879816 5月 14 10:30 u-boot-nodtb.bin* -rwxr-xr-x 1 root root 2529568 5月 14 10:30 u-boot.srec* -rw-r--r-- 1 root root 300850 5月 14 10:30 u-boot.sym
2.2 生成u-boot.img
在uboot项目根路径下执行如下命令生成u-boot.img镜像文件:
root@zhengyang:/work/sambashare/rk3399/u-boot# ./tools/loaderimage --pack --uboot ./u-boot.bin u-boot.img 0x00200000 load addr is 0x200000! pack input ./u-boot.bin pack file size: 933064(911 KB) crc = 0x0f6e6977 uboot version: U-Boot 2017.09-gef1dd65-dirty #root (May 14 2023 - 18:27:08) pack u-boot.img success! root@zhengyang:/work/sambashare/rk3399/u-boot# root@zhengyang:/work/sambashare/rk3399/u-boot# ll u-boot.img -rw-r--r-- 1 root root 4194304 5月 15 22:14 u-boot.img
其中0x00200000为uboot加载到DDR中的地址。
三、trust.img
使用Rockchip miniloader的 idbloader 时,需要将bl31.bin通过tools/trust_merge转换为可加载的miniloader格式。
在rkbin项目根路径下执行如下命令生成trust.img镜像文件:
root@zhengyang:/work/sambashare/rk3399/rkbin# ./tools/trust_merger ./RKTRUST/RK3399TRUST.ini out:trust.img merge success(trust.img) root@zhengyang:/work/sambashare/rk3399/rkbin# ll trust.img -rw-r--r-- 1 root root 4194304 5月 15 20:54 trust.img
其中./RKTRUST/RK3399TRUST.ini文件内容如下:
root@zhengyang:/work/sambashare/rk3399/u-boot# cat ./RKTRUST/RK3399TRUST.ini [VERSION] MAJOR=1 MINOR=0 [BL30_OPTION] SEC=0 [BL31_OPTION] SEC=1 PATH=bin/rk33/rk3399_bl31_v1.35.elf ADDR=0x00040000 [BL32_OPTION] SEC=1 PATH=bin/rk33/rk3399_bl32_v2.10.bin ADDR=0x08400000 [BL33_OPTION] SEC=0 [OUTPUT] PATH=trust.img
四、rkdeveloptool
rkdeveloptool是Rockchip提供的一个与Rockusb设备进行通信的工具,通过该工具我们可以将镜像文件下载到开发板的eMMC。它被认为是upgrade_tool的一个开源版本,只有很少区别。
要使用rkdeveloptool进行升级,首先要知道rkdeveloptool是基于什么情况下才会起作用的,是在SoC进入MASKROM模式后而且跟主机通过USB连接,因为这个时候主板的DDR并没有初始化,而升级过程是需要很大的内存空间的,所以升级之前第一步要做的就是执行rkdeveloptool db rkxx_loader_vx.xx.bin(这个固件本质上也是idbloader.img),只不过这时候只是在内存中执行,如果不执行db命令的话其他的命令则无法执行因为没有做内存初始化工作。
4.1 下载源码
在/work/sambashare/rk3399目录下执行如下命令:
root@zhengyang:/work/sambashare/rk3399# git clone https://github.com/rockchip-linux/rkdeveloptool.git --depth 1
4.2 配置
首先安装libusb与udev,例如对于ubuntu:
root@zhengyang:/work/sambashare/rk3399# sudo apt-get install libudev-dev libusb-1.0-0-dev dh-autoreconf
切换到rkdeveloptool/目录进行配置:
root@zhengyang:/work/sambashare/rk3399# cd rkdeveloptool/ root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# autoreconf -i configure.ac:12: installing 'cfg/compile' configure.ac:19: installing 'cfg/config.guess' configure.ac:19: installing 'cfg/config.sub' configure.ac:7: installing 'cfg/install-sh' configure.ac:7: installing 'cfg/missing' Makefile.am: installing 'cfg/depcomp' root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# ./configure
4.3 编译安装
运行如下命令:
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# make root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# make install
如果遇到如下编译错误:
./configure: line 4269: syntax error near unexpected token `LIBUSB1,libusb-1.0' ./configure: line 4269: `PKG_CHECK_MODULES(LIBUSB1,libusb-1.0)'
还需要安装pkg-config与libusb-1.0:
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# sudo apt-get install pkg-config libusb-1.0
编译完成后,在当前路径下生成rkdeveloptool可执行文件:
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# ll rkdeveloptool -rwxr-xr-x 1 root root 1059720 5月 11 19:56 rkdeveloptool*
4.4 rk3399_loader_v1.27.126.bin
由于SoC进入到MASKROM模式后,目标板子会运行Rockusb驱动程序。在MASKROM模式下,需要使用到DDR,因此需要下载固件进行DDR的初始化。Rockchip rkbin项目提供了ddr.bin、usbplug.bin、miniloader.bin这三个包:
- ddr.bin:等价于我们之前说的TPL,用于初始化DDR;
- usbplug.bin:Rockusb驱动程序,用于将程序通过usb下载到eMMC;
- miniloader.bin:Rockchip修改的一个bootloader,等价于我们之前说的SPL,用于加载uboot;
在rkbin目录下执行如下命令,可以将ddr.bin、usbplug.bin、miniloader.bin这三个包合并,得到rk3399_loader_v1.27.126.bin:
root@zhengyang:/work/sambashare/rk3399# cd rkbin/ root@zhengyang:/work/sambashare/rk3399/rkbin# tools/boot_merger /work/sambashare/rk3399/rkbin/RKBOOT/RK3399MINIALL.ini ********boot_merger ver 1.2******** Info:Pack loader ok. root@zhengyang:/work/sambashare/rk3399/rkbin# ll rk3399_loader_v1.27.126.bin -rw-r--r-- 1 root root 465230 5月 11 20:06 rk3399_loader_v1.27.126.bin
可以根据自己的需求可以在./RKBOOT/RK3399MINIALL.ini修改ddr、usbplug、miniloader:
[CHIP_NAME] NAME=RK330C [VERSION] MAJOR=1 MINOR=26 [CODE471_OPTION] NUM=1 Path1=bin/rk33/rk3399_ddr_800MHz_v1.27.bin Sleep=1 [CODE472_OPTION] NUM=1 Path1=bin/rk33/rk3399_usbplug_v1.26.bin [LOADER_OPTION] NUM=2 LOADER1=FlashData LOADER2=FlashBoot FlashData=bin/rk33/rk3399_ddr_800MHz_v1.27.bin FlashBoot=bin/rk33/rk3399_miniloader_v1.26.bin [OUTPUT] PATH=rk3399_loader_v1.27.126.bin
将rk3399_loader_v1.27.126.bin拷贝到rkdeveloptool路径下:
root@zhengyang:/work/sambashare/rk3399/rkbin# cp rk3399_loader_v1.27.126.bin ../rkdeveloptool/
五、烧录程序
5.1 准备镜像
我们按照之前的流程得到了idbloader.img、u-boot.img,trust.img文件,由于我们这里不进行内核和根文件系统的烧录,所以暂时不需要准备这俩。
按照Rockchip官方要求将idbloader.img烧录到eMMC的0x40扇区,u-boot.img烧录到0x4000扇区,trust.img烧录到0x6000扇区。
我们需要将idbloader.img、u-boot.img、trust.img拷贝到rkdeveloptool路径下:
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# cp ../rkbin/trust.img ./ root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# cp ../u-boot/u-boot.img ./ root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# cp ../rkbin/idbloader.img ./
5.2 进入MASKROM升级模式
NanoPC-T4开发板如需进入MASKROM升级模式,需要进入如下操作:
- 将开发板连接上电源,并且连接Type-C数据线到PC;
- 按住BOOT键再长按Power键开机(保持按下BOOT键5秒以上),将强制进入MASKROM模式。
一般电脑识别到USB连接,都会发出声音。或者观察虚拟机右下角是否突然多个USB设备:右键点击链接;
5.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.img Write LBA from file (100%) root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# rkdeveloptool wl 0x6000 trust.img Write LBA from file (100%)
在烧写镜像完成后使用rd命令重启目标机器:
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# rkdeveloptool rd
Reset Device OK.
需要注意的是:如果这个时候你也烧录了内核程序,执行完rd命令后是无法进入uboot命令的的,这里会直接启动内核。
六、测试
6.1 串口连接
使用准备好的USB转串口适配器和连接线(需另购),连接开发板:
引脚 | 开发板接口 | USB转串口 |
1 | GNC | - |
2 | VCC 5V | - |
3 | UART2DBG_TX | RX |
4 | UART2DBG_RX | TX |
6.2 MobaXterm
这里我使用的串口调试工具是MobaXterm,选择串口端口,设置波特率为1500000,8位数据位,1位停止位。
6.3 上电
给开发板上电,通过串口打印输出:
DDR Version 1.27 20211018 In soft reset SRX Channel 0: LPDDR3, 800MHz CS = 0 MR0=0x58 MR1=0x58 MR2=0x58 MR3=0x58 MR4=0x3 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=0x3 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=0x3 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=0x3 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: May 29 2020 17:36:36, version: 1.26 CPUId = 0x0 ChipType = 0x10, 431 SdmmcInit=2 0 BootCapSize=100000 UserCapSize=14910MB FwPartOffset=2000 , 100000 mmc0:cmd8,20 mmc0:cmd5,20 mmc0:cmd55,20 mmc0:cmd1,20 mmc0:cmd8,20 mmc0:cmd5,20 mmc0:cmd55,20 mmc0:cmd1,20 mmc0:cmd8,20 mmc0:cmd5,20 mmc0:cmd55,20 mmc0:cmd1,20 SdmmcInit=0 1 StorageInit ok = 69291 SecureMode = 0 SecureInit read PBA: 0x4 SecureInit read PBA: 0x404 SecureInit read PBA: 0x804 SecureInit read PBA: 0xc04 SecureInit read PBA: 0x1004 SecureInit read PBA: 0x1404 SecureInit read PBA: 0x1804 SecureInit read PBA: 0x1c04 SecureInit ret = 0, SecureMode = 0 atags_set_bootdev: ret:(0) GPT 0x3335db8 signature is wrong recovery gpt... GPT 0x3335db8 signature is wrong recovery gpt fail! Trust Addr:0x4000, 0x58334c42 No find bl30.bin Load uboot, ReadLba = 2000 Load OK, addr=0x200000, size=0xe3cc8 RunBL31 0x40000 @ 103019 us NOTICE: BL31: v1.3(release):845ee93 NOTICE: BL31: Built : 15:51:11, Jul 22 2020 NOTICE: BL31: Rockchip release version: v1.1 INFO: GICv3 with legacy support detected. ARM GICV3 driver initialized in EL3 INFO: Using opteed sec cpu_context! INFO: boot cpu mask: 0 INFO: plat_rockchip_pmu_init(1196): pd status 3e INFO: BL31: Initializing runtime services INFO: BL31: Initializing BL32 INF [0x0] TEE-CORE:init_primary_helper:337: Initializing (1.1.0-278-gef70f120a #zhangzj #9 Fri Sep 17 09:39:24 UTC 2021 aarch64) INF [0x0] TEE-CORE:init_primary_helper:338: Release version: 1.2 INF [0x0] TEE-CORE:init_teecore:83: teecore inits done INFO: BL31: Preparing for EL3 exit to normal world INFO: Entry point address = 0x200000 INFO: SPSR = 0x3c9 U-Boot 2017.09-gef1dd65-dirty #root (May 14 2023 - 18:26:10 +0800) Model: Rockchip RK3399 Evaluation Board PreSerial: 2, raw, 0xff1a0000 DRAM: 3.8 GiB Sysmem: init Relocation Offset: f5ba0000 Relocation fdt: f3d8a2e0 - f3d96cc5 CR: M/C/I I2c0 speed: 400000Hz PMIC: RK808 vdd_center init 950000 uV *** Warning - No MMC card found, using default environment MMC: dwmmc@fe320000: 1, sdhci@fe330000: 0 Bootdev(atags): mmc 0 MMC0: HS400, 150Mhz PartType: RKPARM Could not find baseparameter partition In: serial Out: serial Err: serial Model: Rockchip RK3399 Evaluation Board boot mode: normal Found DTB in resource part Rockchip UBOOT DRM driver version: v1.0.1 AUX CH command reply failed! AUX CH error happens: 2 AUX CH command reply failed! failed to read link rate: -110 edp@ff970000 disconnected CLK: (uboot. arml: enter 400000 KHz, init 816000 KHz, kernel 0N/A) CLK: (uboot. armb: enter 24000 KHz, init 816000 KHz, kernel 0N/A) aplll 816000 KHz apllb 816000 KHz dpll 800000 KHz cpll 24000 KHz gpll 800000 KHz npll 600000 KHz vpll 24000 KHz aclk_perihp 133333 KHz hclk_perihp 66666 KHz pclk_perihp 33333 KHz aclk_perilp0 266666 KHz hclk_perilp0 88888 KHz pclk_perilp0 44444 KHz hclk_perilp1 100000 KHz pclk_perilp1 50000 KHz Net: eth0: ethernet@fe300000 ### main_loop entered: bootdelay=5 ### main_loop: bootcmd="boot_android ${devtype} ${devnum};boot_fit;bootrkp;run distro_bootcmd;" Hit key to stop autoboot('CTRL+C'): 0 =>
在倒计时执行完之前,按CTRL+C即可进入uboot命令行。
参考文章