《uboot教程 Exynos4412》-第3章-汇编之源码分析

在第一章中,介绍了Exynos4412的iROM、启动方式、源码组成等;在第二章中,介绍
uboot 编译等。经过前面对编译的详细分析,了解到 uboot 源码中有如下几个文件是很是重
要的:
“cpu/ARM_cortexa9/start.S”
“board/samsung/smdkc210/lowlevel_init_SCP.S 或者 lowlevel_init_POP.S”
“include/configs/itop_4412_android.h 或者 itop_4412_ubuntu.h”
其中“cpu/arm_cortexa9/start.S”是 uboot 代码入口文件,分析 uboot 通常是从
“start.S”文件开始,“lowlevel_init_SCP.S”文件是内存初始化、时钟初始化和串口初始化
等的文件,start.S 文件在运行过程当中会跳到这个文件中。
“itop_4412_android.h 或者 itop_4412_ubuntu.h”文件是重要的配置头文件,里面的
宏配置,会影响以上文件如何编译和运行,包括在下一章节中 uboot 源码的 C 语言部分,很
多代码编译和运行都会受到这个头文件的影响。
本章主要内容是,从“start.S”文件开始分析全部汇编代码,截止于 uboot 开始执行 C
代码。其中涉及到不少不经常使用概念,须要咱们去了解和掌握;涉及到汇编语法,须要咱们去了
解。
3.1 分析 uboot 汇编源码必要的知识和学习方法汇总
本小节,结合 datasheet 介绍 4412 的物理地址概念,这部分和单片机中相似;介绍汇编
语法如何学习以及要掌握到什么程度;汇编部分调试方法。
3.1.1 4412 的物理地址和虚拟地址介绍
若是用户学习过迅为的 linux 驱动教程,其中有一期,专门介绍物理地址和虚拟地址的概
念。几乎在全部现代操做系统中,物理地址都是经过 MMU(内存管理单元)映射为虚拟地
址。可是在 uboot 汇编部分,仍是直接操做物理地址的。
物理地址的概念。
MPU 地址总线传来的地址,由硬件电路控制其具体含义。物理地址中很大一部分是留给
内存条中的内存的。物理地址空间,一部分给内存用,一部分给总线用,这是由硬件设计来决
定的,所以在 32 bits 地址线的处理器中,物理地址空间是 2 的 32 次方,即 4GB,但物理
RAM 通常不能上到 4GB,由于还有一部分要给总线用(总线上还挂着别的许多设备)。
对于有单片机基础的用户来讲,物理地址仍是比较好理解,例如在 51 单片机中,P0.0 表
示小灯的输出寄存器,给这个寄存器写 1 小灯灭,写 0 小灯亮,寄存器 P0.0 的地址就是物理
地址。php

P0 = 0xfe;//小灯亮html

P0 = 0xff;//小灯灭linux

P0 在 51 寄存器头文件中,有一个宏定义它的实际地址,也就是物理地址。android

在 4412 中,物理地址太多了,根本没有办法所有介绍,2000 多页的 datasheet 中大部
分都是介绍寄存器,一个一个介绍是没法实现的。可是咱们有必要掌握和理解其中的寄存器框
架和典型寄存器。
在 4412datasheet 第三章“Memory Map”中,以下图所示,这是 4412 所有基地址的描述。
 
注意上表中,0x4000_0000~0xA000_0000,0xA000_0000~0x0000_0000 这两个地址
区间,这两个区间是 DMC 内存控制器的寻址地址,也就是内存的物理地址。实际上 4412 最
大支持的内存能够达到 3G,32 位处理器理论上能够支持 2 的 32 次方(最大 4G),如上表
所示,其中 1G 的地址给了 iROM、iRAM 等等这些 MPU 内部寄存器使用,因此 32 位 MPU
是不可能达到 4G 内存的。
现代操做系统广泛采用虚拟内存管理(Virtual Memory Management)机制,这须要
MMU(Memory Management Unit)的支持。MMU 一般是 CPU 的一部分,若是处理器
没有 MMU,或者有 MMU 但没有启用,CPU 执行单元发出的内存地址将直接传到芯片引脚
上,被内存芯片(物理内存)接收,这称为物理地址(Physical Address),若是处理器启用
了 MMU,CPU 执行单元发出的内存地址将被 MMU 截获,从 CPU 到 MMU 的地址称为虚拟
地址(Virtual Address),而 MMU 将这个地址翻译成另外一个地址发到 CPU 芯片的外部地址
引脚上,也就是将虚拟地址映射成物理地址。经过内存管理单元,能够实现 4G 的虚拟内存。
在 uboot 代码中,须要屡次用到以上地址的概念,其中内存管理单元被开启或者关闭,
因此有必要先介绍一下这几个地址的概念。
3.1.2 关于汇编语法
若是学习过单片机课程,会发现大部分都是使用 C 语言去编码,汇编使用的很是少了。
那么还有必要去学习汇编么?实际上是没有必要的,由于在 uboot 中汇编代码量很是少,以
4412 的 uboot 源码为例,其中有效的汇编代码不足 200 行,咱们根本不须要为了读懂 200
行代码专门去学习一门编程语言。
做者这里建议,首先咱们的目标是必定要把这些代码读明白,若是不明白会影响后面 C
代码的阅读,以及 uboot 的移植;其次,咱们要弄清楚每一行有效汇编代码的语法。
如今咱们已经知道汇编是从“cpu/arm_cortexa9/start.S”这个文件开始执行,那么咱们
就从第一行代码的语法开始学习,代码执行到或者跳到哪一行,咱们就学习这一行代码的语
法。
在手册的附录部分,咱们会依次介绍汇编代码中出现的语法,你们也能够经过互联网学习
每一行执行的汇编语法。
3.1.3 uboot 汇编代码初始化串口以前的简易调试方法
在前面教程中咱们介绍过,从 A9 开始,开发板通常都不配 jtag,jtag 价格昂贵,在 A9
以前,因为引导程序 uboot 必须经过 jtag 来烧写,可是在 A9 处理器上,大部分都是支持 tf
卡引导,这样能够免去 jtag 的费用,烧写变的简单高效。
那么没有 jtag,对于 uboot 的调试,咱们无法单步调试,若是有一行代码咱们不是很确
定到底执行了没,或者跳到哪一行。若是代码已经执行到串口初始化阶段,固然是能够经过串
口打印字符来实现,在串口初始化以前,其实能够经过控制 LED 灯来跟踪代码。
如下是开发板上两个小灯控制的代码,能够将小灯点亮。
点亮 LED2 灯:ldr r0, =0x11000104 /* GPL2(0) */
ldr r1, =0x00000001 /* GPL2(0 output high) */
str r1, [r0]
ldr r0, =0x11000100 /* GPL2(0) */
ldr r1, =0x00000001 /* GPL2(0 output high) */
str r1, [r0]
点亮 LED3:
ldr r0, =0x11000060
ldr r1, =0x00000010
str r1, [r0]
ldr r0, =0x11000064
ldr r1, =0x00000002
str r1, [r0]
这里简单介绍下这几行汇编代码的含义。
ldr r0, =0x11000104
ldr 是将 0x11000104 值赋给 r0 寄存器。这个值地址为 GPL2DAT。
ldr r1, =0x00000001
ldr 是取 0x11000104 地址的值赋给 r1 寄存器。
str r1, [r0]
str 是将 r1 的值写入到 r0 数值对应物理地址寄存器中。将 0x00000001 写入到
0x11000104 地址寄存器中,0x11000104 地址是 GPL2DAT 寄存器。
ldr r0, =0x11000100 /* GPL2(0) */
ldr r1, =0x00000001 /* GPL2(0 output high) */
str r1, [r0]
将 0x00000001 写入到 0x11000100 地址寄存器中,0x11000100 地址是 GPL2CON 寄
存器。执行这两步就能够将 LED2 点亮。
点亮 LED3 和点亮 LED2 相似。
在串口初始化以前能够经过点灯来实现调试,串口初始化以后能够经过打印字符来跟踪调
试代码。编程

相关文章
相关标签/搜索