浙江大学嵌入式系统课程
安装交叉编译工具,并设置NAS
1 2 3 4
| sudo apt-get install gcc-arm-linux-gnueabi cd ~ mkdir pi sudo mount 192.168.0.4:/home/pi /home/neo/pi
|
详情见搭建RaspberryPi的交叉编译环境。
下载Raspberry Pi的源码
1 2 3 4 5 6
| cd ~/pi mkdir kernel cd kernel git clone https://github.com/raspberrypi/linux.git git clone https://github.com/raspberrypi/firmware.git
|
因为网络原因这一步耗时较长,需要耐心等待。也可以直接在github上下载zip压缩包自行解压,不过无论是使用RPi解压或是通过NAS解压速度都不快,可以考虑取下SD卡在PC上直接解压。
提取原有的内核配置文件配置新内核
1 2 3 4 5
| cd ~/kernel/linux sudo zcat /proc/config.gz > .config make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- oldconfig
|
因为不需要修改内核配置,直接一路回车结束配置即可。
增加新的系统调用
- 在linux/arch/arm/kernel/目录下新建mysyscall.c文件,输入以下内容
1 2 3 4
| #include <linux/kernel.h> void hello(void) { printk("Hello world!\tFrom Neo\n"); }
|
- 在linux/arch/arm/kernel/call.S中添加新的系统调用,这里我替换的是原本为sys_ni_syscall的0x900000+223号系统调用,如下图所示。

- 修改arch/arm/kernel/目录下的Makefile文件,在obj-y后面添加mysyscall.o,如下图。

编译内核
1 2
| make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- -k
|
之所以选择交叉编译是因为RPi的主频和PC比起来相差太多,若是直接用RPi编译内核耗时太长了。
编译新lib
1 2 3 4 5
| cd ~/pi/kernel mkdir modules cd linux make modules_install ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- INSTALL_MOD_PATH=../modules
|
备份 firmware
1 2 3 4 5
| cd ~/kernel mkdir firmware_ori cd /boot cp *.elf *.bin ~/kernel/firmware_ori
|
更新内核、lib和firmware
1 2 3 4 5 6
| cd ~/kernel sudo cp linux/arch/arm/boot/Image /boot/kernel_new.img sudo cp modules/lib / cd firmware/boot sudo cp bootcode.bin fixup.dat fixup_cd.dat start.elf /boot
|
修改RPi的配置文件/boot/config.txt
1 2
| sudo nano /boot/config.txt
|
在首行加上“kernel=kernel_new.img”即可。若原来已经存在了kernel字段,直接修改就可以了。

重启,测试新内核
先看看原内核信息,如下图。

新内核信息如下图。

可以看到内核已经从3.2.27+升级到了3.6.11。
测试新增加的系统调用
1 2 3 4 5 6 7 8 9
| #include <stdio.h> #define sys_hello() {__asm__ __volatile__ ("swi 0x900000+223\n\t");} while(0) int main(void) { sys_hello(); printf("Type \"dmesg | tail\" to see the result.\n"); return 0; }
|
1 2 3 4
| gcc hello.c -o hello ./hello dmesg | tail
|
结果如下图。

在内核信息的最后一行可以看到我们的hello()函数已经成功执行了。