mini2440启动代码分析之第七篇(ResetHandler和存储控制寄存器初始化)

1212阅读 0评论2012-02-17 378333581
分类:

 LTORG       ;用于声明一个数据缓冲池,也叫文字池

;=============================================================================

上电和复位后,程序开始从位于0x0 执行b ResetHandler 程序跳转到这里执行,将看门狗,中断之类的程序关掉,以免打扰初始化程序的进行。

; ENTRY

;=============================================================================

ResetHandler

       ldr   r0,=WTCON       ;watch dog disable

       ldr   r1,=0x0

       str    r1,[r0]

;WTCON 为看门狗控制寄存器,此处将其写入0x0,就是禁止它的所有功能,包括定时器定时,溢出中断及溢出复位。

       ldr   r0,=INTMSK

       ldr   r1,=0xffffffff  ;all interrupt disable

       str    r1,[r0]

;INTMSK 为中断屏蔽寄存器,写入0xffffffff,就是禁止所有的中断产生,因为中断向量表还未初始化,如果此时产生中断会使程序进入未知的状态而跑飞。因为外设的中断太多,INTMSK 不够用,还需要将子中断INTSUBMSK 来将剩余的中断源也禁止掉。

       ldr   r0,=INTSUBMSK

       ldr   r1,=0x7fff             ;all sub interrupt disable

       str    r1,[r0]

 

      [ {FALSE}                ;亮灯用的,可以用来调试用

              ;rGPFDAT = (rGPFDAT & ~(0xf<<4)) | ((~data & 0xf)<<4);

              ; Led_Display

              ldr   r0,=GPBCON

              ldr   r1,=0x155500

              str    r1,[r0]

              ldr   r0,=GPBDAT

              ldr   r1,=0x0

              str    r1,[r0]

       ]

 

       ;To reduce PLL lock time, adjust the LOCKTIME register.

       ldr   r0,=LOCKTIME                 ;设置pll 锁定时间

       ldr   r1,=0xffffff

       str    r1,[r0]

;LOCKTIME PLL 锁定时间计数寄存器,重新设定分频值时,PLL 进入锁定,输出稳定频率的时钟需要一定的时间。这里设置成默认的值,以满足锁定的要求。

 

       [ PLL_ON_START     ;在option.inc中定义,初始化为真

              ; Added for confirm clock divide. for 2440为2440添加时钟设备.

              ; Setting value Fclk:Hclk:Pclk

              ldr   r0,=CLKDIVN             ;用于设定FCLKHCLKPCLK的比例

              ldr   r1,=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中有定义

              str    r1,[r0]

; MMU_SetAsyncBusMode and MMU_SetFastBusMode over 4K, so do not call here
; call it after copy
; [ CLKDIV_VAL>1   ; means Fclk:Hclk is not 1:1.
; bl MMU_SetAsyncBusMode
; |
; bl MMU_SetFastBusMode ; default value.
; ]

;三星手册里提供的MMU_SetAsyncBusMode 和 MMU_SetFastBusMode 函数都在4K代码以上(三星2440芯片就提供4K的内部SRAM),如果你想你编译出来的程序能在NAND上运行的话,就不能在这调用这两函数了.如果你不要求的话,你就可以直接调用.下面的代码就是实现和上面两函数一样的功能. 利用的协处理器的命令实现了对总线模式的设置

       ;program has not been copied, so use these directly

              [ CLKDIV_VAL>1              ; means Fclk:Hclk is not 1:1.

                     mrc p15,0,r0,c1,c0,0

                     orr r0,r0,#0xc0000000;R1_nF:OR:R1_iA

                     mcr p15,0,r0,c1,c0,0

                     |

                     mrc p15,0,r0,c1,c0,0

                     bic r0,r0,#0xc0000000;R1_iA:OR:R1_nF

                     mcr p15,0,r0,c1,c0,0

              ]

;配置UPLL一定要使最后的频率为48MHz,不然你甭想用USB接口了, 先赔UPLL再配MPLL,不能颠倒了

              ;Configure UPLL

              ldr   r0,=UPLLCON

              ldr   r1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV)          ;Fin = 12.0MHz, UCLK = 48MHz

              str    r1,[r0]

              nop       ;UPP 设定之后,必须等待个时钟的延迟,设定才会有效(因为5级流水线,搞不懂)

              nop

              nop

              nop

              nop

              nop

              nop

;Configure MPLL,设置MPLL, 2440主频可达400MHz

              ldr   r0,=MPLLCON

              ldr   r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV)         ;Fin = 12.0MHz, FCLK = 400MHz

              str   r1,[r0]

       ]

;查看是否是由睡眠状态启动,如果是则跳转到WAKEUP_SLEEP状态

;Check if the boot is caused by the wake-up from SLEEP mode.

       ldr   r1,=GSTATUS2

       ldr   r0,[r1]

       tst    r0,#0x2     ;In case of the wake-up from SLEEP mode, go to SLEEP_WAKEUP handler.

       bne  WAKEUP_SLEEP

 

       EXPORT StartPointAfterSleepWakeUp

StartPointAfterSleepWakeUp

;初始化内存控制器其实就是对S3C2440 memory bank 进行设置,使其扩展的存储器或外部设备能够被处理器通过内存控制器正确读写。由于S3C2440 的最终应用程序是在SDRAMbank6)中运行,并与语言变量等的用户数据,各种模式的堆栈,中断向量表,都被定位在SDRAM 的空间,所以它必须在涉及这些处理之前完成初始化工作。

      ;Set memory control registers,设置存储器控制寄存器,SMRDATA中涉及的值请参考memcfg.inc程序

      ;ldr  r0,=SMRDATA

      adrl  r0, SMRDATA       ;be careful!不要用错,adr装载相对地址,ldr装载绝对地址,ro是数据区起始地址

       ldr   r1,=BWSCON       ;BWSCON Address,BWSCON地址,r1是寄存器的起始地址

       add  r2, r0, #52            ;End address of SMRDATA,SMRDATA结束地址,r2是数据区结束地址

0

       ldr   r3, [r0], #4

       str    r3, [r1], #4

       cmp r2, r0

       bne  %B0

;这段是功能寄存器初始化,把13 个存储控制器的内容批量的读取到了对应的特殊功能寄存器中,首先是下面有一个数据区SMRDATA,在程序的后面有定义,这个数据区给13 个寄存器分配52 字节的地址空间。在上面的代码中,r0 是这个数据区的起始地址,r2 是数据区的结束地址,r1 是寄存器的起始地址。这样,用一个判断语句就可以把内存中的数据赋给这13 个存储控制寄存器了。

上一篇:Linux中Workqueue机制分析
下一篇:C++ 指针和引用的区别