新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > S3C2440启动代码分析

S3C2440启动代码分析

作者: 时间:2016-11-21 来源:网络 收藏
  1. ;==;=========================================
  2. ;NAME:2440INIT.S
  3. ;DESC:Cstartupcodes
  4. ;Configurememory,ISR,stacks
  5. ;InitializeC-variables
  6. ;完全注释;=========================================
  7. ;NAME:2440INIT.S
  8. ;DESC:Cstartupcodes
  9. ;Configurememory,ISR,stacks
  10. ;InitializeC-variables
  11. ;完全注释
  12. ;HISTORY:
  13. ;2002.02.25:kwtark:ver0.0
  14. ;2002.03.20:purnnamu:AddsomefunctionsfortestingSTOP,Sleepmode
  15. ;2003.03.14:DonGo:Modifiedfor2440.
  16. ;200906.24:TinkoModified
  17. ;=========================================
  18. ;汇编不能使用include包含头文件,所有用Get
  19. ;汇编也不认识*.h文件,所有只能用*.inc
  20. GEToption.inc;定义芯片相关的配置
  21. GETmemcfg.inc;定义存储器配置
  22. GET2440addr.inc;定义了寄存器符号
  23. ;REFRESH寄存器[22]bit:0-autorefresh;1-selfrefresh
  24. BIT_SELFREFRESHEQU(1<<22);用于节电模式中,SDRAM自动刷新
  25. ;处理器模式常量:CPSR寄存器的后5位决定目前处理器模式M[4:0]
  26. USERMODEEQU0x10
  27. FIQMODEEQU0x11
  28. IRQMODEEQU0x12
  29. SVCMODEEQU0x13
  30. ABORTMODEEQU0x17
  31. UNDEFMODEEQU0x1b
  32. MODEMASKEQU0x1f;M[4:0]
  33. NOINTEQU0xc0
  34. ;定义处理器各模式下堆栈地址常量
  35. UserStackEQU(_STACK_BASEADDRESS-0x3800);0x33ff4800~_STACK_BASEADDRESS定义在option.inc中
  36. SVCStackEQU(_STACK_BASEADDRESS-0x2800);0x33ff5800~
  37. UndefStackEQU(_STACK_BASEADDRESS-0x2400);0x33ff5c00~
  38. AbortStackEQU(_STACK_BASEADDRESS-0x2000);0x33ff6000~
  39. IRQStackEQU(_STACK_BASEADDRESS-0x1000);0x33ff7000~
  40. FIQStackEQU(_STACK_BASEADDRESS-0x0);0x33ff8000~
  41. ;arm处理器有两种工作状态1.arm:32位这种工作状态下执行字对准的arm指令2.Thumb:16位这种工作状
  42. ;态执行半字对准的Thumb指令
  43. ;因为处理器分为16位32位两种工作状态程序的编译器也是分16位和32两种编译方式所以下面的程序用
  44. ;于根据处理器工作状态确定编译器编译方式
  45. ;code16伪指令指示汇编编译器后面的指令为16位的thumb指令
  46. ;code32伪指令指示汇编编译器后面的指令为32位的arm指令
  47. ;
  48. ;Arm上电时处于ARM状态,故无论指令为ARM集或Thumb集,都先强制成ARM集,待init.s初始化完成后
  49. ;再根据用户的编译配置转换成相应的指令模式。为此,定义变量THUMBCODE作为指示,跳转到main之前
  50. ;根据其值切换指令模式
  51. ;
  52. ;这段是为了统一目前的处理器工作状态和软件编译方式(16位编译环境使用tasm.exe编译
  53. ;Checkiftasm.exe(armasm-16...@ADS1.0)isused.
  54. GBLLTHUMBCODE;定义THUMBCODE全局变量注意EQU所定义的宏与变量的区别
  55. [{CONFIG}=16;如果发现是在用16位代码的话(编译选项中指定使用thumb指令)
  56. THUMBCODESETL{TRUE};一方面把THUMBCODE设置为TURE
  57. CODE32;另一方面暂且把处理器设置成为ARM模式,以方便初始化
  58. |;(|表示else)如果编译选项本来就指定为ARM模式
  59. THUMBCODESETL{FALSE};把THUMBCODE设置为FALSE就行了
  60. ];结束
  61. MACRO;一个根据THUMBCODE把PC寄存的值保存到LR的宏
  62. MOV_PC_LR;宏名称
  63. [THUMBCODE;如果定义了THUMBCODE,则
  64. bxlr;在ARM模式中要使用BX指令转跳到THUMB指令,并转换模式.bx指令会根据PC最后1位来确定是否进入thumb状态
  65. |;否则,
  66. movpc,lr;如果目标地址也是ARM指令的话就采用这种方式
  67. ]
  68. MEND;宏定义结束标志
  69. MACRO;和上面的宏一样,只是多了一个相等的条件
  70. MOVEQ_PC_LR
  71. [THUMBCODE
  72. bxeqlr
  73. |
  74. moveqpc,lr
  75. ]
  76. MEND
  77. ;=======================================================================================
  78. ;下面这个宏是用于第一次查表过程的实现中断向量的重定向,如果你比较细心的话就是发现
  79. ;在_ISR_STARTADDRESS=0x33FF_FF00里定义的第一级中断向量表是采用型如Handle***的方式的.
  80. ;而在程序的ENTRY处(程序开始处)采用的是bHandler***的方式.
  81. ;在这里Handler***就是通过HANDLER这个宏和Handle***建立联系的.
  82. ;这种方式的优点就是正真定义的向量数据在内存空间里,而不是在ENTRY处的ROM(FLASH)空间里,
  83. ;这样,我们就可以在程序里灵活的改动向量的数据了.
  84. ;========================================================================================
  85. ;;这段程序用于把中断服务程序的首地址装载到pc中,有人称之为“加载程序”。
  86. ;本初始化程序定义了一个数据区(在文件最后),34个字空间,存放相应中断服务程序的首地址。每个字
  87. ;空间都有一个标号,以Handle***命名。
  88. ;在向量中断模式下使用“加载程序”来执行中断服务程序。
  89. ;这里就必须讲一下向量中断模式和非向量中断模式的概念
  90. ;向量中断模式是当cpu读取位于0x18处的IRQ中断指令的时候,系统自动读取对应于该中断源确定地址上的;
  91. ;指令取代0x18处的指令,通过跳转指令系统就直接跳转到对应地址
  92. ;函数中节省了中断处理时间提高了中断处理速度标例如ADC中断的向量地址为0xC0,则在0xC0处放如下
  93. ;代码:ldrPC,=HandlerADC当ADC中断产生的时候系统会
  94. ;自动跳转到HandlerADC函数中
  95. ;非向量中断模式处理方式是一种传统的中断处理方法,当系统产生中断的时候,系统将interrupt
  96. ;pending寄存器中对应标志位置位然后跳转到位于0x18处的统一中断
  97. ;函数中该函数通过读取interruptpending寄存器中对应标志位来判断中断源并根据优先级关系再跳到
  98. ;对应中断源的处理代码中
  99. ;
  100. ;H|------|H|------|H|------|H|------|H|------|
  101. ;|///||///||///||///||///|
  102. ;|------|<----sp|------||------||------||------|<------sp
  103. ;L|||------|<----spL|------||-isr--||------|isr==>pc
  104. ;|||||--r0--|<----sp|---r0-|<----spL|------|r0==>r0
  105. ;(0)(1)(2)(3)(4)
  106. MACRO
  107. $HandlerLabelHANDLER$HandleLabel
  108. $HandlerLabel;标号
  109. subsp,sp,#4;(1)减少sp(用于存放转跳地址)
  110. stmfdsp!,{r0};(2)把工作寄存器压入栈(lrdoesnotpushbecauseitreturntooriginaladdress)
  111. ldrr0,=$HandleLabel;将HandleXXX的址址放入r0
  112. ldrr0,[r0];把HandleXXX所指向的内容(也就是中断程序的入口)放入r0
  113. strr0,[sp,#4];(3)把中断服务程序(ISR)压入栈
  114. ldmfdsp!,{r0,pc};(4)用出栈的方式恢复r0的原值和为pc设定新值(也就完成了到ISR的转跳)
  115. MEND
  116. ;=========================================================================================
  117. ;在这里用IMPORT伪指令(和c语言的extren一样)引入|Image
    RO
    Base|,|Image
    RO
    Limit|...
  118. ;这些变量是通过ADS的工程设置里面设定的ROBase和RWBase设定的,
  119. ;最终由编译脚本和连接程序导入程序.
  120. ;那为什么要引入这玩意呢,最简单的用处是可以根据它们拷贝自已
  121. ;==========================================================================================
  122. ;Image
    RO
    Base等比较古怪的变量是编译器生成的。RO,RW,ZI这三个段都保存在Flash中,但RW,ZI在Flash中
  123. ;的地址肯定不是程序运行时变量所存储的位置,因此我们的程序在初始化时应该把Flash中的RW,ZI拷贝到RAM的对应位置。
  124. ;一般情况下,我们可以利用编译器替我们实现这个操作。比如我们跳转到main()时,使用b__Main,编译器就会在__Main
  125. ;和Main之间插入一段汇编代码,来替我们完成RW,ZI段的初始化。如果我们使用bMain,那么初始化工作要我们自己做。
  126. ;编译器会生成如下变量告诉我们RO,RW,ZI三个段应该位于什么位置,但是它并没有告诉我们RW,ZI在Flash中存储在什么位置,
  127. ;实际上RW,ZI在Flash中的位置就紧接着RO存储。我们知道了Image
    RO
    Base,Image
    RO
    Limit,那么Image
    RO
    Limit就
  128. ;是RW(ROMdata)的开始。
  129. IMPORT|Image
    RO
    Base|;BaseofROMcode
  130. IMPORT|Image
    RO
    Limit|;EndofROMcode(=startofROMdata)
  131. IMPORT|Image
    RW
    Base|;BaseofRAMtoinitialise
  132. IMPORT|Image
    ZI
    Base|;Baseandlimitofarea
  133. IMPORT|Image
    ZI
    Limit|;tozeroinitialise
  134. ;这里引入一些在其它文件中实现在函数,包括为我们所熟知的main函数
  135. ;IMPORTMMU_SetAsyncBusMode
  136. ;IMPORTMMU_SetFastBusMode;hzh
  137. IMPORTMain
  138. ;从这里开始就是正真的代码入口了!
  139. AREAInit,CODE,READONLY;这表明下面的是一个名为Init的代码段
  140. ENTRY;定义程序的入口(调试用)
  141. EXPORT__ENTRY;导出符号_ENTRY,但在那用到就还没查明
  142. __ENTRY
  143. ResetEntry
  144. ;1)Thecode,whichconvertstoBig-endian,shouldbeinlittleendiancode.
  145. ;2)ThefollowinglittleendiancodewillbecompiledinBig-Endianmode.
  146. ;Thecodebyteordershouldbechangedasthememorybuswidth.
  147. ;3)Thepseudoinstruction,DCDcannotbeusedherebecausethelinkergenerateserror.
  148. ;条件编译,在编译成机器码前就设定好
  149. ASSERT:DEF:ENDIAN_CHANGE;判断ENDIAN_CHANGE是否已定义
  150. [ENDIAN_CHANGE;如果已经定义了ENDIAN_CHANGE,则(在Option.inc里已经设为FALSE)
  151. ASSERT:DEF:ENTRY_BUS_WIDTH;判断ENTRY_BUS_WIDTH是否已定义
  152. [ENTRY_BUS_WIDTH=32;如果已经定义了ENTRY_BUS_WIDTH,则判断是不是为32
  153. bChangeBigEndian;DCD0xea000007
  154. ]
  155. ;在bigendian中,地址为A的字单元包括字节单元A,A+1,A+2,A+3,字节单元由高位到低位为A,A+1,A+2,A+3
  156. ;地址为A的字单元包括半字单元A,A+2,半字单元由高位到低位为A,A+2
  157. [ENTRY_BUS_WIDTH=16
  158. andeqr14,r7,r0,lsl#20;DCD0x0007ea00也是bChangeBigEndian指令,只是由于总线不一样而取机器码的顺序不一样
  159. ];先取低位->高位上述指令是通过机器码装换而来的
  160. [ENTRY_BUS_WIDTH=8
  161. streqr0,[r0,-r10,ror#1];DCD0x070000ea也是bChangeBigEndian指令,只是由于总线不一样而取机器码的顺序不一样
  162. ]
  163. |
  164. bResetHandler;我们的程序由于ENDIAN_CHANGE设成FALSE就到这儿了,转跳到复位程序入口
  165. ]
  166. bHandlerUndef;handlerforUndefinedmode;0x04
  167. bHandlerSWI;handlerforSWIinterrupt;0x08
  168. bHandlerPabort;handlerforPAbort;0x0c
  169. bHandlerDabort;handlerforDAbort;0x10
  170. b.;reserved注意小圆点;0x14
  171. bHandlerIRQ;handlerforIRQinterrupt;0x18
  172. bHandlerFIQ;handlerforFIQinterrupt;0x1c
  173. ;@0x20
  174. bEnterPWDN;Mustbe@0x20.
  175. ;==================================================================================
  176. ;下面是改变大小端的程序,这里采用直接定义机器码的方式,至说为什么这么做就得问三星了
  177. ;反正我们程序里这段代码也不会去执行,不用去管它
  178. ;==================================================================================
  179. ;通过设置CP15的C1的位7,设置存储格式为Bigendian,三种总线方式
  180. ChangeBigEndian;//hereENTRY_BUS_WIDTH=16
  181. ;@0x24
  182. [ENTRY_BUS_WIDTH=32
  183. DCD0xee110f10;0xee110f10=>mrcp15,0,r0,c1,c0,0
  184. DCD0xe3800080;0xe3800080=>orrr0,r0,#0x80;//Big-endian
  185. DCD0xee010f10;0xee010f10=>mcrp15,0,r0,c1,c0,0
  186. ;对存储器控制寄存器操作,指定内存模式为Big-endian
  187. ;因为刚开始CPU都是按照32位总线的指令格式运行的,如果采用其他的话,CPU别不了,必须转化
  188. ;但当系统初始化好以后,则CPU能自动识别
  189. ]
  190. [ENTRY_BUS_WIDTH=16
  191. DCD0x0f10ee11
  192. DCD0x0080e380
  193. DCD0x0f10ee01
  194. ;因为采用Big-endian模式,采用16位总线时,物理地址的高位和数据的地位对应
  195. ;所以指令的机器码也相应的高低对调
  196. ]
  197. [ENTRY_BUS_WIDTH=8
  198. DCD0x100f11ee
  199. DCD0x800080e3
  200. DCD0x100f01ee
  201. ]
  202. DCD0xffffffff;swinv0xffffffissimilarwithNOPandrunwellinbothendianmode.
  203. DCD0xffffffff
  204. DCD0xffffffff
  205. DCD0xffffffff
  206. DCD0xffffffff
  207. bResetHandler
  208. ;=========================================================================================
  209. ;Functionforenteringpowerdownmode
  210. ;1.SDRAMshouldbeinself-refreshmode.
  211. ;2.AllinterruptshouldbemakskedforSDRAM/DRAMself-refresh.
  212. ;3.LCDcontrollershouldbedisabledforSDRAM/DRAMself-refresh.
  213. ;4.TheI-cachemayhavetobeturnedon.
  214. ;5.Thelocationofthefollowingcodemayhavenottobechanged.
  215. ;voidEnterPWDN(intCLKCON);
  216. EnterPWDN
  217. movr2,r0;r2=rCLKCON保存原始数据0x4c00000c使能各模块的时钟输入
  218. tstr0,#0x8;测试bit[3]SLEEPmode?1=>sleep
  219. bneENTER_SLEEP;C=0,即TST结果非0,bit[3]=1
  220. ;//进入PWDN后如果不是sleep则进入stop
  221. ;//进入Stopmode
  222. ENTER_STOP
  223. ldrr0,=REFRESH;0x48000024DRAM/SDRAMrefreshconfig
  224. ldrr3,[r0];r3=rREFRESH
  225. movr1,r3
  226. orrr1,r1,#BIT_SELFREFRESH;EnableSDRAMself-refresh
  227. strr1,[r0];EnableSDRAMself-refresh
  228. movr1,#16;waituntilself-refreshisissued.maynotbeneeded.
  229. 0
  230. subsr1,r1,#1
  231. bne%B0
  232. ;//wait16fclksforself-refresh
  233. ldrr0,=CLKCON;enterSTOPmode.
  234. strr2,[r0]
  235. movr1,#32
  236. 0
  237. subsr1,r1,#1;1)waituntiltheSTOPmodeisineffect.
  238. bne%B0;2)OrwaithereuntiltheCPU&Peripheralswillbeturned-off
  239. ;EnteringSLEEPmode,onlytheresetbywake-upisavailable.
  240. ldrr0,=REFRESH;exitfromSDRAMselfrefreshmode.
  241. strr3,[r0]
  242. MOV_PC_LR;backtomainprocess
  243. ENTER_SLEEP
  244. ;NOTE.
  245. ;1)rGSTATUS3shouldhavethereturnaddressafterwake-upfromSLEEPmode.
  246. ldrr0,=REFRESH
  247. ldrr1,[r0];r1=rREFRESH
  248. orrr1,r1,#BIT_SELFREFRESH
  249. strr1,[r0];EnableSDRAMself-refresh
  250. ;//EnableSDRAMself-refresh
  251. movr1,#16;Waituntilself-refreshisissued,whichmaynotbeneeded.
  252. 0
  253. subsr1,r1,#1
  254. bne%B0
  255. ;//Waituntilself-refreshisissued,whichmaynotbeneeded
  256. ldrr1,=MISCCR;IOregister
  257. ldrr0,[r1]
  258. orrr0,r0,#(7<<17);SetSCLK0=1,SCLK1=1,SCKE=1.
  259. strr0,[r1]
  260. ldrr0,=CLKCON;Entersleepmode
  261. strr2,[r0]
  262. b.;CPUwilldiehere.
  263. ;//进入SleepMode,1)设置SDRAM为self-refresh
  264. ;//2)设置MISCCRbit[17]1:sclk0=sclk0:sclk0=0
  265. ;//bit[18]1:sclk1=sclk0:sclk1=0
  266. ;//bit[19]1:Selfrefreshretainenable
  267. ;//0:Selfrefreshretaindisable
  268. ;//When1,Afterwake-upfromsleep,Theself-refreshwillberetained.
  269. WAKEUP_SLEEP
  270. ;ReleaseSCLKnafterwake-upfromtheSLEEPmode.
  271. ldrr1,=MISCCR
  272. ldrr0,[r1]
  273. bicr0,r0,#(7<<17);SCLK0:0->SCLK,SCLK1:0->SCLK,SCKE:0->=SCKE.
  274. strr0,[r1]
  275. ;//设置MISCCR
  276. ;Setmemorycontrolregisters
  277. ;ldrr0,=SMRDATA
  278. adrlr0,SMRDATA
  279. ldrr1,=BWSCON;BWSCONAddress;//总线宽度和等待控制寄存器
  280. addr2,r0,#52;EndaddressofSMRDATA
  281. 0
  282. ldrr3,[r0],#4;数据处理后R0自加4,[R0]->R3,R0+4->R0
  283. strr3,[r1],#4
  284. cmpr2,r0
  285. bne%B0
  286. ;//设置所有的memorycontrolregister,他的初始地址为BWSCON,初始化
  287. ;//数据在以SMRDATA为起始的存储区
  288. movr1,#256
  289. 0
  290. subsr1,r1,#1;1)waituntiltheSelfRefreshisreleased.
  291. bne%B0
  292. ;//1)waituntiltheSelfRefreshisreleased.
  293. ldrr1,=GSTATUS3;GSTATUS3hasthestartaddressjustafterSLEEPwake-up
  294. ldrr0,[r1]
  295. movpc,r0
  296. ;//跳出SleepMode,进入Sleep状态前的PC
  297. ;============================================================================================
  298. ;如上所说,这里采用HANDLER宏去建立Hander***和Handle***之间的联系
  299. LTORG;声明文字池,因为我们用了ldr伪指令
  300. HandlerFIQHANDLERHandleFIQ
  301. HandlerIRQHANDLERHandleIRQ
  302. HandlerUndefHANDLERHandleUndef
  303. HandlerSWIHANDLERHandleSWI
  304. HandlerDabortHANDLERHandleDabort
  305. HandlerPabortHANDLERHandlePabort
  306. ;===================================================================================
  307. ;呵呵,来了来了.好戏来了,这一段程序就是用来进行第二次查表的过程了.
  308. ;如果说第一次查表是由硬件来完成的,那这一次查表就是由软件来实现的了.
  309. ;为什么要查两次表??
  310. ;没有办法,ARM把所有的中断都归纳成一个IRQ中断异常和一个FIRQ中断异常
  311. ;第一次查表主要是查出是什么异常,可我们总要知道是这个中断异常中的什么中断呀!
  312. ;没办法了,再查一次表呗!
  313. ;===================================================================================
  314. ;//外部中断号判断,通过中断服务程序入口地址存储器的地址偏移确定
  315. ;//PC=[HandleEINT0+[INTOFFSET]]
  316. ;H|------|
  317. ;|///|
  318. ;|--isr-|====>pc
  319. ;L|--r8--|
  320. ;|--r9--|<----sp
  321. IsrIRQ
  322. subsp,sp,#4;给PC寄存器保留reservedforPC
  323. stmfdsp!,{r8-r9};把r8-r9压入栈
  324. ldrr9,=INTOFFSET;把INTOFFSET的地址装入r9INTOFFSET是一个内部的寄存器,存着中断的偏移
  325. ldrr9,[r9];I_ISR
  326. ldrr8,=HandleEINT0;这就是我们第二个中断向量表的入口的,先装入r8
  327. ;===================================================================================
  328. ;哈哈,这查表方法够好了吧,r8(入口)+index*4(别望了一条指令是4bytes的喔),
  329. ;这不就是我们要找的那一项了吗.找到了表项,下一步做什么?肯定先装入了!
  330. ;==================================================================================
  331. addr8,r8,r9,lsl#2;地址对齐,因为每个中断向量占4个字节,即isr=IvectTable+Offeset*4
  332. ldrr8,[r8];装入中断服务程序的入口
  333. strr8,[sp,#8];把入口也入栈,准备用旧招
  334. ldmfdsp!,{r8-r9,pc};施招,弹出栈,哈哈,顺便把r8弹出到PC了,跳转成功!
  335. LTORG
  336. ;==============================================================================
  337. ;ENTRY(好了,我们的CPU要在这复位了.)
  338. ;==============================================================================
  339. ResetHandler
  340. ldrr0,=WTCON;1.关看门狗
  341. ldrr1,=0x0;bit[5]:0-disable;1-enable(reset默认)
  342. strr1,[r0]
  343. ldrr0,=INTMSK
  344. ldrr1,=0xffffffff;2.关中断
  345. strr1,[r0]
  346. ldrr0,=INTSUBMSK
  347. ldrr1,=0x7fff;3.关子中断
  348. strr1,[r0]
  349. [{FALSE};4.得有些表示了,该点点LED灯了,不过被FALSE掉了.
  350. ;rGPFDAT=(rGPFDAT&~(0xf<<4))|((~data&0xf)<<4);
  351. ;Led_Display
  352. ldrr0,=GPFCON
  353. ldrr1,=0x5500
  354. strr1,[r0]
  355. ldrr0,=GPFDAT
  356. ldrr1,=0x10
  357. strr1,[r0]
  358. ]
  359. ;5.为了减少PLL的locktime,调整LOCKTIME寄存器.
  360. ;ToreducePLLlocktime,adjusttheLOCKTIMEregister.
  361. ldrr0,=LOCKTIME
  362. ldrr1,=0xffffff;reset的默认值
  363. strr1,[r0]
  364. ;6.下面就来设置PLL了,你的板快不快就看这了!!
  365. ;这里介绍一下计算公式
  366. ;//Fpllo=(m*Fin)/(p*2^s)
  367. ;//m=MDIV+8,p=PDIV+2,s=SDIV
  368. ;TheproperrangeofPandM:1<=P<=62,1<=M<=248
  369. ;Fpllo必须大于200Mhz小于600Mhz
  370. ;Fpllo*2^s必须小于1.2GHz
  371. ;如下面的PLLCON设定中的M_DIVP_DIVS_DIV是取自option.h中
  372. ;#elif(MCLK==40000000)
  373. ;#definePLL_M(0x48)
  374. ;#definePLL_P(0x3)
  375. ;#definePLL_S(0x2)
  376. ;所以m=MDIV+8=80,p=PDIV+2=5,s=SDIV=2
  377. ;硬件使用晶振为10Mhz,即Fin=10Mhz
  378. ;Fpllo=80*10/5*2^2=40Mhz
  379. [PLL_ON_START
  380. ;Addedforconfirmclockdivide.for2440.
  381. ;SettingvalueFclk:Hclk:Pclk
  382. ldrr0,=CLKDIVN
  383. ldrr1,=CLKDIV_VAL;0=1:1:1,1=1:1:2,2=1:2:2,3=1:2:4,4=1:4:4,5=1:4:8,6=1:3:3,7=1:3:6.option.inc中定义CLKDIV_VAL=7
  384. strr1,[r0];//数据表示分频数
  385. ;===============================================================================
  386. ;MMU_SetAsyncBusMode和MMU_SetFastBusMode都在4K代码以上,
  387. ;如果你想你编译出来的程序能在NAND上运行的话,就不要在这调用这两函数了.
  388. ;如果你不要求的话,你就用把.啥事没有.
  389. ;为什么是4K,问三星吧,就提供4K的内部SRAM,要是提供400K多好呀.
  390. ;好了,好了,4K就4K吧,不能用这两函数,自己写还不行吗,下面的代码这这么来了,
  391. ;实现和上面两函数一样的功能.
  392. ;===============================================================================
  393. ;[CLKDIV_VAL>1;意思是Fclk:Hclk不是1:1.
  394. ;blMMU_SetAsyncBusMode
  395. ;|
  396. ;blMMU_SetFastBusMode;defaultvalue.
  397. ;]
  398. ;==手册第243页==
  399. ;IfHDIVNisnot0,theCPUbusmodehastobechangedfromthefastbusmodetotheasynchronous
  400. ;busmodeusingfollowinginstructions
  401. ;MMU_SetAsyncBusMode
  402. ;mrcp15,0,r0,c1,c0,0
  403. ;orrr0,r0,#R1_nF:OR:R1_iA
  404. ;mcrp15,0,r0,c1,c0,0
  405. [CLKDIV_VAL>1;意思是Fclk:Hclk不是1:1.
  406. mrcp15,0,r0,c1,c0,0
  407. orrr0,r0,#0xc0000000;R1_nF:OR:R1_iA
  408. mcrp15,0,r0,c1,c0,0
  409. |
  410. mrcp15,0,r0,c1,c0,0
  411. bicr0,r0,#0xc0000000;R1_iA:OR:R1_nF
  412. mcrp15,0,r0,c1,c0,0
  413. ]
  414. ;配置UPLL
  415. ;//ConfigureUPLLFin=12.0MHzUFout=48MHz
  416. ldrr0,=UPLLCON
  417. ldrr1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV);//USBPLLCONFIG56,2,2===>48MHz
  418. strr1,[r0]
  419. ;7个nop必不可少!!
  420. nop;//Caution:AfterUPLLsetting,atleast7-clocksdelaymustbeinsertedforsettinghardwarebecompleted.
  421. nop
  422. nop
  423. nop
  424. nop
  425. nop
  426. nop
  427. ;配置MPLL
  428. ;//ConfigureMPLLFin=12.0MHzMFout=304.8MHz
  429. ldrr0,=MPLLCON
  430. ldrr1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV);68,1,1==>304MHz
  431. strr1,[r0]
  432. ]
  433. ;检查是否从SLEEP模式中恢复
  434. ;//Checkifthebootiscausedbythewake-upfromSLEEPmode.
  435. ldrr1,=GSTATUS2
  436. ldrr0,[r1]
  437. tstr0,#0x2;testifbit[1]is1or00->C=1
  438. ;1->C=0
  439. ;Incaseofthewake-upfromSLEEPmode,gotoSLEEP_WAKEUPhandler.
  440. bneWAKEUP_SLEEP;C=0,jump
  441. EXPORTStartPointAfterSleepWakeUp
  442. StartPointAfterSleepWakeUp
  443. ;===============================================================================
  444. ;设置内存控制器等寄存器的值,因为这些寄存器是连续排列的,所以采用如下办法对这些
  445. ;寄存器进行连续设置.其中用到了SMRDATA的数据,这在代码后面有定义
  446. ;===============================================================================
  447. ;这是设置SDRAM,flashROM存储器连接和工作时序的程序,片选定义的程序
  448. ;SMRDATAmap在下面的程序中定义
  449. ;SMRDATA中涉及的值请参考memcfg.inc程序
  450. ;Setmemorycontrolregisters
  451. ;ldrr0,=SMRDATA;dangerous!!!
  452. adrlr0,SMRDATA;becareful!,tinko
  453. ldrr1,=BWSCON;BWSCONAddress
  454. addr2,r0,#52;EndaddressofSMRDATA;SMRDATA数据的结束地址,共有52字节的数据
  455. 0
  456. ldrr3,[r0],#4
  457. strr3,[r1],#4
  458. cmpr2,r0
  459. bne%B0;%表示搜索,B表示反向-back(F表示向前-forward),0为局部标号(0~99)
  460. ;================================================================================
  461. ;如果EINT0产生(这中断就是我们按键产生的),就清除SDRAM,不过好像没人会在这个时候按
  462. ;================================================================================
  463. ;checkifEIN0buttonispressed
  464. ldrr0,=GPFCON
  465. ldrr1,=0x0;00=Input
  466. strr1,[r0]
  467. ldrr0,=GPFUP
  468. ldrr1,=0xff;1-Thepullupfunctionisdisabled.
  469. strr1,[r0]
  470. ldrr1,=GPFDAT
  471. ldrr0,[r1]
  472. bicr0,r0,#(0x1e<<1);bitclear
  473. tstr0,#0x1
  474. bne%F1;如果没有按,就跳到后面的1标号处=>Initializestacks
  475. ;这就是清零内存的代码
  476. ldrr0,=GPFCON
  477. ldrr1,=0x55aa
  478. strr1,[r0]
  479. ;ldrr0,=GPFUP
  480. ;ldrr1,=0xff
  481. ;strr1,[r0]
  482. ldrr0,=GPFDAT
  483. ldrr1,=0x0
  484. strr1,[r0];LED=****
  485. movr1,#0
  486. movr2,#0
  487. movr3,#0
  488. movr4,#0
  489. movr5,#0
  490. movr6,#0
  491. movr7,#0
  492. movr8,#0
  493. ldrr9,=0x4000000;64MB
  494. ldrr0,=0x30000000
  495. 0
  496. stmiar0!,{r1-r8}
  497. subsr9,r9,#32
  498. bne%B0
  499. ;到这就结束了.
  500. ;//4.初始化各模式下的栈指针
  501. ;Initializestacks
  502. 1
  503. blInitStacks
  504. ;=======================================================================
  505. ;哈哈,下面又有看头了,这个初始化程序好像被名曰hzh的高手改过
  506. ;能在NORNAND还有内存中运行,当然了,在内存中运行最简单了.
  507. ;在NORNAND中运行的话都要先把自己拷到内存中.
  508. ;此外,还记得上面提到的|Image
    RO
    Base|,|Image
    RO
    Limit|...吗?
  509. ;这就是拷贝的依据了!!!
  510. ;=========================================================================
  511. ;BWSCON的[2:1]反映了外部引脚OM[1:0]:若OM[1:0]!=00,从NORFLash启动或直接在内存运行;若OM[1:0]==00,则为NandFlashMode
  512. ldrr0,=BWSCON
  513. ldrr0,[r0]
  514. andsr0,r0,#6;#6==0110-->BWSCON[2:1]
  515. bnecopy_proc_beg;OM[1:0]!=00,NORFLashboot,不读取NANDFLASH
  516. adrr0,ResetEntry;否则,OM[1:0]==0,为从NANDFLash启动
  517. cmpr0,#0;再比较入口是否为0地址处
  518. ;如果是0才是真正从NAND启动,因为其4k被复制到0地址开始的stepingstone内部sram中
  519. ;注意adr得到的是相对地址,非绝对地址==ifuseMulti-ice,
  520. bnecopy_proc_beg;如果!=0,说明在usingice,这种情况也不读取NANDFLASH.dontreadnandflashforboot
  521. ;nop
  522. ;==============这一段代码完成从NANDFlash读代码到RAM=====================
  523. nand_boot_beg;
  524. movr5,#NFCONF;首先设定NAND的一些控制寄存器
  525. ;settimingvalue
  526. ldrr0,=(7<<12)|(7<<8)|(7<<4)
  527. strr0,[r5]
  528. ;enablecontrol
  529. ldrr0,=(0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0)
  530. strr0,[r5,#4]
  531. blReadNandID;按着读取NAND的ID号,结果保存在r5里
  532. movr6,#0;r6设初值0.
  533. ldrr0,=0xec73;期望的NANDID号
  534. cmpr5,r0;这里进行比较
  535. beq%F1;相等的话就跳到下一个1标号处
  536. ldrr0,=0xec75;这是另一个期望值
  537. cmpr5,r0
  538. beq%F1;相等的话就跳到下一个1标号处
  539. movr6,#1;不相等,设置r6=1.
  540. 1
  541. blReadNandStatus;读取NAND状态,结果放在r1里
  542. movr8,#0;r8设初值0,意义为页号
  543. ldrr9,=ResetEntry;r9设初值为初始化程序入口地址
  544. ;注意,在这里使用的是ldr伪指令,而不是上面用的adr伪指令,它加载的是ResetEntry
  545. ;的绝对地址,也就是我们期望的RAM中的地址,在这里,它和|Image
    RO
    Base|一样
  546. ;也就是说,我如我们编译程序时RObase指定的地址在RAM里,而把生成的文件拷到
  547. ;NAND里运行,由ldr加载的r9的值还是定位在内存.???
  548. 2
  549. andsr0,r8,#0x1f;凡r8为0x1f(32)的整数倍-1,eq有效,ne无效
  550. bne%F3;这句的意思是对每个块(32页)进行检错--在每个块的开始页进行
  551. movr0,r8;r8->r0
  552. blCheckBadBlk;检查NAND的坏区
  553. cmpr0,#0;比较r0和0
  554. addner8,r8,#32;存在坏块的话就跳过这个坏块:+32得到下一块.故:r8=blockpageaddr,因为读写是按页进行的(每页512Byte)
  555. bne%F4;然后跳到4进行循环条件判断。没有的话就跳到标号3处copy当前页
  556. 3
  557. movr0,r8;当前页号->r0
  558. movr1,r9;当前目标地址->r1
  559. blReadNandPage;读取该页的NAND数据到RAM
  560. addr9,r9,#512;每一页的大小是512Bytes
  561. addr8,r8,#1;r8指向下一页
  562. 4
  563. cmpr8,#256;比较是否读完256页即128KBytes
  564. ;注意:这说明此程序默认拷贝128KByte的代码(byTinko)
  565. bcc%B2;如果r8小于256(没读完),就返回前面的标号2处
  566. ;nowcopycompleted
  567. movr5,#NFCONF;DisableNandFlash
  568. ldrr0,[r5,#4]
  569. bicr0,r0,#1
  570. strr0,[r5,#4]
  571. ldrpc,=copy_proc_beg;调用copy_proc_beg
  572. ;个人认为应该为InitRam?????????????????????????????
  573. ;===========================================================
  574. copy_proc_beg
  575. adrlr0,ResetEntry;ResetEntry值->r0
  576. ;这里应该注意,使用的是adr,而不是ldr。使用ldr说明ResetEntry是个绝对地址,这个地址是在程序链接的时候
  577. ;确定的。而使用adr则说明ResetEntry的地址和当前代码的执行位置有关,它是一个相对的地址。比如这段代码
  578. ;在stepingstone里面执行,那么ResetEntry的地址就是零。如果在RAM里执行,那么ResetEntry就应是RAM的一个
  579. ;地址,应该等于RObase。
  580. ldrr2,BaseOfROM;BaseOfROM值(后面有定义)->r2
  581. cmpr0,r2;比较ResetEntry和BaseOfROM
  582. ldreqr0,TopOfROM;如果相等的话(在内存运行---ice--无需复制code区中的ro段,但需要复制code区中的rw段),TopOfROM->r0
  583. beqInitRam;同时跳到InitRam
  584. ;否则,下面开始复制code的RO段
  585. ;=========================================================
  586. ;下面这个是针对代码在NORFLASH时的拷贝方法
  587. ;功能为把从ResetEntry起,TopOfROM-BaseOfROM大小的数据拷到BaseOfROM
  588. ;TopOfROM和BaseOfROM为|Image
    RO
    Limit|和|Image
    RO
    Base|
  589. ;|Image
    RO
    Limit|和|Image
    RO
    Base|由连接器生成
  590. ;为生成的代码的代码段运行时的起启和终止地址
  591. ;BaseOfBSS和BaseOfZero为|Image
    RW
    Base|和|Image
    ZI
    Base|
  592. ;|Image
    RW
    Base|和|Image
    ZI
    Base|也是由连接器生成
  593. ;两者之间就是初始化数据的存放地
  594. ;--在加载阶段,不存在ZI区域--
  595. ;=======================================================
  596. ldrr3,TopOfROM
  597. 0
  598. ldmiar0!,{r4-r7};开始时,r0=ResetEntry---source
  599. stmiar2!,{r4-r7};开始时,r2=BaseOfROM---destination
  600. cmpr2,r3;终止条件:复制了TopOfROM-BaseOfROM大小
  601. bcc%B0
  602. ;---------------------------------------------------------------
  603. ;下面2行,根据理解,由tinko添加
  604. ;猜测上面的代码不应该用"!",以至于地址被修改。这里重新赋值
  605. ;---------------------------------------------------------------
  606. adrlr0,ResetEntry;dontuseadr,causeoutofrangeerroroccures
  607. ldrr2,BaseOfROM
  608. ;旨在计算出正确的RW区起始位置
  609. ;下面2行目的是为了计算正确的r0(必须使之指向code区中的rw域开始处)
  610. subr2,r2,r3;r2=BaseOfROM-TopOfROM=(-)代码长度
  611. subr0,r0,r2;r0=ResetEntry-(-)代码长度=ResetEntry+代码长度
  612. InitRam
  613. ;复制代码加载位置中的RM区到|Image
    RW
    Base|
  614. ldrr2,BaseOfBSS;BaseOfBSS->r2,BaseOfBSS=|Image
    RW
    Base|
  615. ldrr3,BaseOfZero;BaseOfZero->r3,BaseOfZero=|Image
    ZI
    Base|
  616. 0
  617. cmpr2,r3;比较BaseOfBSS和BaseOfZero
  618. ldrccr1,[r0],#4;当代码在内存中运行时,r0(初始值)=TopOfROM.这之后的BaseOfZero-BaseOfBSS仍属于code,需拷贝到BaseOfBSS
  619. strccr1,[r2],#4
  620. bcc%B0
  621. ;用0初始化ZI区
  622. movr0,#0
  623. ldrr3,EndOfBSS;EndOfBSS=|Image
    ZI
    Limit|
  624. 1
  625. cmpr2,r3
  626. strccr0,[r2],#4
  627. bcc%B1
  628. ;要是r21;meansFclk:Hclkisnot1:1.
  629. ;blMMU_SetAsyncBusMode
  630. ;|
  631. ;blMMU_SetFastBusMode;defaultvalue.
  632. ;]
  633. ;blLed_Test
  634. ;===========================================================
  635. ;进入C语言前的最后一步了,就是把我们用说查二级向量表
  636. ;的中断例程安装到一级向量表(异常向量表)里.
  637. ;//5.设置缺省中断处理函数
  638. ;SetupIRQhandler
  639. ldrr0,=HandleIRQ;Thisroutineisneeded
  640. ldrr1,=IsrIRQ;ifthereisntsubspc,lr,#4at0x18,0x1c
  641. strr1,[r0]
  642. ;//initializetheIRQ将普通中断判断程序的入口地址给HandleIRQ
  643. ;//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  644. ;注意,以下这段可能不需要!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  645. ;//6.将数据段拷贝到ram中将零初始化数据段清零跳入C语言的main函数执行到这步结束bootloader初步引导结束
  646. ;Ifmain()isused,thevariableinitializationwillbedonein__main().
  647. [{FALSE};bytinko--最外面的条件由tinko添加,实际上不再执行这段
  648. [:LNOT:USE_MAIN;initialized{FALSE}
  649. ;CopyandpasteRWdata/zeroinitializeddata
  650. LDRr0,=|Image
    RO
    Limit|;GetpointertoROMdata
  651. LDRr1,=|Image
    RW
    Base|;andRAMcopy
  652. LDRr3,=|Image
    ZI
    Base|
  653. ;Zeroinitbase=>topofinitialiseddata
  654. CMPr0,r1;Checkthattheyaredifferentjustfordebug??????????????????????????
  655. BEQ%F2
  656. 1
  657. CMPr1,r3;Copyinitdata
  658. LDRCCr2,[r0],#4;-->LDRCCr2,[r0]+ADDr0,r0,#4
  659. STRCCr2,[r1],#4;-->STRCCr2,[r1]+ADDr1,r1,#4
  660. BCC%B1
  661. 2
  662. LDRr1,=|Image
    ZI
    Limit|;Topofzeroinitsegment
  663. MOVr2,#0
  664. 3
  665. CMPr3,r1;Zeroinit
  666. STRCCr2,[r3],#4
  667. BCC%B3
  668. ]
  669. ]
  670. ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  671. ;***************************************
  672. ;bytinko
  673. [{TRUE};得有些表示了,该点点LED灯了
  674. ;rGPFDAT=(rGPFDAT&~(0xf<<4))|((~data&0xf)<<4);
  675. ;Led_Display
  676. ldrr0,=GPFCON
  677. ldrr1,=0x5500
  678. strr1,[r0]
  679. ldrr0,=GPFDAT
  680. ldrr1,=0xe0
  681. strr1,[r0]
  682. ldrr2,=0xffffffff;
  683. 1
  684. subr2,r2,#1
  685. bne%b1
  686. ldrr0,=GPFDAT
  687. ldrr1,=0xe0
  688. ;b.;diehere
  689. ]
  690. ;*****************************************
  691. ;*****************************************************************************
  692. ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  693. ;妈呀,终说见到艳阳天了!!!!!!!!!!
  694. ;跳到C语言的main函数处了.
  695. ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  696. ;*****************************************************************************
  697. [:LNOT:THUMBCODE;ifthumbcode={false}blmainL代表logic变量
  698. blMain;Dontusemain()because......
  699. b.;注意小圆点
  700. ]
  701. ;//ifthumbcod={ture}
  702. [THUMBCODE;forstart-upcodeforThumbmode
  703. orrlr,pc,#1
  704. bxlr
  705. CODE16
  706. blMain;Dontusemain()because......
  707. b.;注意小圆点
  708. CODE32
  709. ]
  710. ;functioninitializingstacks
  711. InitStacks
  712. ;DontuseDRAM,suchasstmfd,ldmfd......
  713. ;SVCstackisinitializedbefore
  714. ;Undertoolkitver2.5,msrcpsr,r1canbeusedinsteadofmsrcpsr_cxsf,r1
  715. mrsr0,cpsr
  716. bicr0,r0,#MODEMASK
  717. orrr1,r0,#UNDEFMODE|NOINT
  718. msrcpsr_cxsf,r1;UndefMode
  719. ldrsp,=UndefStack;UndefStack=0x33FF_5C00
  720. orrr1,r0,#ABORTMODE|NOINT
  721. msrcpsr_cxsf,r1;AbortMode
  722. ldrsp,=AbortStack;AbortStack=0x33FF_6000
  723. orrr1,r0,#IRQMODE|NOINT
  724. msrcpsr_cxsf,r1;IRQMode
  725. ldrsp,=IRQStack;IRQStack=0x33FF_7000
  726. orrr1,r0,#FIQMODE|NOINT
  727. msrcpsr_cxsf,r1;FIQMode
  728. ldrsp,=FIQStack;FIQStack=0x33FF_8000
  729. bicr0,r0,#MODEMASK|NOINT
  730. orrr1,r0,#SVCMODE
  731. msrcpsr_cxsf,r1;SVCMode
  732. ldrsp,=SVCStack;SVCStack=0x33FF_5800
  733. ;USERmodehasnotbeinitialized.
  734. ;//为什么不用初始化user的stacks,系统刚启动的时候运行在哪个模式下?
  735. movpc,lr
  736. ;TheLRregisterwontbevalidifthecurrentmodeisnotSVCmode.?
  737. ;//系统一开始运行就是SVCmode?
  738. ;===========================================================
  739. ReadNandID
  740. movr7,#NFCONF
  741. ldrr0,[r7,#4];NFChipEn();
  742. bicr0,r0,#2
  743. strr0,[r7,#4]
  744. movr0,#0x90;WrNFCmd(RdIDCMD);
  745. strbr0,[r7,#8]
  746. movr4,#0;WrNFAddr(0);
  747. strbr4,[r7,#0xc]
  748. 1;while(NFIsBusy());
  749. ldrr0,[r7,#0x20]
  750. tstr0,#1
  751. beq%B1
  752. ldrbr0,[r7,#0x10];id=RdNFDat()<<8;
  753. movr0,r0,lsl#8
  754. ldrbr1,[r7,#0x10];id|=RdNFDat();
  755. orrr5,r1,r0
  756. ldrr0,[r7,#4];NFChipDs();
  757. orrr0,r0,#2
  758. strr0,[r7,#4]
  759. movpc,lr
  760. ReadNandStatus
  761. movr7,#NFCONF
  762. ldrr0,[r7,#4];NFChipEn();
  763. bicr0,r0,#2
  764. strr0,[r7,#4]
  765. movr0,#0x70;WrNFCmd(QUERYCMD);
  766. strbr0,[r7,#8]
  767. ldrbr1,[r7,#0x10];r1=RdNFDat();
  768. ldrr0,[r7,#4];NFChipDs();
  769. orrr0,r0,#2
  770. strr0,[r7,#4]
  771. movpc,lr
  772. WaitNandBusy
  773. movr0,#0x70;WrNFCmd(QUERYCMD);
  774. movr1,#NFCONF
  775. strbr0,[r1,#8]
  776. 1;while(!(RdNFDat()&0x40));
  777. ldrbr0,[r1,#0x10]
  778. tstr0,#0x40
  779. beq%B1
  780. movr0,#0;WrNFCmd(READCMD0);
  781. strbr0,[r1,#8]
  782. movpc,lr
  783. CheckBadBlk
  784. movr7,lr
  785. movr5,#NFCONF
  786. bicr0,r0,#0x1f;addr&=~0x1f;
  787. ldrr1,[r5,#4];NFChipEn()
  788. bicr1,r1,#2
  789. strr1,[r5,#4]
  790. movr1,#0x50;WrNFCmd(READCMD2)
  791. strbr1,[r5,#8]
  792. movr1,#5;6;6->5
  793. strbr1,[r5,#0xc];WrNFAddr(5);(6)6->5
  794. strbr0,[r5,#0xc];WrNFAddr(addr)
  795. movr1,r0,lsr#8;WrNFAddr(addr>>8)
  796. strbr1,[r5,#0xc]
  797. cmpr6,#0;if(NandAddr)
  798. movner0,r0,lsr#16;WrNFAddr(addr>>16)
  799. strnebr0,[r5,#0xc]
  800. ;blWaitNandBusy;WaitNFBusy()
  801. ;donotuseWaitNandBusy,afterWaitNandBusywillreadpartA!
  802. movr0,#100
  803. 1
  804. subsr0,r0,#1
  805. bne%B1
  806. 2
  807. ldrr0,[r5,#0x20]
  808. tstr0,#1
  809. beq%B2
  810. ldrbr0,[r5,#0x10];RdNFDat()
  811. subr0,r0,#0xff
  812. movr1,#0;WrNFCmd(READCMD0)
  813. strbr1,[r5,#8]
  814. ldrr1,[r5,#4];NFChipDs()
  815. orrr1,r1,#2
  816. strr1,[r5,#4]
  817. movpc,r7
  818. ReadNandPage
  819. movr7,lr
  820. movr4,r1
  821. movr5,#NFCONF
  822. ldrr1,[r5,#4];NFChipEn()
  823. bicr1,r1,#2
  824. strr1,[r5,#4]
  825. movr1,#0;WrNFCmd(READCMD0)
  826. strbr1,[r5,#8]
  827. strbr1,[r5,#0xc];WrNFAddr(0)
  828. strbr0,[r5,#0xc];WrNFAddr(addr)
  829. movr1,r0,lsr#8;WrNFAddr(addr>>8)
  830. strbr1,[r5,#0xc]
  831. cmpr6,#0;if(NandAddr)
  832. movner0,r0,lsr#16;WrNFAddr(addr>>16)
  833. strnebr0,[r5,#0xc]
  834. ldrr0,[r5,#4];InitEcc()
  835. orrr0,r0,#0x10
  836. strr0,[r5,#4]
  837. blWaitNandBusy;WaitNFBusy()
  838. movr0,#0;for(i=0;i<512;i++)
  839. 1
  840. ldrbr1,[r5,#0x10];buf[i]=RdNFDat()
  841. strbr1,[r4,r0]
  842. addr0,r0,#1
  843. bicr0,r0,#0x10000
  844. cmpr0,#0x200
  845. bcc%B1
  846. ldrr0,[r5,#4];NFChipDs()
  847. orrr0,r0,#2
  848. strr0,[r5,#4]
  849. movpc,r7
  850. ;--------------------LEDtest
  851. EXPORTLed_Test
  852. Led_Test
  853. movr0,#0x56000000
  854. movr1,#0x5500
  855. strr1,[r0,#0x50]
  856. 0
  857. movr1,#0x50
  858. strr1,[r0,#0x54]
  859. movr2,#0x100000
  860. 1
  861. subsr2,r2,#1
  862. bne%B1
  863. movr1,#0xa0
  864. strr1,[r0,#0x54]
  865. movr2,#0x100000
  866. 2
  867. subsr2,r2,#1
  868. bne%B2
  869. b%B0
  870. movpc,lr
  871. ;===========================================================
  872. ;=====================================================================
  873. ;Clockdivisiontest
  874. ;Assemblecode,becauseVSYNCtimeisveryshort
  875. ;=====================================================================
  876. EXPORTCLKDIV124
  877. EXPORTCLKDIV144
  878. CLKDIV124
  879. ldrr0,=CLKDIVN
  880. ldrr1,=0x3;0x3=1:2:4
  881. strr1,[r0]
  882. ;waituntilclockisstable
  883. nop
  884. nop
  885. nop
  886. nop
  887. nop
  888. ldrr0,=REFRESH
  889. ldrr1,[r0]
  890. bicr1,r1,#0xff
  891. bicr1,r1,#(0x7<<8)
  892. orrr1,r1,#0x470;REFCNT135
  893. strr1,[r0]
  894. nop
  895. nop
  896. nop
  897. nop
  898. nop
  899. movpc,lr
  900. CLKDIV144
  901. ldrr0,=CLKDIVN
  902. ldrr1,=0x4;0x4=1:4:4
  903. strr1,[r0]
  904. ;waituntilclockisstable
  905. nop
  906. nop
  907. nop
  908. nop
  909. nop
  910. ldrr0,=REFRESH
  911. ldrr1,[r0]
  912. bicr1,r1,#0xff
  913. bicr1,r1,#(0x7<<8)
  914. orrr1,r1,#0x630;REFCNT675-1520
  915. strr1,[r0]
  916. nop
  917. nop
  918. nop
  919. nop
  920. nop
  921. movpc,lr
  922. ;存储器控制寄存器的定义区
  923. LTORG
  924. SMRDATADATA
  925. ;Memoryconfigurationshouldbeoptimizedforbestperformance
  926. ;Thefollowingparameterisnotoptimized.
  927. ;Memoryaccesscycleparameterstrategy
  928. ;1)ThememorysettingsissafeparametersevenatHCLK=75Mhz.
  929. ;2)SDRAMrefreshperiodisforHCLK<=75Mhz.
  930. DCD(0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28));各bank的buswidth;没有B0,因为由OM[1:0]pins确定
  931. DCD((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC));GCS0
  932. DCD((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC));GCS1
  933. DCD((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC));GCS2
  934. DCD((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC));GCS3
  935. DCD((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC));GCS4
  936. DCD((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC));GCS5
  937. DCD((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN));GCS6B6_MT定义在memcfg.inc中,11-->SDRAM;B6_SCAN-非reset默认值
  938. DCD((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN));GCS7
  939. DCD((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT);Tchr-notused
  940. ;DCD0x32;SCLKpowersavingmode,BANKSIZE128M/128M
  941. DCD0x31;SCLKpowersavingmode,BANKSIZE64M/64M
  942. DCD0x30;MRSR6CL=3clk
  943. DCD0x30;MRSR7CL=3clk
  944. BaseOfROMDCD|Image
    RO
    Base|
  945. TopOfROMDCD|Image
    RO
    Limit|
  946. BaseOfBSSDCD|Image
    RW
    Base|
  947. BaseOfZeroDCD|Image
    ZI
    Base|
  948. EndOfBSSDCD|Image
    ZI
    Limit|
  949. ALIGN
  950. AREARamData,DATA,READWRITE
  951. ^_ISR_STARTADDRESS;_ISR_STARTADDRESS=0x33FF_FF00
  952. HandleReset#4
  953. HandleUndef#4
  954. HandleSWI#4
  955. HandlePabort#4
  956. HandleDabort#4
  957. HandleReserved#4
  958. HandleIRQ#4
  959. HandleFIQ#4
  960. ;DontusethelabelIntVectorTable,
  961. ;ThevalueofIntVectorTableisdifferentwiththeaddressyouthinkitmaybe.
  962. ;IntVectorTable
  963. ;@0x33FF_FF20
  964. HandleEINT0#4
  965. HandleEINT1#4
  966. HandleEINT2#4
  967. HandleEINT3#4
  968. HandleEINT4_7#4
  969. HandleEINT8_23#4
  970. HandleCAM#4;Addedfor2440.
  971. HandleBATFLT#4
  972. HandleTICK#4
  973. HandleWDT#4
  974. HandleTIMER0#4
  975. HandleTIMER1#4
  976. HandleTIMER2#4
  977. HandleTIMER3#4
  978. HandleTIMER4#4
  979. HandleUART2#4
  980. ;@0x33FF_FF60
  981. HandleLCD#4
  982. HandleDMA0#4
  983. HandleDMA1#4
  984. HandleDMA2#4
  985. HandleDMA3#4
  986. HandleMMC#4
  987. HandleSPI0#4
  988. HandleUART1#4
  989. HandleNFCON#4;Addedfor2440.
  990. HandleUSBD#4
  991. HandleUSBH#4
  992. HandleIIC#4
  993. HandleUART0#4
  994. HandleSPI1#4
  995. HandleRTC#4
  996. HandleADC#4
  997. ;@0x33FF_FFA0
  998. END


关键词: S3C2440启动代

评论


技术专区

关闭