历史上的今天
今天是:2024年11月08日(星期五)
2019年11月08日 | ARM9学习4-S3C2410的启动代码分析-For ADSv1.2
2019-11-08 来源:51hei
通常,启动代码是指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.
;=================================================================================
史海拾趣
|
Android编译环境(1) - 编译Native C的helloworld模块 ZT Android编译环境本身比较复杂,且不像普通的编译环境:只有顶层目录下才有Makefile文件,而其他的每个component都使用统一标准的Android.mk. Android.mk文件本身是比较简单的,不过它并不是我们熟悉的Makefile,而是经过了Android自身编译系统的很 ...… 查看全部问答> |
|
你的能力并不能确保你的安全 很多公司在招聘员工或对外宣传时说我们公司注重员工的能力,提倡员工能发挥自己的主观能动性 (确实有一些公司是提倡创新的,但是极少数,大部分都只是打打口号而已)。对于刚入职的员工来说可能都会有一种心理,那就 ...… 查看全部问答> |
|
要做个充电器,不知道与充电芯片相连的元件的参数.还有接口要接MICROUSB,有四条线,地线、读数据线、写数据线、+5V线 ,就直接把OUT接在5V线上就可以了贝? … 查看全部问答> |
|
比如在IE中点击一个avi文件的链接,自动就会启动mediaplayer来播放,如果点击一个bt文件的链接,自动就会启动bt程序来下载,这个过程如何实现?需要用到哪些技术?请高手指点 … 查看全部问答> |
|
初学嵌入式软件开发,不知道该从那些方面入手,有经验的可否提供一些建议? 我是学软件工程的,专业方向选的是嵌入式方向,现在课程比较少 我想先找点书看,可不知道该看什么样的书,大家可否给点意见?… 查看全部问答> |
|
感创ZT2000自动借还书设备是通过与图书馆自动化系统数据相连接,由读者自行借还馆内图书资料;帮助图书馆在有限的人力资源条件下,增进图书流通速率、简化借还流程,进而提高图书馆从业人员工作效率及服务品质的一种自助设备。 该自助借还书设备 ...… 查看全部问答> |
|
传索尼最早将在今年年底前全球裁员1万人,约占雇员总数的6%。这家公司一直是日系企业的中间代表,大家知道日系企业的一大特点就是不到万不得已是尽量不裁员,号召企业与员工共同成长,这比中国的国企还国企。究竟日本电子企业出什么问题了,本人不 ...… 查看全部问答> |




