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 r2, r2, r3      ;r0+16,r2+16 every time,if r2>r3 
   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|         
   0       ; 复制 RW 数据到 BaseOfBSS 
   cmp r2, r3        ;比较 r2,r3;看 RW 数据段有没有复制完 
   ldrcc  r1, [r0], #4  ; R2r1,然后 r0=r0+4, r0 是 RW 数据段在 ROM 内的起始地址  
   strcc  r1, [r2], #4  ;r2 为 |Image

RWRW

Base|地址,由编译器指定 
   bcc %B0     ;若 r2 
从 NOR Flash 的 RO 段结束点开始复制 RW 数据到 SDRAM 的RW Base 处,数据长度为 R W Limit - RW Base 



还是有必要交代一下 ADS 中预定义的几个变量以及它们的作用。|Image

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|的值 
    TopOfROM  DCD |Image

RORO

Limit|    ;  
    BaseOfBSS  DCD |Image

RWRW

Base| 
    BaseOfZero  DCD |Image

ZIZI

Base|    ;ZI Base = RW Limit  
    EndOfBSS  DCD |Image

ZIZI

Limit| 
    这样“ldr  r2, BaseOfBSS”实际是加载了|Image

RWRW

Base|到 r2。 
    实际上也可以直接用 ldr r2,= |Image

RWRW

Base| 。 
 
复制完 RW 数据段,需要将 ZI 段清 0。ZI 段在 SDRAM 内是紧跟着 RW 段的,所以其起始地址


|Image

ZIZI

Base|,同时也是 RW 段的结束地址。 


    下面的代码很简单明了: 
     mov r0, #0    ;用0初始化ZI区 
     ldr r3, EndOfBSS    ;r3 = | Image

ZIZI

Limit| ; ZI 段的结束地址 
    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 内执行了。 

      b  .           ;就是仍跳回这一指令...不做任何事情的死循环                   
    ] 
   关于 GotoMain 标号,是在文件的最后定义的: 
  GBLS  main_entry 
  main_entry  SETS  "Main"   
  IMPORT  $main_entry 
  GotoMain  DCD $main_entry    

因为“ldr pc, GotoMain”把$main_entry 的绝对地址(即 Main 函数的入口地址)赋给 PC,由于程序已经复制到 SDRAM 中,而且$main_entry的绝对地址是在 SDRAM 范围内,所以从这句代码以后,程序就开始从 ROM跳到 SDRAM 内执行了。 

 
二、从 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 启动 

   cmp r0, #0    ;所以入口是 0 地址表示是从 NAND 的 StepingStone 启动 
   bne copy_proc_beg    ;若从 NOR 启动,跳转到标号 copy_proc_beg。否则往下执行


若判断是从 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  
  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

RORO

Base|=0x30000000, 
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); 


  bne  %F4    ;若有坏块就跳到 4 进行循环条件判断。没有坏块的话就跳到标号3处copy当前页 
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 内执行了。程序中所有标号的地址也相应要加上运行

域的基址 RO Base(0x30000000)。另外在这句之前的程序大小要控制在 4K 以内。 


然后执行 copy_proc_beg 子程序: 
copy_proc_beg 
  adr r0, ResetEntry    ; 从这里开始 ResetEntry 变成了 0x30000000 
  ldr r2, BaseOfROM    ;加载 BaseOfROM 内的数据即|Image

RORO

Base|=0x30000000   
  cmp r0, r2    ;//如果从 norflash 启动,那么 ResetEntry=0 BaseOfROM=0x3000000,显然不相同  
  ldreq  r0, TopOfROM  ; 如果相等的话,加载|Image

[1] [2]
关键字:S3C2410  启动代码 引用地址:S3C2410-2440启动代码内数据复制过程的分析

上一篇:JZ2440存储管理器代码实现(使用SDRAM)
下一篇:ARMV7架构下的普通寄存器和CPSR寄存器及SPSR寄存器

推荐阅读

能源互联网研究与实践快速推进,新理念、新技术开始涌现,呈现开放、融合态势。准确把握能源互联网发展方向与基本特征对研判中国能源行业未来形态、科学推进能源转型尤为重要。立足于中国中长期能源转型不同路径比较,着眼于“能源+”的高度去定位能源在未来经济高质量发展中的位置,结合对能源互联网架构与运行机理的分析以及对跨界融合实践特点的总结...
GPIO 即通用输入输出口。凡事都要熟悉,熟能生巧。一定要掌握MDK软件的工程操作方法。对于GPIO的操作。Project里面要有以下几个文件夹(开发之前需要包含相应的库文件,这里默认已经包含)STEP BY STEP(以按键和LED灯为例):1.在USER文件夹里新建对应功能的C文件和H文件(这里对应 Key.c Key.h LED.c LED.h)其中C文件用来进行对应外设的硬件配置...
安富利旗下全球电子元器件产品与解决方案分销商e络盟大力拓展Omega产品系列,极大地丰富了其工业自动化与控制产品供应范围。全球电子设计工程师、工业工程师及维修工程师现可通过e络盟采购到Omega世界一流的产品系列,适用于测量和控制温度、湿度、压力、应力、力、流量、液位、pH值和电导率。 Omega可助力航空航天、汽车、无线、测试与测量、过程控制及电...
  高低高变频器的特点  采用升降压的办法,将低压或通用变频器应用在中、高压环境中而得名。原理是通过降压变压器,将电网电压降到低压变频器额定或允许的电压输入范围内,经变频器的变换形成频率和幅度都可变的交流电,再经过升压变压器变换成电机所需要的电压等级。  这种方式,由于采用标准的低压变频器,配合降压,升压变压器,故可以任意匹配电...

史海拾趣

问答坊 | AI 解惑

关于网络

网络与通信是一门极具‘艺术’的内容,是值得我们大家广泛探讨的一个问题,所以大家一定的认真的研究、提问,本人鼓励大家踊跃的发表个人意见,请大家共同的研讨,以求共同的进步!!!…

查看全部问答∨

求c6000 的 c 编程

请问 谁有 c6000 的c编程的教程啊,我现在主要是用ccs编程,还不太熟悉具体的编程方法,比如中断,和cmd文件的编写,哪位高手帮一下啊,小弟感激不尽啊。我的邮箱 :1775671@163.com qq:214497453…

查看全部问答∨

驱动三级管不稳定

请位高手指点下: 我现在的目的是单片机信号,高电平输出,使9013导通,继电器K工作,使的交流电机运行。 这一功能已经实现,不过在运行当中,继电器偶尔会不停的跳动,单片机始终输出高电平,是交流对我的直流有干扰吗? 用TIP122代替9013可以吗 ...…

查看全部问答∨

继续9650的问题

现在的问题是图像已经清楚了,只是发现不只是一个窗口显示图像,有若干个连着的窗口都显示,不知原因,望各位高手指教…

查看全部问答∨

如何防止软件读取我的主板或CPU的序列号啊?

下载个软件,第二次安装的时候,就提示我已经安装过一次,不给再安装了,我想可能是软件读取了序列号什么的,如何不让读取,或读取到假的?…

查看全部问答∨

legacy SD Bus Driver和SD Bus Driver

求助!!!     最近在调试一个WinCE项目,学着玩的!~     在选组件时,选到Device Drivers下sd及sdio时,sd下有两个单选项:legacy SD Bus Driver和SD Bus Driver,想问问他俩有啥区别啊?      SDIO ...…

查看全部问答∨

革命家同学,你还好吗?

初中一年级,开班会,班主任问大家的理想是什么? 当时我回答的是当科学家,呵呵 轮到我旁边一个同学了,他站起来不快不满的、清晰的吐出几个字:我要当革命家 一语惊人 除了我们班当时最漂亮的女生,还有几个好朋友之外,我就记得他了,呵呵, ...…

查看全部问答∨

wince驱动开发

请问朋友们,wince驱动开发可以有什么具体的开发项目,介绍几个,要求能够拿出台面展示或者能够参加程序设计比赛的。 …

查看全部问答∨

方波中段出现向下尖峰可能是什么原因

  这种状况发生在把后端的运放改为减法器之后 此信号为正输入端信号 负反馈电阻上还并联了滤波电容,负支路的R1是200k,R2是1.8M正支路的R1是非颠倒330K,R2是10M 是因为正输入端接地的大电阻产生感性或容性效果吗? 这点电势突然降低,是因 ...…

查看全部问答∨

求助:μC/OS-2有何优势?

一直没接触过操作系统, 程序中一直是一个while(1)循环, 顺序执行相应的任务, 突发时间就用中断处理, 如果用μC/OS-2, 有什么不一样了?…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved