MEND
;将$HandleLabel地址空间中的数据给PC,中断服务程序的入口
IMPORT |Image$$RO$$Limit| ; End of ROM code (=start of ROM data)
IMPORT |Image$$RW$$Base| ; Base of RAM to initialise
IMPORT |Image$$ZI$$Base| ; Base and limit of area
IMPORT |Image$$ZI$$Limit| ; to zero initialise
IMPORT Main
;导入要用到的字符常量
AREA Init,CODE,READONLY
;异常中断矢量表(每个表项占4个字节) 下面是中断向量表 一旦系统运行时有中断发生 即使移植了操作
;系统 如linux 处理器已经把控制权交给了操作系统 一旦发生中断 处理器还是会跳转到从0x0开始
;中断向量表中某个中断表项(依据中断类型)开始执行
;具体中断向量布局请参考s3c44b0 spec 例如 adc中断向量为 0x000000c0下面对应表中第49项位置向量地址0x0+4*(49-1)=0x000000c0
ENTRY
;板子上电和复位后 程序开始从位于0x0处开始执行硬件刚刚上电复位后 程序从这里开始执行跳转到标
;为ResetHandler处执行
;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 cant be used here because the linker generates error.
;条件编译,在编译成机器码前就设定好
ASSERT :DEF:ENDIAN_CHANGE ;判断ENDIAN_CHANGE是否已定义
[ ENDIAN_CHANGE ;如果已经定义了ENDIAN_CHANGE,则判断,here is FALSE
ASSERT :DEF:ENTRY_BUS_WIDTH ;判断ENTRY_BUS_WIDTH是否已定义
][ ENTRY_BUS_WIDTH=32 ;如果已经定义了ENTRY_BUS_WIDTH,则判断是不是为32
b ChangeBigEndian ;DCD 0xea000007
]
;在bigendian中,地址为A的字单元包括字节单元A,A+1,A+2,A+3,字节单元由高位到低位为A,A+1,A+2,A+3
; 地址为A的字单元包括半字单元A,A+2,半字单元由高位到低位为A,A+2
[ ENTRY_BUS_WIDTH=16
andeq r14,r7,r0,lsl #20 ;DCD 0x0007ea00 也是b ChangeBigEndian指令,只是由于总线不一样而取机器码的顺序不一样
] ;先取低位->高位 上述指令是通过机器码装换而来的
[ ENTRY_BUS_WIDTH=8
streq r0,][r0,-r10,ror #1] ;DCD 0x070000ea 也是b ChangeBigEndian指令,只是由于总线不一样而取机器码的顺序不一样
]
|
b ResetHandler ;//here is the first instrument 0x00
]
b HandlerUndef ;handler for Undefined mode ;0x04
b HandlerSWI ;handler for SWI interrupt ;0x08
b HandlerPabort ;handler for PAbort ;0x0c
b HandlerDabort ;handler for DAbort ;0x10
b . ;reserved ;0x14
b HandlerIRQ ;handler for IRQ interrupt ;0x18
b HandlerFIQ ;handler for FIQ interrupt ;0x1c
;@0x20
b EnterPWDN ; Must be @0x20.
;通过设置CP15的C1的位7,设置存储格式为Bigendian,三种总线方式
ChangeBigEndian ;//here ENTRY_BUS_WIDTH=16
;@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
DCD 0x0f10ee11
DCD 0x0080e380
DCD 0x0f10ee01
;因为采用Big-endian模式,采用16位总线时,物理地址的高位和数据的地位对应
;所以指令的机器码也相应的高低对调
]
[ 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.
; 2. All interrupt should be maksked for SDRAM/DRAM self-refresh.
; 3. LCD controller should be disabled for SDRAM/DRAM self-refresh.
; 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);
EnterPWDN
mov r2,r0 ;r2=rCLKCON 保存原始数据 0x4c00000c 使能各模块的时钟输入
tst r0,#0x8 ;测试bit[3] SLEEP mode? 1=>sleep
|