经过前面十篇博文,咱们已经完成了对BL1阶段的分析,经过这些分析相信咱们对u-boot已经有了一个比较深刻的认识,在BL2阶段大部分是对外设的初始化,而且有的咱们已经分析过,在这篇博文我打算对BL1阶段没有分析到的重要外设进行简单分析,并结束对u-boot的分析,同时对后面本身的博文进行简单的规划,但愿有兴趣的朋友跟我一块学习和研究嵌入式。程序员
今天咱们会分析到如下内容:学习
1. MMU分析(内容出自我之前的博客)spa
2. 裸机开发总结调试
3. 后期学习规划orm
1. MMU做用接口
MMU就是负责虚拟地址(virtual address)转化成物理地址(physical address)。内存
2. 基本概念ci
下面我来讲一下ARM CPU上的地址转换过程涉及三个概念:虚拟地址(VA)(CPU内核对外发出VA),变换后的虚拟地址(MVA)(VA被转换为MVA供cache和MMU使用,在此将MVA转换为PA),物理地址(PA)(最后使用PA读写实际设备)。
1. CPU看到的用到的只是VA,CPU无论VA最终是怎样到PA的。
2. cache、MMU也是看不到VA的,它们使用的是MVA(VA到MVA的转换是由硬件自动完成的)。
3. 实际设备看不到VA、MVA,读写设备使用的是PA物理地址。
3. 如何地址转换
在此过程当中要用到如下两个必备的东西:
1. cp15协处理器的c2寄存器(这个里面的东西须要程序员本身装载)
2. 虚拟地址MVA。
接下来我说如下mmu对虚拟地址到物理地址的转化过程。
1. 不管进行那种有效转换都必须进行一级页表的转换,因此咱们先去产生一级页表。产生一级页表通过如下步骤
a) 由协处理器CP15中的寄存器C2(高18位,即[31:14]为转换表基地址,低14位为0)为一级转换表基地址,即TTB该地址指向了一个2^14=16KB大小的存储区,即一级转换表。
b) 将MVA的高12位,即位[31:20]做为一级转换表的地址索引,所以一级转换表具备2^12=4096项,这4096项的地址为32位,最高的18位[31:14]为寄存器C2的高18位,中间12位为MVA的高12位[31:20],最低2位为0b00。这4096项中的内容称为一级描述符。至此一级页表产生完毕。
2. mmu拿到一级描述符首先看它的后两位也就是bits[1:0],根据这两位的取值mmu会进入不一样的转换模式,这两位会出现下面四种取值。其中这四种取值分别对应四种模式,下面我一一解释。
a) 00 无效不进行转换
b) 01 进行粗页式转换
c) 10 进行段式转换
d) 11 进行细页式转换
3. 接下来对于不一样的转换模式,就要进行不一样的转换。我下面将对三种转换模式进行一一分析。
a) 0b10(段式转换),把段式转换放在第一个说的缘由是在ARM中大量用到了段式和细页式转换。
段式转换是最简单的一种转换方式,它是将咱们刚才产生的一级描述符(即4096项中的内容)的高12位做为段的基地址,用MVA的低20位做为每一个段的偏移量,由此咱们能够轻松的推出每一个段的大小为2^20=1MB,至此咱们就获得了一个物理地址PA。
b) 0b11(细页式转换)
细页式转换,它是将咱们刚才产生的一级描述符的高20位bits[31:12],再加上MVA的bits[19:10](第二级表索引)合体,bits[1:0]补0,获取第二级描述符的地址,至此其一级转换结束,由于其二级转换方式和粗页式的二级转换方式相同因此我下面一块分析。
c) 0b01(粗页式转换)
粗页式转换,它是将咱们刚才产生的一级描述符的高22位bits[31:10],再加上MVA的bits[19:12](第二级表索引)合体,最后两位补0,获取第二级描述符的地址(32位),至此其一级转换结束。
4. 下面咱们将进入二级转换,对于二级转换只针对细页式和粗页式,没有段式转换。
a) 通过一级转换咱们获得了二级描述符的地址,咱们经过此地址能够获得二级描述符,咱们根据二级描述符的低两位bits[1:0]一样能够分为四种转换模式:
i. 00 无效不进行转换
ii. 01 大页描述符
iii. 10 小页描述符
iv. 11 极小页描述符
b) 接下来我将对各个模式进行分析。
i. 01(大页描述符)
此时咱们取出二级描述符中的bits[31:16]——大页基址,它和MVA的bits[15:0]组成一个32位的物理地址,这就是MVA对应的PA。
ii. 10(小页描述符)
此时咱们取出二级描述符中的bits[31:12]与MVA的bits[11:0]组成一个32位的地址,这就是MVA对应的PA。
iii. 11(极小页描述符)
此时咱们取出二级描述符中的bits[31:10]与MVA的bits[9:0]组成一个32位的地址,这就是MVA对应的PA。
l 裸机开发总结
在前十篇博文中咱们分析了整个u-boot的工做流程,并对其中重要的代码和外设进行了分析,对于嵌入式的外设是至关多的,咱们要所有分析的话是不太现实的,因此咱们应该在学习中总结方法,下面我将本身对于裸机的方法跟你们进行分享,不足之处还望你们互相交流。
1) 熟悉外设大致工做原理,好比咱们在前几篇博文中首先分析的就是该外设的工做原理,这些工做原理以及运做方式大部分均可以在该外设的手册中找到相应的说明。
2) 从该外设的芯片手册中找到其控制方法,好比时序图,通讯方式等等可控制信息。
3) 从咱们使用的控制芯片中找到有没有专门为此外设提供的控制接口,好比咱们之前说到的内存控制器、串口控制器、nand控制器等。
4) 从控制芯片手册中找到其对该外设提供的控制方式,好比控制流程等信息。
5) 检查硬件链接方式,肯定管脚等信息
6) 根据从外设芯片获得的所须要的控制信息,配置咱们控制芯片所提供的控制信息,获得所需数据。
7) 根据6)获得的内容进行代码的编写。
8) 编译调试(这个过程能够用到串口、示波器、万用表、j-link等进行调试)
以上就是本身简单总结的外设裸机开发步骤,有不少不足之处,但愿各位提宝贵意见。
l 后期学习规划
经过对u-boot的分析,咱们对arm裸机的开发有了必定认识,在接下来我会去分析linux中的各类子系统、驱动模型等内容,整个过程必然很困难,本身只是进行简单的分析,有不足之处还请各位大神及时指导,让咱们向内核进军。