b . ;reserved 保留未用 注意小圆点 0X14
b HandlerIRQ ;handlerfor IRQ interrupt 0X18
b HandlerFIQ ;handlerfor FIQ interrupt 0X1C
;这7个中断,每个中断都有固定的中断入口地址,它们位于代码的最前端,不允许另作他用
;@0x20
b EnterPWDN ;Must be 0x20
;下面是改变大小端的程序,采用直接定义 <机器码> 的方式,为什么这么做就得问三星了
;反正我们程序里这段代码也不会去执行,不用去管它
;每一个汇编指令,都对应着一个二进制机器码,这里没有使用指令,直接用了机器码,含义未知
ChangeBigEndian
;@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
;对存储器控制寄存器操作,指定内存模式为Big-endian
;因为刚开始CPU都是按照32位总线的指令格式运行的,如果采用其他的话,CPU别不了,必须转化
;但当系统初始化好以后,则CPU能自动识别
]
[ENTRY_BUS_WIDTH=16
DCD0x0f10ee11
DCD0x0080e380
DCD0x0f10ee01
;因为采用Big-endian模式,采用16位总线时,物理地址的高位和数据的地位对应
;所以指令的机器码也相应的高低对调
]
[ENTRY_BUS_WIDTH=8
DCD0x100f11ee
DCD0x800080e3
DCD0x100f01ee
]
DCD0xffffffff ;swinv 0xffffff is similarwith NOP and run well in both endian mode.
DCD0xffffffff
DCD0xffffffff
DCD0xffffffff
DCD0xffffffff
bResetHandler ;设置成大端后,再次跳到复位指令处
;本文件底部定义了一个数据区(在文件最后),34个字空间,存放相应中断服务程序的首地址。每个字
;空间都有一个标号,以Handle***命名。
;这是宏实例 在这里Handler***就是通过HANDLER这个宏和Handle***建立联系的.
;详细分析:
; 这是宏示例,也就是宏的调用指令,当编译时编译器会把宏调用指令展开
; 这是向量中断
;展开方式(举例):
;HandlerFIQ HANDLERHandleFIQ
;展开后变成:
;HandlerFIQ ;标号,由 " b HandlerFIQ "指令使用(见上,复位处)
; sub sp,sp,#4 ;留出一个空间,为了存放跳转地址给pc。见:strr0,[sp,#4] ,注意sp值并未改变
;
; stmfd sp!,{r0} ;把r0中的内容入栈,保存起来
;
; ldr r0,=HandleFIQ ;HandleFIQ标号,在本文件最下方定义
;
; ldr r0,[r0] ;把HandleXXX所指向的内容(也就是中断程序的入口地址)放入r0
;
; str r0,[sp,#4] ;把入口地址放入刚才留出的一个空间里
;
; ldmfd sp!,{r0,pc} ;出栈的方式恢复r0原值和为pc设定新值(也就完成了到ISR的转跳)。注:栈中r0内容在低地址
;
; 后边的语句展开方式,同上。编译后,代码都展开放置
HandlerFIQ HANDLERHandleFIQ
HandlerIRQ HANDLERHandleIRQ
HandlerUndef HANDLER HandleUndef
HandlerSWI HANDLERHandleSWI
HandlerDabort HANDLER HandleDabort
HandlerPabort HANDLER HandlePabort
;非向量中断总入口(需要自己判断中断类型,而不是直��跳转到相应程序)
;产生中断后,需要中断服务程序自己来判断,到底是哪个中断请求,根据的就是INTOFFSET寄存器中的偏移,再计算中断服务地址
IsrIRQ
sub sp,sp,#4 ;reserved for PC,预留返回指针的存储位置
stmfd sp!,{r8-r9}
ldr r9,=INTOFFSET ;the interrupt request source offset
ldr r9,[r9]
ldr r8,=HandleEINT0 ;HandleEINT0 ,在本文件最下边定义的
add r8,r8,r9,lsl #2 ;r9中只是偏移单位的个数,需要*4变成具体字节偏移(相对于EINT0)
ldr r8,[r8]
str r8,[sp,#8] ;pc值放在了高位置
ldmfd sp!,{r8-r9,pc}
LTORG
;LTORG用于声明一个文字池,在使用LDR伪指令时,要在适当的地方加入LTORG声明文字池,这样就会把要加载的数据保存在
;文字池内,再用ARM的《加载指令》读出数据。(若没有使用LTORG声明文字池,则汇编器会在程序末尾自动声明)
;LTORG 伪指令常放在无条件跳转指令之后,或者子程序返回指令之后,这样处理器就不会错误地将文字池中的数据当做指令来执行
;注:在此,文字池内存储的是INTOFFSET宏所代表的值:0x4a000014 。毕竟,当把指令编译成二进制代码时,arm指令(32位)
;不能既表示出指令内容,又表示出数据地址(32位)。估计在编译时,会被汇编成其他的加载指令,再编译成机器码
;LTORG 只要单独写出来就可以了,其他的交给编译器来做,而且它跟它下面的代码没有任何关系
;=======
; ENTRY
;=======
ResetHandler
ldr r0,=WTCON ;watch dog disable 编译时就是 ldr r0,=53000000;伪指令有=号