Rockchip RK3399-uboot移植

Posted 大奥特曼打小怪兽

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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,该方式不开源;

一、TPL/SPL加载

1.1 编译uboot

uboot通常有三种:

  • uboot官方源码:https://github.com/u-boot/u-boot,uboot官方源码是由uboot官方维护,支持非常全面的芯片,但对具体某款开发板支持情况一般;
  • 半导体厂商瑞芯微官方源码:https://github.com/rockchip-linux/u-boot,半导体厂商基于uboot官方源码进行修改,对自家的芯片进行完善的支持,针对某款处理器支持情况较好;
  • 开发板友善之家官方源码:https://github.com/friendlyarm/uboot-rockchip,开发板厂商基于半导体厂商维护的uboot,对自家的开发板进行板级支持,针对某款开发板支持情况较好;

这里我们本着学习的原则,所以这里我们直接选择半导体厂商瑞芯微官方源码维护的uboot。然后后面参考开发板友善之家官方源码修改使其能够支持NanoPC-T4开发板。

1.1.1 下载源码

我们可以在Rockchip的github上下载到芯片厂商提供的u-boot源码,如下图所示:

这里我们下载的是release分支的代码:

root@zhengyang:/work/sambashare/rk3399# git clone https://github.com/rockchip-linux/u-boot.git --depth 1 -b release

这里我是下载到/work/sambashare/rk3399路径下的,这个路径后面专门存放与rk3399相关的内容。

进入到u-boot文件夹里,这就是我们需要的uboot的源码了,后面就可以进行二次开发了;

root@zhengyang:/work/sambashare/rk3399/u-boot# cd ..
root@zhengyang:/work/sambashare/rk3399# cd u-boot/
root@zhengyang:/work/sambashare/rk3399/u-boot# ls -l
总用量 488
drwxr-xr-x   2 root root   4096 5月   7 20:00 api
drwxr-xr-x  14 root root   4096 5月   7 20:00 arch
drwxr-xr-x 181 root root   4096 5月   7 20:00 board
drwxr-xr-x   6 root root   4096 5月   7 20:00 cmd
drwxr-xr-x   5 root root   4096 5月   7 20:00 common
-rw-r--r--   1 root root   2260 5月   7 20:00 config.mk
drwxr-xr-x   2 root root  69632 5月   7 20:00 configs
drwxr-xr-x   2 root root   4096 5月   7 20:00 disk
drwxr-xr-x  10 root root  12288 5月   7 20:00 doc
drwxr-xr-x   3 root root   4096 5月   7 20:00 Documentation
drwxr-xr-x  56 root root   4096 5月   7 20:00 drivers
drwxr-xr-x   2 root root   4096 5月   7 20:00 dts
drwxr-xr-x   2 root root   4096 5月   7 20:00 env
drwxr-xr-x   4 root root   4096 5月   7 20:00 examples
drwxr-xr-x  12 root root   4096 5月   7 20:00 fs
drwxr-xr-x  32 root root  16384 5月   7 20:00 include
-rw-r--r--   1 root root   1863 5月   7 20:00 Kbuild
-rw-r--r--   1 root root  14162 5月   7 20:00 Kconfig
drwxr-xr-x  14 root root   4096 5月   7 20:00 lib
drwxr-xr-x   2 root root   4096 5月   7 20:00 Licenses
-rw-r--r--   1 root root  12587 5月   7 20:00 MAINTAINERS
-rw-r--r--   1 root root  56469 5月   7 20:00 Makefile
-rwxr-xr-x   1 root root  19845 5月   7 20:00 make.sh
drwxr-xr-x   2 root root   4096 5月   7 20:00 net
-rwxr-xr-x   1 root root   1640 5月   7 20:00 pack_resource.sh
drwxr-xr-x   5 root root   4096 5月   7 20:00 post
-rw-r--r--   1 root root     34 5月   7 20:00 PREUPLOAD.cfg
-rw-r--r--   1 root root 189024 5月   7 20:00 README
drwxr-xr-x   6 root root   4096 5月   7 20:00 scripts
-rw-r--r--   1 root root     17 5月   7 20:00 snapshot.commit
drwxr-xr-x  12 root root   4096 5月   7 20:00 test
drwxr-xr-x  16 root root   4096 5月   7 20:00 tools
1.1.2 配置uboot

uboot的编译分为两步:配置、编译。配置选择所要使用的board ,我的开发板型号是NanoPC-T4,与开发板匹配的应该是configs/evb-rk3399_defconfig。但是这里我们选择configs/rk3399_defconfig

root@zhengyang:/work/sambashare/rk3399/u-boot# cat configs/rk3399_defconfig
CONFIG_ARM=y
CONFIG_ARCH_ROCKCHIP=y
CONFIG_SPL_LIBCOMMON_SUPPORT=y
CONFIG_SPL_LIBGENERIC_SUPPORT=y
CONFIG_SYS_MALLOC_F_LEN=0x4000
CONFIG_SPL_FIT_GENERATOR="arch/arm/mach-rockchip/make_fit_atf.py"
CONFIG_ROCKCHIP_RK3399=y
CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x50000
CONFIG_RKIMG_BOOTLOADER=y
CONFIG_ROCKCHIP_VENDOR_PARTITION=y
CONFIG_SPL_STACK_R_ADDR=0x80000
CONFIG_DEFAULT_DEVICE_TREE="rk3399-evb"
CONFIG_DEBUG_UART=y
CONFIG_FIT=y
CONFIG_SPL_LOAD_FIT=y
CONFIG_BOOTDELAY=0
CONFIG_SYS_CONSOLE_INFO_QUIET=y
# CONFIG_DISPLAY_CPUINFO is not set
CONFIG_ANDROID_BOOTLOADER=y
CONFIG_ANDROID_AVB=y
CONFIG_SPL_STACK_R=y
CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x10000
CONFIG_SPL_ATF=y
CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y
CONFIG_FASTBOOT_BUF_ADDR=0x00800800
CONFIG_FASTBOOT_BUF_SIZE=0x08000000
CONFIG_FASTBOOT_FLASH=y
CONFIG_FASTBOOT_FLASH_MMC_DEV=0
# CONFIG_CMD_BOOTD is not set
CONFIG_CMD_BOOTZ=y
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_IMI is not set
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_XIMG is not set
# CONFIG_CMD_LZMADEC is not set
# CONFIG_CMD_UNZIP is not set
# CONFIG_CMD_FLASH is not set
# CONFIG_CMD_FPGA is not set
CONFIG_CMD_GPT=y
# CONFIG_CMD_LOADB is not set
# CONFIG_CMD_LOADS is not set
CONFIG_CMD_BOOT_ANDROID=y
CONFIG_CMD_BOOT_ROCKCHIP=y
CONFIG_CMD_MMC=y
CONFIG_CMD_USB=y
# CONFIG_CMD_ITEST is not set
# CONFIG_CMD_SETEXPR is not set
# CONFIG_CMD_MISC is not set
# CONFIG_DOS_PARTITION is not set
# CONFIG_ISO_PARTITION is not set
CONFIG_EFI_PARTITION_ENTRIES_NUMBERS=64
CONFIG_RKPARM_PARTITION=y
CONFIG_SPL_OF_CONTROL=y
CONFIG_OF_LIVE=y
CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
# CONFIG_NET_TFTP_VARS is not set
CONFIG_REGMAP=y
CONFIG_SPL_REGMAP=y
CONFIG_SYSCON=y
CONFIG_SPL_SYSCON=y
CONFIG_CLK=y
CONFIG_SPL_CLK=y
CONFIG_ROCKCHIP_GPIO=y
CONFIG_SYS_I2C_ROCKCHIP=y
CONFIG_DM_KEY=y
CONFIG_ADC_KEY=y
CONFIG_GPIO_KEY=y
CONFIG_RK_KEY=y
CONFIG_MISC=y
CONFIG_ROCKCHIP_EFUSE=y
CONFIG_MMC_DW=y
CONFIG_MMC_DW_ROCKCHIP=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_ROCKCHIP=y
CONFIG_DM_ETH=y
CONFIG_ETH_DESIGNWARE=y
CONFIG_GMAC_ROCKCHIP=y
CONFIG_PHY=y
CONFIG_PHY_ROCKCHIP_INNO_USB2=y
CONFIG_PINCTRL=y
CONFIG_SPL_PINCTRL=y
CONFIG_DM_FUEL_GAUGE=y
CONFIG_POWER_FG_RK818=y
CONFIG_DM_PMIC=y
CONFIG_PMIC_RK8XX=y
CONFIG_REGULATOR_PWM=y
CONFIG_DM_REGULATOR_FIXED=y
CONFIG_REGULATOR_RK8XX=y
CONFIG_DM_CHARGE_DISPLAY=y
CONFIG_CHARGE_ANIMATION=y
CONFIG_PWM_ROCKCHIP=y
CONFIG_RAM=y
CONFIG_SPL_RAM=y
CONFIG_ROCKCHIP_SDRAM_COMMON=y
CONFIG_SDRAM_COMMON_CAP_DETECT=y
CONFIG_SDRAM_COMMON_OSREG=y
CONFIG_SDRAM_COMMON_MSCH_RK3399=y
CONFIG_DM_RESET=y
CONFIG_BAUDRATE=1500000
CONFIG_DEBUG_UART_BASE=0xFF1A0000
CONFIG_DEBUG_UART_CLOCK=24000000
CONFIG_DEBUG_UART_SHIFT=2
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_OHCI_HCD=y
CONFIG_USB_OHCI_GENERIC=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_GADGET=y
CONFIG_USB_STORAGE=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DOWNLOAD=y
CONFIG_G_DNL_MANUFACTURER="Rockchip"
CONFIG_G_DNL_VENDOR_NUM=0x2207
CONFIG_G_DNL_PRODUCT_NUM=0x330a
CONFIG_DM_VIDEO=y
CONFIG_DISPLAY=y
CONFIG_DRM_ROCKCHIP=y
CONFIG_DRM_ROCKCHIP_DW_HDMI=y
CONFIG_DRM_ROCKCHIP_DW_MIPI_DSI=y
CONFIG_DRM_ROCKCHIP_ANALOGIX_DP=y
CONFIG_LCD=y
CONFIG_USE_TINY_PRINTF=y
CONFIG_LIB_RAND=y
CONFIG_SPL_TINY_MEMSET=y
CONFIG_ERRNO_STR=y
# CONFIG_EFI_LOADER is not set
CONFIG_AVB_LIBAVB=y
CONFIG_AVB_LIBAVB_AB=y
CONFIG_AVB_LIBAVB_ATX=y
CONFIG_AVB_LIBAVB_USER=y
CONFIG_RK_AVB_LIBAVB_USER=y
CONFIG_OPTEE_CLIENT=y
CONFIG_OPTEE_V1=y
CONFIG_OPTEE_ALWAYS_USE_SECURITY_PARTITION=y
CONFIG_TEST_ROCKCHIP=y

因此执行如下命令,生成.config文件:

root@zhengyang:/work/sambashare/rk3399/u-boot# make rk3399_defconfig V=1

出如下(忽略编译器警告信息):

配置主要分为三个步骤:

  • 第一步:执行make -f ./scripts/Makefile.build obj=scripts/basic,编译生成scripts/basic/fixdep工具;
  • 第二步:执行make -f ./scripts/Makefile.build obj=scripts/kconfig rk3399_defconfig,编译生成scripts/kcofig/conf工具;
  • 第三步:执行scripts/kconfig/conf --defconfig=arch/../configs/rk3399_defconfig Kconfig,scripts/kconfig/conf根据rk3399_defconfig生成.config配置文件;

这里会在当前路径下生成.config文件,这实际上是一个配置文件,这个文件是怎么生成的呢,实际上就是根据configs/rk3399_defconfig文件以及我们make menuconfig看到的那些默认配置(或者说是各个目录下的Kconfig文件中有效的default项)生成的。

在进行make编译的时候,会根据这个文件生成include/config/auto.conf文件,同时在顶层Makefile会引入auto.conf文件:

ifeq ($(dot-config),1)
# Read in config
-include include/config/auto.conf

这样在执行make编译过程中,就可以根据include/config/auto.conf中的宏的定义编译不同的库文件。

更多内容可以参考我之前写的有关s3c2440 uboot配置的文章:make smdk2410_defconfig配置分析,虽然SoC不同,但是make配置流程是一样的。

1.1.3 编译uboot

执行make命令,生成u-boot文件:

root@zhengyang:/work/sambashare/rk3399/u-boot# make ARCH=arm CROSS_COMPILE=arm-linux- 

译过程我们会发现有一些错误,这些错误的处理我们在文章的最后单独介绍。

注:CROSS-COPILE是在Makefile文件中定义的变量,是用来指定交叉工具链,ARCH用来指定处理器架构。此外,我们可以在u-boot的顶层Makefile中定义:

CROSS_COMPILE=arm-linux-
ARCH=arm

这样就省去了每次编译都要在控制台输入的麻烦。

更多内容可以参考我之前写的有关s3c2440 uboot编译的文章:make编译正向分析之顶层目标依赖,虽然SoC不同,但是make编译流程是一样的。

1.1.4 image镜像

成功编译之后,就会在 uboot源码的根目录下产生多个可执行二进制文件以及编译过程文件,这些文件都是 u-bootxxx 的命名方式。这些文件由一些列名为.xxx.cmd 的文件生成,.xxx.cmd 这些文件都是由编译系统产生的用于处理最终的可执行程序的。

在根录下生成文件有:

root@zhengyang:/work/sambashare/rk3399/u-boot# ls u-boot* -l
-rwxr-xr-x 1 root root 6055488 5月  10 22:44 u-boot
-rw-r--r-- 1 root root  888127 5月  10 22:45 u-boot.bin        # u-boot-nodtb.bin + u-boot.dtb
-rw-r--r-- 1 root root   14558 5月  10 22:45 u-boot.cfg
-rw-r--r-- 1 root root    9186 5月  10 22:45 u-boot.cfg.configs
-rw-r--r-- 1 root root   49503 5月  10 22:45 u-boot.dtb        # 设备树
-rw-r--r-- 1 root root  888127 5月  10 22:45 u-boot-dtb.bin    # 等同u-boot.bin 
-rw-r--r-- 1 root root  927440 5月  10 22:45 u-boot-dtb.img    # 等同u-boot.img 
-rw-r--r-- 1 root root  927440 5月  10 22:45 u-boot.img        # u-boot.bin + 64字节头
-rw-r--r-- 1 root root    1304 5月  10 22:44 u-boot.lds        # 链接文件
-rw-r--r-- 1 root root  740823 5月  10 22:44 u-boot.map
-rwxr-xr-x 1 root root  877088 5月  10 22:44 u-boot-nodtb.bin   
-rwxr-xr-x 1 root root 2521704 5月  10 22:44 u-boot.srec
-rw-r--r-- 1 root root  283819 5月  10 22:45 u-boot.sym

其中:

  • u-boot: 这个文件是编译后产生的ELF格式的最原始的uboot镜像文件,后续的文件都是由它产生的.u-boot.cmd 这个命令脚本描述了如何产生;
  • u-boot-nodtb.bin: 这文件是使用编译工具链的objcopy工具从u-boot这个文件中提取来的,它只包含可执行的二进制代码。就是把 u-boot 这个文件中对于执行不需要的节区删除后剩余的仅执行需要的部分。由 .u-boot-nodtb.bin.cmd 这个命令脚本产生;
  • u-boot-dtb.bin: 在 u-boot-nodtb.bin尾部拼接上设备树后形成的文件。由 .u-boot-dtb.bin.cmd 这个命令脚本产生;
  • u-boot.bin: 就是把u-boot-dtb.bin重命名得到的。由 .u-boot.bin.cmd 这个命令脚本产生;
  • u-boot.img: 在 u-boot.bin 开头拼接一些信息后形成的文件。由 .u-boot.img.cmd这个命令脚本产生;
  • u-boot-dtb.img: 在 u-boot.bin开头拼接一些信息后形成的文件。由 .u-boot-dtb.img.cmd这个命令脚本产生;
  • u-boot.srec: S-Record 格式的镜像文件。由 .u-boot.srec.cmd 这个命令脚本产生;
  • u-boot.sym: 这个是从 u-boot 中导出的符号表文件。由 .u-boot.sym.cmd 这个命令脚本产生;
  • u-boot.lds: 编译使用的链接脚本文件。由 .u-boot.lds.cmd 这个命令脚本产生;
  • u-boot.map: 编译的内存映射文件。该文件是有编译工具链的连接器输出的;
  • System.map: 记录 U-Boot 中各个符号在内核中位置,但是这个文件是使用了 nm 和 grep工具来手动生成的;

由于开启了SPL和TPL 的,因此,在编译uboot时会额外单独编译SPL、TPL,编译产生的镜像文件就存放在 ./spl、./tpl目录下。这下面的镜像生成方式与uboot基本是一模一样的。

root@zhengyang:/work/sambashare/rk3399/u-boot# ls  tpl
arch   cmd     drivers  env  include  u-boot.cfg      u-boot-tpl      u-boot-tpl.dtb      u-boot-tpl.map
board  common  dts      fs   lib      u-boot-spl.lds  u-boot-tpl.bin  u-boot-tpl-dtb.bin  u-boot-tpl-nodtb.bin
root@zhengyang:/work/sambashare/rk3399/u-boot# ls spl
arch   cmd     drivers  env  include  u-boot.cfg  u-boot-spl.bin  u-boot-spl-dtb.bin  u-boot-spl.map
board  common  dts      fs   lib      u-boot-spl  u-boot-spl.dtb  u-boot-spl.lds      u-boot-spl-nodtb.bin

以SPL为例:

  • u-boot-spl: 这个文件是编译后产生的 ELF格式的SPL镜像文件,后续的文件都是由它产生的.u-boot-spl.cmd 这个命令脚本描述了如何产生;
  • u-boot-spl-nodtb.bin: 这文件是使用编译工具链的objcopy工具从u-boot-spl这个文件中提取来的,它只包含可执行的二进制代码。就是把 u-boot-spl 这个文件中对于执行不需要的节区删除后剩余的仅执行需要的部分。由 .u-boot-spl-nodtb.bin.cmd 这个命令脚本产生;
  • u-boot-spl-dtb.bin: 在 u-boot-nodtb.bin 尾部依次拼接上 u-boot-spl-pad.bin 和 u-boot-spl.dtb 后形成的文件。由 .u-boot-spl-dtb.bin.cmd 这个命令脚本产生;
  • u-boot-spl.bin: 就是把 u-boot-dtb.bin 重命名得到的。由 .u-boot-spl.bin.cmd 这个命令脚本产生;
  • u-boot-spl.lds: 编译使用的链接脚本文件。由 .u-boot-spl.lds.cmd 这个命令脚本产生;
  • u-boot-spl.map: 编译SPL的内存映射文件;
  • u-boot-spl.dtb: 这个是编译好的设备树二进制文件。就是 ./dts/dt.dtb 重命名得到的。./dts/dt.dtb 来自于 arch/arm/dts/stm32f769-eval.dtb 重命名;

1.2 idbloader.img

我们基于uboot源码编译出TPL/SPL,其中TPL负责实现DDR初始化,TPL初始化结束之后会回跳到BootROM程序,BootROM程序继续加载SPL,由SPL加载u-boot.itb文件。

idbloader.img是由tpl/u-boot-tpl.bin文件生成,这里我们需要使用到mkimage工具,该工具由Rockchip提供。

1.2.1 Rockchip rkbin

在uboot同级目录下执行如下命令:

root@zhengyang:/work/sambashare/rk3399# git clone https://github.com/rockchip-linux/rkbin.git --depth 1
1.2.2 生成idbloader.img

在rkbin目录下执行:

root@zhengyang:/work/sambashare/rk3399# cd rkbin/
root@zhengyang:/work/sambashare/rk3399/rkbin# tools/mkimage -n rk3399 -T rksd -d ../u-boot/tpl/u-boot-tpl.bin ../u-boot/idbloader.img
Image Type:   Rockchip RK33 (SD/MMC) boot image
Init Data Size: 79872 bytes

在u-boot路径下生成idbloader.img文件:

root@zhengyang:/work/sambashare/rk3399/rkbin# cd ../u-boot/
root@zhengyang:/work/sambashare/rk3399/u-boot# ll idbloader.img
-rw-r--r-- 1 root root 81920 5月  10 23:40 idbloader.img

1.3 u-boot.idb

当使用SPL来加载ATF/OP-TEE时,可以将bl31.bin、u-boot-nodtb.bin和u-boot.dtb打包到u-boot.itb文件。在顶层Makefile文件中:

u-boot.itb: u-boot-nodtb.bin dts/dt.dtb $(U_BOOT_ITS) FORCE
        $(call if_changed,mkfitimage)
1.3.1 编译ATF

因为rk399是arm64,所以我们还需要编译 ATF (Arm trust firmware), ATF 主要负责在启动uboot之前把CPU从安全的EL3 切换到 EL2,然后跳转到uboot,并且在内核启动后负责启动其他的CPU。

下载arm-trusted-fireware到uboot同级目录:

root@zhengyang:/work/sambashare/rk3399# git clone https://github.com/ARM-software/arm-trusted-firmware.git --depth 1 

查看文件内容:

运行如下命令:

root@zhengyang:/work/sambashare/rk3399/arm-trusted-firmware# make CROSS_COMPILE=arm-linux- PLAT=rk3399

编译后报出一个缺少​​arm-none-eabi-gcc​​工具链的错误:

安装该工具链并重新编译:

root@zhengyang:/work/sambashare/rk3399/arm-trusted-firmware# sudo apt-get install gcc-arm-none-eabi
root@zhengyang:/work/sambashare/rk3399/arm-trusted-firmware# make CROSS_COMPILE=arm-linux- PLAT=rk3399

最终编译出来的目标文件为:build/rk3399/release/bl31/bl31.elf, 这个文件需要和编译出来的uboot一起打包成fit格式的镜像才能被SPL加载。

1.3.2 u-boot.itb

将bl31.elf拷贝到uboot根目录下:

root@zhengyang:/work/sambashare/rk3399/u-boot# cp /work/sambashare/rk3399/arm-trusted-firmware/build/rk3399/release/bl31/bl31.elf ./

然后执行编译命令:

root@zhengyang:/work/sambashare/rk3399/u-boot# make u-boot.itb

这里提示我们缺少python依赖elffile,如下图所示:

我们直接使用如下命令安装python依赖包(需要注意自己的python版本,这里是2.7版本):

root@zhengyang:/work/sambashare/rk3399/u-boot# pip2 install pyelftools

 四、uboot编译错误处理

由于Makefile在编译的时候配置 -Werror,将所有warning视为error,直接搜索代码:

root@zhengyang:/work/sambashare/rk3399/u-boot# grep "\\-Werror" * -nR
Makefile:366:KBUILD_CFLAGS      += -fshort-wchar -Werror
Makefile:620:KBUILD_CFLAGS   += $(call cc-option,-Werror=date-time)
scripts/Kbuild.include:116:     $(CC) -Werror $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2))
scripts/Kbuild.include:121:     $(CC) -Werror $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n)
scripts/gcc-stack-usage.sh:10:cat <<END | $@ -Werror -fstack-usage -x c - -c -o $TMP >/dev/null 2>&1 \\
tools/buildman/builderthread.py:429:                # We could avoid this by using -Werror everywhere...

KBUILD_CFLAGS是CC编译选项:

KBUILD_CFLAGS   += $(call cc-option,-Werror=date-time)          # 621行

在scripts/Kbuild.include定义了cc-option函数,函数用于检测$(CC) 是否支持给定的选项。比如注释中的例子的意思:如果交叉编译工具$(CC)支持cc-optionl函数的参数一表示的选项(也就是指-marm),那么cc-option函数的返回就是该选项(指-marm),否则返回的是call函数的参数二表示的选项。

# cc-option
# Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586)

cc-option = $(call try-run,\\
        $(CC) -Werror $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2))

由于编译选项配置了-Werror,因此在编译源代码的时候,会将所有warning视为error.。

因此我们可以通过修改Makefile、以及scripts/Kbuild.include文件 ,将-Werror修改为-Wno-error从而达到禁用 -Werror的目的。

关闭 -Werror可能会导致程序中隐藏的问题,因此建议在调试和测试期间使用-Werror来确保代码质量。一旦您已经验证了程序的正确性,就可以将其关闭,并在开发过程中保持高水平的代码质量。如果不想关闭-Werror标志,可以参考下面的源码修改方案。

4.1 resource_img.c文件

错误提示如下:

arch/arm/mach-rockchip/resource_img.c: In function ‘resource_image_check_header’:
arch/arm/mach-rockchip/resource_img.c:118:35: error: the comparison will always evaluate as ‘truefor the address of ‘magic’ will never be NULL [-Werror=address]
  118 |                        hdr->magic ? hdr->magic : "none");
      |                                   ^
arch/arm/mach-rockchip/resource_img.c:85:25: note: ‘magic’ declared here
   85 |         char            magic[4];

错误信息显示hdr->magic永远不会为NULL,定位到arch/arm/mach-rockchip/resource_img.c文件函数源代码:

static int resource_image_check_header(const struct resource_img_hdr *hdr)

        int ret;

        ret = memcmp(RESOURCE_MAGIC, hdr->magic, RESOURCE_MAGIC_SIZE);
        if (ret) 
                printf("bad resource image magic: %s\\n",
                           hdr->magic ? hdr->magic : "none");
                ret = -EINVAL;
        
        ......

            

为什么hdr->magic永远不会为NULL呢,主要是因为结构体struct resource_img_hdr的成员magic是一个数组,结构体在分配的时候数组地址就初始化了,因此不可能为NULL。

这里修改也很简单,直接改为:

printf("bad resource image magic: %s\\n",hdr->magic);

4.2 part_efi.c文件

错误提示如下:

disk/part_efi.c: In function ‘gpt_verify_partitions’:
disk/part_efi.c:858:63: error: taking address of packed member of ‘struct _gpt_entry’ may result in an unaligned pointer value [-Werror=address-of-packed-member]
  858 |                 gpt_convert_efi_name_to_char(efi_str, gpt_e[i].partition_name,
      |                                                       ~~~~~~~~^~~~~~~~~~~~~~~

这个编译警告是说对结构体struct _gpt_entry中的某个成员取了地址,而该成员被指定为packed,可能会导致指针访问不对齐的问题。

我们参考warning: taking address of packed member of \'struct details\' may result in an unaligned pointer value [-Waddress-of-packed-member]文章,根据错误行号将下面代码:

gpt_convert_efi_name_to_char(efi_str, gpt_e[i].partition_name,PARTNAME_SZ + 1);

修改为:

gpt_convert_efi_name_to_char(efi_str, member_nowarn(gpt_entry,efi_char16_t,&gpt_e[i],partition_name), PARTNAME_SZ + 1); 

同时在该文件头部新增宏定义:

#define member_nowarn(structType, elementType, structPtr, memberName) \\
  ((elementType*)(((char*)(structPtr)) + offsetof(structType, memberName)))

4.3 composite.c文件

错误提示如下:

drivers/usb/gadget/composite.c: In function ‘get_string’:
drivers/usb/gadget/composite.c:631:44: error: taking address of packed member of ‘struct usb_string_descriptor’ may result in an unaligned pointer value [-Werror=address-of-packed-member]
  631 |                         collect_langs(sp, s->wData);
      |                                           ~^~~~~~~
drivers/usb/gadget/composite.c:636:52: error: taking address of packed member of ‘struct usb_string_descriptor’ may result in an unaligned pointer value [-Werror=address-of-packed-member]
  636 |                                 collect_langs(sp, s->wData);
      |                                                   ~^~~~~~~
drivers/usb/gadget/composite.c:641:60: error: taking address of packed member of ‘struct usb_string_descriptor’ may result in an unaligned pointer value [-Werror=address-of-packed-member]
  641 |                                         collect_langs(sp, s->wData);
      |                                                           ~^~~~~~~
cc1: all warnings being treated as errors

和上面的问题一样,直接修改drivers/usb/gadget/composite.c文件get_string函数,根据错误行号将下面代码:

collect_langs(sp, s->wData);

替换为:

collect_langs(sp,member_nowarn(struct usb_string_descriptor,__le16, s, wData));

同时在该文件头部新增宏定义:

#define member_nowarn(structType, elementType, structPtr, memberName) \\
  ((elementType*)(((char*)(structPtr)) + offsetof(structType, memberName)))

4.4 uuid.c文件

错误提示如下:

lib/uuid.c: In function ‘gen_rand_uuid’:
lib/uuid.c:239:9: error: converting a packed ‘struct uuid’ pointer (alignment 1) to a ‘unsigned int’ pointer (alignment 4) may result in an unaligned pointer value [-Werror=address-of-packed-member]
  239 |         unsigned int *ptr = (unsigned int *)&uuid;
      |         ^~~~~~~~
In file included from include/part.h:12,
                 from include/common.h:37,
                 from lib/uuid.c:7:
include/uuid.h:11:8: note: defined here
   11 | struct uuid 
      |        ^~~~
cc1: all warnings being treated as errors
make[1]: *** [scripts/Makefile.build:281: lib/uuid.o] Error 1
make: *** [Makefile:1292: lib] Error 2

和上面的问题一样,直接修改include/uuid.h文件struct uuid定义,我们可以通过在结构体定义前加上属性__attribute__((packed, aligned(sizeof(unsigned int))))来声明结构体对齐方式为4字节,并将其设置为紧凑型。

/* This is structure is in big-endian */
struct uuid 
        unsigned int time_low;
        unsigned short time_mid;
        unsigned short time_hi_and_version;
        unsigned char clock_seq_hi_and_reserved;
        unsigned char clock_seq_low;
        unsigned char node[6];
 __attribute__((packed, aligned(sizeof(unsigned int))));

4.5 bootp.c文件

错误提示如下:

net/bootp.c: In function ‘check_reply_packet’:
net/bootp.c:134:47: error: taking address of packed member of ‘struct bootp_hdr’ may result in an unaligned pointer value [-Werror=address-of-packed-member]
  134 |         else if (!bootp_match_id(net_read_u32(&bp->bp_id)))
      |                                               ^~~~~~~~~~
net/bootp.c: In function ‘bootp_request’:
net/bootp.c:792:22: error: taking address of packed member of ‘struct bootp_hdr’ may result in an unaligned pointer value [-Werror=address-of-packed-member]
  792 |         net_copy_u32(&bp->bp_id, &bootp_id);
      |                      ^~~~~~~~~~
net/bootp.c: In function ‘dhcp_send_request_packet’:
net/bootp.c:996:22: error: taking address of packed member of ‘struct bootp_hdr’ may result in an unaligned pointer value [-Werror=address-of-packed-member]
  996 |         net_copy_u32(&bp->bp_id, &bp_offer->bp_id);
      |                      ^~~~~~~~~~
net/bootp.c:996:34: error: taking address of packed member of ‘struct bootp_hdr’ may result in an unaligned pointer value [-Werror=address-of-packed-member]
  996 |         net_copy_u32(&bp->bp_id, &bp_offer->bp_id);
      |                                  ^~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
make[1]: *** [scripts/Makefile.build:281: net/bootp.o] Error 

和上面的问题一样,直接修改net/bootp.c文件,根据错误行号将下面代码:

&bp->bp_id  或者 &bp_offer->bp_id

替换为:

member_nowarn(struct bootp_hdr,u32, bp, bp_id) 或者  member_nowarn(struct bootp_hdr,u32, bp_offser, bp_id)

同时在该文件头部新增宏定义:

#define member_nowarn(structType, elementType, structPtr, memberName) \\
  ((elementType*)(((char*)(structPtr)) + offsetof(structType, memberName)))

4.6 nfs.c文件

错误提示如下:

net/nfs.c: In function ‘rpc_req’:
net/nfs.c:199:25: error: taking address of packed member of ‘struct rpc_t’ may result in an unaligned pointer value [-Werror=address-of-packed-member]
  199 |         p = (uint32_t *)&(rpc_pkt.u.call.data);
      |                         ^~~~~~~~~~~~~~~~~~~~~~
net/nfs.c: In function ‘nfs_readlink_reply’:
net/nfs.c:631:67: error: taking address of packed member of ‘struct rpc_t’ may result in an unaligned pointer value [-Werror=address-of-packed-member]
  631 |                         nfs3_get_attributes_offset(rpc_pkt.u.reply.data);
      |                                                    ~~~~~~~~~~~~~~~^~~~~
net/nfs.c: In function ‘nfs_read_reply’:
net/nfs.c:692:67: error: taking address of packed member of ‘struct rpc_t’ may result in an unaligned pointer value [-Werror=address-of-packed-member]
  692 |                         nfs3_get_attributes_offset(rpc_pkt.u.reply.data);
      |                                                    ~~~~~~~~~~~~~~~^~~~~
cc1: all warnings being treated as errors
make[1]: *** [scripts/Makefile.build:281: net/nfs.o] Error 1
make: *** [Makefile:1292: net] Error 2

和上面的问题一样,直接修改net/nfs.c,根据错误行号将&(rpc_pkt.u.call.data)、以及rpc_pkt.u.call.data替换为:

member_nowarn(struct rpc_t,uint32_t, &rpc_pkt, u.call.data)

同时在该文件头部新增宏定义:

#define member_nowarn(structType, elementType, structPtr, memberName) \\
  ((elementType*)(((char*)(structPtr)) + offsetof(structType, memberName)))

uboot编译生成的uboot镜像并不能直接烧录到开发板中运行要与atf、bl31、ddr配置文件等必备文件合成后,才能烧录到板卡中运行。

由于官方不提供必备文件的源码,需要使用官方提供的bin文件包,因此本节从github的官方网站下载bin文件包。下载rockchip-linux/rkbin到uboot同级目录:

root@zhengyang:/work/sambashare/rk3399# git clone https://github.com/rockchip-linux/rkbin.git --depth 1

五、 脚本方式

u-boot文件夹下有个make.sh,它是个编译脚本,该脚本实际上就是做了我们之前说的配置、编译的过程,有兴趣,可以看一下这个shell的源码。

#!/bin/bash
set -e
BOARD=$1
SUBCMD=$1
FUNCADDR=$1
JOB=`sed -n "N;/processor/p" /proc/cpuinfo|wc -l`
SUPPORT_LIST=`ls configs/*[r,p][x,v,k][0-9][0-9]*_defconfig`

# @target board: defined in arch/arm/mach-rockchip/<soc>/Kconfig
# @label: show build message
# @loader: search for ini file to pack loader
# @trust: search for ini file to pack trust
#
# "NA" means use default name reading from .config
#
# Format:           target board               label         loader      trust
RKCHIP_INI_DESC=("CONFIG_TARGET_GVA_RK3229       NA          RK322XAT     NA"
                 "CONFIG_COPROCESSOR_RK1808  RK3399PRO-NPU  RK3399PRONPU  RK3399PRONPU"
# to be add...
                )

########################################### User can modify #############################################
# User\'s rkbin tool relative path
RKBIN_TOOLS=../rkbin/tools

# User\'s GCC toolchain and relative path
ADDR2LINE_ARM32=arm-none-linux-gnueabihf-addr2line
ADDR2LINE_ARM64=aarch64-none-linux-gnu-addr2line
OBJ_ARM32=arm-none-linux-gnueabihf-objdump
OBJ_ARM64=aarch64-none-linux-gnu-objdump
GCC_ARM32=arm-none-linux-gnueabihf-
GCC_ARM64=aarch64-none-linux-gnu-
TOOLCHAIN_ARM32=/usr/local/arm/12.2.1/bin
TOOLCHAIN_ARM64=/usr/local/arm/12.2.1/bin

########################################### User not touch #############################################
BIN_PATH_FIXUP="--replace tools/rk_tools/ ./"
RKTOOLS=./tools

# Declare global INI file searching index name for every chip, update in select_chip_info()
RKCHIP=
RKCHIP_LABEL=
RKCHIP_LOADER=
RKCHIP_TRUST=

# Declare rkbin repository path, updated in prepare()
RKBIN=

# Declare global toolchain path for CROSS_COMPILE, updated in select_toolchain()
TOOLCHAIN_GCC=
TOOLCHAIN_OBJDUMP=
TOOLCHAIN_ADDR2LINE=

# Declare global default output dir and cmd, update in prepare()
OUTDIR=$2
OUTOPT=

# Declare global plaform configure, updated in fixup_platform_configure()
PLATFORM_RSA=
PLATFORM_SHA=
PLATFORM_UBOOT_IMG_SIZE=
PLATFORM_TRUST_IMG_SIZE=
PLATFORM_AARCH32=
#########################################################################################################
help()

        echo
        echo "Usage:"
        echo "  ./make.sh [board|subcmd] [O=<dir>]"
        echo
        echo "   - board: board name of defconfig"
        echo "   - subcmd: loader|loader-all|trust|uboot|elf|map|sym|<addr>|"
        echo "   - O=<dir>: assigned output directory"
        echo
        echo "Example:"
        echo
        echo "1. Build board:"
        echo "  ./make.sh evb-rk3399               --- build for evb-rk3399_defconfig"
        echo "  ./make.sh evb-rk3399 O=rockdev     --- build for evb-rk3399_defconfig with output dir "./rockdev""
        echo "  ./make.sh firefly-rk3288           --- build for firefly-rk3288_defconfig"
        echo "  ./make.sh                          --- build with exist .config"
        echo
        echo "  After build, Images of uboot, loader and trust are all generated."
        echo
        echo "2. Pack helper:"
        echo "  ./make.sh trust                    --- pack trust.img"
        echo "  ./make.sh uboot                    --- pack uboot.img"
        echo "  ./make.sh loader                   --- pack loader bin"
        echo "  ./make.sh loader-all               --- pack loader bin (all supported loaders)"
        echo
        echo "3. Debug helper:"
        echo "  ./make.sh elf                      --- dump elf file with -D(default)"
        echo "  ./make.sh elf-S                    --- dump elf file with -S"
        echo "  ./make.sh elf-d                    --- dump elf file with -d"
        echo "  ./make.sh <no reloc_addr>          --- dump function symbol and code position of address(no relocated)"
        echo "  ./make.sh <reloc_addr-reloc_off>   --- dump function symbol and code position of address(relocated)"
        echo "  ./make.sh map                      --- cat u-boot.map"
        echo "  ./make.sh sym                      --- cat u-boot.sym"


prepare()

        local absolute_path cmd dir count

        # Parse output directory \'O=<dir>\'
        cmd=$OUTDIR%=*
        if [ "$cmd" = \'O\' ]; then
                OUTDIR=$OUTDIR#*=
                OUTOPT=O=$OUTDIR
        else
                case $BOARD in
                        # Parse from exit .config
                        \'\'|elf*|loader*|debug*|trust|uboot|map|sym)
                        count=`find -name .config | wc -l`
                        dir=`find -name .config`
                        # Good, find only one .config
                        if [ $count -eq 1 ]; then
                                dir=$dir%/*
                                OUTDIR=$dir#*/
                                # Set OUTOPT if not current directory
                                if [ $OUTDIR != \'.\' ]; then
                                        OUTOPT=O=$OUTDIR
                                fi
                        elif [ $count -eq 0 ]; then
                                echo
                                echo "Build failed, Can\'t find .config"
                                help
                                exit 1
                        else
                                echo
                                echo "Build failed, find $count \'.config\': "
                                echo "$dir"
                                echo "Please leave only one of them"
                                exit 1
                        fi
                        ;;

                        *)
                        OUTDIR=.
                        ;;
                esac
        fi

        # Parse help and make defconfig
        case $BOARD in
                #Help
                --help|-help|help|--h|-h)
                help
                exit 0
                ;;

                #Subcmd
                \'\'|elf*|loader*|debug*|trust|uboot|map|sym)
                ;;

                *)
                #Func address is valid ?
                if [ -z $(echo $FUNCADDR | sed \'s/[0-9,a-f,A-F,x,X,-]//g\') ]; then
                        return
                elif [ ! -f configs/$BOARD_defconfig ]; then
                        echo
                        echo "Can\'t find: configs/$BOARD_defconfig"
                        echo
                        echo "******** Rockchip Support List *************"
                        echo "$SUPPORT_LIST"
                        echo "********************************************"
                        echo
                        exit 1
                else
                        echo "make for $BOARD_defconfig by -j$JOB"
                        make $BOARD_defconfig $OUTOPT
                fi
                ;;
        esac

        # Initialize RKBIN
        if [ -d $RKBIN_TOOLS ]; then
                absolute_path=$(cd `dirname $RKBIN_TOOLS`; pwd)
                RKBIN=$absolute_path
        else
                echo
                echo "Can\'t find \'../rkbin/\' repository, please download it before pack image!"
                echo "How to obtain? 3 ways:"
                echo "  1. Login your Rockchip gerrit account: \\"Projects\\" -> \\"List\\" -> search \\"rk/rkbin\\" repository"
                echo "  2. Github repository: https://github.com/rockchip-linux/rkbin"
                echo "  3. Download full release SDK repository"
                exit 1
        fi


select_toolchain()

        local absolute_path

        if grep  -q \'^CONFIG_ARM64=y\' $OUTDIR/.config ; then
                if [ -d $TOOLCHAIN_ARM64 ]; then
                        absolute_path=$(cd `dirname $TOOLCHAIN_ARM64`; pwd)
                        TOOLCHAIN_GCC=$absolute_path/bin/$GCC_ARM64
                        TOOLCHAIN_OBJDUMP=$absolute_path/bin/$OBJ_ARM64
                        TOOLCHAIN_ADDR2LINE=$absolute_path/bin/$ADDR2LINE_ARM64
                else
                        echo "Can\'t find toolchain: $TOOLCHAIN_ARM64"
                        exit 1
                fi
        else
                if [ -d $TOOLCHAIN_ARM32 ]; then
                        absolute_path=$(cd `dirname $TOOLCHAIN_ARM32`; pwd)
                        TOOLCHAIN_GCC=$absolute_path/bin/$GCC_ARM32
                        TOOLCHAIN_OBJDUMP=$absolute_path/bin/$OBJ_ARM32
                        TOOLCHAIN_ADDR2LINE=$absolute_path/bin/$ADDR2LINE_ARM32
                else
                        echo "Can\'t find toolchain: $TOOLCHAIN_ARM32"
                        exit 1
                fi
        fi

        # echo "toolchain: $TOOLCHAIN_GCC"


sub_commands()

        local cmd=$SUBCMD%-* opt=$SUBCMD#*-

        case $cmd in
                elf)
                if [ ! -f $OUTDIR/u-boot ]; then
                        echo "Can\'t find elf file: $OUTDIR/u-boot"
                        exit 1
                else
                        # default \'cmd\' without option, use \'-D\'
                        if [ "$cmd" = \'elf\' -a "$opt" = \'elf\' ]; then
                                opt=D
                        fi
                        $TOOLCHAIN_OBJDUMP -$opt $OUTDIR/u-boot | less
                        exit 0
                fi
                ;;

                debug)
                debug_command
                exit 0
                ;;

                map)
                cat $OUTDIR/u-boot.map | less
                exit 0
                ;;

                sym)
                cat $OUTDIR/u-boot.sym | less
                exit 0
                ;;

                trust)
                pack_trust_image
                exit 0
                ;;

                loader)
                pack_loader_image $opt
                exit 0
                ;;

                uboot)
                pack_uboot_image
                exit 0
                ;;

                *)
                # Search function and code position of address
                RELOC_OFF=$FUNCADDR#*-
                FUNCADDR=$FUNCADDR%-*
                if [ -z $(echo $FUNCADDR | sed \'s/[0-9,a-f,A-F,x,X,-]//g\') ] && [ $FUNCADDR ]; then
                        # With prefix: \'0x\' or \'0X\'
                        if [ `echo $FUNCADDR | sed -n "/0[x,X]/p" | wc -l` -ne 0 ]; then
                                FUNCADDR=`echo $FUNCADDR | awk \' print strtonum($0) \'`
                                FUNCADDR=`echo "obase=16;$FUNCADDR"|bc |tr \'[A-Z]\' \'[a-z]\'`
                        fi
                        if [ `echo $RELOC_OFF | sed -n "/0[x,X]/p" | wc -l` -ne 0 ] && [ $RELOC_OFF ]; then
                                RELOC_OFF=`echo $RELOC_OFF | awk \' print strtonum($0) \'`
                                RELOC_OFF=`echo "obase=16;$RELOC_OFF"|bc |tr \'[A-Z]\' \'[a-z]\'`
                        fi

                        # If reloc address is assigned, do sub
                        if [ "$FUNCADDR" != "$RELOC_OFF" ]; then
                                # Hex -> Dec -> SUB -> Hex
                                FUNCADDR=`echo $((16#$FUNCADDR))`
                                RELOC_OFF=`echo $((16#$RELOC_OFF))`
                                FUNCADDR=$((FUNCADDR-RELOC_OFF))
                                FUNCADDR=$(echo "obase=16;$FUNCADDR"|bc |tr \'[A-Z]\' \'[a-z]\')
                        fi

                        echo
                        sed -n "/$FUNCADDR/p" $OUTDIR/u-boot.sym
                        $TOOLCHAIN_ADDR2LINE -e $OUTDIR/u-boot $FUNCADDR
                        exit 0
                fi
                ;;
        esac


# We select chip info to do:
#       1. RKCHIP: fixup platform configure
#       2. RKCHIP_LOADER: search ini file to pack loader
#       3. RKCHIP_TRUST: search ini file to pack trust
#       4. RKCHIP_LABEL: show build message
#
# We read chip info from .config and \'RKCHIP_INI_DESC\'
select_chip_info()

        local target_board item value

        # Read RKCHIP firstly from .config
        # The 

Android7.1 移植 GPS Ublox HAL

  • 找到 Ublox 的 驱动包。

    网上找了很久没有找到,后面随便在网上搜索了一个 3.1版本的。
    放入 Android 源码的 hardware 目录下

  • 在 Android 板级文件里面添加文件添加GPS 的驱动。

    主要是如下两个文件
    device/rockchip/common/BoardConfig.mk

    310 BOARD_HAS_GPS ?= true
    311 BOARD_GPS_TYPE ?= ublox
    

    device/rockchip/rk3288/system.prop

    persist.sys.gpsTTY=/dev/ttyS1
    
  • 修改 ublox 的配置文件。

    hardware/u-blox/gps/u-blox.conf

    39 SERIAL_DEVICE                    /dev/ttyS1
    
  • 编译 ublox

    cd hardware/u-blox/gps/
    mm -B
    

    这个Android 版本里面,直接编译有一个小错误,类似 DATA 这个值找不到,把有这个错误的两行注释掉就好了。
    大致在 hardware/u-blox/gps/supl/suplSMmanager.cpp 这个文件
    编译完成之后, 复制文件

    cp out/target/product/rk3288/obj/lib/gps.default.so out/target/product/rk3288/system/lib/hw/ -rf
    cp hardware/u-blox/gps/gps.conf  out/target/product/rk3288/system/etc/ -rf
    cp hardware/u-blox/gps/u-blox.conf  out/target/product/rk3288/system/etc/ -rf
    

    然后重新编译Android
    烧录新系统,安装 u-center

以上是关于Rockchip RK3399-uboot移植的主要内容,如果未能解决你的问题,请参考以下文章

Rockchip RK3399

RK3399之ap6212移植

Rockchip | Rockchip原始固件与RK固件格式

瑞芯微的Rockchip的Rk3399的优势多吗?

[Rockchip RK3399] | RK格式固件分区表文件parameter.txt浅析

Rockchip | Rockchip U-Boot命令判断存储器是否有RK固件