SMARTARM2200 ADS工程在IAR EWARM 5.3上的移植(1)-启动代码(cstartup.s)分析
手上有块ZLG的SMARTARM2200(LPC2220)的板子,其中的例子都是基于ADS的,想都移植到IAR上去,同时好好研究下IAR,ARM,uCOSII。我用的IAR版本是IAR EWARM5.3.
从Micrium网站上下了uCOSII LPC2148的例子作为模板,修改好的工程可以从http://download.csdn.net/source/1485629上得到。这个工程只含有uCOS及其实例任务,FS,TCP-IP,GUI什么的之后会陆续加入,文章的描述可能与此有差异,如有疑问欢迎与我交流shevsten#gmail.com(#换为@)
启动文件:cstartup.s
;
;********************************************************************************************************
; EXCEPTION VECTORS & STARTUP CODE
;
; File : cstartup.s
; For : ARM7 or ARM9
; Toolchain : IAR EWARM V5.10 and higher
;********************************************************************************************************
;
;开始进行了一些宏定义,供下面的代码调用,如ARM的7种模式对应寄存器值还有LPC2220寄存器地址(之后会用到)
;********************************************************************************************************
; MACROS AND DEFINIITIONS
;********************************************************************************************************
; Mode, correspords to bits 0-5 in CPSR
MODE_BITS DEFINE 0x1F ; Bit mask for mode bits in CPSR
USR_MODE DEFINE 0x10 ; User mode
FIQ_MODE DEFINE 0x11 ; Fast Interrupt Request mode
IRQ_MODE DEFINE 0x12 ; Interrupt Request mode
SVC_MODE DEFINE 0x13 ; Supervisor mode
ABT_MODE DEFINE 0x17 ; Abort mode
UND_MODE DEFINE 0x1B ; Undefined Instruction mode
SYS_MODE DEFINE 0x1F ; System mode
;Extenal bus controller Definitions
PINSEL2 DEFINE 0xE002C014
BCFG0 DEFINE 0xFFE00000
BCFG1 DEFINE 0xFFE00004
BCFG2 DEFINE 0xFFE00008
BCFG3 DEFINE 0xFFE0000C
;这边使用了DEFINE这个关键字,和EQU相比,其作用域更大,相当于全局的。EQU只在定义的模块内有效,而DEFINE定义的宏在其他文件中同样有效,详情请参考EWARM_AssemblerReference.ENU.pdf。
;ARM异常向量
;********************************************************************************************************
; ARM EXCEPTION VECTORS
;********************************************************************************************************
;SECTION-段声明(也可用RSEG) .intvec-复位及中断向量 CODE-代码段
;NOROOT表示如果这个段里的标号没引用就被linker舍弃,ROOT则一定不舍弃
;如果注释掉PUBLIC __vector_0x14,那么编译后在map文件里就看不到第二行了
;__vector 0x80000000 Code Gb cstartup.o [1]
;__vector_0x14 0x80000014 Code Gb cstartup.o [1]
;(2)表示字节对齐数,为2的幂,(2)表示4字节对齐,(3)表示8字节对齐
SECTION .intvec:CODE:NOROOT(2)
;声明可以被外部引用的标号
PUBLIC __vector
PUBLIC __iar_program_start
PUBLIC __vector_0x14
;引用外部声明的标号,这些标号定义在os_cpu_a.asm(uCOSII移植文件)中
IMPORT OS_CPU_ARM_ExceptUndefInstrHndlr
IMPORT OS_CPU_ARM_ExceptSwiHndlr
IMPORT OS_CPU_ARM_ExceptPrefetchAbortHndlr
IMPORT OS_CPU_ARM_ExceptDataAbortHndlr
IMPORT OS_CPU_ARM_ExceptIrqHndlr
IMPORT OS_CPU_ARM_ExceptFiqHndlr
;告诉编译器为arm指令,也可以用CODE32
ARM
;异常向量表
__vector:
;绝对跳转,跳转到相应的异常处理程序,PC总是指向当前指令的下两条指令的地址,即PC的值为当前指令的地址值加8个字节。
;所以LDR PC, [PC,#24]跳转到24+8=32字节后,第一行LDR PC, [PC,#24]就是跳转到__iar_program_start(相当于reset_handler)
LDR PC, [PC,#24] ; Absolute jump can reach 4 GByte
LDR PC, [PC,#24] ; Branch to undef_handler
LDR PC, [PC,#24] ; Branch to swi_handler
LDR PC, [PC,#24] ; Branch to prefetch_handler
LDR PC, [PC,#24] ; Branch to data_handler
__vector_0x14:
DC32 0 ; Reserved
LDR PC, [PC,#24] ; Branch to irq_handler
LDR PC, [PC,#24] ; Branch to fiq_handler
;DC32指的是定义32位的常量,同理还有DC16 DS32等数据类型
DC32 __iar_program_start
DC32 OS_CPU_ARM_ExceptUndefInstrHndlr
DC32 OS_CPU_ARM_ExceptSwiHndlr
DC32 OS_CPU_ARM_ExceptPrefetchAbortHndlr
DC32 OS_CPU_ARM_ExceptDataAbortHndlr
DC32 0
DC32 OS_CPU_ARM_ExceptIrqHndlr
DC32 OS_CPU_ARM_ExceptFiqHndlr
;********************************************************************************************************
; LOW-LEVEL INITIALIZATION
;********************************************************************************************************
;定义各种模式STACK,具体大小位置是由linker文件(相当于ADS中的分散加载)决定的,之后在详细介绍。这些STACK都定义在内部RAM中,以CSTACK为例,地址为0x40000040
SECTION FIQ_STACK:DATA:NOROOT(3)
SECTION IRQ_STACK:DATA:NOROOT(3)
SECTION SVC_STACK:DATA:NOROOT(3)
SECTION ABT_STACK:DATA:NOROOT(3)
SECTION UND_STACK:DATA:NOROOT(3)
SECTION CSTACK:DATA:NOROOT(3)
;定义text代码段
SECTION text:CODE:NOROOT(2)
;强制__vector被引用,这样__vector就一定会被link了
REQUIRE __vector
;引用外部C main函数
EXTERN ?main
;声明__iar_program_start和lowlevel_init标号
PUBLIC __iar_program_start
PUBLIC lowlevel_init
;__iar_program_start内容,实际上就是系统复位后首先运行的代码
__iar_program_start:
;********************************************************************************************************
; STACK POINTER INITIALIZATION
;********************************************************************************************************
;初始化堆栈指针,就不详细描述了,主要就是对CPSR寄存器的操作,请参考ARM相关资料
MRS r0,cpsr ; Original PSR value
BIC r0,r0,#MODE_BITS ; Clear the mode bits
ORR r0,r0,#SVC_MODE ; Set SVC mode bits
MSR cpsr_c,r0 ; Change the mode
LDR sp,=SFE(SVC_STACK) ; End of SVC_STACK
BIC r0,r0,#MODE_BITS ; Clear the mode bits
ORR r0,r0,#UND_MODE ; Set UND mode bits
MSR cpsr_c,r0 ; Change the mode
LDR sp,=SFE(UND_STACK) ; End of UND_STACK
BIC r0,r0,#MODE_BITS ; Clear the mode bits
ORR r0,r0,#ABT_MODE ; Set ABT mode bits
MSR cpsr_c,r0 ; Change the mode
LDR sp,=SFE(ABT_STACK) ; End of ABT_STACK
BIC r0,r0,#MODE_BITS ; Clear the mode bits
ORR r0,r0,#FIQ_MODE ; Set FIQ mode bits
MSR cpsr_c,r0 ; Change the mode
LDR sp,=SFE(FIQ_STACK) ; End of FIQ_STACK
BIC r0,r0,#MODE_BITS ; Clear the mode bits
ORR r0,r0,#IRQ_MODE ; Set IRQ mode bits
MSR cpsr_c,r0 ; Change the mode
LDR sp,=SFE(IRQ_STACK) ; End of IRQ_STACK
BIC r0,r0,#MODE_BITS ; Clear the mode bits
ORR r0,r0,#SYS_MODE ; Set System mode bits
MSR cpsr_c,r0 ; Change the mode
LDR sp,=SFE(CSTACK) ; End of CSTACK
;********************************************************************************************************
; ADDITIONAL INITIALIZATION
;********************************************************************************************************
;这段初始化代码是我添加的,主要用来设置外部总线控制器,使外接的PSRAM等外设能正常工作,这样程序的readwrite段就能在RAM中运行了
lowlevel_init:
;Initial extenal bus controller.
LDR R0, =PINSEL2
LDR R1, =0x0f814914
STR R1, [R0]
; 定义总线速度控制字
LDR R0, =BCFG0
LDR R1, =0x1000ffef
STR R1, [R0]
LDR R0, =BCFG1
LDR R1, =0x1000ffef
STR R1, [R0]
LDR R0, =BCFG3
LDR R1, =0x10001460
STR R1, [R0]
;********************************************************************************************************
; CONTINUE TO ?main FOR ADDITIONAL INITIALIZATION
;********************************************************************************************************
;跳转到C代码中的main函数
LDR r0,=?main
BX r0
END