版权声明:转载请注明出处: http://blog.csdn.net/sy373466062 作者: TonyHo https://blog.csdn.net/sy373466062/article/details/50381067
Yocto tips (1): Yocto 编译后文件放在了哪里 输出文件位置
编译完成后内核以及rootfs,内核,uboot以及dtb会放在相对于build目录的tmp/deploy/images/MACHINE/下面,这里MACHINE需要可能为空(对于老版本的poky/yocto),也可能是你的板子名字,例如sabresd。
对于toolchain,那么放在mp/deploy/sdk/MACHINE/下。
图片示例:
编译完成后内核以及rootfs以及dtb会放在相对于build目录的tmp/deploy/images/imx6qsabresd/下面
各个文件都有一个软连接来指向最新编译产生的文件,因此如果需要看到最新的文件,可以直接使用软链接即可:
Yocto tips (2): Yocto Linux内核编译目录在哪?
内核放在了哪里? 这个是放在了如下位置,我们可以用下面命令来确定:
bitbake -e linux-imx | grep ^S=
图示:
Yocto tips (3): Yocto 如何重新编译Linux内核与dtb,并放到deploy目录?
编译内核,并生成uImage+dtb,编译的命令如下:
bitbake linux-imx -C compile
注意这里的-C的C是大写,和小写的c是有区别的。
注意这里的linux-imx是针对imx的内核,你的内核名字可能不一样,关于如何确定一个包的名字,请看:
Yocto tips (4): Yocto 如何确定(找到)一个包的名字
Yocto tips (4): Yocto 如何确定(找到)一个包的名字
使用下面命令来却确定:
bitbake -s | grep XXX
其中XXX为包的关键字,例如linux或者uboot,这样就可以看到所有带有关键字的包了,如下图,就是为了找到内核:
Yocto tips (5): Yocto如何更改source code的下载与git clone地址
现象
Yocto中在fetch一些软件包的时候经常出现一天也下载不下来,这种情况极大浪费了我们的时间。
例如,下面有三个Package下载了一天也没有完成:
解决方法
确定下载的地址,手动下载
先确定软件包的下载地址,例如对于opencv与opencv-samples软件包:
可以看到他们的git地址都是一样的,因此,我们可以手动来git clone:
可以看到我们只使用了几十分钟而已。clone下来以后,我们就可以让软件包使用我们本地的这个repo了,而不需要忙忙的去远程repo去clone。
让package克隆时使用本地的git
找到软件包对应的bb文件
我们可以使用find命令来查找
更改bb文件
注意里面添加了一个protocol指定。
再一次获取
bitbake opencv -c fetch
结果如下:
提示找不到branch,于是我们到我们本地的repo中将此branch切出来,也可以将其制作成bare repo:
然后再一次进行fetch就可以了:
对于其他软件也是类似的。
Yocto tips (6): Yocto中如何共享已经下载的文件
Yocto的下载耗时可能会超过编译的时间,因此大家都希望下载一次后大家都用共用下载好了的文件,而不要再去下载。
Yocto中所有下载了的以及git clone的文件都放在环境变量DL_DIR指示的目录下,这个目录默认在machine build directory下面。
因此要共享下载文件只需要指定此变量到下载好了的目录即可,可以在local.conf中指定即可:
Yocto tips (7): Yocto Bitbake的clean与cleanall以及cleansstate的区别
Yocto中对于不同的Package,有不同的task,即可以执行不同的操作,有一些是所有包共通的,例如clean,build等。
我们可以使用下面命令来查看一个包都有哪些可执行的task:
bitbake Package -c listtasks
图示:
我们可以从里面看到clean与cleanall以及cleansstate的区别。
Yocto tips (8): Yocto 如何加快软件包的下载 如何只下载所有需要的软件包而不编译
加快下载
Yocto中下载是最耗时的,因此我们可以尽可能的开启最多的并行数量。
对此,我们可以在local.conf中将并行数目调大,例如我的CPU 是E3-1230 v2, 8核,所以我可以开启16个线程来下载,因为我们的网速慢,所以其实这些下载操作并非CPU密集型任务,很多包也很小,所以同时IO也不密集,因此可以适当调大:
效果如下:
下载所有需要的软件包而不编译
有的时候我们可能需要先将所有需要的软件包下载下来,等离线回家或者其他时机再编译,对此我们可以使用如下命令来完成:
bitbake fsl-image-qt5 -c fetchall
对于不同的目标,需要替换fsl-image-qt5为其他的,例如可能是core-image-minimal,我们可以看到fetchall的意义:
do_fetchall Fetches all remote sources required to build a target
Yocto tips (9): Yocto 软件包的下载地址在哪
一般而言,可以使用
Yocto tips (5): Yocto如何更改source code的下载与git clone地址中提到的方法,但是有的时候一些地址是在bb文件include的文件中,而inc文件又可能层层包含,查找比较繁琐,因此直接到env中查找比较快。
例如要找到imx kenrel的fetch地址可以使用下面命令:
bitbake -e linux-imx | grep ^SRC_URI=
效果如下:
Yocto tips (10): Yocto hellworld 添加一个软件包
Yocto中一个软件包是放在bb文件中的,然后很多的bb文件集成一个recipe(配方),然后许多的recipe又组成一个meta layer,因此,要添加一个包其实就是在recipe下面添加一个bb(bitbake配置文件)。下面使用helloworld作为一个例子。
clone bb文件
首先是进入到一个recipe目录下,例如下面就是到了recipes-graphics:
-
$ pwd
-
/media/work/iMX6/Yocto/sources/meta-fsl-arm/recipes-graphics
然后clone Package配置与source目录的repo:
git clone https://github.com/tonyho/helloYocto.git
查看软件包是否已经在Yocto中
-
09:25 hexiongjun:imx6qsabresd_build $ bitbake -s | grep hello
-
hello :3-r0
确认在了以后,就可以执行编译等task了,如果有需要也可以deploy到rootfs中,这些操作可以参考我以前的一些博客。
一个软件包的结构
使用tree可以看到,其有一个bb文件,然后其中还有一个目录放着Makefile与source code:
其中的bb文件内容如下:
-
DESCRIPTION = "Hello World and Zlib test"
-
DEPENDS = "zlib"
-
SECTION = "libs"
-
LICENSE = "MIT"
-
PV = "3"
-
PR = "r0"
-
-
-
SRC_URI = "
-
file://helloYocto.c
-
file://zlibtest.c
-
file://makefile
-
"
-
-
-
LIC_FILES_CHKSUM = "file://helloYocto.c;md5=2dac018fa193620dc085aa1402e0b346"
-
S = "${WORKDIR}"
-
do_compile () {
-
make
-
}
-
-
-
do_install () {
-
install -d ${D}${bindir}/
-
install -m 0755 ${S}/helloYocto ${D}${bindir}/
-
install -m 0755 ${S}/zlibtest ${D}${bindir}/
-
}
-
-
-
FILES_${PN} = "${bindir}/helloYocto
-
${bindir}/zlibtest "
可以看到,bb文件中指定了下面几个变量的值:
- SRC_URI
- LIC_FILES_CHKSUM:这个是checksum,如果是基于版本管理的source,那么不需要,例如git与svn
- FILES_$(PN):PN是Package number,指代软件版本使用的PV与PR结合表示,即前面bitbake -s中看到的3-r0
还有两个方法,这2个方法重载了bitbake中默认方法:
- do_compile
- do_install
这两个方法,对应了Package中的compile与install task。
Yocto tips (11): Yocto如何往最终的rootfs中添加软件
在Yocto中如果我们期望在rootfs中添加一些软件,例如可能是bash,可能是lsusb等,那么,我们可以有两种方法:
- 手动添加,一个个文件的拷贝
- 在bb文件中添加安装项目,让Yocto自动帮助我们添加
第一种方法需要手动将软件包的所有文件以及依赖都一个个添加进去,耗时耗力且易错,因此使用第二中方法比较合适。
Yocto中Rootfs中添加软件包的步骤
找到打包rootfs的最终bb
如果我们使用的是下面命令:
bitbake fsl-image-qt5
那么,我们可以按照如下来搜索fsl-image-qt5这个软件包(任务),使用的是哪个bb文件:
添加需要安装到rootfs的软件包
然后打开,并添加需要添加的包即可,例如下面添加的是linux-firmware:
保存,然后我们再一次使用bitbake构建系统,然后就可以看到rootfs中有对应的文件了:
Yocto tips (12): 使用Yocto帮助我们寻找难找的固件与固件放置路径
有很多的硬件需要firmware才能工作,而这些firmware需要不仅仅需要找到,还需要放置到正确的位置,一般这个位置是/lib/firmware下面,但是很多也不尽然。
手动去查找这些固件,容易出现遗漏或者混淆,也有可能是年久不匹配了的固件,例如在我前面的博客中:
Yocto i.MX6 (TQIMX6) (02) : USB Wifi (TP-Link WN821N等设备)AR9170的Linux内核支持与固件使用,就出现了自己按照wiki与help去查找firmware,结果却花了大量时间也没有解决,而使用yocto中的linux-firmware软件包,非法快速的解决了这个问题。
对于firmware放置的path也是类似,例如有些驱动放置的path为非标准的path,例如下面这些都是放在各自的目录中的:
因此,直接将linux-firmware添加到打包rootfs,或者直接查看linux-firmware中的image文件夹就可以知道path了,例如前面的ar9170:
Yocto tips (13): Yocto 查看软件包的依赖关系
查看一个文件包的依赖,我们可以使用图形化来查看,下面是一些官方说明:
例如我们要查看weston的依赖:
bitbake --ui=depexp -g weston或者 bitbake -g -u depexp weston
这个会列出不同的依赖,例如中间的是编译时候需要依赖的东西,结果如下:
Yocto tips (14): Yocto中编译链的配置变更(tuning)
这个在我们自己编译toolchain以及针对不同的硬件自己调整toolchain的时候用得多。变更方法也很简单,只需要在poky对应的配置查找一个合适的即可。
例如针对armv7而言,我们可以到下面文件查找一个合适的来使用:
将自己选择好的写入到local.conf中:
Yocto tips (15): Yocto中的包管理器
使用包管理器
在local.conf中使能即可:
然后编译后就会有rpm包了:
配置文件服务器
可以使用ngix和apache,但是我们也可以只用使用python:
python -m SimpleHTTPServer
打开浏览器可以看到:
在机器上面查看包的status
smart status
在机器上面配置channel
对于rpm使用的smart工具,添加channel:
-
smart channel --add all type=rpm-md baseurl=http://192.168.2.100:8000/all
-
smart channel --add cortexa9hf_vfp_neon type=rpm-md baseurl=http://192.168.2.100:8000/cortexa9hf_vfp_neon
-
smart channel --add cortexa9hf_vfp_neon_mx6qdl type=rpm-md baseurl=http://192.168.2.100:8000/cortexa9hf_vfp_neon_mx6qdl
-
smart channel --add imx6qsabresd type=rpm-md baseurl=http://192.168.2.100:8000/imx6qsabresd
添加参数之后,就可以update了:
smart update
正确的是下面命令的情形:
如果配置参数不对,那么就会出错,如果出错,那么检查IP与格式是否正确,例如下面的http少了两个//:
如果弄错了,那么可以先移除掉:
smart channel --remove all cortexa9hf_vfp_neon_mx6qdl imx6qsabresd cortexa9hf_vfp_neon
然后重新添加。
再看包的数量,可以看到变多了:
使用包管理器安装软件
使用smart install Package即可安装:
如果在PC中使用bitbake新编译了程序,那么需要使用下面命令重建index,否则客服端找不到新的软件包:
bitbake package-index
参考:
http://www.jumpnowtek.com/yocto/Using-your-build-workstation-as-a-remote-package-repository.html
package-manager-white-paper.pdf
Yocto tips (16): Yocto 制作SDK分发Toolchain 脱离Yocto环境开发
Yocto中SDK有两种:
- 只有Toolchain,或者Toolchain+某类GUI特性
- 有针对某个Distribution的SDK,即含有Toolchian也含有这个Distrbutition特殊的文件
下面分别说明。
第一类
这类的软件包有如下这些:
其实就是两类:
- meta-toolchain
- meta-toolchain-qt/qte/qt5
后者包含了qt相关的东西,qte是面向embed的,如果需要做qt相关的application开发,那么包含qt的是合适的选择,否则仅仅开发普通application,那么使用meta-toolchian即可。
第二类
这类SDK才是推荐使用的,这个在distribution的task中有一个特别的任务,专门用来制作这个SDK,叫做populate_sdk,例如对应要制作一个fsl-image-qt5 目标的Distribution(也叫做image),那么可以这样子:
bitbake fsl-image-qt5 -c populate_sdk
这两类制作完成后,可以在deploy中看到了:
其中xml文件是SDK包含了的文件列表。
SDK的安装
因为SDK文件是sh脚本+压缩的文件内容组成的,所以直接运行即可,例如:
在prompt提示中,输入安装的路径。
Yocto tips (17): Yocto License问题:restricted license not whitelisted in LICENSE_FLAGS_WHITELIST
Yocto中可以配置一个Distrbution的License,然后所有的软件包,都需要符合这个license才可以被shipped到image中,如果我们需要使用违反此license的软件包,那么就需要额外配置。
例如,在bitbake编译vlc的时候出现下面的错误log:
-
$ bitbake vlc
-
Parsing recipes: 100% |###################################################################################################################################| Time: 00:00:26
-
Parsing of 2029 .bb files complete (0 cached, 2029 parsed). 2524 targets, 210 skipped, 1 masked, 0 errors.
-
NOTE: Resolving any missing task queue dependencies
-
ERROR: Nothing PROVIDES 'ffmpeg' (but /media/work/iMX6/Yocto/sources/meta-openembedded/meta-multimedia/recipes-multimedia/vlc/vlc_2.1.4.bb DEPENDS on or otherwise requires it)
-
ERROR: libav PROVIDES ffmpeg but was skipped: because it has a restricted license not whitelisted in LICENSE_FLAGS_WHITELIST
-
ERROR: libav PROVIDES ffmpeg but was skipped: because it has a restricted license not whitelisted in LICENSE_FLAGS_WHITELIST
-
ERROR: Required build target 'vlc' has no buildable providers.
-
Missing or unbuildable dependency chain was: ['vlc', 'ffmpeg']
那么就是因为vlc依赖libav,但是libav,的license不符合Distribution的License而无法编译。在libav中的bb文件配置中,可以看到其license flag为commercial:
开启接受所有的commercial license软件包
因此如果我们需要添加一些commercial Lincense的软件包,就需要添加对commercial的支持,只需要在local.conf中添加一行即可:
LICENSE_FLAGS_WHITELIST="commercial"
只接受特定的commercial license软件包
但是如果我们只期望某些特殊的commercial软件包可以被编译放入到rootfs中,那么我们就需要逐个指定,例如指定libav等包可以被编译:
Yocto tips (18): Yocto SDK Toolchian中静态库的添加
Toolchian中静态库的添加
没有静态库,是无法静态编译应用程序的,因此,为了方便,还需要在SDK中添加静态库,例如libc。
这个特性在只需要开启即可,在local.conf中添加一行:
SDKIMAGE_FEATURES_append = "staticdev-pkgs"
Toolchian中静态库的验证
然后重新build SDK,并安装SDK之后,我们可以验证其是否存在。
首先source env,导入各种bash变量:
source ../qt5_sdk/environment-setup-cortexa9hf-vfp-neon-poky-linux-gnueabi
然后确认libgcc.a是否exist:
$CC -print-file-name=libgcc.a
如果输出的存在,那么就有了,例如:
Yocto tips (19): Yocto SDK Toolchian的使用
在使用之前需要先source env,导入各种环境变量(注意将路径变更成你自己的):
source ../qt5_sdk/environment-setup-cortexa9hf-vfp-neon-poky-linux-gnueabi
然后我们可以查看一下bash的env了,下面是多出来的一些env,直接在bash中输入export即可看到:
-
declare -x AR="arm-poky-linux-gnueabi-ar"
-
declare -x ARCH="arm"
-
declare -x AS="arm-poky-linux-gnueabi-as "
-
declare -x CC="arm-poky-linux-gnueabi-gcc -march=armv7-a -mthumb-interwork -mfloat-abi=hard -mfpu=neon -mtune=cortex-a9 --sysroot=/media/work/iMX6/Yocto/qt5_sdk/sysroots
-
/cortexa9hf-vfp-neon-poky-linux-gnueabi"
-
declare -x CFLAGS=" -O2 -pipe -g -feliminate-unused-debug-types"
-
declare -x CONFIGURE_FLAGS="--target=arm-poky-linux-gnueabi --host=arm-poky-linux-gnueabi --build=x86_64-linux --with-libtool-sysroot=/media/work/iMX6/Yocto/qt5_sdk/sysro
-
ots/cortexa9hf-vfp-neon-poky-linux-gnueabi"
-
declare -x CONFIG_SITE="/media/work/iMX6/Yocto/qt5_sdk/site-config-cortexa9hf-vfp-neon-poky-linux-gnueabi"
-
declare -x CPP="arm-poky-linux-gnueabi-gcc -E -march=armv7-a -mthumb-interwork -mfloat-abi=hard -mfpu=neon -mtune=cortex-a9 --sysroot=/media/work/iMX6/Yocto/qt5_sdk/sysr
-
oots/cortexa9hf-vfp-neon-poky-linux-gnueabi"
-
declare -x CPPFLAGS=""
-
declare -x CROSS_COMPILE="arm-poky-linux-gnueabi-"
-
declare -x CXX="arm-poky-linux-gnueabi-g++ -march=armv7-a -mthumb-interwork -mfloat-abi=hard -mfpu=neon -mtune=cortex-a9 --sysroot=/media/work/iMX6/Yocto/qt5_sdk/sysroot
-
s/cortexa9hf-vfp-neon-poky-linux-gnueabi"
-
declare -x CXXFLAGS=" -O2 -pipe -g -feliminate-unused-debug-types"
-
declare -x M4="m4"
-
declare -x MANDATORY_PATH="/usr/share/gconf/kde-plasma.mandatory.path"
-
declare -x NM="arm-poky-linux-gnueabi-nm"
-
declare -x OBJCOPY="arm-poky-linux-gnueabi-objcopy"
-
declare -x OBJDUMP="arm-poky-linux-gnueabi-objdump"
-
declare -x OECORE_ACLOCAL_OPTS="-I /media/work/iMX6/Yocto/qt5_sdk/sysroots/x86_64-pokysdk-linux/usr/share/aclocal"
-
declare -x OECORE_DISTRO_VERSION="1.7"
-
declare -x OECORE_NATIVE_SYSROOT="/media/work/iMX6/Yocto/qt5_sdk/sysroots/x86_64-pokysdk-linux"
-
declare -x OECORE_SDK_VERSION="1.7"
-
declare -x OECORE_TARGET_SYSROOT="/media/work/iMX6/Yocto/qt5_sdk/sysroots/cortexa9hf-vfp-neon-poky-linux-gnueabi"
-
declare -x OLDPWD="/media/work/iMX6/Yocto/video2lcd_arm/test"
-
declare -x PATH="/media/work/iMX6/Yocto/qt5_sdk/sysroots/x86_64-pokysdk-linux/usr/bin:/media/work/iMX6/Yocto/qt5_sdk/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi:/home/hexiongjun/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/hexiongjun/010editor:/home/hexiongjun/010editor"
-
declare -x PKG_CONFIG_PATH="/media/work/iMX6/Yocto/qt5_sdk/sysroots/cortexa9hf-vfp-neon-poky-linux-gnueabi/usr/lib/pkgconfig"
-
declare -x PKG_CONFIG_SYSROOT_DIR="/media/work/iMX6/Yocto/qt5_sdk/sysroots/cortexa9hf-vfp-neon-poky-linux-gnueabi"
-
declare -x PWD="/media/work/iMX6/Yocto/video2lcd_arm"
-
declare -x PYTHONHOME="/media/work/iMX6/Yocto/qt5_sdk/sysroots/x86_64-pokysdk-linux/usr"
-
declare -x QMAKESPEC="/home/hexiongjun/github/BBB/SDK/ti-sdk-am335x-evm-05.07.00.00/linux-devkit/arm-arago-linux-gnueabi/usr/share/qtopia/mkspecs/linux-g++"
-
declare -x QT_IM_MODULE="fcitx"
-
declare -x QT_PLUGIN_PATH="/home/hexiongjun/.kde/lib/kde4/plugins/:/usr/lib/kde4/plugins/"
-
declare -x RANLIB="arm-poky-linux-gnueabi-ranlib"
-
declare -x SDKTARGETSYSROOT="/media/work/iMX6/Yocto/qt5_sdk/sysroots/cortexa9hf-vfp-neon-poky-linux-gnueabi"
-
declare -x SESSION_MANAGER="local/hexiongjun-pc:@/tmp/.ICE-unix/3595,unix/hexiongjun-pc:/tmp/.ICE-unix/3595"
注意点
其中我们重点需要关注的是与编译相关的变量:
- CC/LD等编译相关
- ARCH/CROSS_COMPILE等croos编译相关
可以看到CC已经被重定义为cross toolchain了,而ARCH和CROSS_COMPILE也悉心的帮我们配置成了对应的。
因此,其实如果我们需要交叉编译一个app,那么很多变量将不再需要自己手动设定了。
同时因为各种tuning的指定,我们必须注意和硬件的匹配。例如这里指定了为cortex-a9而优化。
如何使用
最好的方法就是使用变量来使用Toolchian,例如使用$CC而不是使用arm-poky-XXX-gcc,因为我们可以看到CC其实是对arm-xxx-gcc添加了一些配置:
-
CC="arm-poky-linux-gnueabi-gcc -march=armv7-a -mthumb-interwork -mfloat-abi=hard -mfpu=neon -mtune=cortex-a9 --sysroot=/media/work/iMX6/Yocto/qt5_sdk/sysroots
-
/cortexa9hf-vfp-neon-poky-linux-gnueabi"
其中最为核心的是sysroot这个选项,这个选项将告诉toolchian去哪里查找库与头文件,而如果不指定这个,那么就会出现问题,例如,我们直接使用arm-poky-gnueabi-gcc来编译:
-
$ make
-
make -C ./ -f /media/work/iMX6/Yocto/video2lcd_arm/Makefile.build
-
make[1]: Entering directory `/media/work/iMX6/Yocto/video2lcd_arm'
-
make -C convert -f /media/work/iMX6/Yocto/video2lcd_arm/Makefile.build
-
make[2]: Entering directory `/media/work/iMX6/Yocto/video2lcd_arm/convert'
-
arm-poky-linux-gnueabi-gcc -Wall -Werror -O2 -g -I /media/work/iMX6/Yocto/video2lcd_arm/include -I /media/work/iMX6/Yocto/imx6qsabresd_build/tmp/work/imx6qsabresd-poky-linux-gnueabi/fsl-image-qt5/1.0-r0/rootfs/usr/include/ -Wp,-MD,.convert_manager.o.d -c -o convert_manager.o convert_manager.c
-
In file included from /media/work/iMX6/Yocto/imx6qsabresd_build/tmp/work/imx6qsabresd-poky-linux-gnueabi/fsl-image-qt5/1.0-r0/rootfs/usr/include/features.h:389:0,
-
from /media/work/iMX6/Yocto/imx6qsabresd_build/tmp/work/imx6qsabresd-poky-linux-gnueabi/fsl-image-qt5/1.0-r0/rootfs/usr/include/stdio.h:27,
-
from /media/work/iMX6/Yocto/video2lcd_arm/include/config.h:5,
-
from convert_manager.c:2:
-
/media/work/iMX6/Yocto/imx6qsabresd_build/tmp/work/imx6qsabresd-poky-linux-gnueabi/fsl-image-qt5/1.0-r0/rootfs/usr/include/gnu/stubs.h:7:29: fatal error: gnu/stubs-soft.h: No such file or directory
-
# include
-
^
-
compilation terminated.
-
make[2]: *** [convert_manager.o] Error 1
-
make[2]: Leaving directory `/media/work/iMX6/Yocto/video2lcd_arm/convert'
-
make[1]: *** [convert] Error 2
-
make[1]: Leaving directory `/media/work/iMX6/Yocto/video2lcd_arm'
-
make: *** [all] Error 2
可以看到提示说找不到一些标准的头文件,其实这个是因为我们没有添加一些指定的选择来告诉其使用stubs-hard.h,所以默认的去查找stubs-soft.h。
例如我们编译一个helloworld,那么可以按照如下编译:
$CC hello.c -o hello
这样将省去了诸多选项的手动指定,也不会出问题。
Yocto tips (20): Yocto中qemu模拟器的使用,以zynq Cortex-A9为例
在以前的文章《
使用Buildroot与Qemu学习ARM linux IIC驱动》中,写到过使用qemu来模拟使用ARM Linux,那个时候借助的是buildroot,这次我们使用Yocto来做同样的事情。
优点
使用Qemu的好处在于,当我们在开发Userspace的程序时,可以在没有硬件的情况下完成测试。
同时不像以前一样我们需要自己去编译qemu,这次我们使用Yocto编译出来的native qemu来模拟。省去了我们手动编译可能出现的问题。
选择
这里的选择指的是,我们在local.conf中指定MACHINE变量的值。我将其分成两种:
1. 默认的qemuarm
以前我一直使用这个,但是这个模拟的是一个ARM9的处理器,各种外设功能不足,我们希望可以模拟一个更高ARM架构的SoC。
2. Xilinx的zynq-9:xilinx-zynq-a9
在Qemu的模拟中,据个人有限经验对不同的板子的模拟情况的了解,zynq在Qemu中有较好的支持。同时xilinx对此也有不少的文档,同时xilinx的一些板子的支持属于Qemu默认的测试与支持Machine,因此选择Xilinx的板子来模拟比较合适。
同时,我们关注的是ARM相关,因此使用Cortex-A9比较好,对此,我们选择xilinx-zynq-a9。
在我们的Host PC中如果安装了qemu-system-arm,那么我们可以看到其支持的板子里面是有这个板子的:
-
qemu-system-arm -M ?
-
Supported machines are:
-
versatileab ARM Versatile/AB (ARM926EJ-S)
-
versatilepb ARM Versatile/PB (ARM926EJ-S)
-
lm3s811evb Stellaris LM3S811EVB
-
z2 Zipit Z2 (PXA27x)
-
connex Gumstix Connex (PXA255)
-
sx1 Siemens SX1 (OMAP310) V2
-
realview-eb ARM RealView Emulation Baseboard (ARM926EJ-S)
-
cubieboard cubietech cubieboard
-
vexpress-a9 ARM Versatile Express for Cortex-A9
-
lm3s6965evb Stellaris LM3S6965EVB
-
realview-pbx-a9 ARM RealView Platform Baseboard Explore for Cortex-A9
-
musicpal Marvell 88w8618 / MusicPal (ARM926EJ-S)
-
mainstone Mainstone II (PXA27x)
-
terrier Terrier PDA (PXA270)
-
n810 Nokia N810 tablet aka. RX-44 (OMAP2420)
-
xilinx-zynq-a9 Xilinx Zynq Platform Baseboard for Cortex-A9
-
nuri Samsung NURI board (Exynos4210)
-
realview-eb-mpcore ARM RealView Emulation Baseboard (ARM11MPCore)
-
verdex Gumstix Verdex (PXA270)
-
spitz Spitz PDA (PXA270)
-
canon-a1100 Canon PowerShot A1100 IS
-
akita Akita PDA (PXA270)
-
smdkc210 Samsung SMDKC210 board (Exynos4210)
-
integratorcp ARM Integrator/CP (ARM926EJ-S)
-
sx1-v1 Siemens SX1 (OMAP310) V1
-
kzm ARM KZM Emulation Baseboard (ARM1136)
-
highbank Calxeda Highbank (ECX-1000)
-
n800 Nokia N800 tablet aka. RX-34 (OMAP2420)
-
collie Collie PDA (SA-1110)
-
realview-pb-a8 ARM RealView Platform Baseboard for Cortex-A8
-
vexpress-a15 ARM Versatile Express for Cortex-A15
-
none empty machine
-
cheetah Palm Tungsten|E aka. Cheetah PDA (OMAP310)
-
tosa Tosa PDA (PXA255)
-
midway Calxeda Midway (ECX-2000)
-
virt ARM Virtual Machine
-
borzoi Borzoi PDA (PXA270)
针对这个板子在Yocto中的模拟,官方也有一个网页:
Yocto for znyqmp,我们可以参考这个网页,但是根据这个网页做其实是行不通的。下面我主要说明一下需要更改和注意的地方。
构建与使用步骤
先根据官方的step1到step6来编译出需要的image。需要注意的是我们这里使用单核的A9,因此machine应该为qemuzynq,即在local.conf中应该为:
-
# This sets the default machine to be qemux86 if no other machine is selected:
-
MACHINE ??= "qemuzynq"
这个machine的定义位于其layer中的config中:
-
$ ls ../meta-xilinx/conf/machine/ -l
-
total 52
-
drwxrwxr-x 11 hexiongjun hexiongjun 4096 May 16 10:38 boards
-
-rw-rw-r-- 1 hexiongjun hexiongjun 593 May 16 10:38 ep108-zynqmp.conf
-
drwxrwxr-x 3 hexiongjun hexiongjun 4096 May 16 10:38 include
-
-rw-rw-r-- 1 hexiongjun hexiongjun 1049 May 16 10:38 kc705-trd-microblazeel.conf
-
-rw-rw-r-- 1 hexiongjun hexiongjun 623 May 16 10:38 microzed-zynq7.conf
-
-rw-rw-r-- 1 hexiongjun hexiongjun 804 May 16 10:38 picozed-zynq7.conf
-
-rw-rw-r-- 1 hexiongjun hexiongjun 564 May 16 10:16 qemumicroblaze.conf
-
-rw-rw-r-- 1 hexiongjun hexiongjun 512 May 16 10:16 qemumicroblaze-s3adsp1800.conf
-
-rw-rw-r-- 1 hexiongjun hexiongjun 496 May 16 10:38 qemuzynq.conf
-
-rw-rw-r-- 1 hexiongjun hexiongjun 1059 May 16 10:38 zc702-zynq7.conf
-
-rw-rw-r-- 1 hexiongjun hexiongjun 1008 May 16 10:38 zc706-zynq7.conf
-
-rw-rw-r-- 1 hexiongjun hexiongjun 847 May 16 10:38 zedboard-zynq7.conf
-
-rw-rw-r-- 1 hexiongjun hexiongjun 627 May 16 10:38 zybo-zynq7.conf
同时还需要配置output的initrd type为cpio:
IMAGE_FSTYPES = "jffs2 tar.bz2 cpio"
否则我们在后面的qemu中指定initrd的时候无法指定。
至此,我们就准备好了所有的材料。
运行模拟器
直接使用runqemu即可:
-
$ runqemu qemuzynq
-
-
Continuing with the following parameters:
-
KERNEL: [/home/hexiongjun/EmbProj/am335X_Yocto/qemuzynq/tmp/deploy/images/qemuzynq/uImage]
-
ROOTFS: [/home/hexiongjun/EmbProj/am335X_Yocto/qemuzynq/tmp/deploy/images/qemuzynq/core-image-minimal-qemuzynq-20160516035635.rootfs.cpio]
-
FSTYPE: [cpio]
-
Setting up tap interface under sudo
-
Acquiring lockfile for tap0...
-
Running qemu-system-arm...
-
/home/hexiongjun/EmbProj/am335X_Yocto/qemuzynq/tmp/sysroots/x86_64-linux/usr/bin/qemu-system-arm -kernel /home/hexiongjun/EmbProj/am335X_Yocto/qemuzynq/tmp/deploy/images/qemuzynq/uImage -net nic,model=virtio -net tap,vlan=0,ifname=tap0,script=no,downscript=no -M xilinx-zynq-a9 -serial null -serial mon:stdio -dtb /home/hexiongjun/EmbProj/am335X_Yocto/qemuzynq/tmp/deploy/images/qemuzynq/uImage-qemuzynq.dtb -initrd /home/hexiongjun/EmbProj/am335X_Yocto/qemuzynq/tmp/deploy/images/qemuzynq/core-image-minimal-qemuzynq-20160516035635.rootfs.cpio -no-reboot -m 1024 --append "earlyprintk root=/dev/ram rw ip=192.168.7.2::192.168.7.1:255.255.255.0 mem=1024M "
-
qemu-system-arm: Unsupported NIC model: virtio
-
Set 'tap0' nonpersistent
-
Releasing lockfile of preconfigured tap device 'tap0'
然后遇到了问题:qemu-system-arm: Unsupported NIC model: virtio
对此,有多种处理方法,最为简单的是我们直接使用qemu至此的 NIC model即可,因此先查询一下:
-
$ /home/hexiongjun/EmbProj/am335X_Yocto/qemuzynq/tmp/sysroots/x86_64-linux/usr/bin/qemu-system-arm -M xilinx-zynq-a9 -net nic,model=?
-
qemu: Supported NIC models: cadence_gem
可以看到支持的是cadence_gem,因此我们需要更改成这个。
runqemu的更改
runqemu的脚本位于:
poky/scripts/runqemu-internal中,在里面我们可以看到其指定了NIC model,因此我们将其改成cadence_gem即可:
-
KERNEL_NETWORK_CMD="ip=192.168.7.$n2::192.168.7.$n1:255.255.255.0"
-
QEMU_TAP_CMD="-net tap,vlan=0,ifname=$TAP,script=no,downscript=no"
-
if [ "$VHOST_ACTIVE" = "yes" ]; then
-
QEMU_NETWORK_CMD="-net nic,model=virtio $QEMU_TAP_CMD,vhost=on"
-
else
-
QEMU_NETWORK_CMD="-net nic,model=virtio $QEMU_TAP_CMD"
-
fi
然后再次运行,就可以工作了,可以看到其部分log如下:
-
$ runqemu qemuzynq
-
-
Continuing with the following parameters:
-
KERNEL: [/home/hexiongjun/EmbProj/am335X_Yocto/qemuzynq/tmp/deploy/images/qemuzynq/uImage]
-
ROOTFS: [/home/hexiongjun/EmbProj/am335X_Yocto/qemuzynq/tmp/deploy/images/qemuzynq/core-image-minimal-qemuzynq-20160516035635.rootfs.cpio]
-
FSTYPE: [cpio]
-
Setting up tap interface under sudo
-
Acquiring lockfile for tap0...
-
Running qemu-system-arm...
-
/home/hexiongjun/EmbProj/am335X_Yocto/qemuzynq/tmp/sysroots/x86_64-linux/usr/bin/qemu-system-arm -kernel /home/hexiongjun/EmbProj/am335X_Yocto/qemuzynq/tmp/deploy/images/qemuzynq/uImage -net nic,model=cadence_gem -net tap,vlan=0,ifname=tap0,script=no,downscript=no -M xilinx-zynq-a9 -serial null -serial mon:stdio -dtb /home/hexiongjun/EmbProj/am335X_Yocto/qemuzynq/tmp/deploy/images/qemuzynq/uImage-qemuzynq.dtb -initrd /home/hexiongjun/EmbProj/am335X_Yocto/qemuzynq/tmp/deploy/images/qemuzynq/core-image-minimal-qemuzynq-20160516035635.rootfs.cpio -no-reboot -m 1024 --append "earlyprintk root=/dev/ram rw ip=192.168.7.2::192.168.7.1:255.255.255.0 mem=1024M "
-
Warning: nic cadence_gem.1 has no peer
-
[ 0.000000] Booting Linux on physical CPU 0x0
-
[ 0.000000] Linux version 3.19.0-xilinx (hexiongjun@hexiongjun-9020) (gcc version 5.2.0 (GCC) ) #1 SMP PREEMPT Mon May 16 11:54:40 CST 2016
-
[ 0.000000] CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=10c5387d
-
[ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
-
[ 0.000000] Machine model: xilinx-zynq-a9
-
[ 0.000000] Memory policy: Data cache writeback
-
[ 0.000000] CPU: All CPU(s) started in SVC mode.
-
[ 0.000000] PERCPU: Embedded 9 pages/cpu @eefd8000 s8128 r8192 d20544 u36864
-
[ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 260624
-
[ 0.000000] Kernel command line: earlyprintk root=/dev/ram rw ip=192.168.7.2::192.168.7.1:255.255.255.0 mem=1024M
-
[ 0.000000] PID hash table entries: 4096 (order: 2, 16384 bytes)
-
[ 0.000000] Dentry cache hash table entries: 131072 (order: 7, 524288 bytes)
-
[ 0.000000] Inode-cache hash table entries: 65536 (order: 6, 262144 bytes)
-
[ 0.000000] Memory: 1028324K/1048576K available (4457K kernel code, 234K rwdata, 1408K rodata, 220K init, 198K bss, 20252K reserved, 0K cma-reserved, 270336K highmem)
-
[ 0.000000] Virtual kernel memory layout:
-
[ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB)
-
[ 0.000000] fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
-
[ 0.000000] vmalloc : 0xf0000000 - 0xff000000 ( 240 MB)
-
[ 0.000000] lowmem : 0xc0000000 - 0xef800000 ( 760 MB)
-
[ 0.000000] pkmap : 0xbfe00000 - 0xc0000000 ( 2 MB)
-
[ 0.000000] modules : 0xbf000000 - 0xbfe00000 ( 14 MB)
-
[ 0.000000] .text : 0xc0008000 - 0xc05c28f4 (5867 kB)
-
[ 0.000000] .init : 0xc05c3000 - 0xc05fa000 ( 220 kB)
-
[ 0.000000] .data : 0xc05fa000 - 0xc06349e0 ( 235 kB)
-
[ 0.000000] .bss : 0xc06349e0 - 0xc0666470 ( 199 kB)
-
[ 0.000000] Preemptible hierarchical RCU implementation.
-
[ 0.000000] RCU restricting CPUs from NR_CPUS=4 to nr_cpu_ids=2.
退出Qemu
输入Ctrl + A C,并输入q回车即可,Ctrl+C是无法退出的。
runqemu的其他工具
所有的工具有:
-
$ runqemu
-
runqemu runqemu-addptable2image runqemu-export-rootfs runqemu-extract-sdk
runqemu-gen-tapdevs runqemu-ifdown runqemu-ifup runqemu-internal
可以看到主要涉及到TAP功能的up down与create,与nfsroot相关的两个工具。
参考
http://www.wiki.xilinx.com/QEMU
http://zedboard.org/content/qemu-deep-dive-0
https://lists.gnu.org/archive/html/qemu-devel/2015-10/msg00755.html