本文分析 4412 的 uboot 源码,结合 uboot 源码来分析 uboot 完成了哪些工作。分析的源码文件是“cpu/arm_cortexa9/start.S”文件。
1 源码分析
.globl _start :globl 类似 C 语言中的 Extern,类似定义一个全局函数_start,外部可以访问_start,_start 是整个 uboot 的入口,第一行代码就是从这里开始执行的。
_start: b reset :_start:表示进入到“全局函数”_start 的主体结构; b reset 表示跳到 reset。类似 c 语言中的 goto reset,跳转到 reset。_start 中在正常启动的时候只运行一条语句“b reset”,就跳转到 reset,剩余部分不会执行。
_start“全局函数”剩下的部分,在出现异常情况下,它会强制跳到异常处理代码中。
ldr pc, _undefined_instruction //“未定义指令”的时候,系统所要去执行的代码。
ldr pc, _software_interrupt //软件中断
ldr pc, _prefetch_abort //预取指错误
ldr pc, _data_abort //数据错误
ldr pc, _not_used //未定义
ldr pc, _irq //(普通)中断
ldr pc, _fiq //快速中断
以下代码是异常向量地址。
下面的代码表示接下来的代码,都要 16 字节对齐,不足之处,用 0xdeadbeef 填充
接着看一下 reset 主体部分,将其中#if 0 等无关部分去掉,有效代码如下所示。
可以先直接看注释,不具体看每一行汇编的含义。
将 CPU 设置为 SVC32 模式。
cache 初始化和关闭。
关闭 TLBs,和 icache。
关闭 MMU 和 caches。
大家可能对以上名词比较陌生,事实上不理解这部分,并不影响我们移植新的 uboot,只需要将这部分和新的 uboot 这部分对比,有不同的地方修改下就成。
4412 开发板,使用的处理器是 Exynos 4412,它是采用 arm v7 指令集(体系结构),cortex a9 架构(CPU 核心内构),关于 cache、MMU 和 TLBs 等概念,在 4412 的datasheet 中是没有描述。如果大家感兴趣,可以在 ARM 官网中搜索文档。
arm 官网网址:
https://developer.arm.com/
作者下载了 A9 架构“DDI0388I_cortex_a9_r4p1_trm.pdf”的文档,这个文档中有关于这几个寄存器详细介绍,如果大家非常感兴趣,可以读一读。
在移植新的 uboot 时,这部分只需要将代码 copy 过去即可,更多的情况是,uboot 新版的源码中自带这部分源码。
这里给大家简要介绍下上面的几个重要名词概念。
3.2.2 ARM 的协处理器
作者将介绍前面涉及到的寄存器(SVC32、MMU 和 iCACHE 等寄存器),对应的 ARM官方英文文档来来回回看了好多遍,发现“协处理器”这个翻译让人很困惑。
“协助处理器”在网上有人这么描述“协处理器是一种芯片,用于减轻系统微处理器的特定处理任务。”
关于 ARM 处理器的协处理器,有这样定义的“协处理器可以附属于 ARM 处理器。一个协处理器通过扩展指令集或提供配置寄存器来扩展内核处理功能。一个或多个协处理器可以通
过协处理器接口与 ARM 内核相连。”
如果定义“协处理器”为一般用来指辅助 CPU 的芯片,这样独立显卡中的芯片也可以称为协处理器。如果使用“协处理器可以附属 ARM...”,那么 4412 中的硬件解码、3D 图形处理等也可以称为协处理器。
作者觉得还是要看 ARM 官网文档是如何描述这部分内容,如下图所示。
上面红色框中,第一行翻译为“系统控制协处理器”,我觉得用“系统控制协处理器”还是容易理解,可以接收。它包含了 15 个特殊的寄存器,主要提供“所有的系统控制和配置”、“MMC 控制和管理”、“cache 控制和管理”和“系统性能监控”功能。
在 ARM 的汇编代码中,凡是看到“mrc”和“mcr”指令,就表明接下来有一小段代码用来控制协处理器(后面全部简称为协处理器)。具体的含义,可以通过注释了解下,如果特别感兴趣,可以看下关于文档,里面对每一 bit 的作用都有详细的描述。
3.2.3 SVC32 模式
在协处理器操作中,首先是将系统设置为 SVC32 工作模式,ARM 系统有 7 种工作模式:
除了用户模式之外的其他 6 种处理器模式称为特权模式,特权模式下,程序可以访问所有的系统资源,也可以任意地进行处理器模式的切换。特权模式中,除系统模式外,其他 5 种模式又称为异常模式。大多数的用户程序运行在用户模式下,此时,应用程序不能够访问一些受操作系统保护的系统资源,应用程序也不能直接进行处理器模式的切换。用户模式下,当需要进行处理器模式切换时,应用程序可以产生异常处理,在异常处理中进行处理器模式的切换。
svc 模式是特权模式,可以访问受限制的资源,它和 sys 模式所用的寄存器组是一样的,但是 svc 模式下的一些资源是 sys 模式不能访问的。
uboot 要完成初始化硬件的工作,最终目标是启动 kernel,在 uboot 跳转到 kernel 之前,MPU 需要设置为 svc 模式。
结合在 uboot 完成初始化硬件和引导内核的功能来分析,在 uboot 初始化阶段就应该将uboot 设置为 svc 模式。
3.3.4 MMU 内存管理单元
在协处理器中,最重要的是内存管理单元。它是一种负责处理*处理器的内存访问请求的计算机硬件。它的功能包括虚拟地址到物理地址的转换(即虚拟内存管理)、内存保护、*处理器高速缓存的控制。
如果学习过驱动教程,会了解到在内核源码中,操作 GPIO 的时候,操作的是虚拟地址,而不是物理地址。MMU 是物理地址和虚拟地址转化的控制单元。
cache 是高速缓存,cpu 的处理速度越来越快,假如 CPU 直接和内存通信,内存的速度仍然达不到要求,CPU 要通过高速缓存来和内存通信,高速缓存的速度比内存要快。
TLB 是用于链接 cache 和内存,mmu 用于链接内存和物理地址。
这里我们需要理解的是,在系统启动过程中,cpu 和内存之间要完成通信,首先需要 TLB实现 cache 和内存之间的地址映射,通过 mmu 实现虚拟地址和物理地址之间的映射。
如果不将 mmu、TLB 以及 cache 关闭,cpu 可能会直接去 cache 取值,这个时候内存和 cache 之间可能还无法正常通信,可能导致 cpu 读取数据出现错误。
关于协处理器就介绍完毕了,涉及到的汇编指令,这部分建议只通过附录来了解一下。我们要尽快掌握全貌,不能陷入到某一个概念中,而且这部分也不影响最终目标--uboot 的移植。