分析X210开发板的BSP(即板级支持包)

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。

参考博客

buildroot详解和分析_Alex-wu的博客-CSDN博客_buildroot

前言

板级支持包(Board Support Package),是由引导程序(bootloader)、内核( kernel)、根文件系统(rootfs)、工具链(toolchain)等软件组成的资源包,一般由芯片厂家或板卡厂家提供。

ARM+linux形式的BSP,其内容和结构都是相似的,因此以X210开发板的BSP为例进行说明。

X210开发板的BSP见下载地址,它包括以下文件或文件夹。

文件或文件夹       描述
tslib_x210_qtopia.tgz用来支持QT的触摸屏操作的应用层库
xboot和uboot文件夹X210支持的2个bootloader源代码
kernel文件夹内核源代码
buildroot文件夹用来构建根文件系统的文件夹
tools文件夹一些有用工具
mk文件用来管理和编译整个bsp

一、分析mk文件

1、mk文件内容

#!/bin/sh
#
# Description	: Build Qt Script.
# Authors		: jianjun jiang - jerryjianjun@gmail.com
# Version		: 0.01
# Notes			: None
#

CPU_NUM=$(cat /proc/cpuinfo |grep processor|wc -l)
CPU_NUM=$((CPU_NUM+1))

SOURCE_DIR=$(cd `dirname $0` ; pwd)

RELEASE_DIR=${SOURCE_DIR}/release/
BOOTLOADER_XBOOT_CONFIG=arm32-x210ii
QT_KERNEL_CONFIG=x210ii_qt_defconfig
INITRD_KERNEL_CONFIG=x210ii_initrd_defconfig
BUILDROOT_CONFIG=x210_defconfig

setup_environment()
{
	cd ${SOURCE_DIR};
	mkdir -p ${RELEASE_DIR} || return 1;
}

build_bootloader_xboot()
{
	if [ ! -f ${RELEASE_DIR}/zImage-initrd ]; then
		echo "not found kernel zImage-initrd, please build kernel first" >&2
		return 1
	fi

	if [ ! -f ${RELEASE_DIR}/zImage-qt ]; then
		echo "not found kernel zImage-qt, please build kernel first" >&2
		return 1
	fi

	# copy zImage-initrd and zImage-qt to xboot's romdisk directory
	cp -v ${RELEASE_DIR}/zImage-initrd ${SOURCE_DIR}/xboot/src/arch/arm32/mach-x210ii/romdisk/boot || return 1;
	cp -v ${RELEASE_DIR}/zImage-qt ${SOURCE_DIR}/xboot/src/arch/arm32/mach-x210ii/romdisk/boot || return 1;

	# compiler xboot
	cd ${SOURCE_DIR}/xboot || return 1
	make TARGET=${BOOTLOADER_XBOOT_CONFIG} CROSS=/usr/local/arm/arm-2012.09/bin/arm-none-eabi- clean || return 1;
	make TARGET=${BOOTLOADER_XBOOT_CONFIG} CROSS=/usr/local/arm/arm-2012.09/bin/arm-none-eabi- || return 1;

	# rm zImage-initrd and zImage-qt
	rm -fr ${SOURCE_DIR}/xboot/src/arch/arm32/mach-x210ii/romdisk/boot/zImage-initrd
	rm -fr ${SOURCE_DIR}/xboot/src/arch/arm32/mach-x210ii/romdisk/boot/zImage-qt

	# copy xboot.bin to release directory
	cp -v ${SOURCE_DIR}/xboot/output/xboot.bin ${RELEASE_DIR}

	echo "" >&2
	echo "^_^ xboot path: ${RELEASE_DIR}/xboot.bin" >&2
	return 0
}

build_bootloader_uboot_nand()
{
	cd ${SOURCE_DIR}/uboot || return 1

	make distclean
	make x210_nand_config
	make -j${CPU_NUM}
	mv u-boot.bin uboot_nand.bin
	if [ -f uboot_nand.bin ]; then
		cp uboot_nand.bin ${RELEASE_DIR}/uboot.bin
		cd ${RELEASE_DIR}
		${SOURCE_DIR}/tools/mkheader uboot.bin
		echo "^_^ uboot_nand.bin is finished successful!"
		exit
	else
		echo "make error,cann't compile u-boot.bin!"
		exit
	fi
}

build_bootloader_uboot_inand()
{
	cd ${SOURCE_DIR}/uboot || return 1

	make distclean
	make x210_sd_config
	make -j${CPU_NUM}
	mv u-boot.bin uboot_inand.bin
	if [ -f uboot_inand.bin ]; then 
		cp uboot_inand.bin ${RELEASE_DIR}/uboot.bin
		cd ${RELEASE_DIR}
		${SOURCE_DIR}/tools/mkheader uboot.bin
		echo "^_^ uboot_inand.bin is finished successful!"
		exit
	else
		echo "make error,cann't compile u-boot.bin!"
		exit
	fi
}


build_kernel()
{
	cd ${SOURCE_DIR}/kernel || return 1

	# make ${INITRD_KERNEL_CONFIG} || return 1
	# make -j${threads} || return 1
	# dd if=${SOURCE_DIR}/kernel/arch/arm/boot/zImage of=${RELEASE_DIR}/zImage-initrd bs=2048 count=8192 conv=sync;

	make ${QT_KERNEL_CONFIG} || return 1
	make -j${threads} || return 1
	dd if=${SOURCE_DIR}/kernel/arch/arm/boot/zImage of=${RELEASE_DIR}/zImage-qt bs=2048 count=8192 conv=sync;

	echo "" >&2
	# echo "^_^ initrd kernel path: ${RELEASE_DIR}/zImage-initrd" >&2
	echo "^_^ qt kernel path: ${RELEASE_DIR}/zImage-qt" >&2

	return 0
}

build_rootfs()
{
	cd ${SOURCE_DIR}/buildroot || return 1

	make ${BUILDROOT_CONFIG} || return 1
	make || return 1

	# copy rootfs.tar to release directory
	cp -v ${SOURCE_DIR}/buildroot/output/images/rootfs.tar ${RELEASE_DIR} || { return 1; }
}

# must root user
gen_qt_rootfs_ext3()
{
	if [ ! -f ${RELEASE_DIR}/rootfs.tar ]; then
		echo "not found rootfs.tar, please build rootfs" >&2
		return 1
	fi

	echo "making ext3 qt4.8 rootfs now,wait a moment..."
	cd ${RELEASE_DIR}
	rm -rf rootfs
	mkdir -p rootfs
	tar xf rootfs.tar -C rootfs
	
	rm rootfs_qt4.ext3
	rm -rf rootfs_img
	mkdir -p rootfs_img

	dd if=/dev/zero of=rootfs_qt4.ext3 bs=1024 count=262144
	mkfs.ext3 rootfs_qt4.ext3
	mount -o loop rootfs_qt4.ext3 ./rootfs_img

	cp ./rootfs/* ./rootfs_img -ar
	umount ./rootfs_img
	
	echo "^_^ make rootfs_qt4.ext3 successful!"
}

# must root user
gen_qt_rootfs_jffs2()
{
	if [ ! -f ${RELEASE_DIR}/rootfs.tar ]; then
		echo "not found rootfs.tar, please build rootfs" >&2
		return 1
	fi

	echo "making jffs2 qt4.8 rootfs now,wait a moment..."
	cd ${RELEASE_DIR}
	rm -rf rootfs
	mkdir -p rootfs
	tar xf rootfs.tar -C rootfs

	[ -e "rootfs" ] ||{ echo "error!can't find rootfs dir"; exit;}

	mkfs.jffs2 -r rootfs -o rootfs_qt4.jffs2 -e 0x20000 -s 0x800 --pad=0x5000000 -n
	echo "^_^ make rootfs_qt4.jffs2 successful!"
}

gen_qt_update_bin()
{
	# check image files
	if [ ! -f ${RELEASE_DIR}/xboot.bin ]; then
		echo "not found bootloader xboot.bin, please build bootloader" >&2
		return 1
	fi

	if [ ! -f ${RELEASE_DIR}/zImage-initrd ]; then
		echo "not found kernel zImage-initrd, please build kernel first" >&2
		return 1
	fi

	if [ ! -f ${RELEASE_DIR}/zImage-qt ]; then
		echo "not found kernel zImage-qt, please build kernel first" >&2
		return 1
	fi

	if [ ! -f ${RELEASE_DIR}/rootfs.tar ]; then
		echo "not found rootfs.tar, please build rootfs" >&2
		return 1
	fi

	rm -fr ${RELEASE_DIR}/tmp || return 1;
	rm -fr ${RELEASE_DIR}/qt-update.bin || return 1;
	mkdir -p ${RELEASE_DIR}/tmp || return 1;

	# copy image files
	cp ${RELEASE_DIR}/xboot.bin ${RELEASE_DIR}/tmp/;
	cp ${RELEASE_DIR}/zImage-initrd ${RELEASE_DIR}/tmp/;
	cp ${RELEASE_DIR}/zImage-qt ${RELEASE_DIR}/tmp/;
	cp ${RELEASE_DIR}/rootfs.tar ${RELEASE_DIR}/tmp/;

	# create md5sum.txt
	cd ${RELEASE_DIR}/tmp/;
	find . -type f -print | while read line; do
		if [ $line != 0 ]; then
			md5sum ${line} >> md5sum.txt
		fi
	done

	# mkisofs
	mkisofs -l -r -o ${RELEASE_DIR}/qt-update.bin ${RELEASE_DIR}/tmp/ || return 1;

	cd ${SOURCE_DIR} || return 1 
	rm -fr ${RELEASE_DIR}/tmp || return 1;
	return 0;
}

threads=4;
xboot=no;
uboot_inand=no;
uboot_nand=no;
kernel=no;
rootfs=no;
rootfs_ext3=no;
rootfs_jffs2=no;
update=no;

if [ -z $1 ]; then
	xboot=yes
	uboot_inand=no;
	uboot_nand=no;
	kernel=yes
	rootfs=yes
	rootfs_ext3=no;
	rootfs_jffs2=no;
	update=yes
fi

while [ "$1" ]; do
    case "$1" in
	-j=*)
		x=$1
		threads=${x#-j=}
		;;
	-x|--xboot)
		xboot=yes
	    ;;
	-ui|--uboot_inand)
		uboot_inand=yes
	    ;;
	-un|--uboot_nand)
		uboot_nand=yes
	    ;;
	-k|--kernel)
	    kernel=yes
	    ;;
	-r|--rootfs)
		rootfs=yes
	    ;;
	-re|--rootfs_ext3)
		rootfs_ext3=yes
	    ;;
	-rj|--rootfs_jffs2)
		rootfs_jffs2=yes
	    ;;
	-U|--update)
		update=yes
	    ;;
	-a|--all)
		xboot=yes
		kernel=yes
		rootfs=yes
		update=yes
	    ;;
	-h|--help)
	    cat >&2 <<EOF
Usage: mk [OPTION]
Build script for compile the source of telechips project.

  -j=n                 using n threads when building source project (example: -j=16)
  -x, --xboot          build bootloader xboot from source file
  -ui,--uboot_inand    build uboot for emmc
  -un,--uboot_nand     build uboot for nand flash
  -k, --kernel         build kernel from source file and using default config file
  -r, --rootfs         build root file system
  -re,--rootfs_ext3    build rootfs for emmc,used with uboot
  -rj,--rootfs_jffs2   build rootfs for nand,used with uboot
  -U, --update         gen update package update.bin,used with xboot
  -a, --all            build all, include anything
  -h, --help           display this help and exit
EOF
	    exit 0
	    ;;
	*)
	    echo "build.sh: Unrecognised option $1" >&2
	    exit 1
	    ;;
    esac
    shift
done

setup_environment || exit 1

if [ "${kernel}" = yes ]; then
	build_kernel || exit 1
fi

if [ "${xboot}" = yes ]; then
	build_bootloader_xboot || exit 1
fi

if [ "${uboot_inand}" = yes ]; then
	build_bootloader_uboot_inand || exit 1
fi

if [ "${uboot_nand}" = yes ]; then
	build_bootloader_uboot_nand || exit 1
fi

if [ "${rootfs}" = yes ]; then
	build_rootfs || exit 1
fi

if [ "${rootfs_ext3}" = yes ]; then
	gen_qt_rootfs_ext3 || exit 1
fi

if [ "${rootfs_jffs2}" = yes ]; then
	gen_qt_rootfs_jffs2 || exit 1
fi

if [ "${update}" = yes ]; then
	gen_qt_update_bin || exit 1
fi

exit 0

2、mk文件作用

利用mk脚本可以选择性地编译,即可以通过参数来指定想要编译的内容。

命令描述
./mk -a编译所有的bsp源代码
./mk -x只编译xboot
./mk -ui只编译uboot针对inand版本开发板的源代码
./mk -r只编译buildroot,得到文件夹形式的rootfs
./mk -re编译buildroot并且制作得到ext3格式的rootfs镜像
./mk -rj编译buildroot并且制作得到jffs2格式的rootfs镜像
./mk -h查看mk的帮助信息

这是如何实现的? 

  • mk脚本内部用一个函数来完成某块内容的编译(见mk脚本代码),比如编译内核用build_kernel函数,编译inand版本的uboot用build_bootloader_uboot_inand。
  • 然后用一些变量来控制这个函数是否被编译,比如变量uboot_inand=yes则表示要编译inand版本的uboot,=no则表示不编译。
  • 编译时通过“./mk -xxx”来传参时,这些传参会影响这些变量的值(yes或no)。
  • 如果直接./mk并不传参,则$1为空,这时候按照一套默认的配置来编译。

二、分析buildroot文件夹

1、buildroot的作用

buildroot是一个集成包,主要集成了制作交叉编译工具链、构建rootfs等功能。

  • 之前的交叉编译工具链arm-linux-gcc,我们都是从soc官方那里得到的,但官方的工具链从何而来?实际上交叉编译工具链都是由gcc配置编译生成的。
  • 构建根文件系统中介绍了从零开始构建根文件系统,但是步骤麻烦。使用buildroot可以很简便的得到一个做好的文件夹形式的根文件系统。buildroot移植了kernel的make xxx_defconfig、make menuconfig的2步配置法。在buildroot的配置界面下完成配置,然后直接make,最终可以得到文件夹形式的rootfs。

2、buildroot的目录

├── arch:   存放CPU架构相关的配置脚本,如arm/mips/x86,这些CPU相关的配置,在制作工具链时,编译uboot和kernel时很关键.
├── board   存放了一些默认开发板的配置补丁之类的
├── boot
├── CHANGES
├── Config.in
├── Config.in.legacy
├── configs:  放置开发板的一些配置参数. 
├── COPYING
├── DEVELOPERS
├── dl:       存放下载的源代码及应用软件的压缩包. 
├── docs:     存放相关的参考文档. 
├── fs:       放各种文件系统的源代码. 
├── linux:    存放着Linux kernel的自动构建脚本. 
├── Makefile
├── Makefile.legacy
├── output: 是编译出来的输出文件夹. 
│   ├── build: 存放解压后的各种软件包编译完成后的现场.
│   ├── host: 存放着制作好的编译工具链,如gcc、arm-linux-gcc等工具.
│   ├── images: 存放着编译好的uboot.bin, zImage, rootfs等镜像文件,可烧写到板子里, 让linux系统跑起来.
│   ├── staging
│   └── target: 用来制作rootfs文件系统,里面放着Linux系统基本的目录结构,以及编译好的应用库和bin可执行文件. (buildroot根据用户配置把.ko .so .bin文件安装到对应的目录下去,根据用户的配置安装指定位置)
├── package:下面放着应用软件的配置文件,每个应用软件的配置文件有Config.in和soft_name.mk,其中soft_name.mk(这种其实就Makefile脚本的自动构建脚本)文件可以去下载应用软件的包。
├── README
├── support
├── system
└── toolchain

 3、配置与编译过程

(1)先执行“make x210_defconfig”。

root@ubuntu:/home/xjh/iot/embedded_basic/bsp/buildroot/configs# ls
x210_defconfig       #由这里可以知道是make x210_defconfig

root@ubuntu:/home/xjh/iot/embedded_basic/bsp/buildroot# ls
arch   CHANGES           configs  docs   Makefile         package    system
board  Config.in         COPYING  fs     Makefile.legacy  S99qttest  toolchain
boot   Config.in.legacy  dl       linux  output           support
root@ubuntu:/home/xjh/iot/embedded_basic/bsp/buildroot# make x210_defconfig
//省略部分内容
#
# configuration written to /home/xjh/iot/embedded_basic/bsp/buildroot/.config
#
root@ubuntu:/home/xjh/iot/embedded_basic/bsp/buildroot# 

(2)接着执行“make menuconfig”。因为九鼎移植的时候已经配置好了,这个步骤可以省略。

(3)最后执行“make”。

直接执行make会遇到很多错误,这些错误原因都是因为ubuntu中缺乏一些必要软件包造成的。我们需要从网上下载这些软件包,因此整个编译过程需要在联网状态下进行。

You must install 'bison' on your build machine
#sudo apt-get install bison

You must install 'flex' on your build machine
#sudo apt-get install flex

You must install 'makeinfo' on your build machine
makeinfo is usually part of the texinfo package in your distribution
#sudo apt-get install makeinfo
#sudo apt-get install texinfo

You must install 'git' on your build machine
#sudo apt-get install git

You must install 'hg' on your build machine
#sudo apt-get install hg
E: 无法定位软件包 hg
#sudo apt-get install hgsubversion 这个是由在命令行输入“apt-cache search hg”查询得知的

You need the 'mkpasswd' utility to set the root password
(in Debian/ubuntu, 'mkpasswd' provided by the whois package)
#sudo apt-get install whois

(4)编译生成的文件夹格式的rootfs,位于buildroot/output/images/rootfs.tar。

root@ubuntu:/home/xjh/iot/embedded_basic/BSP/buildroot/output# ls
build  host  images  staging  stamps  target  toolchain
root@ubuntu:/home/xjh/iot/embedded_basic/BSP/buildroot/output# cd images/
root@ubuntu:/home/xjh/iot/embedded_basic/BSP/buildroot/output/images# ls
rootfs.tar
root@ubuntu:/home/xjh/iot/embedded_basic/BSP/buildroot/output/images#

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天糊土

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值