目录
- 一、buildroot根文件系统简介
- 二、buildroot下载
- 三、buildroot构建根文件系统
- 1、配置 buildroot
- ①配置 Target options
- ②配置 Toolchain
- ③配置 System configuration
- ④配置 Filesystem images
- ⑤禁止编译 Linux 内核和 uboot
- 2、 buildroot 下的 busybox 配置
- ①修改 Makefile,添加编译器
- ②busybox 中文字符支持
- ③配置 busybox
- ④编译busybox
- 3、编译buildroot
- 4、buildroot 根文件系统测试
- ①创建/lib/modules/4.1.15文件夹
- ①让命令行显示当前目录路径
- 四、加载驱动程序xxx.ko文件测试
- 1、将icm20608.ko文件拷贝到/buildroot/lib/modules/4.1.15目录下,如下图所示:
- 2、使用depmod命令驱动挂载
- 3、使用modprobe命令加载驱动,如下图所示:
- 4、使用icm20608APP应用程序测试,如下图所示:
- 5、使用lsmod查看当前加载的驱动程序和使用rmmod卸载驱动程序,如下图所示:
一、buildroot根文件系统简介
buildroot 构建的根文件系统相对比较齐全,很多东西需要它会自行添加,比如 lib 库文件。并且,如果单纯使用busybox的话,在后面的驱动开发中很多第三方软件也需要我们自己去移植,这些第三方软件有很多又依赖其他的库文件,导致移植过程非常的繁琐,而buildroot可以为我们省去这些大部分的麻烦。
二、buildroot下载
buildroot 官网下载地址为https://buildroot.org/。如下图所示:
三、buildroot构建根文件系统
1、配置 buildroot
将下载的buildroot源码拷贝到ubuntu中,然后对其进行解压,操作命令如下:
tar -vxjf buildroot-2019.02.6.tar.bz2
解压完成以后就会得到一个名为“buildroot-2019.02.6”的目录,此目录就是我们解压得到的 buildroot 源码,进入到此目录中,此目录如下图所示:
buildroot 和 uboot、 Linux kernel 一样也支持图形化配置,输入如下命令即可打开图形化配置界:
make menuconfig
打开以后的图形化配置界面如下图所示:
①配置 Target options
首先配置 Target options 选项,需要配置的项目和其对应的内容如下(“=”号后面是配置项
要选择的内容!):
Target options
-> Target Architecture = ARM (little endian)
-> Target Binary Format = ELF
-> Target Architecture Variant = cortex-A7
-> Target ABI = EABIhf
-> Floating point strategy = NEON/VFPv4
-> ARM instruction set = ARM
配置完成以后如下图所示:
②配置 Toolchain
③配置 System configuration
④配置 Filesystem images
⑤禁止编译 Linux 内核和 uboot
2、 buildroot 下的 busybox 配置
buildroot 在构建根文件系统的时候也是要用到 busybox 的,既然用到了 busybox 那么就涉及到 busybox 的配置。 buildroot 会自动下载 busybox 压缩包, buildroot 下载的源码压缩包都存放在/dl 目录下,在 dl 目录下就有一个叫做“busybox”的文件夹,此目录下保存着 busybox 压缩包,如下图所示:
可以看出, buildroot 下载的 busybox 版本为 1.29.3。要想编译 busybox,必须对上图中的压缩包进行解压缩, buildroot 将所有解压缩后的软件保存在/output/build 软件中,我们可以在找到/output/build/busybox-1.29.3 这个文件夹,此文件夹就是解压后的 busybox 源码,文件内容如下图所示:
①修改 Makefile,添加编译器
打开 busybox 的顶层 Makefile,添加 ARCH 和 CROSS_COMPILE的值,如下所示:
164 CROSS_COMPILE ?= /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
…
190 ARCH ?= arm
注意:CORSS_COMPILE 使用了绝对路径!主要是为了防止编译出错。
②busybox 中文字符支持
修改 busybox 源码,取消 busybox 对中文显示的限制,打开文件 busybox-1.29.3/libbb/printable_string.c,找到函数 printable_string,缩减后的函数内容如下:
12 const char* FAST_FUNC printable_string(uni_stat_t *stats, const char
*str)
13 {
14 char *dst;
15 const char *s;
16
17 s = str;
18 while (1) {
19 unsigned char c = *s;
20 if (c == '\0') {
......
28 }
29 if (c < ' ')
30 break;
31 if (c >= 0x7f)
32 break;
33 s++;
34 }
35
36 #if ENABLE_UNICODE_SUPPORT
37 dst = unicode_conv_to_printable(stats, str);
38 #else
39 {
40 char *d = dst = xstrdup(str);
41 while (1) {
42 unsigned char c = *d;
43 if (c == '\0')
44 break;
45 if (c < ' ' || c >= 0x7f)
46 *d = '?';
47 d++;
48 }
......
55 #endif
56 return auto_string(dst);
57 }
如果支持 UNICODE 码的话,当字符大于 0X7F 就直接输出‘?’。所以我们需要对这 4 行代码进行修改,修改以后如下所示:
12 const char* FAST_FUNC printable_string(uni_stat_t *stats, const char
*str)
13 {
14 char *dst;
15 const char *s;
16
17 s = str;
18 while (1) {
......
30 if (c < ' ')
31 break;
32 /* 注释掉下面这个两行代码 */
33 /* if (c >= 0x7f)
34 break; */
35 s++;
36 }
37
38 #if ENABLE_UNICODE_SUPPORT
39 dst = unicode_conv_to_printable(stats, str);
40 #else
41 {
42 char *d = dst = xstrdup(str);
43 while (1) {
44 unsigned char c = *d;
45 if (c == '\0')
46 break;
47 /* 修改下面代码 */
48 /* if (c < ' ' || c >= 0x7f) */
49 if( c < ' ')
50 *d = '?';
51 d++;
52 }
......
59 #endif
60 return auto_string(dst);
61 }
接着打开文件 busybox1.29.3/libbb/unicode.c,找到如下内容(修改后):
1003 static char* FAST_FUNC unicode_conv_to_printable2(uni_stat_t*stats, const char *src, unsigned width, int flags)
1004 {
1005 char *dst;
1006 unsigned dst_len;
1007 unsigned uni_count;
1008 unsigned uni_width;
1009
1010 if (unicode_status != UNICODE_ON) {
1011 char *d;
1012 if (flags & UNI_FLAG_PAD) {
1013 d = dst = xmalloc(width + 1);
......
1022 /* 修改下面一行代码 */
1023 /* *d++ = (c >= ' ' && c < 0x7f) ? c : '?'; */
1024 *d++ = (c >= ' ') ? c : '?';
1025 src++;
1026 }
1027 *d = '\0';
1028 } else {
1029 d = dst = xstrndup(src, width);
1030 while (*d) {
1031 unsigned char c = *d;
1032 /* 修改下面一行代码 */
1033 /* if (c < ' ' || c >= 0x7f) */
1034 if(c < ' ')
1035 *d = '?';
1036 d++;
1037 }
1038 }
......
1044 return dst;
1045 }
......
1047
1048 return dst;
1049 }
③配置 busybox
配置 buildroot 下的 busybox,因此打开 busybox 的配置界面,命令(两种打开方式)如下:
sudo make busybox-menuconfig
在buildroot根目录下
sudo make menuconfig在/output/build/busybox-1.29.3 目录下
配置界面如下图所示:
不采用静态编译,配置路径如下:
选项“Build static binary (no shared libs)”用来决定是静态编译 busybox 还是动态编译,静态编译的话就不需要库文件,但是编译出来的库会很大。动态编译的话要求根文件系统中有库文件,但是编译出来的 busybox 会小很多。这里我们不能采用静态编译!因为采用静态编译的话 DNS 会出问题!无法进行域名解析,配置如图下所示:
选择vi风格的行编辑命令,配置路径如下:
取消勾选Simplified modutils,配置路径如下:
使能系统启动和热插拔或动态加载驱动程序时,自动产生驱动程序所需的节点文件作用的选项mdev,配置路径如下:
使能 busybox 的 unicode 编码以支持中文,配置路径如下:
注意!
退出 linux Modules Utilites后 返回步骤 1 界面;在步骤 1界面选择最后一项 Save configuration to an alternate file,进入如下图界面:
在buildroot-2019.02.6/output/build/busybox-1.29.3目录下会生成busybox.config文件,如下图所示:
将buildroot-2019.02.6/package/busybox/busybox.config文件替换成上一步生成的buildroot-2019.02.6/output/build/busybox-1.29.3/busybox.config文件,如下图所示:
④编译busybox
查看当前 buildroot 所有配置了的目标软件包,也就是 packages,命令如下:
sudo make show-targets
单独编译并安装 busybox 如下命令:
sudo make busybox
3、编译buildroot
编译 buildroot,主要是对其进行打包,输入如下命令:
sudo make
然后在output/images目录下查看是否生成了rootfs.tar压缩包,如下图所示:
在 nfs 目录下新建一个名为 buildrootfs 的文件夹,然后将上图 中的 rootfs.tar 拷贝到 buildrootfs 目录下并解压,命令如下:
cd /home/djw/linux/nfs //进入到 nfs 目录下
mkdir buildrootfs //创建 buildrootfs 目录
cd buildrootfs //进入到 buildrootfs 目录
cp …/…/IMX6ULL/tool/buildroot-2019.02.6/output/images/rootfs.tar ./ //拷贝到 rootfs.tar
tar -vxf rootfs.tar //解压缩 rootfs.tar
rm rootfs.tar //删除 rootfs.tar
解压缩完成以后的 buildrootfs 目录如下图所示:
4、buildroot 根文件系统测试
buildroot 制作出来的根文件系统已经准备好了,接下来就是对其进行测试。测试方法也是通过 nfs 挂载的方式,启动 uboot,修改 bootargs 环境变量,设置 nfsroot 目录为 Ubuntu 中的buildrootfs 目录,命令如下:
setenv bootargs 'console=tty1 console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.1.111:
/home/djw/linux/nfs/buildrootfs rw ip=192.168.1.119:192.168.1.111:192.168.1.1:255.255.
255.0::eth0:off
这里我们重点说一下另外一个问题,我们使用构建的根文件系统启动以后会发现,输入命令的时候命令行前面一直都是“#”,如果我们进入到某个目录的话前面并不会显示当前目录路径,如下图 所示:
由上面可知,有两个问题,第一个是缺少/lib/modules文件夹,第二个是命令行不显示当前目录路径。
①创建/lib/modules/4.1.15文件夹
modprobe 命令主要智能在提供了模块的依赖性分析、错误检查、错误报告等功能,推荐使用 modprobe 命令来加载驱动。 modprobe 命令默认会去/lib/modules/目录中查找模块,我使用的 Linux kernel 的版本号为 4.1.15,因此 modprobe 命令默认会到/lib/modules/4.1.15 这个目录中查找相应的驱动模块,一般自己制作的根文件系统中是不会有这个目录的,所以需要自己手动创建,如下图所示:
①让命令行显示当前目录路径
先了解一下“PS1”这个环境变量, PS1 用于设置命令提示符格式,格式如下:
打开/etc/profile 文件,修改好后如下图所示:
etc/profile 文件修改完成以后重启开发板,这个时候我们就如到某个目录的时候命令行就会有提示,如下图所示:
四、加载驱动程序xxx.ko文件测试
1、将icm20608.ko文件拷贝到/buildroot/lib/modules/4.1.15目录下,如下图所示:
2、使用depmod命令驱动挂载
输入“depmod”命令以后会自动生成 modules.alias、modules.symbols 和 modules.dep 这三个文件,如下图所示: