故事的背景
本学期俺老孙学习嵌入式操作系统(),最终课程项目是定制内核与开发一个视频播放程序:
1.定制和移植6410开发板上的嵌入式linux最小内核与最小文件系统
2.在最小系统的基础上加入利用6410平台视频硬编码的视频播放器
我手上拥有的硬件:Tiny6410开发板一个(屏幕型号是H43)。
目标:最短时间内最高效地完成任务。
交叉编译环境搭建
安装虚拟机
上头给的开发系统是Fedora 9
(32位),有点老,安装时需要注意一些问题。
问题1
我的虚拟机是VM 11,安装Fedora 9
时需将处理器数量设为1,每处理器核心设为2,如果不这样做您就会卡在安装界面,如下图:
正常的安装界面是这样的:
问题2
设置磁盘大小时,最好设置为20G,太小可能出问题,到时需要重装(编译内核需要占用极大的空间)。
问题3
启动Fedora 9
虚拟机时,VM11提示VMware Workstation cannot connect to the virtual machine
。
对付此问题,只需打开控制面板——管理工具——服务,找到VMware Authorization Service服务,右键设置启动类型为自动,再右键启动。
问题4
安装完,开机后直接进入黑乎乎的字符界面,尝试用startx
命令进入图形界面时,被告知no screen found
。
这是由于您使用了VM11的简便安装
模式,它会默认跳过图形界面的安装,只安装服务器必须的软件,默认安装只828个包,实际上需要一千多个才有图形界面:
解决方法:在创建虚拟机时选择稍后安装操作系统
,创建完毕再添加镜像文件
,启动后就是自定义安装了。
问题5
一切装置完了之后,再次卡住,卡在Starting udev
:
这个有点复杂,估计是硬件不兼容之类的问题,持续等待几分钟后再次提示“Wait timeout. Will continue in the background.”
于是俺百度谷歌了一番,有人说是fedora识别方面有些BUG需要修改fedora的一些文件,但我进不了系统,也就没法从这里入手解决;有人说是CPU数量大于1的关系,我将CPU数量设为1,核心数量也设为1,依旧不行。
这时我想起来,按照VM11的简便模式安装后可以进入登录界面,而自定义安装加上图形界面就无法初始化硬件,莫非,是屏幕显示器的问题?
于是我修改虚拟机的屏幕,改“将主机设置用于监视器”
为“制定监视器设置”
,并指定分辨率为1024 * 768(我的显示器是27寸1080P,可能fedora9带不起),然后,就能成功进入设置界面了。
注意以上问题,虚拟机很容易就安装完毕了。
交叉编译工具
准备工具包
crosstool-0.43.tar.gz
binutils-2.16.1.tar.bz2
gcc-4.0.2.tar.gz
glibc-2.3.6.tar.gz glibc-linuxthreads-2.3.6.tar.gz linux-2.6.26.tar.gz linux-libc-headers-2.6.12.0.tar.bz
使用非root用户登录
建立存放工具包源码的cross目录
mkdir /home/qiuyongchen/cross
将 crosstool-0.43.tar.gz 复制到 cross 目录并解压
将其它工具包复制到cross目录
进入crosstool-0.43 目录对相关文件进行修改
【1】修改 arm.dat
KERNELCONFIG=`pwd`/arm.config
TARGET=arm-linux
TARGET_CFLAGS="-O"
【2】修改 demo-arm.sh:
#!/bin/sh
# This script has one line for each known working toolchain
# for this architecture. Uncomment the one you want.
# Generated by generate-demo.pl from buildlogs/all.dats.txt
TARBALLS_DIR=/home/lit/cross(修改这里) #下载的源码包存放的路径
RESULT_TOP=/home/qiuyongchen/crosstool(修改这里)#交叉编译工具链安装的路径
export TARBALLS_DIR RESULT_TOP
GCC_LANGUAGES="c,c++"
export GCC_LANGUAGES
# Really, you should do the mkdir before running this,
# and chown /opt/crosstool to yourself so you don't need to run as root.
mkdir -p $RESULT_TOP
#eval `cat arm.dat gcc-2.95.3-glibc-2.1.3.dat` sh all.sh --notest
#eval `cat arm.dat gcc-2.95.3-glibc-2.2.2.dat` sh all.sh --notest
#eval `cat arm.dat gcc-2.95.3-glibc-2.2.5.dat` sh all.sh --notest
#eval `cat arm.dat gcc-3.2.3-glibc-2.2.5.dat` sh all.sh --notest
#eval `cat arm.dat gcc-3.2.3-glibc-2.3.2.dat` sh all.sh --notest
#eval `cat arm.dat gcc-3.2.3-glibc-2.3.2-tls.dat` sh all.sh --notest
#eval `cat arm.dat gcc-3.3.6-glibc-2.2.2.dat` sh all.sh --notest
#eval `cat arm.dat gcc-3.3.6-glibc-2.2.5.dat` sh all.sh --notest
#eval `cat arm.dat gcc-3.3.6-glibc-2.3.2.dat` sh all.sh --notest
#eval `cat arm.dat gcc-3.3.6-glibc-2.3.2-tls.dat` sh all.sh --notest
#eval `cat arm.dat gcc-3.4.5-glibc-2.2.2.dat` sh all.sh --notest
#eval `cat arm.dat gcc-3.4.5-glibc-2.2.5.dat` sh all.sh --notest
#eval `cat arm.dat gcc-3.4.5-glibc-2.3.2.dat` sh all.sh --notest
#eval `cat arm.dat gcc-3.4.5-glibc-2.3.2-tls.dat` sh all.sh --notest
#eval `cat arm.dat gcc-3.4.5-glibc-2.3.5.dat` sh all.sh --notest
#eval `cat arm.dat gcc-3.4.5-glibc-2.3.5-tls.dat` sh all.sh --notest
#eval `cat arm.dat gcc-3.4.5-glibc-2.3.6.dat` sh all.sh --notest
#eval `cat arm.dat gcc-3.4.5-glibc-2.3.6-tls.dat` sh all.sh --notest
#eval `cat arm.dat gcc-4.0.2-glibc-2.2.2.dat` sh all.sh --notest
#eval `cat arm.dat gcc-4.0.2-glibc-2.3.2.dat` sh all.sh --notest
#eval `cat arm.dat gcc-4.0.2-glibc-2.3.2-tls.dat` sh all.sh --notest
#eval `cat arm.dat gcc-4.0.2-glibc-2.3.5.dat` sh all.sh --notest
#eval `cat arm.dat gcc-4.0.2-glibc-2.3.5-tls.dat` sh all.sh --notest
#eval `cat arm.dat gcc-4.0.2-glibc-2.3.6.dat` sh all.sh --notest
#eval `cat arm.dat gcc-4.0.2-glibc-2.3.6-tls.dat` sh all.sh --notest
#eval `cat arm.dat gcc-4.1.0-glibc-2.2.2.dat` sh all.sh --notest
#eval `cat arm.dat gcc-4.1.0-glibc-2.3.2.dat` sh all.sh --notest
#eval `cat arm.dat gcc-4.1.0-glibc-2.3.2-tls.dat` sh all.sh --notest #注释掉这行
eval `cat arm.dat gcc-4.0.2-glibc-2.3.6.dat` sh all.sh --notestt #添加此行
echo Done.
【3】修改 gcc-4.0.2-glibc-2.3.6.dat
BINUTILS_DIR=binutils-2.16.1
GCC_DIR=gcc-4.0.2
GLIBC_DIR=glibc-2.3.6
LINUX_DIR=linux-2.6.26 (修改这里) LINUX_SANITIZED_HEADER_DIR=linux-libc-headers-2.6.12.0
GLIBCTHREADS_FILENAME=glibc-linuxthreads-2.3.6
执行./demo-arm.sh
进行编译,等差不多一个小时就编译出交叉编译工具
了,至此呢,编译工具就弄到手了。
值得注意:交叉编译工具对版本的要求很严格,各个版本之间的兼容性较差,所以尽可能都下载到上述对应版本的工具包。
定制最小内核
准备
第一步 得到默认的内核配置
拷贝6410光盘文件A下Linux文件夹中的linux-2.6.28.6-20111212.tar.gz到虚拟机中,并解压。
进入解压后的目录,执行命令
mv config_mini6410_h43 .config
此命令会使用已经配置好的供h43屏幕的开发板使用
第二步 找到交叉编译环境
在Terminal中执行cd
命令回到你的主目录,编辑你的个人脚本配置:
gedit .bashrc
在最后面加上这两行:
export PRE=/home/qiuyongchen/crosstool/gcc-4.0.2-glibc-2.3.6/arm-linux/bin
export PATH=$PRE:$PATH
(保存该文件,关闭Terminal,重开一个Terminal,输入arm-再点击tab键,此时系统会弹出类似arm-linux-gcc之类的选项,这证明系统已经可以找到交叉编译器)
这是为了让你在下一步执行make命令时,系统能找到交叉编译器。
开始编译
执行make
命令,如果没有错的话,应该会报错:
invalid option `abi=aapcs-linux'
之所以会出错,是因为配置内核时使用了OABI的选项,你需要去掉它:
执行make menuconfig打开内核配置的界面,找到Kernel Features ---->Use the ARM EABIto compile the kernel
选项,不选该项。
修改一遍再执行make
命令,你就可以看到编译的过程了(一行行命令快速地刷过去)。
到了这里,我们就可以正常地编译内核了,但上头的要求是:尽可能地小,所以我们需要特殊地定制一个内核。
定制的详细过程
模板
定制前,我使用了源码包中针对h43屏幕已经调好的配置(config_mini6410_h43),在它的基础上进行修改。
在修改之前,我使用make zImage命令编译一个可以用的内核,发现其大小为3M,我的目标是删减到2M:
开始定制
执行make menuconfig
进入图形化配置界面
【1】 General setup
在此选项下,我去除了Automatically append version information to the version string,其余的保留
【2】Enable loadable module support
只选择Module unloading,以便后面以模块形式加载卸载。
【3】System Type
在ARM system type下选择Samsung S3C64XX,其余也保留不变
【4】Bus support / Kernel Features
均保持不变
【5】Floating point emulation
去掉NWFPE math emulation与VFP-format floating point maths选项。后面可能要播放视频需要用到浮点数运算,这里先不管。
【6】Networking suppot
直接去掉这个大选项,毕竟是不用联网的
【7】Device Drivers
这个有点麻烦,我全部去掉了SCSI device support下的全部支持,不需要与外部设备链接。
而在Input device support下,我去掉了Event interface与Touchscreens的支持,不需要事件也不需要触摸屏。
在**Character devices下,我去掉了模块示例和Buzzer的驱动。
去掉USB support和MMC/SD/SDIO card support。
其余的暂且不变(包括文件系统的配置)
定制结果
重新编译生成zImage,我发现其大小为2M,符合预期目标:
至此呢,您就得到了一个大小约为2M的内核zImage文件,可以进一步处理烧写进开发板了。
定制最小文件系统
编译BusyBox
准备
将busybox-1.14.2.tar.gz复制到虚拟机中,解压。
这里会遇到一些权限不足的问题cannot mknod operation not permitted,解决方法:在命令行中输入su
,然后输入root密码,进入超级管理员权限,之后再进行解压。
在安装包中已经有别人编译好的文件,所以先执行make clean
清除掉。
调整busybox配置
执行make menuconfig
进入编译前的配置。
进入busybox setting -> Build Options -> prefix,修改编译的前缀为/home/qiuyongchen/crosstool/gcc-4.0.2-glibc-2.3.6/arm-linux/bin/arm-linux-,如下图:
第一次编译
先退出配置界面,执行make
命令,尝试编译一遍(先不管定制),可以编译!
完了之后,执行make install
。
在子目录_instll
下面会生成3个目录bin/sbin/linuxsrc,进入各个目录,我发现虽然有很多链接,实际上只有一个busybox文件,大小为1M
建立文件系统
建立基本框架
在_install 下建立etc 目录;
在此etc 下分别建立rc,inittab,motd 三个文件;
进入刚新建的etc,在其下用”vi rc”命令建立rc 文件:
#!/bin/sh
mount -t proc proc /proc
cat /etc/motd
保存后退出,用chmod 命令改变rc 文件属性 :
[root@localhost etc]$chmod 755 rc
在etc 下新建一个inittab 文件,内容如下 :
# /etc/inittab init(8) configuration for BusyBox
#
# Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org>
#
#
::sysinit:/etc/rc.d/rcS
::askfirst:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a
继续在etc 下建立motd 文件,其内容随意。
在etc 下建立init.d 目录,而后在init.d 目录下建立rc 文件的符号连接文件rcS:
[root@localhost init.d]$ ln -s ../rc rcS
在_install 下建立dev 目录,创建设备文件:
#mknod console c 5 1
#mknod mdblock3 b 31 3
至此呢,基本的框架就有了,也就是上头所需的最小文件系统了:
封装基本框架
我使用了光盘中的mkubimage-mlc2工具(光盘A的linux目录下有个mktools-20110720.tar.gz文件,内部有该打包软件)
【1】安装mkubimage-mlc2
先解压mktools-20110720.tar.gz,用如下命令:
tar -vxzf mktools-20110720.tar.gz -C /
上述命令将所有的打包软件全部解压到/usr/sbin/目录
【2】打包busybox
进入busybox目录,执行命令:
/usr/sbin/mkubimage-mlc2 _install rootfs_my.ubi
执行完后就得到了rootfs_my.ubi文件系统镜像,利用上课时说的方法将它放到SD卡中就能刷进开发板了。
执行上述命令时系统会报错:mkubimage-mlc2: error while loading shared libraries: liblzo2.so.2: cannot open shared object file: No such file or directory
原因是缺少了liblzo2.so.2,用yum安装上即可(先执行su
进入root)
yum update(fedora太老,必须先更新软件库的列表)
yum install liblzo2.so.2
至此,我们就得到了一个“最小文件系统”。先烧入开发板看一下
烧录配置:
刚烧录进去时,没有任何响应,需要配置内核,让内核支持ubi格式才行:
Device Drivers --->
Memory Technology Device(MTD) support --->
UBI - Unsorted block images --->
<*> Enable UBI
<*> MTD devices emulation driver(gluebi)(NEW)
配置mtd支持UBI接口
File systems --->
Miscellaneous filesystems --->
<*> UBIFS file system support
开机效果图:
是可以开机的。