;========================================= ; NAME: 2440INIT.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,Sleep mode ; 2003.03.14:DonGo: Modified for 2440. ;=========================================
;首先,启动代码定义了一些常量 GET option.inc GET memcfg.inc GET 2440addr.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
;定义处理器各模式下堆栈地址常量 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 ~
;检查在tasm.exe里是否设置了采用THUMB(16位)代码(armasm -16 ...@ADS 1.0) GBLL THUMBCODE ;定义THUMBCODE全局变量 [ {CONFIG} = 16 ;如果发现是才用16位代码的话 THUMBCODE SETL {TRUE} ;把THUMBCODE设置为TURE CODE32 ;把处理器从新设置成为ARM模式 | ;如果处理器现在就是ARM模式 THUMBCODE SETL {FALSE} ;把THUMBCODE设置为FALSE就行了 ]
MACRO ;一个根据THUMBCODE把PC寄存的值保存到LR的宏 MOV_PC_LR [ THUMBCODE bx lr ;在ARM模式中要使用BX指令转跳到THUMB指令,并转换模式 | mov pc,lr ;如果目标地址也是ARM指令的话就采用这种方式 ] MEND
MACRO ;和上面的宏一样,只是多了一个相等的条件 MOVEQ_PC_LR [ THUMBCODE bxeq lr | moveq pc,lr ] MEND
;======================================================================================= ;下面这个宏是用于第一次查表过程的实现中断向量的重定向,如果你比较细心的话就是发现 ;在_ISR_STARTADDRESS=0x33FF_FF00里定义的第一级中断向量表是采用型如Handle***的方式的. ;而在程序的ENTRY处(程序开始处)采用的是b Handler***的方式. ;在这里Handler***就是通过HANDLER这个宏和Handle***进立联系的. ;这种方式的优点就是正真定义的向量数据在内存空间里,而不是在ENTRY处的ROM(FLASH)空间里, ;这样,我们就可以在程序里灵活的改动向量的数据了. ;========================================================================================
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)压入栈 ldmfd sp!,{r0,pc} ;用出栈的方式恢复r0的原值和为pc设定新值(也就完成了到ISR的转跳) MEND
;========================================================================================= ;在这里用IMPORT伪指令(和c语言的extren一样)引入|Image$$RO$$Base|,|Image$$RO$$Limit|... ;这些变量是通过ADS的工程设置里面设定的RO Base和RW Base设定的, ;最终由编译脚本和连接程序导入程序. ;那为什么要引入这玩意呢,最简单的用处是可以根据它们拷贝自已 ;========================================================================================== IMPORT |Image$$RO$$Base| ; ROM code(也就是代码)的开始地址 IMPORT |Image$$RO$$Limit| ; ROM code的结束地址 (=ROM data的开始地址) IMPORT |Image$$RW$$Base| ; 要初始化的RAM的开始地址 IMPORT |Image$$ZI$$Base| ; area(需要清零的RAM区域)的开始地址 IMPORT |Image$$ZI$$Limit| ; area的结束地址
;这里引入一些在其它文件中实现在函数,包括为我们所熟知的main函数 IMPORT MMU_SetAsyncBusMode IMPORT MMU_SetFastBusMode ;hzh
IMPORT Main ; The main entry of mon program
;从这里开始就是正真的代码入口了! AREA Init,CODE,READONLY ;这表明下面的是一个名为Init的代码段
ENTRY ;定义程序的入口(调试用)
EXPORT __ENTRY ;导出符号_ENTRY,但在那用到就还没查明 __ENTRY ResetEntry ;1)The code, which converts to Big-endian, should be in little endian code. ;2)The following little endian code will be compi |