Chinaunix首页 | 论坛 | 博客
  • 博客访问: 233460
  • 博文数量: 50
  • 博客积分: 1793
  • 博客等级: 上尉
  • 技术积分: 393
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-22 23:28
文章分类
文章存档

2012年(7)

2011年(17)

2010年(26)

我的朋友

分类:

2010-07-23 12:01:42

    才开始学嵌入式没多久,用得友善之臂的2440板子,前段时间一直在搞linux系统,软件移植,内核裁剪等,最近发现还是应该从最基本的学起,想自己写 一个bootloader,然后就研究了友善之臂那个板子上光盘里面配的一个示例程序,哎,搞了一天多才研究出来一点点东西,贴上来,免得忘了!

S3C2440启动过程(约略):
1、关闭watch dog
2、屏蔽所有中断
3、屏蔽所有子中断
4、设置时钟更改稳定等待时间(LOCKTIME)
5、设置各部件时钟频率与CPU主频的比例关系(Fclk:Hclk:Pclk)
6、设置USB总线时钟频率(UPLLCON)
7、nap * 7
8、设置主时钟(MPLLCON)
9、判断是否是从睡眠状态唤醒的,如果是,则做出相应处理(具体处理还没看)
10、初始化存储设备、包括外存,内存等(BWSCON,BANKCONn,BANKSIZE,MRSRB6,MRSRB7)
11、初始化处理器各模式的堆栈(还没看懂)
12、Setup IRQ handler(也没咋看懂,似乎是对IRQ终端进行处理)
13、进入C程序(bl Main)


代码分析:
;=========================================
; NAME: 2440INIT.S
; DESC: C start up codes
      Configure memory, ISR ,stacks
   Initialize C-variables
; HISTORY:
; 2002.02.25:kwtark: ver 0.0
; 2002.03.20:purnnamu: Add some functions for testing STOP,Sleep mode
; 2003.03.14:DonGo: Modified for 2440.
; 2009.02.19:PuHao: Comments
;=========================================


;=========================
; ENTRY 这里是关键的入口,正文数量超过最大限制,只有忽略其他我没看懂的了,等下能不能把那个文件传上来,好恶心的规定……
;=========================
ResetHandler
 
   ;WTCON定义在2440addr.inc里面,WTCON     EQU  0x53000000
    ;把WTCON地址放到R0里,然后在设置r1为0,最后把r1中的0值
    ;拷贝到r0所指向的地址里面,即禁用watch dog
    ldr    r0,=WTCON       ;watch dog disable
    ldr    r1,=0x0
    str    r1,[r0]
    
    ;基本同上,INTMSK 0x4A000008 R/W Interrupt mask control
    ldr    r0,=INTMSK
    ldr    r1,=0xffffffff  ;all interrupt disable
    str    r1,[r0]

    ;基本同上
    ldr    r0,=INTSUBMSK
    ldr    r1,=0x3ff        ;all sub interrupt disable,0x3ff => 0000 0011  1111 1111
    str    r1,[r0]

    ;由于条件为FALSE,我觉得这段根本就不会执行
    [ {FALSE}
    ; rGPFDAT = (rGPFDAT & ~(0xf<<4)) | ((~data & 0xf)<<4);
    ; Led_Display
    ldr    r0,=GPFCON
    ldr    r1,=0x5500
    str    r1,[r0]
    ldr    r0,=GPFDAT
    ldr    r1,=0x10
    str    r1,[r0]
    ]

    ;由于在更改了主时钟控制器(MPLL)之后,新的频率需要一定时间过后才能稳定
    ;所以需要等待一段时间,而这个等待的时间就是使用LOCKTIME寄存器来设置的
    ;LOCKTIME[15:00] MPLL lock time count value for FCLK, HCLK, and PCLK
    ;LOCKTIME[32:16] UPLL lock time count value for UCLK.
    ; FCLK用于CPU核
    ; HCLK用于AHB总线的设备(比如SDRAM)
    ; PCLK用于APB总线的设备(比如UART)
    ; UPLL为USB的控制时钟,根据USB规范,好像是48MHz
    ; ARM920T内核使用FCLK
    ; 内存控制器,LCD控制器等使用HCLK;
    ; 看门狗、串口等使用PCLK
    ;To reduce PLL lock time, adjust the LOCKTIME register.
    ldr    r0,=LOCKTIME
    ldr    r1,=0xffffff ;0000 0000  1111 1111  1111 1111  1111 1111
    str    r1,[r0]      ;为什么UPLL的等待时间要少一些呢?

    [ PLL_ON_START
    ; Added for confirm clock divide. for 2440.
    ; Setting value Fclk:Hclk:Pclk
    ; 这里设置的 Fclk:Hclk:Pclk = 1:3:6,因为 CLKDIV_VAL = 7
    ldr    r0,=CLKDIVN  
    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.
    str    r1,[r0]

    ;UPLL和MPLL的控制参数
    ;PLLCON        Bit        Description             Initial State
    ;MDIV        [19:12] Main divider control    0x96 / 0x4d
    ;PDIV        [9:4]    Pre-divider control        0x03 / 0x03
    ;SDIV        [1:0]    Post divider control    0x0 / 0x0    
    
    ;InputFrequency        OutputFrequency        MDIV        PDIV    SDIV
    ;12.0000MHz         48.00 MHz(Note)     56(0x38)            2
    ;12.0000MHz         96.00 MHz(Note)     56(0x38)            1
    ;12.0000MHz         271.50 MHz             173(0xad)            2
    ;12.0000MHz         304.00 MHz             68(0x44)            1
    ;12.0000MHz         405.00 MHz             127(0x7f)            1
    ;12.0000MHz         532.00 MHz             125(0x7d)            1

    ;Configure UPLL
    ; 根据手册,要对PLL进行设置的话,就需要先设置UPLLCON,再设置MPLLCON
    ; 并且中间需要有至少七个指令周期的延时
    ; (Needs intervals approximately 7 NOP)
    ; U_MDIV        EQU    56        ;Fin=12.0MHz Fout=48MHz
    ; U_PDIV        EQU    2
    ; U_SDIV        EQU    2
    ldr    r0,=UPLLCON
    ldr    r1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV)
    str    r1,[r0]
    
    ;(Needs intervals approximately 7 NOP)
    nop    ; Caution: After UPLL setting, at least 7-clocks delay must be inserted for setting hardware be completed.
    nop
    nop
    nop
    nop
    nop
    nop
    ;Configure MPLL
    ; M_MDIV     EQU    68        ; 68 = 0x44 Fin=12.0MHz Fout=304.8MHz
    ; M_PDIV     EQU    1
    ; M_SDIV     EQU          ; 2440A
    ; 设为(0x44 << 12)|(0x01 << 4)|(0x01),即0x00044011
    ; Fclk:Hclk:Pclk = 1:3:6 =>  Fclk = 300MHz, Hclk = 100MHz, Pclk = 50MHz
    ;
    ldr    r0,=MPLLCON
    ldr    r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV)
    str    r1,[r0]
    ]
    
       ;Check if the boot is caused by the wake-up from SLEEP mode.
       ; GSTATUS2        Bit            Description
    ; Reserved        [3]            Reserved
    ; WDTRST        [2]            Boot is caused by Watch Dog Reset                cleared by writing “1”
    ; SLEEPRST        [1]            Boot is caused by wakeup reset in sleep mode    cleared by writing “1”.
    ; PWRST            [0]            Boot is caused by power on reset                cleared by writing “1”
    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伪指令声明一个全局标号
    EXPORT StartPointAfterSleepWakeUp
StartPointAfterSleepWakeUp
    
    ;Set memory control registers
     ldr    r0,=SMRDATA
    ldr    r1,=BWSCON    ;BWSCON Address
    add    r2, r0, #52    ;End address of SMRDATA
    ;r2 = r0 + 52

    ; beq  %F[ ]中,b为跳转指令,eq为相等条件标识,整条语句的意思就是
    ; 如果相等,则在此条语句后面的代码中搜索[ ]标号并跳转。
    ; 同样的 bcc %B[ ] 其中cc为无符号数小于,%B在此条语句前面的代码中搜索并跳转

    ;下面是一个循环
    ;首先把r0指向的地址单元的一个字(4字节)的内容复制到r3中,
    ;然后r0+4,这样的话下次取的值将会是SMRDATA中的下一个个字
    ;
    ;将r3中的值写入到r1的地址单元(BWSCON)中,并将r1+1,即
    ;下一次将会写入到BWSCON的下一个控制器
    ;控制器以此为:BWSCON - BANKCON0 - BANKCON1 - BANKCON2  ……BANKCON7
                 BANKSIZE - MRSRB6 - MRSRB7
0
    ldr    r3, [r0], #4
    str    r3, [r1], #4
    cmp    r2, r0    ;CPSR = r2 - r0        
    bne    %B0        ;不等于0时跳转,也就是说一直循环直到将上面所说的控制器全部
                ;设置了值之后才继续执行下一步

         ;Initialize stacks
    bl    InitStacks


      ; Setup IRQ handler
    ldr    r0,=HandleIRQ  ;This routine is needed
    ldr    r1,=IsrIRQ       ;if there isn't 'subs pc,lr,#4' at 0x18, 0x1c
    str    r1,[r0]


    ;If main() is used, the variable initialization will be done in __main().
      :LNOT:USE_MAIN    
        ;Copy and paste RW data/zero initialized data
    LDR     r0, =|Image$$RO$$Limit| ; Get pointer to ROM data
    LDR     r1, =|Image$$RW$$Base|  ; and RAM copy
    LDR     r3, =|Image$$ZI$$Base|  
    
    ;Zero init base => top of initialised data
    CMP     r0, r1      ; Check that they are different
    BEQ     %F2
      
    CMP     r1, r3      ; Copy init data
    LDRCC   r2, [r0], #4    ;--> LDRCC r2, [r0] + ADD r0, r0, #4         
    STRCC   r2, [r1], #4    ;--> STRCC r2, [r1] + ADD r1, r1, #4
    BCC     %B1
      
    LDR     r1, =|Image$$ZI$$Limit| ; Top of zero init segment
    MOV     r2, #0
      
    CMP     r3, r1      ; Zero init
    STRCC   r2, [r3], #4
    BCC     %B3
    ]


       
    [ :LNOT:THUMBCODE
        bl    Main        ;Don't use main() because ......because what?
                                 
    ]

    [ THUMBCODE         ;for start-up code for Thumb mode
        orr    lr,pc,#1
        bx    lr
        CODE16
        bl    Main        ;Don't use main() because ......because what?
           .
        CODE32
    ]


;function initializing stacks
;初始化堆栈的代码还没仔细研究正文字数超过最大限制,只有不贴下面的了……
阅读(1372) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~