在进行 Linux 驱动开发之前肯定需要先将

Linux 系统移植到开发板上去。如果学习过 UCOS/FreeRTOS 应该知道,UCOS/FreeRTOS 移植

就是在官方的 SDK 包里面找一个和自己所使用的芯片一样的工程编译一下,然后下载到开发

板就可以了。那么 Linux 的移植是不是也是这样的,下载 Linux 源码,然后找个和我们所使用

的芯片一样的工程编译一下就可以了?很明显不是的!Linux 的移植要复杂的多,在移植 Linux

之前我们需要先移植一个 bootloader 代码,这个 bootloader 代码用于启动 Linux 内核,bootloader

有很多,常用的就是 U-Boot。移植好 U-Boot 以后再移植 Linux 内核,移植完 Linux 内核以后

Linux 还不能正常启动,还需要再移植一个根文件系统(rootfs),根文件系统里面包含了一些最

常用的命令和文件。所以 U-Boot、Linux kernel 和 rootfs 这三者一起构成了一个完整的 Linux 系

统,一个可以正常使用、功能完善的 Linux 系统。在本篇我们就来讲解 U-Boot、Linux Kernel 和

rootfs 的移植,与其说是“移植”,倒不如说是“适配”,因为大部分的移植工作都由 NXP 完成

了,我们这里所谓的“移植”主要是使其能够在 I.MX6U-ALPHA 开发板上跑起来。

Linux 系统要启动就必须需要一个 bootloader 程序,也就说芯片上电以后先运行一段

bootloader程序。这段bootloader程序会先初始化DDR等外设,然后将Linux内核从flash(NAND,

NOR FLASH,SD,MMC 等)拷贝到 DDR 中,最后启动 Linux 内核。当然了,bootloader 的实

际工作要复杂的多,但是它最主要的工作就是启动 Linux 内核,bootloader 和 Linux 内核的关系

就跟 PC 上的 BIOS 和 Windows 的关系一样,bootloader 就相当于 BIOS。所以我们要先搞定

bootloader,很庆幸,有很多现成的 bootloader 软件可以使用,比如 U-Boot、vivi、RedBoot 等

等,其中以 U-Boot 使用最为广泛,为了方便书写,本书会将 U-Boot 写为 uboot。


uboot 的全称是 Universal Boot Loader,uboot 是一个遵循 GPL 协议的开源软件,uboot 是一

个裸机代码,可以看作是一个裸机综合例程。现在的 uboot 已经支持液晶屏、网络、USB 等高

级功能。

图 30.1.3 中就是 uboot 原汁原味的源码文件,目前最新的版本是 2019.04。但是我们一般不

会直接用 uboot 官方的 U-Boot 源码的。uboot 官方的 uboot 源码是给半导体厂商准备的,半导

体厂商会下载 uboot 官方的 uboot 源码,然后将自家相应的芯片移植进去。也就是说半导体厂

商会自己维护一个版本的 uboot,这个版本的 uboot 相当于是他们定制的。既然是定制的,那么

肯定对自家的芯片支持会很全,虽然 uboot 官网的源码中一般也会支持他们的芯片,但是绝对

是没有半导体厂商自己维护的 uboot 全面。


操作系统bootloader是什么_linux系统

操作系统bootloader是什么_linux_02

操作系统bootloader是什么_bootloader_03

使用 chmod 命令给予 mx6ull_alientek_emmc.sh 文件可执行权限,然后就可以使用这个 shell

脚本文件来重新编译 uboot,命令如下:

./mx6ull_alientek_emmc.sh


操作系统bootloader是什么_linux_04

在图 30.4.1.2 中有很多的环境变量,比如 baudrate、board_name、board_rec、boot_fdt、bootcmd

等等。uboot 中的环境变量都是字符串,既然叫做环境变量,那么它的作用就和“变量”一样。也就是说,环境变量在系统中的作用,其实就是程序中的全局变量

比如 bootdelay 这个环境变量就表示 uboot 启动延时时间,默认 bootdelay=3,也就默认延时 3

秒。前面说的 3 秒倒计时就是由 bootdelay 定义的,如果将 bootdelay 改为 5 的话就会倒计时 5s

了。uboot 中的环境变量是可以修改的,有专门的命令来修改环境变量的值,稍后我们会讲解。


uboot 命令中的数字都是十六进制的!不是十进制的!


注意!只能在 uboot 中 ping 其他的机器,其他机器不能 ping uboot,因为 uboot 没有对 ping

命令做处理,如果用其他的机器 ping uboot 的话会失败!



nfs(Network File System)网络文件系统,通过 nfs 可以在计算机之间通过网络来分享资源,

比如我们将 linux 镜像和设备树文件放到 Ubuntu 中,然后在 uboot 中使用 nfs 命令将 Ubuntu 中

的 linux 镜像和设备树下载到开发板的 DRAM 中。这样做的目的是为了方便调试 linux 镜像和

设备树,也就是网络调试,通过网络调试是 Linux 开发中最常用的调试方法。原因是嵌入式 linux

开发不像单片机开发,可以直接通过 JLINK 或 STLink 等仿真器将代码直接烧写到单片机内部

的 flash 中,嵌入式 Linux 通常是烧写到 EMMC、NAND Flash、SPI Flash 等外置 flash 中,但是

嵌入式 Linux 开发也没有 MDK,IAR 这样的 IDE,更没有烧写算法,因此不可能通过点击一个

“download”按钮就将固件烧写到外部 flash 中。虽然半导体厂商一般都会提供一个烧写固件的

软件,但是这个软件使用起来比较复杂,这个烧写软件一般用于量产的。其远没有 MDK、IAR

的一键下载方便,在 Linux 内核调试阶段,如果用这个烧写软件的话将会非常浪费时间,而这

个时候网络调试的优势就显现出来了,可以通过网络将编译好的 linux 镜像和设备树文件下载
到 DRAM 中
,然后就可以直接运行


ftp 命令的作用和 nfs 命令一样,都是用于通过网络下载东西到 DRAM 中。


操作系统bootloader是什么_bootloader_05


因为uBoot存储在flash里,但是运行时候是全部加载到内存中运行的,所以运行时可以去修改flash里的uBoot镜像文件,重新启动板子,会重新从flash加载到内存中运行,因此修改生效。

如果说只是部分加载到内存中运行(内存比较小),此时运行时修改了flash中的镜像文件,那么可能运行时,就会崩掉,因为在内存和外层代码置换的时候,就找到错误代码了,所以运行出错。


千万不要写 SD 卡或者 EMMC 的前两个块(扇区),里面保存着分区表!每个分区内可以放一个文件系统。


要想动态烧录Linux系统,那当然得加载到RAM里面去(而且不能和自己(uBoot)地址冲突,不然把自己干崩了),因为这样就可以动态切换pc指针过去运行了。如果加载到flash里去,flash是无法直接运行代码的(运行速度太慢),还得由uBoot加载到内存中运行。

操作系统bootloader是什么_环境变量_06