把linux在arm开发板上进行定制,并在arm开发板上运行起来。
更好地理解linux的构架过程。
驱动开发是在系统运行起来后,在内核中增加一些驱动子功能而已。
一、概述
1、arm裸机程序系统结构图
硬件层:硬件工程师决定硬件放在哪个资源。如,是在GPA口,GPH口,还是GPG口。
驱动层:驱动工程师根据硬件的架构,把驱动的资源用代码去指向,比如C语言的指针去指向相应的资源;硬件需要什么样的高/低电平或组合的数据,让其工作,是由驱动层封装的。
应用层:根据传递的不同的值,来得到不同的结果。
该架构存在的问题:
耦合性太强,一旦一层发生改变, 其他层都会变。
2、类android等复杂功能系统结构图
为了解决上述问题,引入一个概念:OS;引入一层:kernel层。
可以让应用层程序员解放出来,不用关心底层。
同时,也可以进行资源管理、多进程多线程管理等。
驱动控制硬件工作。
驱动与内核:驱动把支持的设备向内核报告,内核根据传来的信息,会调用不同的驱动程序,来控制相应的硬件。
它们可以认为是一个整体,都属于底层软件的范围。
3、android系统框架图
通过分层,可以实现软件复用性、可移植性。而且不同模块解耦。
不是分层越多越多,分层越多,速度也越慢。
二、系统移植学习内容
1、交叉编译环境
搭建交叉开发环境
2、bootloader功能子系统
bootloader的选择和移植
系统一上电会运行一个程序:bootloader(启动加载),目的是load kernel。
可以做很多种方案的选择。
很多大型项目中,更多是选择适合项目的启动加载代码,然后再改改(移植)。
很多时候,买芯片的时候,芯片厂商就已经提供好了。
3、内核核心子系统
kernel的配置、编译、移植和调试
4、文件系统子系统
根文件系统的制作
给用户用,还得提供文件系统。
这4个就是整个系统移植的精髓。
三、学习思路和方法
先整体后局部,层层推进。
每个子系统是如何编译的 ---> 在基本功能下,如何添加命令或功能 ---> 如何自定义自己的开发板,与自己的开发板具体硬件相联系
每个子系统都具有一个复杂的层次关系。
所以要先掌握整体,需要首先掌握相关子系统的藏宝图,有了这个地图,去探索它就有了方向。
四、系统移植的基本步骤
拿到一块板子,如何让整个系统跑起来呢?
1、确定目标机(开发板,客户端)和主机(PC,开发机器,服务端)的连接方式
主机性能会比目标机好太多,因此一般在主机开发,把主机编译好的内容数据传输给目标机。
数据就是高低电平。
传输方式:
(1)UART异步串行通信接口 (串口)
它是非常经典的与PC机通信的接口。
优点:
- 功能很强大,既可以输入,也可以输出,比较万能。
- 实用性强(90%的板子都支持)
缺点:速度比较低,效率比较差。
大文件一般不用串口传输,小文件可以。
(2)USB串行通信接口
现在已经发展到USB 3.0
优点:速度快
缺点:USB的驱动要移植修改。
板子刚刚上电,就让串口工作,是不现实的。
(3)TCP/IP网络通信接口
优点:速度快(10/100Mbps)
缺点:驱动需要移植
TCP/IP已经很成熟了。开发板与PC可以以C/S模式进行数据的传输和下载。比较通用。而且网卡的速率也比较快,最少10M,100M网卡也很多。
通过网络接口去下载数据的情况很多。
(4)Debug Jtag调试接口
方便快捷,但价格很高,很少使用。
2、安装交叉编译器
PC的cpu架构是X86,X86程序和arm程序不兼容,因此需要交叉编译器。
2种方法:
(1)安装芯片厂商已经编译好的工具链
一般有如下前缀名:
arm-none-linux-gnueabi-
简称:arm-linux-
(把arm-linux-
软链接为上述前缀名)
arm-none-eabi-
这个不支持操作系统。
arm-elf-
这个非常老了。很少见到了。
第一列:目标体系结构
gcc:默认编译x86
有arm,就会编译arm
第二列:厂商名。开源的话,一般是none
第三列:该编译器默认编译出来的功能是针对linux操作系统去用的。
这个编译器内部有些标准C库,是与linux系统相关的。
在windows下运行不了。
第四列:
gnu:开源
eabi:嵌入式的标准调用接口。针对嵌入式精简的相关库。
(2)自己动手编译交叉工具链
《The GNU Toolchain for ARM Target HOWTO》这本书会介绍。
自动动手编译非常耗时,而且会报很多不兼容的问题。调试需要功力,对编译原理要理解的很清楚。很多公司都不会去做。不建议使用该方法。
思路其实比较单一,唯一的不好是版本间的依赖关系比较大。
3、搭建主机-目标机数据传输通道
比如用网络,则需要网络相关服务器的配置。
一般嵌入式中,用的比较多的服务:
- TFTP :基于UDP协议传输的,是FTP的简版。UDP比FTP简单。
- NFS:网络文件系统。目的是linux与linux之间挂载用的。
文件系统的调试,很多时候用NFS作为调试的工具。
4、编译三大子系统:
bootloader功能子系统
内核核心子系统
文件系统子系统
该步骤难度最大。
5、烧写测试
整个进行集成,然后放到工厂进行集成化生产就可以了。
五、环境搭建需求分析
需求分析:
主机中的数据 如何传递 到开发板?
目的1:普通数据的传递:比如,uboot,kernel。
主要目的就是为了传递。
UART很少使用,更多使用的是网络接口。最主要的使用方式是TFTP服务。
TFTP主要传输的是kernel的文件。
uboot会通过其他方式烧写(当然网络接口也可以传输。看开发环境来决定。)
目的2:调试:主机的一块内存空间,直接挂载在板子上。
在x86上调好,再放到板子上。
但是,有可能调试不是很顺利,因此需要开发板与PC间建立更合理、方便的解决方案。
不能在板子上直接调试,就是因为板子容量太小。
要想办法扩大板子空间,但是flash太贵。
板子可以外挂很大空间的存储器,比如U盘。
但是U盘很麻烦,插开发板上,完了还得拔下来插PC上。
思路:调试时,不一定非要进行网络传输。只需要把数据挂到板子上就可以了。
办法:通过网线把共享的数据块(当作USB),通过TCP/IP来传。
共享的数据库就在PC上。
调试起来更加方便,PC上的修改板子上就可以直接看到了,不需要进行更多的数据传输了。
调试内核驱动、应用程序,很多时候是借助这种方式,在PC上进行软件开发,然后直接在板子上进行验证。
六、笔记本移植环境搭建
串口:连接方式方便,驱动简单。
少数据量的东西,会用串口。
标准输入/输出,会定位到串口驱动上。
笔记本都是USB接口,而开发板要用串口,因此要买USB转串口。
如何排查目标机与主机的各层是否通了?
- 应用层:调试程序
- 传输层:主要是端口port没有开放。要不就是服务器开放端口不对或未开放端口,或者客户端访问的端口不对。
- 网络层:通过ping看看在不在一个局域网段。
- 物理层:查看插上的网卡灯有没有亮。