我们在学习或移植嵌入式 Linux 系统的时候都会接触到 Uboot 驱动移植和 Linux 驱动开发,此时对于嵌入式 Linux 初学者来说不免会有疑问,例如:
Uboot 已经有相关芯片平台以及外部硬件设备的驱动程序,为什么 Linux 内核还要还要集成驱动,下面来解释一下。
Uboot 是开源的引导加载程序中的一种,无论是哪种导加载程序其核心工作职责都是启动嵌入式系统(比如就 Linux 内核),所以 Uboot 需要从 FLASH,MMC 等非易失性存储器中读取出 Linux 内核并搬移内核到 DDR 或 RAM 等易失性存储器中去执行。
既然 Uboot 需要从非易失性存储器中读取并搬移 Linux 内核,那么 Uboot 本身就需要先将非易失性存储器(比如 MMC),以及内存(比如 DDR)驱动起来。
以上只是其中一个场景,例如 Uboot 还提供 USB 以及网络通信功能,可以方便后续程序下载与调试。比如使用 USB,或通过网络可以使用 NFS 文件系统,TFTP 服务下载 Linux 内核镜像。
还有比如 Uboot 支持命令交互,但需要利用处理器串口 Uart 和电脑端的终端模拟器通信,才能在模拟终端中输入输出命令,所以 Uboot 还要能够驱动 Uart 。
由于 Uboot 最终工作在某种具体的芯片上,所以以上驱动必须遵循这种芯片的规则去编写。例如 Uboot 运行在全志 sunxi 系列芯片上,那么 MMC 驱动必须按照全志 sunxi 系列芯片的寄存器规则去编写。例如 Uboot 包含了驱动 sunxi_mmc.c 并且标明了 “MMC driver for allwinner sunxi platform”。
Uboot 驱动只需满足引导加载 Linux 内核程序的需求,驱动通常较为简单。
Linux 属于操作系统内核,需要管理计算机上的各种硬件资源或从硬件设备上读取数据,所以 Linux 内核也需要能够驱动硬件的驱动程序。比如需要给用户提供画面显示,那么 Linux 内核就要能够驱动屏幕。比如需要给用户提供输入,那么 Linux 内核就需要能够驱动键盘,鼠标,麦克风,摄像头,U 盘等设备。要能播放音频,就需要能够驱动喇叭。
Linux 内核中的驱动程序并不是 Linux 内核独自使用的,除了自身使用 Linux 内核还需要将驱动提供给运行在系统中的其他应用程序使用,所以对于 Linux 内核驱动还需要提供一组接口(打开,读,写,关闭)给应用程序调用。不仅如此为了更好的分离驱动程序 Linux 内核还需要更加复杂的驱动框架。
Linux 驱动需满足硬件资源的管理,以及要给应用程序提供用户级别的硬件操作接口,驱动通常较为复杂。
回到开头提出的问题:Uboot 已经有相关芯片平台以及外部硬件设备的驱动程序,为什么 Linux 内核还要还要集成驱动,还要使用设备树管理驱动。
举个例子,比如 Uboot 已经驱动了 MMC,但是 Linux 内核还是需要自己去驱动 MMC,这是为什么?这是因为根文件系统 rootfs 也位于 MMC,所以 Linux 内核要从 MMC 挂载根文件系统就必须能够访问 MMC,所以需要 MMC 驱动。
你可能又有疑问,为什么 Linux 内核不使用 Uboot 的 MMC 驱动?
主要有以下三点原因:
(1) 在 Uboot 的工作阶段,MMC 的驱动是按照 Uboot 裸机规则去实现的,属于纯裸机驱动,所以 Linux 内核无法识别 Uboot 的 MMC 驱动。
(2) 即使 Linux 内核可以识别 Uboot 的驱动,Linux 内核被 Uboot 加载到内存并触发运行的那一刻起,Uboot 的职责就结束了,Uboot 包含的所有程序不再运行。所以自然 Uboot 的驱动程序就无法使用了,最终计算机所有的硬件都需要由 Linux 内核控制。
(3) Uboot 的裸机驱动是在程序中写死的,使用起来不灵活,管理硬件设备不方便,不能支持驱动独立安装或卸载。
特例:
前面说到 Uboot 需要使用 DDR(双数据速率存储器)所以 DDR 通常在 Uboot 中就已被初始化,Linux 内核启动后无需再次驱动 DDR,而是使用 Uboot 传递过来的 DDR 配置信息去读写 DDR。
所以对于 DDR 驱动来说是一个特例,Linux 启动后 Linux 内核本身就处于 DDR 中,所以 Linux 内核不能重新初始化 DDR,否则会导致 Linux 内核丢失,所以 Linux 内核必须使用 Uboot 提供的 DDR 驱动。
DDR在 Uboot 中初始化成功,在内核启动过程中,内核会读取 Uboot 传递的 DDR 配置信息,并使用这些信息来正确地配置内存控制器和 DDR。
DDR 属于系统级硬件资源,不需要给应用程序开放,没有灵活性要求,所以 Linux 内核直接使用 Uboot 提供的 DDR 配置也没有太大影响。
Uboot 属于裸机程序,将 Uboot 程序下载到芯片运行只能依赖 STLink,SWD 等调试工具,或者借助半导体芯片厂商固化在芯片的 USB 传输程序。
在 Uboot 驱动的支持下 Linux 内核程序下载到芯片的方式更多,比如可以通过串口,USB,以太网络,SD 卡或 U 盘,甚至无线网络,并且 Linux 内核需要由 Uboot 将其加载到内存才能启动运行。