本帖最后由 _浮沉_ 于 2015-8-25 16:24 编辑
这几天在看《
ARM处理器裸机开发实践---机制而非策略》,这本书对于ARM的初学者来说是非常适合的,基础篇详尽介绍了ARM 汇编程序结构,C语言基础以及混合编程。提高篇一上来就是干货---分析启动代码,看的我简直如获珍宝,看了一遍又一遍,之后就是ARM各个模块逐一各个讲解击破。其他先不多说,这里主要分享几个在分析启动代码时所碰到的几个问题,希望大神不吝赐教。
书中讲到,上电后(Nand Flash启动)首先会在4K的Stepping Stone 中运行,直到运行到nand_boot_beg处,先是执行bl RdNF2SDRAM 完成将Nand Flash所有代码搬移到SDRAM(也就是内存中),然后再执行ldr pc, =copy_proc_beg 通过绝对地址跳转到 SDRAM(内存中)的标号 copy_proc_beg 去执行,copy_proc_beg 标号处代码的功能是将加载域代码搬移到运行域代码,而运行域就是0x30000000起始的一段内存,加载域就是存储代码的地方这里应当是Nand Flash。
所以基于此段描述有如下几个问题:
1. Stepping Stone 中的4KB代码是否会一直存在,跳转到内存执行之后发生异常时会跳到Stepping Stone的异常向量表 还是内存中的异常向量表,为什么?
2. 我理解从加载域到运行域的搬移就是:将代码从存储它的地方(Nand 或 Nor,起始地址都是0x0)搬移到可以较快执行它的地方(内存也就是SRAM,起始地址为0x30000000),不知道这样理解对不对?个人觉得这样理解还是很肤浅,没有领略到它的本质,希望大神解答。
3. Nand 启动跳转到内存之后会去执行 copy_proc_beg 处代码,其功能是将加载域搬移到运行域执行,但是之前
已经通过bl RdNF2SDRAM 将Nand 中所有代码复制到内存了,已经可以往下正常运行了为什么还要再将加载域搬到运行域?运行域不就是位于内存中0X30000000处开始的地方么(ADS1.2 中设置RO Base 为0x30000000)?这两个搬移的本质区别是什么?如果两个搬移都必不可少,目前Nand的所有代码已经被搬移到内存(包括实现从加载域到运行域的代码段),接下来从加载域到运行域的搬移不会覆盖现有的内存中的代码段吗?
4. 参考书中Nor Flash的启动过程,因为代码可以直接在Nor Flash中运行,所以它会直接在Nor Flash中的copy_proc_beg 标号处直接运行 ,实现代码从加载域到运行域的搬移工作,
之后会通过 b Main 跳转到Main函数中运行,执行到此处应该是已经到内存里执行了吧,但是b Main 是怎么实现从Nor Flash跳到内存中执行的?
5. 说这么多,我的困惑其实很简单,可执行代码一般存放于Flash中(掉电非易失,但不能直接运行代码或运行代码很慢),代码一般是在内存中执行的(内存运行速度快,读写速度快,但掉电易失)。这两者的结合使用才能构建一个可以正常启动的计算机系统,
在ARM中,存储代码的就是Nand 或 Nor,运行代码的就是SDRAM,怎样从前者过度到后者实现系统正常启动的过程就是我所关注的焦点,希望得到详尽分析。
参考Nor Flash的启动过程,Nand 启动之所以需要起步石就是因为 Nand不能运行程序,所以Nand启动时,起步石的作用其实跟Nor Flash的作用一样,但由于起步石只有4KB大小,不能存储全部的程序代码,所以将所有代码搬到内存中存储,这就是第一个搬移,这个搬移的作用就是为加载作准备,(想想加载的过程,将代码从存储的地方搬移到内存中运行,起步石根本就没有存储全部的程序代码怎么实现加载),其实这时候这块内存起只是存储的作用;接下来就是加载了,就是第二次搬移,相信已经很清楚了;但是有个问题就是,两次搬移不会互相影响吗?这点我也不能确定,但我想编译器肯定会避免这种情况吧。
个人理解,欢迎指正。
一周热门 更多>