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 ‘true’ for 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 # TheAndroid7.1 移植 GPS Ublox HAL
找到 Ublox 的 驱动包。
网上找了很久没有找到,后面随便在网上搜索了一个 3.1版本的。
放入 Android 源码的 hardware 目录下在 Android 板级文件里面添加文件添加GPS 的驱动。
主要是如下两个文件
device/rockchip/common/BoardConfig.mk310 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 | Rockchip原始固件与RK固件格式