S3C2440init 分析文档格式.docx
《S3C2440init 分析文档格式.docx》由会员分享,可在线阅读,更多相关《S3C2440init 分析文档格式.docx(21页珍藏版)》请在冰豆网上搜索。
禁止IRQ、FIQ中断
定义对应于各堆栈地址的常量(大小自行定义)
UserStackEQU(_STACK_BASEADDRESS-0x3800);
0x33ff4800~
SVCStackEQU(_STACK_BASEADDRESS-0x2800);
0x33ff5800~4KB
UndefStackEQU(_STACK_BASEADDRESS-0x2400);
0x33ff5c00~9KB
AbortStackEQU(_STACK_BASEADDRESS-0x2000);
0x33ff6000~5KB
IRQStackEQU(_STACK_BASEADDRESS-0x1000);
0x33ff7000~4KB
FIQStackEQU(_STACK_BASEADDRESS-0x0);
0x33ff8000~4KB
根据编译器内置的常量CONFIG来判断是否使用的是汇编编译器TASM.EXE
GBLLTHUMBCODE
[{CONFIG}=16
THUMBCODESETL{TRUE}
CODE32;
若是,则"
告诉"
编译器,后面的指令为ARM指令,并启用ARMASM.EXE编译器
|
THUMBCODESETL{FALSE}
]
定义异常处理宏
MACRO
$HandlerLabelHANDLER$HandleLabel
$HandlerLabel
subsp,sp,#4;
留出堆栈空间以存储第一级异常处理函数的地址
stmfdsp!
{r0};
保存需要用到的寄存器R0到堆栈中(先对堆栈指针进行减操作)
ldrr0,=$HandleLabel;
加载$HandleLabel的值到R0
ldrr0,[r0];
加载$HandleLabel地址所指向的内容(即第一级异常处理函数的地址)到R0
strr0,[sp,#4];
将第一级异常处理函数的地址放到预留堆栈空间内
ldmfdsp!
{r0,pc};
从堆栈中取出数据,并将PC值指向第一级异常处理函数的地址
MEND
IMPORTMain;
C语言的入口函数Main,不能使用main的原因是当使用ARMC库以实现程序从加载域到运行域的初始化时,程序默认跳到main处
AREAInit,CODE,READONLY
ENTRY
ResetEntry
;
判断是否要更改指令模式
32位的数据需要2个16位或4个8位来存储,基于此,可以理解DCD后面的数值的位置需要对换
ASSERT:
DEF:
ENDIAN_CHANGE
[ENDIAN_CHANGE
ENTRY_BUS_WIDTH
[ENTRY_BUS_WIDTH=32
bChangeBigEndian;
DCD0xea000007
]
[ENTRY_BUS_WIDTH=16
andeqr14,r7,r0,lsl#20;
DCD0x0007ea00
[ENTRY_BUS_WIDTH=8
streqr0,[r0,-r10,ror#1];
DCD0x070000ea
|
bResetHandler;
bHandlerUndef;
handlerforUndefinedmode
bHandlerSWI;
handlerforSWIinterrupt
bHandlerPabort;
handlerforPAbort
bHandlerDabort;
handlerforDAbort
b.;
死循环
bHandlerIRQ;
handlerforIRQinterrupt
bHandlerFIQ;
handlerforFIQinterrupt
将小段模式更改为大端模式(通过更改协处理器P15中的寄存器C1的第八位来实现)
ChangeBigEndian
[ENTRY_BUS_WIDTH=32
mrcp15,0,r0,c1,c0,0;
DCD0xee110f10
orrr0,r0,#0x80;
DCD0xe3800080
mcrp15,0,r0,c1,c0,0;
DCD0xee010f10
[ENTRY_BUS_WIDTH=16
DCD0x0f10ee11
DCD0x0080e380
DCD0x0f10ee01
DCD0x100f11ee
DCD0x800080e3
DCD0x100f01ee
DCD0xffffffff;
等待小端模式切换到大端模式,相当于NOP指令,只是该指令在大小端模式下更兼容
DCD0xffffffff
更改完后,跳到复位异常
HandlerFIQHANDLERHandleFIQ
HandlerIRQHANDLERHandleIRQ
HandlerUndefHANDLERHandleUndef
HandlerSWIHANDLERHandleSWI
HandlerDabortHANDLERHandleDabort
HandlerPabortHANDLERHandlePabort
IsrIRQ
subsp,sp,#4;
留出堆栈空间,存储第二级异常处理函数的地址
{r8-r9};
保存需要用到的寄存器R8、R9到堆栈中(先对堆栈指针进行减操作)
ldrr9,=INTOFFSET;
获取中断类型偏移值所对应的寄存器地址
ldrr9,[r9];
加载偏移值寄存器中的值
ldrr8,=HandleEINT0;
获取由程序所定义的外部中断异常向量表的首地址
addr8,r8,r9,lsl#2;
获取外部异常中断所对应的地址
ldrr8,[r8]
strr8,[sp,#8];
加载外部异常中断地址所指向的内容,即第二级异常处理函数的地址
{r8-r9,pc};
恢复寄存器R8\R9中的值,并使程序跳转到第二级异常处理函数处执行
LTORG;
声明文件池,常与LDR伪指令连用
初始化硬件
ResetHandler
ldrr0,=WTCON;
关闭看门狗
ldrr1,=0x0
strr1,[r0]
ldrr0,=INTMSK
ldrr1,=0xffffffff;
关闭所有中断
strr1,[r0]
ldrr0,=INTSUBMSK
ldrr1,=0x7fff;
关闭所有子中断
[{FALSE};
若无仿真器,可将FALSE改为TRUE,然后下载程序到开发板,若灯亮且蜂蜜器响,说明程序执行了该初始化代码
ldrr0,=GPBCON
ldrr1,=0x555555
strr1,[r0]
ldrr0,=GPBDAT
ldrr1,=0x1
设定PLL锁定时间。
该寄存器的取值方法:
值>
最小时间(如:
300us,见DATASHEET?
*Fin
ldrr0,=LOCKTIME
ldrr1,=0xfff0fff;
或为0xffffffff最大值
[PLL_ON_START;
{TRUE}
设置CLKDIVN寄存器的值
ldrr0,=CLKDIVN
ldrr1,=CLKDIV_VAL
切换始终模式(通过协处理器P15来进行。
S3C2440两种模式:
异步模式和高速模式,不支持同步模式)
[CLKDIV_VAL>
1;
即HDIVN不等于,应切换到异步模式
mrcp15,0,r0,c1,c0,0
orrr0,r0,#0xc0000000;
R1_nF:
OR:
R1_iA
mcrp15,0,r0,c1,c0,0
bicr0,r0,#0xc0000000;
R1_iA:
R1_nF
配置UPLL
ldrr0,=UPLLCON
ldrr1,=((U_MDIV<
<
12)+(U_PDIV<
4)+U_SDIV)
nop;
等待7个时钟的延迟,以使硬件完成配置
nop
配置MPLL
ldrr0,=MPLLCON
ldrr1,=((M_MDIV<
12)+(M_PDIV<
4)+M_SDIV);
Fin=12MHz
初始化各模式下的堆栈
blInitStacks
建立IRQ中断向量表
ldrr0,=HandleIRQ
ldrr1,=IsrIRQ
[THUMBCODE
orrlr,pc,#1
bxlr
CODE16
blMain
b.
CODE32
b.;
调试时,若Main函数中无死循环,则调用完Main函数后,程序即执行该行代码,进入死循环。
不再执行自编代码
初始化堆栈。
即将以分配的地址空间赋值到各模式下的堆栈中
InitStacks
mrsr0,cpsr
bicr0,r0,#MODEMASK
orrr1,r0,#UNDEFMODE|NOINT
msrcpsr_cxsf,r1;
UndefMode
ldrsp,=UndefStack