历史上的今天

今天是:2024年11月08日(星期五)

正在发生

2019年11月08日 | ARM9学习4-S3C2410的启动代码分析-For ADSv1.2

发布者:自由梦想 来源: 51hei关键字:ARM9  S3C2410  启动代码  ADSv1 手机看文章 扫描二维码
随时随地手机看文章

通常,启动代码是指CPU复位后到进入C语言的main函数之前需要执行的那段汇编代码.这是由于C语言程序的运行需要具备一定的条件,比如:分配好外部数据空闿堆栈空间和中断入口等筿另外汇编代码可以更直接的对硬件进行操使效率更高. 通常启动代码是放在2410init.s汇编文件;特殊功能寄存器定义在2410addr.s;Memory Bank 配置在mencfg.s;还有系统的选项等在option.s文件;2410init.s不仅包括复位后执行的代码,还包括CPU进入掉电模式,产生中断等和处理器直接相关的,用汇编实现的代码.
;=========================================
; NAME: 2410INIT.S
; DESC: C start up codes
;       Configure memory, ISR ,stacks
; Initialize C-variables
; HISTORY:
; 2002.02.25:kwtark: ver 0.0
; 2002.03.20:purnnamu: Add some functions for testing STOP,POWER_OFF mode
; 2003.05.19:jcs:Configure UPLL in init.s not usbmain.c
;=========================================
  //首先,启动代码定义了一些常量 ,相当于C中的INCLUDE
GET option.inc
GET memcfg.inc
GET 2410addr.inc

BIT_SELFREFRESH EQU (1<<22) //自刷新常量
//;;处理器模式常量 
USERMODE    EQU  0x10
FIQMODE     EQU  0x11
IRQMODE     EQU  0x12
SVCMODE     EQU  0x13
ABORTMODE   EQU  0x17
UNDEFMODE   EQU  0x1b
MODEMASK    EQU  0x1f  //系统模式
NOINT           EQU  0xc0  //屏蔽所有的中断,即置位I,F位
//;The location of stacks 定义处理器各模式下堆栈地址常量 
UserStack        EQU (_STACK_BASEADDRESS-0x3800) ;0x33ff4800 ~ 
SVCStack        EQU (_STACK_BASEADDRESS-0x2800)  ;0x33ff5800 ~
UndefStack      EQU (_STACK_BASEADDRESS-0x2400)  ;0x33ff5c00 ~
AbortStack       EQU (_STACK_BASEADDRESS-0x2000)  ;0x33ff6000 ~
IRQStack         EQU (_STACK_BASEADDRESS-0x1000)  ;0x33ff7000 ~
FIQStack         EQU (_STACK_BASEADDRESS-0x0)        ;0x33ff8000 ~ 
;check if tasm.exe is used.
;arm处理器有两种工作状态 1.arm:32位 这种工作状态下执行字对准的arm指令 2.Thumb:16位 这种工作状态执行半字对准的Thumb指令
;因为处理器分为16位 32位两种工作状态程序的编译器也是分16位和32两种编译方式 所以下面的程序用于根据处理器工作状态确定编译器编译方式
;code16伪指令指示汇编编译器后面的指令为16位的thumb指令
;code32伪指令指示汇编编译器后面的指令为32位的arm指令
;这段是为了统一目前的处理器工作状态和软件编译方式(16位编译环境使用tasm.exe编译)
GBLL THUMBCODE ;设置一个全局逻辑变量
[ {CONFIG} = 16 ;if config==16 这里表示你的目前处于领先地16位编译方式,{CONFIG}为汇编器内置变量
THUMBCODE SETL {TRUE} ;设置THUMBCODE 为 true
CODE32 ;转入32位编译模式
|      ;else
THUMBCODE SETL {FALSE} ;设置THUMBCODE 为 false

[ THUMBCODE     ;if THUMBCODE==TRUE
CODE32          ;for start-up code for Thumb mode;转入32位编译方式
]

;注意下面这段程序是个宏定义 很多人对这段程序不理解 我再次强调这是一个宏定义 所以大家要注意了下面包含的HandlerXXX HANDLER HandleXXX将都被下面这段程序展开。

;这段程序用于把中断服务程序的首地址装载到pc中,有人称之为“加载程序”。其大致作用是把宏的第一个参数$HandlerLabel转变为一个标号,然后让程序跳转到第二个参数 $HandleLabel(第二个参数应该为一个地址)对应的值的地址去。可以分析出,sp和r0在执行前后都没有变化,程序就实现了跳转

;本初始化程序定义了一个数据区(在文件最后),34个字空间,存放相应中断服务程序的首地址。每个字空间都有一个标号,以Handle***命名。

;在向量中断模式下使用“加载程序”来执行中断服务程序。

;这里就必须讲一下向量中断模式和非向量中断模式的概念

;向量中断模式是当cpu读取位于0x18处的IRQ中断指令的时候,系统自动读取对应于该中断源确定地址上的指令取代0x18处的指令,通过跳转指令系统就直接跳转到对应地址

;函数中 节省了中断处理时间提高了中断处理速度标 例如 ADC中断的向量地址为0xC0,则在0xC0处放如下代码:ldr PC,=HandlerADC 当ADC中断产生的时候系统会

;自动跳转到HandlerADC函数中

;非向量中断模式处理方式是一种传统的中断处理方法,当系统产生中断的时候,系统将interrupt pending寄存器中对应标志位置位 然后跳转到位于0x18处的统一中断

;函数中 该函数通过读取interrupt pending寄存器中对应标志位 来判断中断源 并根据优先级关系再跳到对应中断源的处理代码中

MACRO 
$HandlerLabel HANDLER $HandleLabel    //
$HandlerLabel 
sub sp,sp,#4                     ;减少sp(预留一个字,用于存放转跳地址) 
stmfd sp!,{r0}                    ;把工作寄存器压入栈(lr does not push because it return to original address) 
ldr     r0,=$HandleLabel    ;将HandleXXX的址址放入r0 
ldr     r0,[r0]                       ;把HandleXXX所指向的内容(也就是中断程序的入口)放入r0 
str     r0,[sp,#4]                  ;把中断服务程序(ISR)压入栈,保存在高一个地址预留的空间中,但SP没变。 
ldmfd   sp!,{r0,pc}              ;用出栈的方式恢复r0的原值和为pc设定新值(也就完成了到ISR的转跳) ;

                   ADS仅支持FD(满递减)型堆栈,故只能用stmfd和ldmfd
MEND

;========================================================================================
//在这里用IMPORT伪指令(和c语言的extren一样)引入|Image$$RO$$Base|,|Image$$RO$$Limit|...
//这些变量是通过ADS的工程设置里面设定的RO Base和RW Base设定的,最终由编译脚本和连接程序导入程序. 
//那为什么要引入这玩意呢,最简单的用处是可以根据它们拷贝自已 ,从把RW和ZI变量从加载域中复制到运行域中
//一个arm由RO,RW,ZI三个断组成 其中RO为代码段,RW是已经初始化的全局变量,ZI是未初始化的全局变量(对于GNU工具 对应的概念是TEXT ,DATA,BSS)。

;========================================================================================
IMPORT  |Image$$RO$$Base|    ; ROM code(也就是代码)的开始地址 
IMPORT  |Image$$RO$$Limit|    ; ROM code的结束地址 (也就是RW在加载域中的起始地址) 
IMPORT  |Image$$RW$$Base|   ; 在运行域中要初始化的RAM的开始地址 
IMPORT  |Image$$ZI$$Base|      ; area(需要清零的RAM区域)的开始地址 
IMPORT  |Image$$ZI$$Limit|       ; area的结束地址 

;这里引入一些在其它文件中实现在函数,包括为我们所熟知的main函数
IMPORT  Main    ; The main entry of mon program 
;从这里开始就是正真的代码入口了! 
AREA    Init,CODE,READONLY       ;这表明下面的是一个名为Init的代码段 
ENTRY                                            ;定义程序的入口(调试用) 其中关键字ENTRY是指定编译器保留这段代码,因为
                                                       编译器可能会认为这是一段亢余代码而加以优化。链接的时候要确保这段代码
                                                         被链接在0地址处,并且作为整个程序的入口 
;1)The code, which converts to Big-endian, should be in little endian code. 
;2)The following little endian code will be compiled in Big-Endian mode. 
;  The code byte order should be changed as the memory bus width. 
;3)The pseudo instruction,DCD can not be used here because the linker generates error. 
ASSERT :DEF:ENDIAN_CHANGE 
[ ENDIAN_CHANGE                         ;下面是大小端的一个判断,在Option.inc里已经设为FALSE 
     ASSERT  :DEF:ENTRY_BUS_WIDTH 
     [ ENTRY_BUS_WIDTH=32          //‘[’=IF
      b ChangeBigEndian                  ;DCD 0xea000007 
     ] 

     [ ENTRY_BUS_WIDTH=16            
      andeq r14,r7,r0,lsl #20              ;DCD 0x0007ea00 
     ] 

     [ ENTRY_BUS_WIDTH=8 
      streq r0,[r0,-r10,ror #1]             ;DCD 0x070000ea 
     ] 

     b ResetHandler ;因为设成FALSE,所以系统复位后就来到这了,转跳到复位程序入口 
    ] 
//=====================================================================================
;ARM要求中断向量表必须放置在仿地址开始,连续8X4字节的空间内.每当一个中断发生以后,ARM处理器便强制把PC指针置为向量表中对应中断类型的地址值。因为每个中断只占据向量表中1个字的存储空间,只能放置一条ARM指令,使程序跳转到存储器的其他地方,再执行中断处理 
//=====================================================================================
b HandlerUndef           ;转跳到Undefined mode程序入口 
b HandlerSWI              ;转跳到SWI 中断程序入口 
b HandlerPabort          ;转跳到PAbort(指令异常)程序入口 
b HandlerDabort          ;转跳到DAbort(数据异常)程序入口 
b .                                ;保留 
b HandlerIRQ              ;转跳到IRQ 中断程序入口 
b HandlerFIQ              ;转跳到FIQ 中断程序入口 
;@0x20 不知道是什么意思,地址?
b EnterPWDN ; Must be @0x20.
;================================================================================== 
;下面是改变大小端的程序,这里采用直接定义机器码的方式,至说为什么这么做就得问三星了 
;反正我们程序里这段代码也不会去执行,不用去管它 
;================================================================================== 
ChangeBigEndian    //通过设置CP15中的C1的位7来设置存储格式为大端模式。
;@0x24 
[ ENTRY_BUS_WIDTH=32 
     DCD 0xee110f10 ;0xee110f10 => mrc p15,0,r0,c1,c0,0 
     DCD 0xe3800080 ;0xe3800080 => orr r0,r0,#0x80;  //Big-endian 
     DCD 0xee010f10 ;0xee010f10 => mcr p15,0,r0,c1,c0,0 

[ ENTRY_BUS_WIDTH=16 
     DCD 0x0f10ee11 
     DCD 0x0080e380 
     DCD 0x0f10ee01 

[ ENTRY_BUS_WIDTH=8 
     DCD 0x100f11ee 
     DCD 0x800080e3 
     DCD 0x100f01ee 
    ] 
DCD 0xffffffff  ;swinv 0xffffff is similar with NOP and run well in both endian mode. 
DCD 0xffffffff 
DCD 0xffffffff 
DCD 0xffffffff 
DCD 0xffffffff 
b ResetHandler 
;Function for entering power down mode,下面这段程序为进入掉电模式及从掉电模式中唤醒的相关设置和处理
; 1. SDRAM should be in self-refresh mode. SDRAm应该设置为自刷新的模式
; 2. All interrupt should be maksked for SDRAM/DRAM self-refresh. 所有中断必须屏蔽 for SDRAM/DRAM self-ref
; 3. LCD controller should be disabled for SDRAM/DRAM self-refresh. LCD 控制器关闭
; 4. The I-cache may have to be turned on.   
; 5. The location of the following code may have not to be changed.
//;void EnterPWDN(int CLKCON);           //PWDN:powerdown
EnterPWDN   
mov r2,r0  ;r2=rCLKCON                 //rCLKCONr [3;2]位为电源模式标置位。若[3]为1,表示转为了掉电模式
tst r0,#0x8  ;POWER_OFF mode?   //按位与判断,若[3]为1则跳转到ENTER_POWER_OFF
bne ENTER_POWER_OFF
ENTER_STOP                              //进入停止模式相关处理
ldr r0,=REFRESH  
ldr r3,[r0]  ;r3=rREFRESH 
mov r1, r3
orr r1, r1, #BIT_SELFREFRESH
str r1, [r0]                                      ;Enable SDRAM self-refresh
mov r1,#16                                   ;wait until self-refresh is issued. may not be needed.等待自刷新生效
0 subs r1,r1,#1
bne %B0                                     //表示不相等则往回跳转到标号为0的位置,在此为上一句。
ldr r0,=CLKCON                         ;enter STOP mode.
str r2,[r0]    
mov r1,#32
0 subs r1,r1,#1                           ;1) wait until the STOP mode is in effect.
bne %B0                                   ;2) Or wait here until the CPU&Peripherals will be turned-off
                                                 ;   Entering POWER_OFF mode, only the reset by wake-up is available.
                                                   //进入掉电 模式后,仅唤醒中断有效
ldr r0,=REFRESH                       ;exit from SDRAM self refresh mode.
str r3,[r0]

MOV_PC_LR                            //开始处定义的返回跳转宏
ENTER_POWER_OFF 
;NOTE.注意在rGSTATUS3寄存器中应该保存掉电模式唤醒的返回地址,rGSTATUS3,4可在掉电下保存信息
;1) rGSTATUS3 should have the return address after wake-up from POWER_OFF mode.

ldr r0,=REFRESH  
ldr r1,[r0]  ;r1=rREFRESH 
orr r1, r1, #BIT_SELFREFRESH
str r1, [r0]  ;Enable SDRAM self-refresh
mov r1,#16     ;Wait until self-refresh is issued,which may not be needed.
0 subs r1,r1,#1
bne %B0
ldr  r1,=MISCCR
ldr r0,[r1]
orr r0,r0,#(7<<17)  ;Make sure that SCLK0:SCLK->0, SCLK1:SCLK->0, SCKE=L during boot-up 
str r0,[r1]
ldr r0,=CLKCON
str r2,[r0]    
b .   ;CPU will die here.

;=================================================================================

[1] [2] [3]
关键字:ARM9  S3C2410  启动代码  ADSv1 引用地址:ARM9学习4-S3C2410的启动代码分析-For ADSv1.2

上一篇:对于51单片机和arm9开发板串口通信问题的分析
下一篇:ARM9学习3-调试第一个ARM汇编程序

推荐阅读

高性能传感器解决方案供应商艾迈斯半导体(ams AG,瑞士股票交易所股票代码:AMS)今日宣布预先推出NanEyeM——一款集成式微型摄像头模块(MCM),该图像传感器的封装尺寸非常小,仅1mm2。 NanEyeM设计紧凑,界面简单,易于集成到空间有限的工业和消费电子应用设计中,为智能玩具和家用电器等产品提供新的嵌入式视觉功能。 NanEyeM提供100k像素高分辨率的10...
近日,微软前 CEO 比尔盖茨在接受外媒采访时,罕见地谈到了自己对于华为的看法。比尔盖茨认为:“认为所有进入美国市场的中国产品都是坏的,或者所有来自美国的东西如飞机引擎、软件等都是不好的,这两种想法都很疯狂。”两个国家应该利用各自的创新,更好地相互依存。比尔盖茨表示,任何认为美国应该阻止华为进入国内的想法都是不现实的,也不是一件好事...
随着骁龙下一代旗舰处理器骁龙 875 发布时间临近,外界开始出现关于搭载这款处理器的新机爆料,小米新一代旗舰也包括在内。今天,微博 @数码闲聊站爆料称,小米首款骁龙 875 旗舰的超广角升级为 4800 万像素,单位像素面积为 0.8μm。  此前,一款型号为 M2012K11C 的小米新机现身 Geekbench 跑分网站,搭载高通 8 核处理器,猜测为小米 ...
   近日,深圳市发改委发布《关于深圳市2020年度新能源汽车充电设施建设补贴资助项目审核情况的公示》。《公示》显示,深圳市发改委计划对普天新能源(深圳)有限公司等39家企业申报的新能源汽车充电设施建设项目进行补贴。   以下为原文 关于深圳市2020年度新能源汽车充电设施建设补贴资助项目审核情况的公示   根据《深圳市2016年新能源汽车...

史海拾趣

问答坊 | AI 解惑

数字钟设计书.

本帖最后由 paulhyde 于 2014-9-15 08:55 编辑 数字钟设计书.  …

查看全部问答∨

S3C2416的wince6.0能进系统,但是找不到NANDFLASH(MLC),Lanuch的地址不对,怎么解决

手上有块S3C2416的板子wince5.0跑起来了 wince6.0能进系统,但是找不到NANDFLASH(MLC),Lanuch的地址不对,是用的SD卡启动方式。请问怎么解决?谢谢!…

查看全部问答∨

分析视频监控系统中处理芯片的应用领域

随着近3-4年来中国数字视频监控市场每年都以超过30%的比例增长和其他领域的增长,视频处理芯片市场也随之得到了增长,安防监控行业的需求逐渐明确,芯片厂家开始关注并主动去推广视频监控这个潜力巨大的市场。视频监控成为工业自动化、消费电子、电 ...…

查看全部问答∨

综合布线存在三大误区,操作应用需谨慎

  一、质量保证   提到布线系统的质量保证,每个厂商都有各自的独特表现,有的提供若干年产品质保,有的提供若干年系统质保,还有的提供终身质保。各厂商对质保的内容和方法的解释也各有不同。厂商提出质保承诺对国内用户来说是件好事,它表示 ...…

查看全部问答∨

德州仪器展示100瓦LED路灯Demo

德州仪器展示100瓦LED路灯,更亮更低碳 $(\'swf_P6k\').innerHTML=AC_FL_RunContent(\'width\', \'550\', \'height\', \'400\', \'allowNetworking\', \'internal\', \'allowScriptAccess\', \'never\', \'src\', encodeURI(\'http://player.youku ...…

查看全部问答∨

求助看门狗相关的问题

想请教下各位,我要在看门狗复位前想保存数据该怎么做?复位中断向量能做个服务程序处理吗?…

查看全部问答∨

PL2303串口调试工具资料

最近用PL2303做了一个串口调试工具,经测试很好用,需要的抱走。 有个问题谁知道解答一下只有把VDD232拨到5V的时候电脑才能认到该模块,在3V3的时候认不到。   也就是说想用3V3串口的时候, 必须先把VDD232拨到5V插入电脑,让电脑认到PL23 ...…

查看全部问答∨

如何查找TI提供的DSP开发工具

TI官方提供的查找DSP开发工具的视频,值得一看~ $(\'flv_W7r\').innerHTML=(mobileplayer() ? \"\" : AC_FL_RunContent(\'width\', \'500\', \'height\', \'375\', \'allowNetworking\', \'internal\', \'allowScriptAccess\', \'never\', \'src\' ...…

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

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

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

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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