S3C2410 启动后先进行一些必要的设置,如关 WatchDog,设置 PLL 与时钟,配置 SDRAM,初始化堆栈等,网上有很多分析启动代码的文章,本文不打算再进行说明。
本文分从 NOR Flash 与 NAND Flash 启动两种情况分别进行分析。首先要知道 NOR Flash 是 XIP 的,如果从 NOR 启动,代码首先在 NOR Flash 内执行,考虑到运行速度,我们要把代码要复制到 SDRAM 内去执行。 当系统被设置成从 NAND FALSH 启动(使用 OM[1:0]引脚的电平来控制)时,由于其自身的特点,NAND Flash 不具备运行程序的功能,程序不能在 NAND Flash 内执行,CPU 会自动把 NAND 内头4K 代码加载到 CPU的内部 SRAM(StepingStone 垫脚石)中,然后把 StepingStone 映射到 CPU 地址空间的 0 地址处(BANK0),因此 CPU 会从 StepingStone 的 0 地址处取指令并执行。因为程序一般都会大于4K,我们必须把代码复制到SDRAM 中去执行。综上所述,不管是从 NOR 的启动还是从 NAND 启动,都要把代码复制到 SDRAM 中去执行,这个复制过程要在头 4K 代码中完成。此后这 4KB 的 SRAM 还可以用作其它用途。
另外必须注意到的是 NOR 的启动与 NAND 启动的程序入口点 ResetEntry 都为 0,CPU 在加电后会去 0x0处取指执行,如下图所示。
一、我们先看从 NOR Flash 启动的情况:
下面这段代码进行复制前的判断,因为从 NAND Flash 与从NOR Flash 启动的复制过程是大不相同的。
;/**************************************************************************************
;BWSCON 的[2:1]反映了外部引脚 OM[1:0]:若 OM[1:0] != 00, 从 N OR FLash 启动或直接在内存运行;
;若 OM[1:0]==00,则为从 Nand Flash 启动
;**************************************************************************************/
ldr r0, =BWSCON
ldr r0, [r0]
ands r0, r0, #6
bne copy_proc_beg ; 若从 NOR 启动,跳转到标号 copy_proc_beg
adr r0, ResetEntry ; 从 NOR 或 NAND 启动,ResetEntry 都为 0, 但上面已经排除了 NOR 启动
cmp r0, #0 ;所以入口是 0 地址表示是从 NAND 的 StepingStone 启动
bne copy_proc_beg ;若从 NOR 启动,跳转到标号 copy_proc_beg。否则往下执行
若判断是从 NOR Flash 启动,程序直接跳转到标号 copy_proc_beg 处执行:
copy_proc_beg
adr r0, ResetEntry ; r0= ResetEntry=0
ldr r2, BaseOfROM ; r2= |Image
RORO
Base| = 0x30000000
cmp r0, r2 ;//如果从 norflash 启动,那么 ResetEntry=0 BaseOfROM=0x3000000,显然不相同
ldreq r0, TopOfROM
beq InitRam ;同时跳到 InitRam
因为现在程序仍然在 NOR Flash 中执行,代码的执行基址还是 0,所以“adr r0, ResetEntry”取得的
ResetEntry 相对地址是 0。则 r0≠r2,先执行下面的代码从 NOR 复制 RO 数据段到 SDRAM,不直接
跳转到InitRam 进行 RW 段复制。
ldr r3, TopOfROM
0 ;循环复制 Code 数据
ldmia r0!, {r4-r7} ; r0 的初始值 ResetEntry=0
stmia r2!, {r4-r7} ; r2 的初始值 RO Base(0x30000000)
;上面的 2 行代码将从 0 开始的地址内的数据保存到 SDRAM 内以 RO Base 开始的地址内
cmp r2, r3 ;复制的终止条件:复制了(RO Limit - RO Base) 大小,即整个 RO 数据段
bcc %B0 ;若 r2
sub r0, r0, r2 ;将可能多加的部分减回来,让 r0 对准 ROM 内 RO 段的结束点,也是 RW 数据段的开始点
复制过程及结果如下图:
代码段复制完紧接着就是复制 RW 段:
InitRam ;从 NOR Flash 复制 RW 段到 SDRM 中预设的 RW BASE 位置
ldr r2, BaseOfBSS ;r2= |Image
RWRW
Base|=|Image
RORO
Limit|
ldr r3, BaseOfZero ;r3= |Image
ZIZI
Base| RWRW Base|地址,由编译器指定 RORO Base|表示连接完成后程 序映像 RO 段的起始地址;|Image RORO Limit|表示连接完成后程序映像 RO 段的结束地址; |Image RWRW Base|表示连接完成后程序映像 RW 段的起始地址;|Image ZIZI Base|表示连接完成后程 序映像 ZI 段的起始地址,注意由于 RW 段与 ZI 段在运行时是紧密挨着的哦,所以这个值也就代表了 RW 段的 结束地址;|Image ZIZI Limit|表示连接完成后程序映像 ZI 段的结束地址。为了书写和阅读的方便,我们分 别把上面几个值赋给变量 BaseOfROM,TopOfROM,BaseOfBSS,BaseOfZero,EndOfBSS 这样看起来 就很简 结了: BaseOfROM DCD |Image RORO Base | ;BaseOfROM 地址内保存| Image RORO Bas e|的值 RORO Limit| ; RWRW Base| ZIZI Base| ;ZI Base = RW Limit ZIZI Limit| RWRW Base|到 r2。 RWRW Base| 。 |Image ZIZI Base|,同时也是 RW 段的结束地址。 下面的代码很简单明了: ZIZI Limit| ; ZI 段的结束地址 b . ;就是仍跳回这一指令...不做任何事情的死循环 因为“ldr pc, GotoMain”把$main_entry 的绝对地址(即 Main 函数的入口地址)赋给 PC,由于程序已经复制到 SDRAM 中,而且$main_entry的绝对地址是在 SDRAM 范围内,所以从这句代码以后,程序就开始从 ROM跳到 SDRAM 内执行了。 cmp r0, #0 ;所以入口是 0 地址表示是从 NAND 的 StepingStone 启动 若判断是从 NAND 启动,不会跳转到 copy_proc_beg,而是紧接着执行从 NAND 复制数据到 SDRAM 的代码,从NAND 的开始处(第一个 Block 的头一页)复制总共 256 页即 128Kbytes 数据。过程与结果如下图所示,代码如下。 对于从NAND Flash 启动,首先程序在4KB 的StepingStone 中运行,会复制128K的数据到SDRAM的RO Base处, 其中包含了RO Data 与RW Data。 nand_boot_beg mov r5, #NFCONF ;首先设定 NAND 的控制寄存器;NFCONF 配置寄存器 地址 0x4E000000 RORO Base|=0x30000000, bne %F4 ;若有坏块就跳到 4 进行循环条件判断。没有坏块的话就跳到标号3处copy当前页 域的基址 RO Base(0x30000000)。另外在这句之前的程序大小要控制在 4K 以内。 然后执行 copy_proc_beg 子程序: RORO Base|=0x30000000
0 ; 复制 RW 数据到 BaseOfBSS
cmp r2, r3 ;比较 r2,r3;看 RW 数据段有没有复制完
ldrcc r1, [r0], #4 ; R2
strcc r1, [r2], #4 ;r2 为 |Image
bcc %B0 ;若 r2
从 NOR Flash 的 RO 段结束点开始复制 RW 数据到 SDRAM 的RW Base 处,数据长度为 R W Limit - RW Base
还是有必要交代一下 ADS 中预定义的几个变量以及它们的作用。|Image
TopOfROM DCD |Image
BaseOfBSS DCD |Image
BaseOfZero DCD |Image
EndOfBSS DCD |Image
这样“ldr r2, BaseOfBSS”实际是加载了|Image
实际上也可以直接用 ldr r2,= |Image
复制完 RW 数据段,需要将 ZI 段清 0。ZI 段在 SDRAM 内是紧跟着 RW 段的,所以其起始地址
mov r0, #0 ;用0初始化ZI区
ldr r3, EndOfBSS ;r3 = | Image
1
cmp r2, r3 ;r2是RW limit,也就是 ZI段的起始地址
strcc r0, [r2], #4 ;ZI 数据段清 0
bcc %B1
此后,程序就可以跳转到 Main 主函数处执行了。
[ :LNOT:THUMBCODE
ldr pc, G otoMain ;//跳转到 Main()主函数; 它把$main_entry 的绝对地址赋给 PC,由于程序已经复制到 SDRAM 中,而且$main_entry 的绝对地址是在 SDRAM 范围内,所以从这句代码以后,程序就开始从 ROM跳到 SDRAM 内执行了。
]
关于 GotoMain 标号,是在文件的最后定义的:
GBLS main_entry
main_entry SETS "Main"
IMPORT $main_entry
GotoMain DCD $main_entry
二、从 NAND 启动的分析
从 NAND 启动,一样是用下面这段代码做判断:
;/**************************************************************************************
;BWSCON 的[2:1]反映了外部引脚 OM[1:0]:若 OM[1:0] != 00, 从 N OR FLash 启动或直接在内存运行;
;若 OM[1:0]==00,则为从 Nand Flash 启动
;**************************************************************************************/
ldr r0, =BWSCON
ldr r0, [r0]
ands r0, r0, #6
bne copy_proc_beg ; 若从 NOR 启动,跳转到标号 copy_proc_beg
adr r0, ResetEntry ; 从 NOR 或 NAND 启动,ResetEntry 都为 0, 但上面已经排除了 NOR 启动
bne copy_proc_beg ;若从 NOR 启动,跳转到标号 copy_proc_beg。否则往下执行
ldr r0, =(1<<15)|(1<<12)|(1<<11)|(7<<8)|(7<<4)|(7)
str r0, [r5] ;
bl ReadNandID ; 接着读取 NAND 的 ID 号,结果保存在 r5 里
mov r6, #0 ; r6 设初值 0.
ldr r0, =0xec73 ; 期望的 NAND ID 号
cmp r5, r0 ; 这里进行比较,r5 是读取到的 ID
beq %F1 ;相等的话就跳到下一个 1 标号处
ldr r0, =0xec75 ; 这是另一个期望值
cmp r5, r0 ; 这里进行比较
beq %F1 ;相等的话就跳到下一个 1 标号处
mov r6, #1 ; 若 ID 不是 0xec73 或 0xec75, 设置 r6=1,否则 r6=0
1
bl ReadNandStatus ; 读取 NAND 状态,结果放在 r1 里
mov r8, #0 ;r8 设初值 0,意义为页号(start page address)
ldr r9, =ResetEntry ; r9 设初值为ResetEntry的绝对地址 |Image
2
ands r0, r8, #0x1f ; 若 r8 为 32 的整数倍(0,32,64...),eq 有效,ne 无效
bne %F3 ;若不是 32 的整数倍,不是当前块的头一页跳转到标号 3 处,不用检查坏块。
mov r0, r8 ; 若 ands 结果所有位为 0,即 r8 是 32 的整数倍或为 0,是每个 Block 的头一页
bl CheckBadBlk ; 检查 NAND 的坏区,结果保存到 r0,r0 是 0 说明当前块不是坏块
cmp r0, #0 ;比较 r0 和 0, r0==0, not bad block
addne r8, r8, #32 ; 存在坏块的话就跳过这个坏块: +32 得到下一块.(1 block=32 page);
3
mov r0, r8 ;加载当前页号到 r0
mov r1, r9 ;加载复制数据的目标地址到 r1 (0x30000000)
bl ReadNandPage ; 读取该页的 NAND 数据到 SDRAM 中由 r1 指定的地址
add r9, r9, #512 ; 目标地址+512(每一页的大小是 512Bytes) 用于复制下一页数据
add r8, r8, #1 ; r8 指向下一页
4
cmp r8, #256 ;比较是否读完 256 页即 128KBytes 共复制 8blocks 128KB 到 SDRAM
bcc %B2 ;如果 r8 小于 256(没读完 256 页),就返回前面的标号 2 处读取下一页
;复制完成后要关闭 NAND 控制器
mov r5, #NFCONF ; Disable NandFlash
ldr r0, [r5]
and r0, r0, #~0x8000 ; clear bit15, Disable NAND Controller
str r0, [r5]
ldr pc, =copy_proc_beg
执行完 NAND 到 SDRAM 的复制,最后一句“ldr pc, =copy_proc_beg”,是重点。它把 copy_proc_beg的绝对地址赋给 PC,由于程序的 RO Base 是SDRAM 的起始地址空间,copy_proc_beg 的绝对地址肯定是在SDRAM 范围内,所以从这句代码以后,程序就开始从 StepingStone 跳到 SDRAM 内执行了。程序中所有标号的地址也相应要加上运行
copy_proc_beg
adr r0, ResetEntry ; 从这里开始 ResetEntry 变成了 0x30000000
ldr r2, BaseOfROM ;加载 BaseOfROM 内的数据即|Image
cmp r0, r2 ;//如果从 norflash 启动,那么 ResetEntry=0 BaseOfROM=0x3000000,显然不相同
ldreq r0, TopOfROM ; 如果相等的话,加载|Image
上一篇:JZ2440存储管理器代码实现(使用SDRAM)
下一篇:ARMV7架构下的普通寄存器和CPSR寄存器及SPSR寄存器
推荐阅读
史海拾趣
2007年10月,G24i在英国建立了DSSC的30MW试产线,这是全球范围内的重要里程碑。这条生产线具备高效的生产能力,能够在不到3小时的时间内制造出长达约800米的太阳能电池,生产速度高达每分钟4米以上。这一成就不仅展示了G24i在规模化生产方面的实力,也为后续的商业化应用奠定了产能基础。尽管初期商业化模组产品的转换效率仅为3%,但G24i通过不断优化生产工艺和降低成本,逐步提升了产品的市场竞争力。
近年来,Aptos将业务重心逐渐转向区块链领域。在经过长时间的研发后,公司成功推出了主网测试环境。在测试中,Aptos实现了惊人的3万TPS峰值以及超20亿笔日交易的处理能力,这一性能突破在行业内引起了广泛关注。
创新是Cincon持续发展的动力。2003年,公司在台北设立了研发中心,专注于电源产品的技术创新和研发。这一举措极大地提升了公司的技术实力和产品创新能力。几年后,Cincon成功设计并制造了LED电源,进一步丰富了产品线,并满足了市场对高效节能照明解决方案的需求。
随着品牌影响力的不断提升,EPT开始积极拓展OEM/ODM业务。公司凭借先进的生产技术和严格的质量管理体系,成功与多家国内外知名企业建立了合作关系。通过为客户提供定制化的产品和服务,EPT不仅实现了业务的快速增长,还为其积累了丰富的行业经验。
在发展过程中,APLUS Products公司注重与上下游企业的合作与共赢。公司积极与供应商建立良好的合作关系,确保原材料的质量和供应的稳定性;同时,也与多家知名企业建立了战略合作关系,共同开拓市场、分享资源。这些合作不仅提高了公司的运营效率,也增强了其市场竞争力。
Astro Tool Corp公司初创时,面临着电子制造行业激烈的竞争环境。然而,公司创始人凭借其在精密工具制造领域的深厚技术背景,带领团队研发出了一款具有高精度和高稳定性的电子制造工具,成功吸引了业内众多客户的关注。这款产品不仅提高了生产效率,还降低了制造成本,迅速在市场上占据了一席之地。公司借此机会,不断扩大生产规模,逐步在电子制造工具市场建立起自己的地位。
请问 谁有 c6000 的c编程的教程啊,我现在主要是用ccs编程,还不太熟悉具体的编程方法,比如中断,和cmd文件的编写,哪位高手帮一下啊,小弟感激不尽啊。我的邮箱 :1775671@163.com qq:214497453… 查看全部问答∨ |
|
legacy SD Bus Driver和SD Bus Driver 求助!!! 最近在调试一个WinCE项目,学着玩的!~ 在选组件时,选到Device Drivers下sd及sdio时,sd下有两个单选项:legacy SD Bus Driver和SD Bus Driver,想问问他俩有啥区别啊? SDIO ...… 查看全部问答∨ |
|
初中一年级,开班会,班主任问大家的理想是什么? 当时我回答的是当科学家,呵呵 轮到我旁边一个同学了,他站起来不快不满的、清晰的吐出几个字:我要当革命家 一语惊人 除了我们班当时最漂亮的女生,还有几个好朋友之外,我就记得他了,呵呵, ...… 查看全部问答∨ |
|
这种状况发生在把后端的运放改为减法器之后 此信号为正输入端信号 负反馈电阻上还并联了滤波电容,负支路的R1是200k,R2是1.8M正支路的R1是非颠倒330K,R2是10M 是因为正输入端接地的大电阻产生感性或容性效果吗? 这点电势突然降低,是因 ...… 查看全部问答∨ |
一直没接触过操作系统, 程序中一直是一个while(1)循环, 顺序执行相应的任务, 突发时间就用中断处理, 如果用μC/OS-2, 有什么不一样了?… 查看全部问答∨ |