邮箱:zhuimengcanyang@163.com 痴爱嵌入式技术的蜗牛
分类: 嵌入式
2016-12-11 20:52:45
1. 从flash上把内核读入内存
1.1 能读flash
1.2 初始化内存,初始化时钟,关看门狗等等
1.3 ......
2. 启动内核
2.1 设置参数,在某个约定的地址设置好参数
2.2 跳转执行
CPU看到的0地址是Nor的0地址,CPU直接将NOR中的u-boot代码复制到SDRAM中。
当上电启动时,硬件会自动将NAND前4K的内容复制到板子内部的SRAM中。
这时CPU看到的0地址为片内SRAM的起始地址,在这4K的程序中,将U-BOOT代码
拷贝到SDRAM中。
这是由它的读写接口决定的。因为NAND没法像内存一样直接读写,在启动的时候要执行u-boot程序,
但是这个时候u-boot程序存储在NAND中,而且NAND也没有初始化接口,没法直接读取NAND中的u-boot程序,
所以必须要借助SRAM,通过硬件自动将前4K的代码复制到SRAM,这样程序才能执行下去。
而对于NOR来说,不存在这样的难题,因为NOR的接口就是内存接口,可以直接读取里面的代码来执行。
位置无关码必须具有位置无关的跳转,位置无关的常量访问等特点,不能访问静态变量,都是相对PC的偏移量
来进行函数的跳转或者常量的访问。
在ARM体系中,使用相对跳转指令b/bl实现程序跳转。指令中所跳转的目标地址用基于当前PC的偏移量来表示,
与链接时分配给地址标号的绝对地址值无关,因而代码可以在任何位置正确的跳转,实现位置无关性。
注意:当前PC的值和运行地址是有差别的。当前PC和加载地址相关,而运行地址是链接文件中指定的地址。
使用ldr伪指令将一个函数标号读取到PC,可以实现位置无关的常量访问。例如:
ldr r0, =WATCHDOG
如果使用ldr伪指令将一个函数标号读取到PC,这是一条与位置有关的跳转指令,执行的结果是跳转到函数的运行地址处。
问题:
在启动代码中,还没有初始化内存控制器之前,应该是不能用内存的。而在这之前就是使用ldr伪指令,问题就是:
这个伪指令,如果后面的地址不能用立即数表示,要存在某个地址,而该地址在内存中,而这个时候内核还没初始化,这不是
有问题吗?
ldr后面如果有"="+一个立即数,则表示是伪指令,如果给定的值WATCHDOG,用立即数可以表示出来,则直接利用mov指令表示
mov r0, #WATCHDOG
如果用立即数表示不出来,则将该数据存储在内存的某个地址处,利用ldr读内存指令,将内存中的该数据读取到r0中。
ldr r0, [pc, #152] ; 33f800ac 将内存地址为33f800ac处的数据加载到 r0中,相当于r0 = WATCHDOG
......
33f800ac: WATCHDOG stcmi 0, cr0, [r0], {20}
是系统上电启动时,程序被加载到可直接执行的存储器的地址,也就是程序在RAM或者FLASH ROM中的地址。
因为有些存储介质只能用来储存数据而不能执行程序,比如SD卡和NAND FLASH等,必须把程序从这些存储介质加载到可以
执行的地址处。
就是程序在链接时确定的地址,比如如果在链接文件xxx.lds中指定了程序的运行地址为0x30000000,那么链接器
在为变量,函数等分配地址的时候就会以0x30000000作为参考。当加载程序和运行地址不相等时,必须使用位置无关码把
程序代码从它的加载地址拷贝搬运到运行地址,然使用"ldr pc, =main"指令跳转到运行地址处执行。
ICACHE: 指令cache,可以在u-boot中开启,这样CPU就可以不用跑去SDRAM读指令了,可以直接从ICACHE中读取指令。
DCACHE: 数据cache,必须开启了MMU功能,才能开启DCACHE。
浅谈Cache和MMU:
ARM-I/Dcache, MMU关系:
http://blog.csdn.net/jijiagang/article/details/8913459