启动代码是几乎是每个ARM程序程序必备的,刚开始看的时候看别人的启动代码时感觉云里雾里,所以懒惰的想法浮现脑中:别人都写好了我还写什么,直接拿来用不就行了,对在我懂得情况下,我一定会拿来就用,但是现在我还不懂,一切就要从头开始,经过几天的努力,现在的感觉是启动代码不过如此 ![]() ;--------------------------------------------------------------------- ;startup.s ;系统启动代码 ;起始时间 : 2009.5.7 ----->2009.5.11 ;--------------------------------------------------------------------- ;--------------------------------------------------------------------- GET ./Include/s3c2440.inc ;寄存器地址信息 GET ./Include/mEMCfg.inc ;内存控制器配置信息 ;处理器模式 USERMODE EQU 0x10 FIQMODE EQU 0x11 IRQMODE EQU 0x12 SVCMODE EQU 0x13 ABORTMODE EQU 0x17 UNDEFMODE EQU 0x1b SYSMODE EQU 0x1f ;相关掩码 MODEMASK EQU 0x1f NOINT EQU 0xc0 ;各个处理器模式下堆栈设置 _STACK_BASEADDRESS EQU 0x33ff8000 ;BANK6 64MB顶部 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 ~ ;导入操作系统入口函数 IMPORT OSEntry ;导入外部C语言编写的异常与中断处理函数 IMPORT vectorUNDEF IMPORT vectorSWI IMPORT vectorPABT IMPORT vectorDABT IMPORT vectorIRQ IMPORT vectoRFIQ ;导入镜像装载域段起始地址 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 ;-------------------------------------------------------------------- ;------------------------------------------------------ AREA startup, CODE, READONLY ENTRY ;系统向量表 b vectorRESET ;复位向量 b vectorUNDEF ;未定义指令 b vectorSWI ;软中断 b vectorPABT ;预取指终止 b vectorDABT ;数据终止 b . ;系统保留 b vectorIRQ ;外部中断 b vectorFIQ ;快速中断 ;------------------------------------------------------- ;-------------------------------------------------------------------------- ;复位向量 ;复位向量是ARM处理器上电后第一个被执行的异常 ;此时系统处理管理(SVC)模式 vectorRESET ;复位向量有以下六件事要做 ;第一步 : 关闭看门狗定时器屏蔽所有中断 ;第二步 : 配置系统时钟 ;第三步 : 配置内存控制器 ;第四步 : 配置每种处理器模式下堆栈指针 ;第五步 : 初始化镜像运行域 ;第六步 : 跳转到操作系统入口 ;------------------------------------------ ;第一步 : 关闭看门狗定时器 ;具体内容请参看s3c2440a数据手册的第18章 ldr r0, =WTCON ldr r1, =0x0 str r1, [r0, #0x0] ;屏蔽所有中断 ldr r0, =INTMSK ldr r1, =0xffffffff str r1, [r0] ;------------------------------------------ ;------------------------------------------ ;第二步 : 配置系统时钟 ;具体内容请看手册第7章 ;先减少锁相环锁定时间,s3c2440a要求PLL ;锁定时间>300us,在上电时s3c2440a预设值 ;mpll为晶体频率,我用的晶体频率为12MHz ;300us*12M = 3600设置LOCKTIME = 0xfff ;足够了 ldr r0, =LOCKTIME ldr r1, =0xfff0fff0 ;高16为对应UPLL ;低16为对应MPLL str r1, [r0, #0x0] ;根据器件手册我们还有以下几个事要做 ;step1.配置UPLL ;step2.配置MPLL ;注:手册要求先配置UPLL后MPLL ; 且之间要间隔7NOP ; 详请看手册第7-21. ;step3.配置分频系数 ;step1: ldr r0, =UPLLCON ldr r1, =((56<<12) + (2<<4) + 2) ldr r1, [r0] ;按手册要求插入7个NOP nop nop nop nop nop nop nop ;step2: ldr r0, =MPLLCON ldr r1, =((127<<12) + (2<<4) + 1) ldr r1, [r0] ;step3: ldr r0, =CLKDIVN ldr r1, =((0<<3) + (2 << 2) + 1) ldr r1, [r0] ;------------------------------------------ ;------------------------------------------ ;第三步 : 配置内存控制器 ;内存控制内的寄存器器地址是连续分布的 ;从0x4800_0000 -- 0x4800_0030,所以可以 ;通过一个循环依次填入各个寄存器的内容 ldr r0, =SMRDATA ;装入配置值的地址 ldr r1, =BWSCON ;装入起始寄存器地址 add r2, r0, #0x34 ;计算结束地址 ;下面是用于向内存控制器 ;装入配置信息的循环 0 ldr r3, [r0], #4 ;装入配置值到r3,后变址 str r3, [r1], #4 ;把r3内包含的配置值写入 ;内存控制器的寄存器 cmp r2, r0 ;结束否? bne %B0 ;没结束则继续 ;------------------------------------------ ;------------------------------------------ ;第四步 : 配置每种处理器模式下堆栈指针 ;方法与原则: ;1: 通过CPSR寄存器切换处理器模式 ;2: 对CPSR的操作方式为 读-修改-写回 ;3: 绝对不要跳到用户模式,跳过去容易 ; 回来就难了 ;4: 切到新处理器模式后要屏蔽IRQ和FIQ ; 防止在未设置好堆栈前进入中断处理 ; 程序,但是在启动代码的最先我们已 ; 经屏蔽了所有的32个中断源,所以感 ; 觉是否屏蔽都可以 ;step1: 先把程序状态寄存器读到r0 mrs r0, cpsr ;step2: 清除处理器模式位(最前面5位) bic r0, r0, #MODEMASK ;step3: 设置未定义状态下的堆栈指针 orr r1, r0, #UNDEFMODE|NOINT msr cpsr_cxsf, r1 ;UndefMode ldr sp, =UndefStack ;UndefStack=0x33FF_5C00 ;step4: 设置终止状态下的堆栈指针 orr r1, r0, #ABORTMODE|NOINT msr cpsr_cxsf, r1 ;AbortMode ldr sp, =AbortStack ;AbortStack=0x33FF_6000 ;step5: 设置中断模式下的堆栈指针 orr r1, r0, #IRQMODE|NOINT msr cpsr_cxsf, r1 ;IRQMode ldr sp, =IRQStack ;IRQStack=0x33FF_7000 ;step6: 设置快速中断模式下的堆栈指针 orr r1, r0, #FIQMODE|NOINT msr cpsr_cxsf, r1 ;FIQMode ldr sp, =FIQStack ;FIQStack=0x33FF_8000 ;step7: 设置管理模式下的堆栈指针 orr r1, r0, #SVCMODE|NOINT msr cpsr_cxsf, r1 ;SVCMode ldr sp, =SVCStack ;SVCStack=0x33FF_5800 ;step8: 因为管理模式与用户模式共用 ; 堆栈指针,所以借着系统模式 ; 来设置用户模式的堆栈指针 orr r1, r0, #SYSMODE|NOINT msr cpsr_cxsf, r1 ;SYSMode ldr sp, =UserStack ;SVCStack & USERMode=0x33ff4800 ;现在处理器处于系统模式 ;------------------------------------------ ;------------------------------------------ ;第五步 : 初始化镜像运行域 ;复制RW段和ZI段到SDRAM指定地址 LDR r0, =|Image$$RO$$Limit| ; 装入RO段结束地址 LDR r1, =|Image$$RW$$Base| ; 装入RW段起始地址 LDR r3, =|Image$$ZI$$Base| ; 装入ZI段起始地址 ;|Image$$RO$$Limit| == |Image$$RW$$Base| ? 跳过RW段复制 : 复制RW段 CMP r0, r1 BEQ %F2 ;复制RW段 1 CMP r1, r3 LDRCC r2, [r0], #4 STRCC r2, [r1], #4 BCC %B1 2 LDR r1, =|Image$$ZI$$Limit| MOV r2, #0 ;构造ZI段 3 CMP r3, r1 STRCC r2, [r3], #4 BCC %B3 ;------------------------------------------ ;------------------------------------------ ;第六步 : 跳转到操作系统入口 b OSEntry ;不要使用main,因为如果使用main ;ads还会调用_main()初始化RW和ZI ;段,但是那里的数据和本程序不同 b . ;------------------------------------------ ;--------------------------------------------------------------------------- SMRDATA DATA ;这里是内存控制器的配置数据 ;配置数据需要根据你使用的存储器修改 ;在第三步时会将以下数据写入 ;内存控制器的相关寄存器中 ;共13个寄存器的配置值 DCD (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28)) DCD ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC)) ;GCS0 DCD ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC)) ;GCS1 DCD ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC)) ;GCS2 DCD ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC)) ;GCS3 DCD ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<< 关键字:arm 程序必备 启动代码 |
关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )
GMT+8, 2025-8-13 08:15 , Processed in 0.109375 second(s), 27 queries , Gzip On.
地址:深圳市南山区科技生态园2栋A座805 电话:19926409050