linux内核源码下载:https://www.kernel.org/
UBoot源码下载:http://www.denx.de/wiki/U-Boot/
BusyBox获取:https://busybox.net/downloads/
目的
系统移植的目的:使操作系统能在某个微处理器或微控制器上运行,此次实验的目的也就是把一个linux系统移植到开发板上,使得我们能在开发板上直接执行linux上的相关命令和程序。
不同架构的处理器指令集不兼容,即便是相同的处理器架构,板卡不同驱动代码也不兼容,Linux是一个通用的内核并不是为某一个特定的处理器架构或板卡设计的,所以从官方获取Linux源码后我们要先经过相应的配置使其与我们当前的硬件平台相匹配后才能进行编译和安装,也就是所谓的移植。
移植所需工具
UBOOT
在介绍过程之前,我们先介绍一下BL0:
BL0,也就是Bootloader,他是在操作系统运行之前运行的一小段代码,用于将软硬件环境初始化到 一个合适的状态,为操作系统的加载和运行做准备(其本身不是操作系统)
Bootloader基本功能:
- 初始化软硬件环境
- 引导加载linux内核
- 给linux内核传参
- 执行用户命令
bootloader是启动引导程序的统称,嵌入式linux常用的bootloader是uboot,可以在其官网进行下载
uboot的特点:
- 代码结构清晰
- 支持丰富的处理器与开发板,易于移植
- 支持丰富的用户命令
- 支持丰富的网络协议
- 支持丰富的文件系统
- 支持丰富的设备驱动
- 更新活跃、用户较多、资料丰富
- 开放源代码
- 较高的稳定性
- 不具有通用性(不同的处理器、开发板uboot不可通用)
uboot源码结构:
平台相关代码:即与CPU架构或开发板硬件相关的源码,硬件的改动对应的代码也需要进行修改
- arch:与CPU架构相关的源代码
- board:与开发板相关的源 代码,包含各种官方评估板对应的源码
平台无关代码:
- api: 应用接口
- common: uboot命令源码
- disk: 对磁盘设备的支持
- drivers: 设备驱动源码
- fs: 对文件系统的支持
- include: 头文件
- lib: 库
- net: 对网络协议的支持
- post: 上电自检程序
配置文件、帮助文档、示例程序、工具等:
- README: 说明文档
- doc: 帮助文档
- Makefile: 编译管理
- CREDITS: 开发者
- COPYING: 版权
- examples: 示例程序
- tools: 工具
linux内核
再来介绍一下linux内核,首先区别一下内核和操作系统:
内核:内核是一个操作系统的核心,提供了操作系统最基本的功能,是操作系统工作的基础,决定着整个系统的性能和稳定性
操作系统:操作系统是在内核的基础上添加了各种工具集、桌面管理器、库、shell、应用程序等
linux内核的特点:
- 代码结构清晰、模块化设计
- 支持丰富的硬件平台
- 较高的稳定性
- 轻量化及较强的裁剪性
- 开放源代码
- 更新活跃、用户较多、资料丰富
- 支持丰富的网络协议
linux内核源码结构:
平台相关代码
- arch: 与CPU架构相关的源代码
平台无关代码
- block:磁盘设备的支持
- crypto:加密相关
- drivers:设备驱动
- firmware:固件
- fs:文件系统
- include:头文件
- init:内核初始化
- ipc:进程间通信
- kernel:内核核心调度机制等
- lib:库
- mm:内存管理
- net:网络协议
- scripts:工具、脚本等
- security:安全
- usr:打包与压缩
- virt:虚拟
帮助文档、示例程序、工具等:
- COPYING: 版权
- CREDITS: 内核贡献者
- README: 说明文档
- Documentation: 帮助文档
- Makefile: 编译管理
- samples: 示例
- tools: 工具
设备树(dtb)
作用:
设备树是一种描述硬件信息的数据结构,Linux内核运行时可以通过设备树将硬件信息直接传递给Linux内核,而不再需要在Linux内核中包含大量的冗余编码,就比如我们想对开发板上的LED1进行操作,当我们编写好代码完成操作后又想让LED2完成相同的操作,如果没有设备树的话我们需要更改许多代码十分麻烦,而使用了设备树之后,我们对应的驱动程序是不需要更改的,只需要告知设备树我们需要驱动哪个硬件即可。
设备树文件:
- dts 设备树源文件
- dtsi 类似于头文件,包含一些公共的信息,可被其它设备树文件引用
- dtb 编译后的设备树文件
根文件系统
定义:
根文件系统是内核启动后挂载的第一个文件系统,系统引导程序会在根文件系统挂载后从中把一些基本的初始化脚本和服务等加载到内存中去运行
Busybox:
BusyBox将很多常用的工具集成到一个很小的可执行文件中,为普通用户提供大多数常用的命令,BusyBox实现的命令都是精简版的,很多扩展都不支持。BusyBox被称为Linux工具里的瑞士军刀
根文件系统存放的内容:
- bin shell命令(elf格式)(通过busybox编译生成)
- dev 设备文件(内核启动后会将设备信息写入该目录)
- etc 内核配置文件
- lib 共享库(elf格式)(从交叉编译工具链中获取)
- linuxrc 内核运行的第一个应用程序(通过busybox编译生成)
- mnt 挂载目录(非必要)
- proc 进程相关文件(内核启动后会将进程信息写入该目录)
- root 超级用户家目录(非必要)
- sbin 系统管理shell命令(elf格式)(通过busybox编译生成)
- sys 驱动相关文件(内核启动后会将驱动信息写入该目录)
- usr shell命令(elf格式)(通过busybox编译生成)
移植的具体过程
具体过程如下:
- 开发板上电后首先运行SOC内部iROM中固化的代码(BL0),这段代码先对基本的软硬件环境(时钟等...)进行初始化,然后再检测拨码开关位置获取启动方式,然后再将对应存储器中的uboot搬移到内存,然后跳转到uboot运行。
- uboot开始运行后首先对开发板上的软硬件环境做进一步初始化,然后将linux内核、设备树(dtb)、根文件系统(rootfs)从外部存储器(或网络)搬移到内存,然后跳转到linux运行
- linux开始运行后先对系统环境做初始化,当系统启动完成后,Linux再从内存中(或网络)挂载根文件系统
总结:
综上所述,我们想将linux移植到开发板上,就需要先将uboot移植,之后去移植linux内核,最后让linux挂载根文件系统,从而实现将linux移植到开发板,想要去移植这些东西,我们可以使用tftp与nfs去将其传输到开发板上。tftp和nfs的区别在于tftp是每次传输完成后,我们要更新这个文件就需要在服务器端调试完成后再重新加载到开发板上,而nfs就是在服务器端对文件进行更改,开发板中的信息也会随之改变。而被传输的uboot、linux内核、设备树和根文件系统可以存放在sd卡或者emmc中,又因为emmc属于外部存储器,他在开发板断电后不会丢失信息,所以我们应当将需要移植的东西都放在开发板的emmc中,再使每次上电开发板都是从emmc里去读取所需要的东西,这样我们就将linux移植到了开发板上。
这篇文章只是大概介绍了一下系统移植的步骤,具体操作需要根据不同的开发板配置许多东西,做个参考即可。