本文概括性地介绍嵌入式Linux移植。
系统移植一般包括三大方面,如下:
bootloader:作为上电运行的第一个程序,负责最原始的初始化操作,初始化芯片、初始化内存、初始化IO复用,读取内核代码并将控制权移交到内核,从而完成使命。
kernel:提供基本的运行环境,提供外设操作控制接口。
rootfs:向用词(应用层)提供基本操作环境,包括命令行、程序库等。
1、bootloader(启动装载程序)
嵌入式Linux常见的bootloader是u-boot,而X86领域中一般称为BIOS。u-boot的学习没有捷径,最好是在有ARM开发板情况下进行研究,通过打印信息的方法跟踪其流程。但是,看懂u-boot代码需要电路基本知识、芯片手册知识等等。——这些知识,同样适用于内核驱动的开发。
首先要建立的是整体概念和认识。建议先把厂商提供的u-boot源码编译通过,并下载到开发板上看到正常结果后,再用串口打印信息搜索代码,以了解u-boot的代码流程。然后再慢慢研究。如果bootloader不是学习重点,在有一定概念前提下就可以跳过到内核驱动层了,不过就笔者经验来看,bootloader和内核关系十分密切且部分代码是相通的。
一般初始化的代码是汇编代码,对于入门者而言,初学阶段不用追究,等有一定基础后再回头研究也不晚。
笔者许多年前移植过u-boot,写了几篇文章,版本旧了一些,但对于学习而言还有有好处的:
http://blog.csdn.net/subfate/article/category/751064
笔者曾经研究过x86的开源bios,写了几篇文章,大家可以看看。虽然对于u-boot学习帮助不大,但可以了解笔者如何从零开始学习一个未知的知识。地址:http://blog.csdn.net/column/details/15826.html
2、kernel(内核)
内核是比较大的一块,涉及内容十分多。作为入门者,与u-boot类似,首先要建立的整体概念。先把厂商提供的内核源码编译通过,并下载到开发板上,串口会打印很多启动信息,这些启动信息能帮助我们学习内核,自己也可以在内核中打印语句,以了解其流程。
每一个平台芯片不同,外设不同,内核均不同,需要进行移植。所谓的“移植”,就是找到合适的驱动,修改适应到该平台的过程。比如,某平台使用2个LCD屏,一个是3.5寸的,另一个是4.3寸的,这需要对内核进行修改。比如,这个平台使用nand flash是1GB的,另一个平台使用的是512MB的,也需要修改内核。其它如EEPROM、电源芯片、网卡,等等,均如此。
内核知识点分2部分,一是kernel本身的知识点,如内存管理机制(MMU)、时间管理、同步机制,等等。二是外设驱动,如LED灯、GPIO、按键。
初学者建议学习:
1、了解内核编译的过程:配置内核、编译uImage。
2、了解platform驱动模型(笔者文章有现成的模板,已经应用于很多个平台上)。
3、了解一般外设驱动模型。建议从简单的LED、GPIO入门。
高阶知识点:
1、学习各种子系统,如MTD、USB、IIC、SPI、RTC、WDT。
2、学习内核知识,如延时队列、时间管理,同步机制,等等。
以下是笔者笔记关于内核专题的目录:
推荐资源:
《Linux设备驱动程序》第三版
《Linux设备驱动开发详解》
笔者开了一个专栏讲内核的,欢迎阅读:http://blog.csdn.net/column/details/15829.htm
3、rootfs(根文件系统)
一般情况下,开发板厂商会提供根文件系统,如果没有,则可以自己编译制作。一般嵌入式Linux使用busybox制作文件系统必要的程序、库、配置文件。因为busybox编译出来的内容体积小,节省空间,所以很多ARM开发板上都是用busybox的。另外还涉及到文件系统格式,像Yaffs2、ramfs、ext4、UBI,等等。所有这些知识点,请自行搜索学习。
掌握程度:
1、知道系统启动过程涉及到哪些脚本。知道上电启动时如何添加自己程序启动。
2、了解各目录功能、存储哪些文件(如改IP在哪个配置文件,动态库在哪些目录)。
4、心得
虽然笔者长期研究的技术点包罗万象,重点还是偏向于底层系统方面。对于u-boot、kernel,我认为前两者有一定程度几乎相似(包括代码和知识点),但kernel十分庞大,值得去研究。如果要选择一个,笔者偏向于kernel。对于rootfs,笔者可以大言不惭地说研究到一定深度了,前任职的公司,arm平台的rootfs由笔者维护多年,而x86的rootfs由笔者创立并维护多年。但是,rootfs技术不及kernel,所以就本文而言,建议以kernel为技术点,u-boot达到了解结构,会看代码即可(因为kernel知识能通用),rootfs在日常中积累。
李迟 2017.4.14 周五 晚