AT91RM9200啟動程式碼分析

來源:互聯網
上載者:User

AT91RM9200 的時鐘源有4個:
慢時鐘(SLK)
主時鐘(Main Clock)
PLLA,PLLB
在這裡需要區別一個概念:主時鐘和主機時鐘
主時鐘(main clock)是指輸入主振蕩器的時鐘
主機時鐘(mck)指CPU的時鐘頻率。
主機時鐘可以在4個時鐘源中選擇(時鐘選取器)一個作為本身的時鐘
時鐘設定流程

啟動代碼中一些預定義的值
;-----------------------------------------------------------------------------
;- ARM Core Mode and Status Bits       ARM核心模式和狀態位
;------------------------------------------------------------------------------

ARM_MODE_USER          EQU     0x10
ARM_MODE_FIQ            EQU     0x11
ARM_MODE_IRQ            EQU     0x12
ARM_MODE_SVC            EQU     0x13
ARM_MODE_ABORT         EQU     0x17
ARM_MODE_UNDEF         EQU     0x1B
ARM_MODE_SYS            EQU     0x1F

I_BIT                   EQU     0x80
F_BIT                  EQU     0x40
T_BIT                  EQU     0x20

;------------------------------------------------------------------
;- Stack Area Definition 堆棧段地區定義
;------------------------------------------------------------------
IRQ_STACK_SIZE         EQU      0x04
FIQ_STACK_SIZE         EQU      0x04
ABT_STACK_SIZE        EQU      0x04
UND_STACK_SIZE        EQU      0x04
SVC_STACK_SIZE        EQU      0x04
USER_STACK_SIZE       EQU      0x100

;----------------------------------------------------------------------------
9200啟動後時鐘變化
由於系統複位後進入慢時鐘狀態,由慢時鐘提供主機時鐘源,但由於內建boot程式可能已經啟動,需要在啟動時重新設定慢時鐘為主機時鐘源。但主機時鐘寄存器要求寫入的值不能和當前值相同,所以要分成兩步,代碼如下:
//第一步,將PMC_MCKR 修改一下,這裡使其選擇PLLB作為主機時鐘源
ldr              r1, = AT91C_BASE_PMC         ;取得PMC的基地址
ldr              r0, = AT91C_PMC_CSS_PLLB_CLK               
str              r0, [r1, #PMC_MCKR]       ;向PMC_MCKR寄存器寫入數值   
//通過測試狀態寄存器 PMC_SR的第3位來判斷時鐘設定是否成功
mov          r4, #0x8
MCKR_Loop
         ldr               r3, [r1, #PMC_SR]
         and            r3, r4, r3   
         cmp     r3, #0x8
         bne             MCKR_Loop

//第二步,修改PMC_MCKR使其選擇慢時鐘SCK作為主機時鐘源
ldr              r0, = AT91C_PMC_CSS_SLOW_CLK :OR:AT91C_PMC_PRES_CLK
str              r0, [r1, #PMC_MCKR]
mov          r4, #0x8
MCKR_Loop2
         ldr               r3, [r1, #PMC_SR]
         and            r3, r4, r3
         cmp     r3, #0x8
         bne             MCKR_Loop2

//為了節省功耗關閉PLLs。
//實際上,在機器複位後PLLs 是被預設關閉的,但是在以前有一個boot程式已經運行過的情況//下,PLLs可能已經被開啟,所以要在這個boot程式開始的時候要先關閉PLLs。
ldr          r1, = AT91C_BASE_CKGR          ; 取得CKGR 的基地址

ldr          r0, = AT91C_CKGR_DIVA_0
str           r0, [r1, #CKGR_PLLAR]            : 關閉 PLLA

ldr          r0, = AT91C_CKGR_DIVB_0
str           r0, [r1, #CKGR_PLLBR]            : 關閉 PLLB

以上動作完成之後,系統的主機時鐘源就是慢時鐘。但是,系統正常運行時不可能用慢時鐘作為時鐘源,(比如此時用plla作為時鐘源),就需要進一步的設定。
對於PLL時鐘,它的時鐘源是主振蕩器時鐘(即主時鐘 main clock),所以要先將主時鐘開啟,代碼如下:
//開啟主時鐘
//MOSCEN 主時鐘使能位;OSCOUNT 指定慢刻度數作為主振蕩器啟動時間
ldr              r0, = AT91C_CKGR_MOSCEN:OR:AT91C_CKGR_OSCOUNT
str              r0, [r1, #CKGR_MOR]
選擇主時鐘作為主機時鐘,設定時鐘頻率等工作等到後面用C語言來完成。這裡將繼續用彙編進行其餘的初始化動作,直到運行至AT91F_LowLevelInit函數。
//為各種處理器模式設定堆棧
; 載入堆棧基地址
add     r0, pc,#-(8+.-StackData)  ; r0 = pc – 8 - . + StackData ,讓r0指向StackData
ldmia   r0, {r1-r6}            ;從r0指向的地址單元載入資料到r1~r6中

;- Set up Supervisor Mode and set SVC Mode Stack
msr     cpsr_c, #ARM_MODE_SVC : OR : I_BIT : OR : F_BIT
bic      r1, r1, #3                  ; Insure word alignement
mov     sp, r1                      ; Init stack SYS

;- Set up Interrupt Mode and set IRQ Mode Stack
msr     CPSR_c, #ARM_MODE_IRQ : OR : I_BIT : OR : F_BIT
bic      r2, r2, #3                  ; 確保字對齊
mov     sp, r2                     ; 設定IRQ模式堆棧指標

;- Set up Fast Interrupt Mode and set FIQ Mode Stack
msr     CPSR_c, #ARM_MODE_FIQ : OR : I_BIT : OR : F_BIT
bic     r3, r3, #3                  ; Insure word alignement
mov    sp, r3                     ; Init stack FIQ

;- Set up Abort Mode and set Abort Mode Stack
msr     CPSR_c, #ARM_MODE_ABORT : OR : I_BIT : OR : F_BIT
bic      r4, r4, #3                 ; Insure word alignement
mov     sp, r4                    ; Init stack Abort

;- Set up Undefined Instruction Mode and set Undef Mode Stack
msr     CPSR_c, #ARM_MODE_UNDEF : OR : I_BIT : OR : F_BIT
bic      r5, r5, #3                 ; Insure word alignement
mov     sp, r5                    ; Init stack Undef

;- Set up user Mode and set Undef Mode Stack
msr     CPSR_c, #ARM_MODE_SYS : OR : I_BIT : OR : F_BIT
bic      r6, r6, #3                  ; Insure word alignement
mov     sp, r6                     ; Init stack Undef

b       EndInitStack

StackData
         DCD     AT91_SVC_Stack_Begin
         DCD     AT91_IRQ_Stack_Begin
         DCD     AT91_FIQ_Stack_Begin
         DCD     AT91_ABT_Stack_Begin
         DCD     AT91_UND_Stack_Begin
         DCD     AT91_USER_Stack_Begin
EndInitStack

; 補償主振蕩器啟動時間
         ldr    r0, =0x00000010
LoopOsc
         subs    r0, r0, #1
         bhi     LoopOsc

; 調用C函數 AT91F_LowLevelInit()
         IMPORT    AT91F_LowLevelInit

         ldr       r0, = AT91F_LowLevelInit
         mov      lr, pc
         bx        r0
;-----------------------------------------------------
;       讀/改/寫 CP15 控制寄存器
;-----------------------------------------------------
    MRC     p15, 0, r0, c1, c0,0    ; read cp15 control register (cp15 r1) in r0
    ldr           r3, =0xC0000080       ; Reset bit :Little Endian end fast bus mode
    ldr          r4, =0xC0000000       ; Set bit :Asynchronous clock mode, Not Fast Bus
    BIC      r0, r0, r3
    ORR     r0, r0, r4
    MCR     p15, 0, r0, c1, c0,0    ; write r0 in cp15 control registre (cp15 r1)

;-----------------------------------------------------
;       初始化C變數
;-----------------------------------------------------

         add        r2, pc,#-(8+.-CInitData)         ; @ where to read values (relative)
         ldmia        r2, {r0, r1, r3, r4}

         cmp       r0, r1                  ; Check that they are different
         beq       EndRW
LoopRW
         cmp       r1, r3                ; Copy init data
         ldrcc       r2, [r0], #4                        ;從r0指向的地址載入資料到r2後,r2+4
         strcc       r2, [r1], #4                        ;將r2中資料存放區到r1指向的地址後,r1+4
         bcc        LoopRW
EndRW

         mov       r2, #0
LoopZI
         cmp       r3, r4                  ; Zero init
         strcc       r2, [r3], #4
         bcc        LoopZI

         b          EndInitC

CInitData
        IMPORT      |Image$$RO$$Limit|      ; ROM 代碼結束處 (=ROM 資料開始處)
         IMPORT      |Image$$RW$$Base|      ; Base of RAM to initialise
         IMPORT      |Image$$ZI$$Base|       ; Base and limit of area
         IMPORT      |Image$$ZI$$Limit|       ; Top of zero init segment

         DCD     |Image$$RO$$Limit|      ; End of ROM code (=start of ROM data)
        DCD     |Image$$RW$$Base|      ; Base of RAM to initialise
        DCD     |Image$$ZI$$Base|       ; Base and limit of area
        DCD     |Image$$ZI$$Limit|       ; Top of zero init segment
EndInitC

;------------------------------------------------------------------------------
;- Branch on C code Main function (with interworking)
;----------------------------------------------------
;- Branch must be performed by an interworking call as either an ARM or Thumb
;- main C function must be supported. This makes the code not position-
;- independant. A Branch with link would generate errors
;------------------------------------------------------------------------------
         IMPORT      main
_main
__main
         EXPORT    _main
         EXPORT    __main
         ldr       r0, =main
         mov       lr, pc
         bx        r0                      ; 跳到mian() 函數中

;------------------------------------------------------------------------------
;- Loop for ever
;---------------
;- End of application. Normally, never occur.
;- Could jump on Software Reset ( B 0x0 ).
;------------------------------------------------------------------------------
End
         b           End
      END
由於之前開啟了主時鐘,但沒有判斷開啟是否成功,所以AT91F_LowLevelInit首先通過AT91F_WaitForMainClockFrequency函數判斷主時鐘是否開啟。代碼略

主時鐘開啟之後,就可以進行真正的PLL時鐘源設定,代碼主體為AT91F_InitClocks函數。
由於時鐘設定要求在一定的範圍條件下,所以要首先判斷是否滿足時鐘要求。主要分成4步:
1.先計算主時鐘的頻率,演算法見datasheet。
2.通過MainClock和預設值(見函數的輸入參數)來判斷頻率是否滿足要求。
3.如果滿足要求則把預設值寫入到PLL控制寄存器。
4.最後一步當然是修改主機時鐘源為需要的PLL,同樣,需要分成兩步。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.