完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
为了更深入了解rk1808 sdk,对其中关于uboot部分的脚本和makefile等做一个分析
主要参考文件:Rockchip_Developer_Guide_Linux_Software_CN.pdf uboot的编译 根据文档的说法,编译uboot有两种方法 在uboot目录下编译 这种方法,先cd到uboot目录下,然后执行 sudo ./make.sh rk1808 在顶层目录下编译 这种方法,利用底层目录的build.sh,传递参数uboot进行编译 sudo ./build.sh uboot 其实利用build.sh脚本,实际上也是cd到uboot目录下,去调用make.sh脚本进行编译,因此这两种方式其实可以认为是一种,那要想弄清楚来龙去脉,就得先分析build.sh脚本 build.sh分析 直接跳到末尾,有这样一段话,首先判断是不是需要打印usage,如果不是,然后再对输入的参数,也就是$@进行遍历,并判断它是什么 例如我这样输入sudo ./build.sh uboot,在下面的case分支语句中,就会进入eval build_$option || usage,这个意思是||前能执行,就去执行,不能执行,就打印usage #========================= # build targets #========================= if echo $@|grep -wqE "help|-h"; then usage exit 0 fi OPTIONS="$@" for option in ${OPTIONS:-allsave}; do echo "processing option: $option" case $option in BoardConfig*.mk) option=$TOP_DIR/device/rockchip/$RK_TARGET_PRODUCT/$option ;& *.mk) CONF=$(realpath $option) echo "switching to board: $CONF" if [ ! -f $CONF ]; then echo "not exist!" exit 1 fi ln -sf $CONF $BOARD_CONFIG ;; buildroot|debian|distro|yocto) build_rootfs $option ;; recovery) build_kernel ;& *) eval build_$option || usage ;; esac done 再往上看,可以找到编译uboot的函数,它首先删除了一个loader什么的bin文件,据说是用于初始化ddr的,这个暂时没太想明白 然后cd到uboot的目录下,执行./make.sh rk1808,它这个参数$RK_UBOOT_DEFCONFIG通过打印可以很清楚地知道,其实就是rk1808,然后判断上一个命令的退出状态,来确定执行成功与否 接下来就是分析make.sh了 function build_uboot(){ echo "============Start build uboot============" echo "TARGET_UBOOT_CONFIG=$RK_UBOOT_DEFCONFIG" echo "=========================================" if [ -f u-boot/*_loader_*.bin ]; then rm u-boot/*_loader_*.bin fi cd u-boot && ./make.sh $RK_UBOOT_DEFCONFIG && cd - if [ $? -eq 0 ]; then echo "====Build uboot ok!====" else echo "====Build uboot failed!====" exit 1 fi } make.sh 这个脚本比刚才的复杂的多,因为瑞星微的sdk是针对所有产品的,一份sdk可以编译出多款芯片的镜像文件,所以这个makefile、编译脚本等都很复杂,但是我们只要抽丝剥茧,抓住核心即可 还是老规矩,直接跳到末尾,看它调用了哪些函数 prepare select_toolchain select_chip_info fixup_platform_configure sub_commands make CROSS_COMPILE=${TOOLCHAIN_GCC} all --jobs=${JOB} ${OUTOPT} pack_uboot_image pack_loader_image pack_trust_image finish prepare prepare() { local absolute_path cmd dir count # Parse output directory 'O= cmd=${OUTDIR%=*} `if [ "${cmd}" = 'O' ]; then` OUTDIR=${OUTDIR#*=} OUTOPT=O=${OUTDIR} else case $BOARD in # Parse from exit .config ''|elf*|loader*|spl*|itb|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*|spl*|itb|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 } 这个函数很长,首先出现了几个变量,然后先看分析第一段# Parse output directory 'O= BOARD=$1 OUTDIR=$2 OUTOPT= 我们传进来的$1是rk1808,后面两个OUT都是空,因此,不会进入if [ "${cmd}" = 'O' ]; then这个条件里面 进到第二个条件后,会去遍历我们传进来的参数 $1,也就是BOARD,然后第一个case条件是''|elf*|loader*|spl*|itb|debug*|trust|uboot|map|sym)很明显rk1808不满足这个,所以会执行末尾的*),这个条件里面,只做了一件事,那就是OUTDIR=. 然后分析第二段,# Parse help and make defconfig 可以看到注释的help和subcmd仍然是不会被执行的,所以直接看Func address is valid ?部分 这个if条件的结果,是rk,不为空,所以不会return 然后判断configs/rk1808_defconfig这个默认配置文件在不在 最后唯一有用的部分,就是执行make ${BOARD}_defconfig ${OUTOPT},也就是make rk1808_defconfig . 这句话的作用是从configs中拷贝配置文件到当前目录下 case $BOARD in #Help --help|-help|help|--h|-h) help exit 0 ;; #Subcmd ''|elf*|loader*|spl*|itb|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 在uboot的同级目录下,有个rkbin目录,编译uboot时需要用到这里面的bin文件,这里就是为了将它的绝对路径赋值给RKBIN # 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 根据当前目录下的.config文件,判断是否有CONFIG_ARM64=y,然后给TOOLCHAIN_GCC等变量赋一个绝对路径 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}" } |
|
|
|
select_chip_info
这个函数个人感觉不怎么重要,所以代码就不贴了,它的作用也是从.config读取一些信息,然后给以下变量赋值 RKCHIP_LABEL、RKCHIP_LOADER、RKCHIP_TRUST fixup_platform_configure 这个函数也没什么意思,也是在赋值 PLATFORM_RSA="--rsa 3" PLATFORM_UBOOT_IMG_SIZE="--size 1024 2" PLATFORM_TRUST_IMG_SIZE="--size 1024 2" sub_commands 说实话我没看懂他要干啥 make make CROSS_COMPILE=${TOOLCHAIN_GCC} all --jobs=${JOB} ${OUTOPT} 这个其实就没啥好说的了,那个jobs是编译所用的线程数,output应该是生成文件的路径,默认是空的 最终是生成u-boot.img u-boot-dtb.img u-boot.bin u-boot-dtb.bin等文件 pack_uboot_image 打包uboot前,先检查u-boot.bin的大小,超过10M,就报错了 # Check file size UBOOT_KB=`ls -l u-boot.bin | awk '{print $5}'` if [ "$PLATFORM_UBOOT_IMG_SIZE" = "" ]; then UBOOT_MAX_KB=1046528 else UBOOT_MAX_KB=`echo $PLATFORM_UBOOT_IMG_SIZE | awk '{print strtonum($2)}'` UBOOT_MAX_KB=$(((UBOOT_MAX_KB-HEAD_KB)*1024)) fi if [ $UBOOT_KB -gt $UBOOT_MAX_KB ]; then echo echo "ERROR: pack uboot failed! u-boot.bin actual: $UBOOT_KB bytes, max limit: $UBOOT_MAX_KB bytes" exit 1 fi 最终在当前目录下,生成了uboot.img,并删除了其它的img结尾的中间文件 # Pack image UBOOT_LOAD_ADDR=`sed -n "/CONFIG_SYS_TEXT_BASE=/s/CONFIG_SYS_TEXT_BASE=//p" ${OUTDIR}/include/autoconf.mk|tr -d 'r'` if [ ! $UBOOT_LOAD_ADDR ]; then UBOOT_LOAD_ADDR=`sed -n "/CONFIG_SYS_TEXT_BASE=/s/CONFIG_SYS_TEXT_BASE=//p" ${OUTDIR}/.config|tr -d 'r'` fi ${RKTOOLS}/loaderimage --pack --uboot ${OUTDIR}/u-boot.bin uboot.img ${UBOOT_LOAD_ADDR} ${PLATFORM_UBOOT_IMG_SIZE} # Delete u-boot.img and u-boot-dtb.img, which makes users not be confused with final uboot.img if [ -f ${OUTDIR}/u-boot.img ]; then rm ${OUTDIR}/u-boot.img fi if [ -f ${OUTDIR}/u-boot-dtb.img ]; then rm ${OUTDIR}/u-boot-dtb.img fi echo "pack uboot okay! Input: ${OUTDIR}/u-boot.bin" pack_loader_image 这一步最终生成这个文件rk1808_loader_v1.04.105.bin,并拷贝到当前目录下 pack_trust_image 这一步生成trust.img,这是arm搞的一个跟安全有关的东西Trustzone,大致是为了保护内存中的数据不被别人窃取之类的 finish 最后一步就是打印一点信息,就ok了 总结 从结果来看,执行make.sh一共得到了以下几个东西 uboot.img rk1808_loader_v1.04.105.bin trust.img 我们烧录的时候,是在顶层目录的rockdev去取镜像文件,在linux下,可以很清晰得看到链接的关系,所生成的这三个文件,都会被链接到 boot.img -> ../kernel/boot.img MiniLoaderAll.bin -> ../u-boot/rk1808_loader_v1.04.105.bin misc.img -> ../device/rockchip/rockimg/wipe_all-misc.img oem.img parameter.txt -> ../device/rockchip/rk1808/parameter-buildroot.txt recovery.img -> ../buildroot/output/rockchip_rk1808_recovery/images/recovery.img rootfs.ext4 -> ../buildroot/output/rockchip_rk1808/images/rootfs.ext2 rootfs.img -> ../buildroot/output/rockchip_rk1808/images/rootfs.ext2 trust.img -> ../u-boot/trust.img uboot.img -> ../u-boot/uboot.img update.img userdata.img 除此之外,如果希望自己修改一些uboot的内容,可以通过类似内核的make menuconfig取修改.config文件,不过注意修改完了,一定要记得将该文件写回原来的位置,就是那个默认的deconfig所在的位置,否则每次编译,当前目录下的.config都会被configs目录下的xxx_deconfig覆盖掉。 |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
1842 浏览 1 评论
synopsys 的design ware:DW_fpv_div,浮点数除法器,默认32位下,想提升覆盖率(TMAX),如果用功能case去提升覆盖率呢?
2298 浏览 1 评论
RK3588 GStreamer调试四路鱼眼摄像头四宫格显示报错
5115 浏览 1 评论
【飞凌嵌入式OK3576-C开发板体验】RKNN神经网络-YOLO图像识别
254 浏览 0 评论
【飞凌嵌入式OK3576-C开发板体验】SSH远程登录网络配置及CAN通讯
1336 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-19 17:23 , Processed in 0.530584 second(s), Total 75, Slave 58 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号