德国赫优讯自动化有限公司 浙江华通信息技术有限公司提供完整Zigbee解决方案    

[硬件] ARM启动代码

[ 486 查看 / 0 回复 ]

学ARM已经41天了,中间断断续续总有点收获,今天把我写的启动代码贴上来,注释很详细,希望对咱们刚学的有帮助吧。

启动代码是几乎是每个arm程序程序必备的,刚开始看的时候看别人的启动代码时感觉云里雾里,所以懒惰的想法浮现脑中:别人都写好了我还写什么,直接拿来用不就行了,对在我懂得情况下,我一定会拿来就用,但是现在我还不懂,一切就要从头开始,经过几天的努力,现在的感觉是启动代码不过如此 ,呵呵。
  1. ;---------------------------------------------------------------------
  2. ;startup.s
  3. ;系统启动代码
  4. ;起始时间 : 2009.5.7 ----->2009.5.11
  5. ;---------------------------------------------------------------------



  6. ;---------------------------------------------------------------------
  7. GET ./Include/s3c2440.inc ;寄存器地址信息
  8. GET ./Include/memcfg.inc ;内存控制器配置信息

  9. ;处理器模式
  10. USERMODE EQU  0x10
  11. FIQMODE EQU  0x11
  12. IRQMODE EQU  0x12
  13. SVCMODE EQU  0x13
  14. ABORTMODE EQU  0x17
  15. UNDEFMODE EQU  0x1b
  16. SYSMODE EQU 0x1f
  17. ;相关掩码
  18. MODEMASK    EQU  0x1f
  19. NOINT EQU  0xc0

  20. ;各个处理器模式下堆栈设置
  21. _STACK_BASEADDRESS EQU 0x33ff8000 ;BANK6 64MB顶部
  22. UserStack EQU (_STACK_BASEADDRESS-0x3800) ;0x33ff4800 ~
  23. SVCStack EQU (_STACK_BASEADDRESS-0x2800) ;0x33ff5800 ~
  24. UndefStack EQU (_STACK_BASEADDRESS-0x2400) ;0x33ff5c00 ~
  25. AbortStack EQU (_STACK_BASEADDRESS-0x2000) ;0x33ff6000 ~
  26. IRQStack EQU (_STACK_BASEADDRESS-0x1000) ;0x33ff7000 ~
  27. FIQStack EQU (_STACK_BASEADDRESS-0x0) ;0x33ff8000 ~

  28. ;导入操作系统入口函数
  29. IMPORT OSEntry

  30. ;导入外部C语言编写的异常与中断处理函数
  31. IMPORT vectorUNDEF
  32. IMPORT vectorSWI
  33. IMPORT vectorPABT
  34. IMPORT vectorDABT
  35. IMPORT vectorIRQ
  36. IMPORT vectorFIQ

  37. ;导入镜像装载域段起始地址
  38. IMPORT  |Image$$RO$$Limit|  ; End of ROM code (=start of ROM data)
  39. IMPORT  |Image$$RW$$Base|  ; Base of RAM to initialise
  40. IMPORT  |Image$$ZI$$Base|  ; Base and limit of area
  41. IMPORT  |Image$$ZI$$Limit|  ; to zero initialise
  42. ;--------------------------------------------------------------------


  43. ;------------------------------------------------------
  44. AREA startup, CODE, READONLY

  45. ENTRY

  46. ;系统向量表

  47. b vectorRESET ;复位向量
  48. b vectorUNDEF ;未定义指令
  49. b vectorSWI ;软中断
  50. b vectorPABT ;预取指终止
  51. b vectorDABT ;数据终止
  52. b . ;系统保留
  53. b vectorIRQ ;外部中断
  54. b vectorFIQ ;快速中断
  55. ;-------------------------------------------------------

  56. ;--------------------------------------------------------------------------
  57. ;复位向量
  58. ;复位向量是ARM处理器上电后第一个被执行的异常
  59. ;此时系统处理管理(SVC)模式

  60. vectorRESET

  61. ;复位向量有以下六件事要做

  62. ;第一步 : 关闭看门狗定时器屏蔽所有中断
  63. ;第二步 : 配置系统时钟
  64. ;第三步 : 配置内存控制器
  65. ;第四步 : 配置每种处理器模式下堆栈指针
  66. ;第五步 : 初始化镜像运行域
  67. ;第六步 : 跳转到操作系统入口


  68. ;------------------------------------------
  69. ;第一步 : 关闭看门狗定时器
  70. ;具体内容请参看s3c2440a数据手册的第18章
  71. ldr r0, =WTCON
  72. ldr  r1, =0x0
  73. str  r1, [r0, #0x0]

  74. ;屏蔽所有中断
  75. ldr r0, =INTMSK
  76. ldr r1, =0xffffffff
  77. str r1, [r0]
  78. ;------------------------------------------



  79. ;------------------------------------------
  80. ;第二步 : 配置系统时钟
  81. ;具体内容请看手册第7章

  82. ;先减少锁相环锁定时间,s3c2440a要求PLL
  83. ;锁定时间>300us,在上电时s3c2440a预设值
  84. ;mpll为晶体频率,我用的晶体频率为12MHz
  85. ;300us*12M = 3600设置LOCKTIME = 0xfff
  86. ;足够了
  87. ldr r0, =LOCKTIME
  88. ldr r1, =0xfff0fff0 ;高16为对应UPLL
  89. ;低16为对应MPLL
  90. str r1, [r0, #0x0]

  91. ;根据器件手册我们还有以下几个事要做
  92. ;step1.配置UPLL
  93. ;step2.配置MPLL
  94. ;注:手册要求先配置UPLL后MPLL
  95. ; 且之间要间隔7NOP
  96. ; 详请看手册第7-21.
  97. ;step3.配置分频系数

  98. ;step1:
  99. ldr r0, =UPLLCON
  100. ldr r1, =((56<<12) + (2<<4) + 2)
  101. ldr r1, [r0]

  102. ;按手册要求插入7个NOP
  103. nop
  104. nop
  105. nop
  106. nop
  107. nop
  108. nop
  109. nop

  110. ;step2:
  111. ldr r0, =MPLLCON
  112. ldr r1, =((127<<12) + (2<<4) + 1)
  113. ldr r1, [r0]

  114. ;step3:
  115. ldr r0, =CLKDIVN
  116. ldr r1, =((0<<3) + (2 << 2) + 1)
  117. ldr r1, [r0]
  118. ;------------------------------------------



  119. ;------------------------------------------
  120. ;第三步 : 配置内存控制器
  121. ;内存控制内的寄存器器地址是连续分布的
  122. ;从0x4800_0000 -- 0x4800_0030,所以可以
  123. ;通过一个循环依次填入各个寄存器的内容

  124. ldr r0, =SMRDATA ;装入配置值的地址
  125. ldr r1, =BWSCON ;装入起始寄存器地址
  126. add r2, r0, #0x34 ;计算结束地址

  127. ;下面是用于向内存控制器
  128. ;装入配置信息的循环
  129. 0
  130. ldr r3, [r0], #4 ;装入配置值到r3,后变址
  131. str r3, [r1], #4  ;把r3内包含的配置值写入
  132. ;内存控制器的寄存器
  133. cmp r2, r0 ;结束否?
  134. bne %B0 ;没结束则继续
  135. ;------------------------------------------



  136. ;------------------------------------------
  137. ;第四步 : 配置每种处理器模式下堆栈指针
  138. ;方法与原则:
  139. ;1: 通过CPSR寄存器切换处理器模式
  140. ;2: 对CPSR的操作方式为 读-修改-写回
  141. ;3: 绝对不要跳到用户模式,跳过去容易
  142. ; 回来就难了
  143. ;4: 切到新处理器模式后要屏蔽IRQ和FIQ
  144. ; 防止在未设置好堆栈前进入中断处理
  145. ; 程序,但是在启动代码的最先我们已
  146. ; 经屏蔽了所有的32个中断源,所以感
  147. ; 觉是否屏蔽都可以

  148. ;step1: 先把程序状态寄存器读到r0
  149. mrs r0, cpsr

  150. ;step2: 清除处理器模式位(最前面5位)
  151. bic r0, r0, #MODEMASK

  152. ;step3: 设置未定义状态下的堆栈指针
  153. orr r1, r0, #UNDEFMODE|NOINT
  154. msr cpsr_cxsf, r1 ;UndefMode
  155. ldr sp, =UndefStack ;UndefStack=0x33FF_5C00

  156. ;step4: 设置终止状态下的堆栈指针
  157. orr r1, r0, #ABORTMODE|NOINT
  158. msr cpsr_cxsf, r1 ;AbortMode
  159. ldr sp, =AbortStack ;AbortStack=0x33FF_6000

  160. ;step5: 设置中断模式下的堆栈指针
  161. orr r1, r0, #IRQMODE|NOINT
  162. msr cpsr_cxsf, r1 ;IRQMode
  163. ldr sp, =IRQStack ;IRQStack=0x33FF_7000

  164. ;step6: 设置快速中断模式下的堆栈指针
  165. orr r1, r0, #FIQMODE|NOINT
  166. msr cpsr_cxsf, r1 ;FIQMode
  167. ldr sp, =FIQStack ;FIQStack=0x33FF_8000

  168. ;step7: 设置管理模式下的堆栈指针
  169. orr r1, r0, #SVCMODE|NOINT
  170. msr cpsr_cxsf, r1 ;SVCMode
  171. ldr sp, =SVCStack ;SVCStack=0x33FF_5800

  172. ;step8: 因为管理模式与用户模式共用
  173. ; 堆栈指针,所以借着系统模式
  174. ; 来设置用户模式的堆栈指针
  175. orr r1, r0, #SYSMODE|NOINT
  176. msr cpsr_cxsf, r1 ;SYSMode
  177. ldr sp, =UserStack ;SVCStack & USERMode=0x33ff4800

  178. ;现在处理器处于系统模式
  179. ;------------------------------------------
  180.    
  181.    
  182.    
  183. ;------------------------------------------
  184. ;第五步 : 初始化镜像运行域
  185. ;复制RW段和ZI段到SDRAM指定地址

  186. LDR    r0, =|Image$$RO$$Limit| ; 装入RO段结束地址
  187. LDR    r1, =|Image$$RW$$Base|  ; 装入RW段起始地址
  188. LDR    r3, =|Image$$ZI$$Base|  ; 装入ZI段起始地址


  189. ;|Image$$RO$$Limit| == |Image$$RW$$Base| ? 跳过RW段复制 : 复制RW段
  190. CMP    r0, r1     
  191. BEQ    %F2

  192. ;复制RW段
  193. 1       
  194. CMP    r1, r3 
  195. LDRCC  r2, [r0], #4     
  196. STRCC  r2, [r1], #4
  197. BCC    %B1
  198. 2       
  199. LDR    r1, =|Image$$ZI$$Limit| 
  200. MOV    r2, #0

  201. ;构造ZI段
  202. 3       
  203. CMP    r3, r1     
  204. STRCC  r2, [r3], #4
  205. BCC    %B3

  206. ;------------------------------------------   



  207. ;------------------------------------------
  208. ;第六步 : 跳转到操作系统入口

  209. b OSEntry ;不要使用main,因为如果使用main
  210. ;ads还会调用_main()初始化RW和ZI
  211. ;段,但是那里的数据和本程序不同

  212. b .

  213. ;------------------------------------------

  214. ;---------------------------------------------------------------------------



  215. SMRDATA DATA

  216. ;这里是内存控制器的配置数据
  217. ;配置数据需要根据你使用的存储器修改
  218. ;在第三步时会将以下数据写入
  219. ;内存控制器的相关寄存器中
  220. ;共13个寄存器的配置值

  221. DCD (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
  222. DCD ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))  ;GCS0
  223. DCD ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))  ;GCS1
  224. DCD ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))  ;GCS2
  225. DCD ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))  ;GCS3
  226. DCD ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))  ;GCS4
  227. DCD ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))  ;GCS5
  228. DCD ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))    ;GCS6
  229. DCD ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))    ;GCS7
  230. DCD ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
  231. DCD 0x32    ;SCLK power saving mode, BANKSIZE 128M/128M
  232. DCD 0x30    ;MRSR6 CL=3clk
  233. DCD 0x30    ;MRSR7 CL=3clk

  234. ALIGN ;数据边界对齐

  235. END
复制代码
我在写一个arm920T的微型OS,主要是想借着写OS的过程学习ARM的底层编程,然后跳到Linux。启动代码是固件的一部分,最经学校要搞个设计,不知OS什么时候能写好,反正搞定后立即发帖。

下边是完整的工程

运行平台:mini2440
最后编辑qiaoni 最后编辑于 2009-10-12 06:04:22
附件:您所在的用户组无法下载或查看附件
分享 转发
TOP