01 系统移植概述
系统移植概述
所谓Linux系统的移植,就是让Linux在自己的嵌入式板子上跑起来。但是不像STM32上移植个FreeRTOS那么简单,移植Linux还是挺复杂的,不仅包含了OS本身,还要移植bootloader和rootfs
为了让Linux系统能够运行,只需保证组成Linux最小系统的那些部分都被移植了就行了,具体地,包括以下几点(具体作用见另一个文档):
- BootLoader:常见的有U-Boot,本质上就是一个裸机程序,用于初始化一些外设,然后将Linux内核从Flash拷贝到DDR启动,内核启动后U-Boot就结束运行了。就相当于PC上的BIOS
- Linux内核:这里需要的不是Linux内核源码,而是编译好的内核镜像
- 根文件系统:一个目录,包含了Linux运行必备的一些文件和程序
只要移植了这3部分,那么一个基础的Linux系统就能跑起来了,而Ubuntu那些的Linux发行版也包含了这几部分,并进行了一定的扩充。
各种配置文件
在编译移植完的uboot、内核、根文件系统时,大致流程都是:
- 1.加载适配此板子的默认(default)配置文件:
make xxx_defconfig
,在根目录生成.config
配置文件 - 2.(可选)在根目录进行图形化配置:
make menuconfig
,对.config
配置文件进一步更改 - 3.交叉编译,顶层Makfile会读取
.config
文件,进行条件编译 - 4.(可选)保存当前的配置文件,方便后续复用
由此我们可以看出,裁剪、移植的成功与否,关键在于能否得到一个正确的
.config
配置文件
下面介绍一下在移植的过程中会看到的各种配置文件:
xxx_defconfig
:特定板子的配置文件模板,用于为特定的开发板或平台提供一套预定义的编译选项,该文件中只包含了不同于默认配置参数的选项,而不像.config
包含了全部配置参数.config
:在编译前的最终配置文件,包含了系统的所有配置选项和参数,它是编译过程中被直接读取的文件Kconfig
:定义了配置菜单和选项的层次结构,用于配置系统的menuconfig
或其他图形化配置工具
配置文件中的依赖关系
Kconfig定义的图形化配置,各个选项可能是树状的,包含了依赖关系,而在
.config
文件中,却都是扁平的
尽管 .config
文件是平面的,但配置项之间的依赖关系仍然会在生成 .config
文件时处理。例如,如果 CONFIG_NET
被禁用,那么依赖于它的 CONFIG_ETHERNET
和 CONFIG_WIRELESS
选项也会被自动禁用,如下:
1 | CONFIG_NET=n |
如何获得配置文件模板
- 方法1:在得到了最终的
.config
文件后,通过make savedefconfig
可以在根目录生成一个defconfig
文件,就是我们要的配置文件模板,后面把它放到对应位置并重命名就行了 - 方法2:直接找一个现有的
xxx_defconfig
文件,在他的基础上改
移植前的准备工作
在移植uboot、kernel、nfs前,需要在宿主机上安装一些必要的服务,比如:tftp、nfs,并需要正确的配置,这部分可以看正点原子的文档
BootLoader的移植
移植步骤
以U-Boot为例,移植大概分为以下几步:
1.下载U-Boot的源码到虚拟机中
2.利用适配自己板子的配置文件对U-Boot进行交叉编译
uboot源码的configs目录中有许多
xxx_deconfig
文件,就是预配置文件,uboot官方会对许多芯片原厂做的开发板写一些demo,到自己的板子可能需要再修改一下才能用,修改有多种方式,可以直接改源码,也有图形化的界面可以用
3.将U-Boot==烧写到SD卡等存设备==中并插到开发板上
4.开发板的boot设置从SD卡启动,此时上电开发板,其将自动运行U-Boot
5.PC上打开串口工具,即可通过命令行使用U-Boot了
Linux内核的移植
移植步骤
1.下载内核源码到虚拟机
这里我们不是去Linux官网下源码,而是去芯片原厂下源码。芯片原厂一般才会去Linux官网下载源码,他们会将Linux内核源码进行修改以适配自己的CPU并发布
2.利用适配自己板子的配置文件对Linux内核进行交叉编译(编译时也会打开一个图形界面,可以在图形界面中手动配置)
3.编译成功后会得到Linux内核镜像文件(叫zImage
)和一堆设备树文件(.dtb
)
4.将zImage
和设备树文件放到网络文件系统中,或者将其下载到外部flash中
5.在U-boot中使用tftp
协议将zImage
和设备树文件从板子的外部存储介质(flash或者nfs)中下载到内存中的指定地址去
对于I.MX6ULL,zImage放到内存地址0x80800000,设备树文件放到内存地址0x83000000,其实也不是必须的,可以改成别的
6.在U-boot中,使用bootz
命令从内存中的指定地址启动Linux内核,就可以进入到Linux系统中了
1 | bootz <kernel_addr> [<ramdisk_addr> <fdt_addr>] |
<kernel_addr>
:指定内核镜像在内存中的加载地址(此处为0x80800000)<ramdisk_addr>
:可选参数,指定 RAM Disk 的加载地址。如果没有 RAM Disk,则可以省略此参数<fdt_addr>
:指定设备树文件在内存中的加载地址(此处为0x83000000)
根文件系统的移植
移植步骤
1.下载Busy Box
的源码到虚拟机
2.在虚拟机的nfs服务器的目录中创建根文件系统的目录rootfs
(一般做Linux驱动开发时,都是通过nfs挂载根文件系统的,在最终版时才将根文件系统烧到flash中)
3.修改busy box
的源码,接触其对中文显示的限制
4.对busy box
进行配置,并进行交叉编译(可以通过修改配置文件的方式或者图形化界面的方式配置)
5.将编译的结果放到nfs的根文件系统目录rootfs
中去
此时
rootfs
中只有bin、sbin、usr这3个目录,还需添加一些目录才能使用
6.向根文件系统添加lib
库目录(本质上就是将交叉编译器中的一些库文件复制到这个目录中,所谓剪裁就是人为决定复制哪些库,不剪裁的话就把所有库都复制进去)
7.向根文件系统添加usr/lib
库目录(本质上就是将交叉编译器中的一些库文件复制到这个目录)
8.创建其他文件夹,如dev、proc、mnt、sys、tmp和root等
9.创建/etc/init.d/rcS
文件:这是一个shell脚本,用于开机时自动启动一些程序
10.创建/etc/fstab
文件:其在Linux启动后自动配置需要挂载的一些分区
11.创建/etc/inittab
文件:init程序会读取该文件,其中包含了一些控制指令
12.U-Boot中设置使用nfs挂载的根文件系统为系统的根文件系统
Linux系统的烧写
在移植并测试完上述几部分(uboot、Linux内核镜像、设备树、根文件系统)后,在产品发布前,需要将这几部分烧写到板载的FLASH(EMMC、NAND FLASH之类的)上,而不是一直使用SD卡 + nfs挂载的根文件系统。