关于启动代码中NANDFLASH启动相关代码的解释
来源:互联网 发布:淘宝贝幼儿园收费 编辑:程序博客网 时间:2024/04/28 01:34
[置顶] 原来程序是这样从NandFlash拷贝并跳转到SDRAM的
重新看了一下FL2440的BootLoader,终于把程序是怎样从Nandflash拷贝并跳转到SDRAM的过程弄清楚了,在这边做一下笔记。先上张图:
1.
当S3C2440被配置成从Nand Flash启动时, S3C2440的Nand Flash控制器会在 S3C2440上电时自动把NandFlash上的前4K代码搬移到Boot Internal SRAM,然后系统从起始地址是0x0000_0000的Boot Internal SRAM启动,在这4K代码中我们必须完成CPU的核心配置,把NandFlash上的代码全部拷贝到SDRAM中去,然后跳转到SDRAM中去执行剩余的代码(进入操作系统等等);
2.
这一步完成的是把NandFlash上的代码拷贝到SDRAM的过程:
(1)先判断是从nor启动还是从nand启动
ldr r0,=BWSCON
ldr r0,[r0]
ands r0,r0, #6 ;OM[1:0] != 0, NOR FLash boot
bne NORRoCopy ;don't read nand flash
adr r0,ResetEntry ;OM[1:0] == 0, NAND FLash boot // ADR 装载参照的地址=subr0,pc,#off_set;
cmp r0,#0 ;if use Multi-ice,//JTAG调试时是直接下载到SDRAM中运行,不需要再从nand拷贝
bne InitRamZero ;don't read nand flash for boot
注意哦,执行adr r0,ResetEntry 后,r0 = PC - off_set,adr得到是相对地址而不是绝对地址。ResetEntry是整个程序的入口处,由链接器指定入口地址,如下图,ResetEntry=RO Base=0x3001_0000即|Image$$RO$$Base|。当程序在SDRAM中运行时,当前PC=0x3001_0000+off_set,r0=0x3001_0000,当程序在Boot Internal SRAM运行时,由于程序是从0x0000_0000开始运行的,所以当前PC=0x0000_0000+off_set,即r0=0x0000_0000。所以可以通过 cmp r0,#0来判断程序是否运行在Boot Internal SRAM,如果是,则把NandFlash中的程序拷贝到SDRAM。
(2)从NandFlash拷贝程序到SDRAM
在这步中最让我困惑的是在SDRAM中从哪个地址开始存放从NandFlash拷过来的程序。
;===========================================================
;//将程序从nandflash拷贝到sdram
;===========================================================
nand_boot_beg
bl ClearSdram
mov r5,#NFCONF
;set timing value
ldr r0, =(7<<12)|(7<<8)|(7<<4)
str r0, [r5]
;enable control
ldr r0,=(0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0)
str r0,[r5, #4]
bl ReadNandID
mov r6,#0
ldr r0,=0xecF1
cmp r5, r0
beq %F1
; ldr r0,=0xecda
; cmp r5,r0
mov r6,#1 ;Nandaddr(寻址周期 0:4 1:5)
1
bl ReadNandStatus
mov r8,#0
ldr r9,=ResetEntry
mov r10,#32 ;+081010 feiling
上面代码中最关键的是这句:
ldr r9,=ResetEntry
其它都是一些NandFlash的相关设置与操作细节,先不管了。这据代码中用ldr来获得在SDRAM存放代码的起始地址,ldr将ResetEntry的绝对地址|Image$$RO$$Base|赋给了r9。也就是说,从NandFlash拷过来的代码放在了SDRAM中从|Image$$RO$$Base|开始的地址空间里。
3.
CPU配置完了,程序和数据也都拷到SDRAM里了,该跳转到SDRAM里去做其他事情了,怎么知道是否跳转到SDRAM呢?这还是地址啊。我之前一直搞不清楚为什么一句ldr pc,=CEntry和bl Main 就能从Boot Internal SRAM直接跳到SDRAM,原来在编译的时候,像ResetEntry和CEntry这些表示地址的标号都被赋于从|Image$$RO$$Base|开始之后的地址,只要|Image$$RO$$Base|大等于0x3000_0000,利用ldr取得绝对地址后赋给PC就能直接跳转到SDRAM里去了。我之前一直以为ResetEntry=0x0000_0000,而且分不清ldr和adr之间的差别,因此纠结了好久。
ldr pc,=CEntry ;goto compiler address
CEntry
bl Main ;Don t use main()because ......
b .
洗洗睡了,明天再看一下中断向量表。
评论:这也说不通, 因为程序中还有这样的代码: ADR R0,ResetEntry 这条指令R0最终存的也是ResetEntry的绝对地址, 只是编译器解释成pc+ResetEntry相对于当前pc的偏移地址, 如果ResetEntry的绝对地址是0x30000000,那这个偏移地址就太大了, 这条指令编译时应该通不过才对!
如果你说的都对,那在执行ldr pc, =copy_proc_beg 的时候,它就已经进入SDRAM中了
- Re: BugSu 2012-05-25 18:08发表 [回复]
- 回复shuizhonglinsname:ADR R0,ResetEntry
这条指令执行后,R0的值是当前PC值减去一个固定值得到的,这个固定值假设为off_set;当程序在SDRAM和Boot Internal SRAM里执行ADR R0,ResetEntry这句时的PC是不同的,这时的PC值在SDRAM比在Boot Internal SRAM里大0x3001_0000,所以当程序在Boot Internal SRAM里时得到的R0是0,而在Boot Internal SRAM里运行时得到的R0是0x3001_0000。
补充一点:关于启动代码中特殊寄存器赋值用LDR以及引用自定义标示用ADR的解释:
特殊寄存器赋值用LDR是因为位置固定。
引用自定义标示用ADR是为了保证代码与地址无关。启动时执行启动代码如果改用ADR的话,标号的值就为SDRAM中的地址去了,而不而不是IRAM中启动代码所标示的标示的位置了。举例如下:
在SDRAM初始化代码中有一句:
adrl r0,SMRDATA
而在IsrIRQ中的:ldr r8,=HandleEINT0处用了ldr的原因是IRQ中是不可能执行此处的代码的,因为启动时IRQ中断是关闭的。
- 关于启动代码中NANDFLASH启动相关代码的解释
- 从Nandflash启动代码
- 关于ARM中断的具体的启动代码解释
- 关于S3C44B0中断的具体的启动代码解释
- 启动代码中关于变量的初始化
- 启动代码中关于变量的初始化
- 深度分析NandFlash—start.s中添加从Nand Flash启动的代码分析
- TQ2440 学习一 启动代码的解释
- [ARM] Cortex-M Startup.s启动文件相关代码解释
- [ARM] Cortex-M Startup.s启动文件相关代码解释
- 关于mini2440启动代码中中断的产生原理分析
- s3c2440的nandflash启动
- s3c2440的nandflash启动
- nandflash的启动原理
- 关于代码实现activity的启动模式
- 【备用】关于ARM的启动代码
- 一篇解释arm启动代码中最生涩隐晦地方的好文
- 关于arm启动代码启动流程
- sicily 1800. Sequence(RMQ,线段树解决)
- 彻底删除文件(File Delete Absolutely) 最新3.01版本 也已经在中关村在线升级成功
- C语言基本数据类型详解
- linux Perl开发
- beginning ssh on ubuntu
- 关于启动代码中NANDFLASH启动相关代码的解释
- js倒计时
- Print Pyramid
- Android 个人信息安全问题,网络安全问题
- Rhadoop中修改Reduce输出分割符
- Android bound service 详解三:使用Messenger
- cocos2d-x XML 读取 libxml2使用
- 使用Java RTP传输声音和视频的程序
- 如何关闭快播QvodTerminal.exe后台运行