[raspberry pi] 树莓派 Kernel 编译笔记

Photobucket

发现自己的知识体系有一段很大的空缺,就是对于 ARM 还是太缺少了解,下面是AVR系列单片机,上面是PC机、服务器,好歹都还算大概见过是怎么一回事,而对于SOC,就了解得很不够,包括对于手机、安卓或是苹果系都只是停留在应用层面,至于开发是怎么样子就没有什么感性认识,感觉一打开这扇门,就会有各种知识领域排山倒海而来。不过该来的总是要来么,连 linux 内核 kernel 都不会编译,实在是不敢自诩为Geeker。好在现在开源ARM平台中,相信树莓派(Raspberry Pi,简称“RPi”)的资料很全,社区也庞大。所以,在盲目去买 ARM 开发板之前,还是先把手边现有的 RPi 和 Mk802 先玩起来再说。

这次尝试给RPi编译 kernel,主要参考了官方教程Peter Mount’s Blog上的这篇文章。我会结合自己操作过程中的实际情况,配合截图做个记录。

开发环境:我使用的系统是Ubuntu 12.10,因为使用的是“交叉编译”,也就说编译环境是PC,而运行环境是RPi,所使用的编译器也都是为目标系统所定制,所以相信不用纠结于PC这边的具体linux发行版。

1. 连接系统

如题图所示,PC通过USB转串口芯片连接到RPi的串口(当然还要共地),这样我在PC终端这边,可以通过minicom登录RPi并进行操作。截图中,蓝底黄字的为minicom窗口,黑底白字为本地终端。通过minicom登录RPi以后,可以运行以下命令以查看当前Kernel的版本。

Photobucket

$ uname -a

我现在使用的kenrel版本为3.2.27,生成日期为2012年9月26日。SD卡上原先烧的镜像是比较经典的“2012-08-08-wheezy-armel.zip”。

2. 下载编译工具、Kernel源文件、固件 Firmware

简单起见,我们都使用官方提供的资源

$ mkdir rasperberrypi
$ cd raspberrypi
$ git clone git://github.com/raspberrypi/firmware.git PRiFirmware
$ git clone git://github.com/raspberrypi/linux.git RpiLinux
$ git clone git://github.com/raspberrypi/tools.git RpiTools

在 git clone 命令的源后,可以跟上文件名,对下载文件夹名称进行指定。因为git clone似乎不支持断点续传,而这几个项目都是上百M,如果网络不稳定的话,下载会比较郁闷。如果对更新不是很关心的话,可以直接下载github上相应的zip压缩包。下载完成以后,应该有这样三个文件夹,分别对应固件、linux源码和编译工具。

Photobucket

3. 获取当前Kernel的.config文件,并进行自定义的配置

复制RPi的config.gz文件。
Photobucket

把config.gz文件拷贝到RPi的home目录之后,就可以将RPi关机,将SD卡插入PC,获取并解压该配置文件。sdc对应SD卡,其又分为两个分区sdc1、sdc2,分别对应RPi的“/boot”和“/”

Photobucket

$ sudo mkdir /media/agu/SD
$ sudo mount /dev/sdc2 /media/agu/SD/
$ cp /media/agu/SD/home/pi/config.gz .
$ zcat config.gz > .config
$ ls -a
.  ..  .config  config.gz  RpiFirmware  RpiLinux  RpiTools
$ sudo umount /media/agu/SD 

当Linux目录下有了.config文件以后,就可以对其进行重新配置。

Photobucket

$ mv .config /RPiLinux
$ cd RpiLinux/
$ make ARCH=arm CROSS_COMPILE=../RpiTools/arm-bcm2708/arm-bcm2708hardfp-linux-gnueabi/bin/arm-bcm2708hardfp-linux-gnueabi- oldconfig

在官方提供的编译工具中包含三套工具链

  • arm-bcm2708hardfp-linux-gnueabi
  • arm-bcm2708-linux-gnueabi
  • gcc-linaro-arm-linux-gnueabihf-raspbian

简单起见,我们就选用其中第一种,命令行的输入都通过tab补全来实现。make oldconfig可以在原.config的基础上更新配置,菜单很长,大部分目前我自己也不清楚是什么意思,所以也是一路enter,选择默认值。大致可以看出里面包含不少对加载驱动的选取。

如果还需要添加什么内容,可以运行

$ make ARCH=arm CROSS_COMPILE=../RpiTools/arm-bcm2708/arm-bcm2708hardfp-linux-gnueabi/bin/arm-bcm2708hardfp-linux-gnueabi- menuconfig

Photobucket

就可以看到kernel的配置菜单:

Photobucket

这里就可以更加从容地添加模块,比方说摄像头之类。完成以后,选择exit退出。

3. 编译Kernel,modules

$ make ARCH=arm CROSS_COMPILE=../RpiTools/arm-bcm2708/arm-bcm2708hardfp-linux-gnueabi/bin/arm-bcm2708hardfp-linux-gnueabi- 

Photobucket

如果没有开启多线程编译的话,这个过程可能需要三四十分钟左右。

Photobucket

arch/arm/boot/zImage 就是我们所编译获得的文件。zImage 是 Compressed kernel image 文件,要转换为 kernel.img 还需要进一步处理。

Photobucket

$ cd ../RpiTools/mkimage/
$ ./imagetool-uncompressed.py ../../RpiLinux/arch/arm/boot/zImage 

可以看到当前目录中多了kenrel.img文件。

编译新lib:
Photobucket

新的Kernel要正确运行,还需要编译所需的module,主要对应”/lib”目录下的内容。编译时,使用“INSTALL_MOD_PATH”参数指定目标路径。

$ cd ../..
$ mkdir modules
$ cd RpiLinux/
$ make modules_install ARCH=arm CROSS_COMPILE=../RpiTools/arm-bcm2708/arm-bcm2708hardfp-linux-gnueabi/bin/arm-bcm2708hardfp-linux-gnueabi- INSTALL_MOD_PATH=../modules

3. 备份 Firmware

Photobucket

$ cd ..
$ mkdir backup
$ sudo mount /dev/sdc1 /media/agu/SD/
$ cd /media/agu/SD/
$ mv *.elf *.bin ~/gitpool/raspberrypi/backup/

因为kernel可以通过在/boot/config.txt中进行设定,所以倒也不急着拷出来。

Photobucket

可以通过vi,可以添加“kernel=kernel_new.img”这行,如果原来有的话,就修改一下。这样系统就会引导到我们刚刚拷入的kernel_new.img

4. 升级RPi的kernel、Firmware、lib

Photobucket

$ sudo cp ~/gitpool/raspberrypi/RpiTools/mkimage/kernel.img kernel_new.img
$ cd ~/gitpool/raspberrypi/RPiFirameware/boot
$ cp bootcode.bin fixup.dat fixup_cd.dat start.elf /media/agu/SD/
$ cd ../hardfp/opt/
$ sudo umount /media/agu/SD 
$ sudo mount /dev/sdc2 /media/agu/SD/

将挂载点换成SD卡的第2分区,即”/”分区。

$ sudo cp -r vc/ /media/agu/SD/opt/

将新的vc库复制到SD卡,因为之前选用的工具链是hardfp(硬浮点),所以现在所选用的vc库也是硬浮点的版本(RPiFramware/hardfp/opt/vc)。

$ cd ../../..
$ sudo cp -r modules/lib /media/agu/SD/

复制编译的module/lib到RPi的”/”根分区内。

5. 享用新的 Kenrel 吧~

Photobucket

将SD插回RPi,可以看到其正常启动,同时其kernel已更新到3.6.11,系统的生成日期是2012年1月10日,也就是今天。

至此,我们就完成了RPi的Kernel更新。至于后续的安装,包括rootfs的选择和安装,还有待继续研究。希望本文对那些从未编译过kernel的朋友一点帮助,如果仔细按照我的步骤,相信会得到和我一样的结果。RPi是很强大而且学习资料相当丰富的ARM平台,通过它来学习嵌入式linux开发,相信是不错的选择。

参考资料:
RPi Kernel Compilation
Compiling a Kernel on the Raspberry PI
基于MK802 MiniPC的扩展开发应用-系统自制,如果希望多硬浮点软浮点多一些了解,可以仔细研究大H的文章哦~

Photobucket

本次操作所使用的USB转串口模块,由圣源电子提供。


这个过程,自己又经历了几次,发现上面记录的还是比较乱。步骤其实更简单一些,

  1. 备份:升级之前,如果需要备份的话,$ sudo dd bs=4M if=/dev/sdc of=2012-01-17.img 可以备份整张SD卡
  2. 升级firmware:RPiFirmware里面的boot和hardfp/opt/vc可以先全部覆盖到SD卡的相应位置。
  3. 编译升级Kernel:如果需要自定义kernel,再进行自定义配置和编译,再将kernel和新编译的lib同时拷入SD卡。

关于aGuegu

阿古 真名:官微宏,技术Geek,玩Arduino,玩Linux,爱Google,爱开源;现居福州
此条目发表在Ubuntu | Linux, 硬件 | Hardware分类目录,贴了, , , , , , , , , , 标签。将固定链接加入收藏夹。