LPC2000 啓動代碼Start.s文件簡要分析


先說一下啓動代碼的位置,啓動代碼是在板子加電後首先執行的。所以非要用匯編來寫纔行。要完成處理器模式的初始化、設置中斷向量表、設置各個模式下的堆棧、初始某些變量從而把系統帶到一個合適的運行環境中開始用戶程序的運行。

;-------------------------------------------------------------------------------

; 本段設置處理器的模式相關常量
;
;-------------------------------------------------------------------------------
; Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs
; 定義常量,處理器的幾種工作模式。
; ARM 有7種工作模式:
;
; User: 非特權模式,大部分任務執行在這種模式   正常程序執行的模式
; FIQ: 當一個高優先級(fast)中斷產生時將會進入這種模式 高速數據傳輸和通道處理
; IRQ: 當一個低優先級(normal)中斷產生時將會進入這種模式 通常的中斷處理
; SVC: 用於操作系統的保護模式 
; Abort: 當存取異常時將會進入這種模式   虛擬存儲及存儲保護
; Undef: 當執行未定義指令時會進入這種模式 軟件仿真硬件協處理器
; System: 使用和User模式相同寄存器集的特權模式

; 這個值將被寫到CPSR寄存器的第0,1,2,3,4,5位,以表示當前的狀態。
Mode_USR        EQU     0x10
Mode_FIQ        EQU     0x11
Mode_IRQ        EQU     0x12
Mode_SVC        EQU     0x13
Mode_ABT        EQU     0x17
Mode_UND        EQU     0x1B
Mode_SYS        EQU     0x1F

; 設置IRQ和FIQ中斷禁止位,這兩個值將被寫到CPSR寄存器的第6位(FIQ)和第7位(IRQ)。1是禁止,0是允許。
I_Bit           EQU     0x80            ; when I bit is set, IRQ is disabled
F_Bit           EQU     0x40            ; when F bit is set, FIQ is disabled


;---------------------------------------------------------------------------------------------------
; 本段將完成堆棧相關的常量,
;
;---------------------------------------------------------------------------------------------------
;
; 設置各個模式下的棧大小

UND_Stack_Size EQU     0x00000000
SVC_Stack_Size EQU     0x00000008
ABT_Stack_Size EQU     0x00000000
FIQ_Stack_Size EQU     0x00000000
IRQ_Stack_Size EQU     0x00000080
USR_Stack_Size EQU     0x00000400

ISR_Stack_Size EQU     (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \
                         FIQ_Stack_Size + IRQ_Stack_Size)
; 初始化棧空間

; 定義一個數據段,名爲STACK,NOINIT - 僅僅保留內存單元,還沒有寫入值,可讀寫,ALIGN=3 - 按字節對齊。 
                AREA    STACK, NOINIT, READWRITE, ALIGN=3
; 分配內存,用戶模式棧名爲Stack_Mem,大小爲1024字節;異常模式堆棧__initial_sp 大小爲128+8字節。

Stack_Mem       SPACE   USR_Stack_Size
__initial_sp    SPACE   ISR_Stack_Size

Stack_Top



Heap_Size       EQU     0x00000000

;堆空間,其中__heap_base 與__heap_limit 這兩個符號是給採用了MICROLIB的程序準備的。

               AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit

;-------------------------------------------------------------------------------------------
;
; 初始化 VPB總線的頻率,Start的時候將分頻因子設置爲1,表示與CPU CLOCK相同
;-------------------------------------------------------------------------------------------

; VPBDIV 是VPB總線的分頻因子
;
; VPBDIV definitions
VPBDIV          EQU     0xE01FC100      ; VPBDIV Address


VPBDIV_SETUP    EQU     1
VPBDIV_Val      EQU     0x00000000

;-------------------------------------------------------------------------------------------
; 定義與鎖相環相關的寄存器
; Phase Locked Loop (PLL) definitions
;-------------------------------------------------------------------------------------------
; 定義 PLL相關寄存器的基地址
PLL_BASE        EQU     0xE01FC080      ; PLL Base Address

; 用偏移量的方法定義其他寄存器
PLLCON_OFS      EQU     0x00            ; PLL Control Offset ;控制寄存器,寫入該寄存器的值在饋送序列執行前不起作用

PLLCFG_OFS      EQU     0x04            ; PLL Configuration Offset ;配置寄存器,屬性同上

PLLSTAT_OFS     EQU     0x08            ; PLL Status Offset ;狀態寄存器,讀取狀態

PLLFEED_OFS     EQU     0x0C            ; PLL Feed Offset ;饋送寄存器,使能裝載PLL控制和配置信息

PLLCON_PLLE     EQU     (1<<0)          ; PLL Enable   ;PLL使能,寫入到配置寄存器的第0位,
         ; 初始爲0,表示沒有激活

PLLCON_PLLC     EQU     (1<<1)          ; PLL Connect   ;PLL連接使能位 ,寫入到配置寄存器的第1位,當PLLC和

        ; PLLE都爲1,且在有效的PLLE饋送後,將PLLE作爲時鐘源接

        ; 入Core,否則Core直接使用振盪器時鐘。

PLLCFG_MSEL     EQU     (0x1F<<0)       ; PLL Multiplier ;PLL 倍頻因子

PLLCFG_PSEL     EQU     (0x03<<5)       ; PLL Divider   ;PLLE 分頻因子

PLLSTAT_PLOCK   EQU     (1<<10)         ; PLL Lock Status ;PLL鎖定狀態位,應該是從PLLSTAT寄存器的第10位讀取數值

        ; 然後與 PLLSTAT_PLOCK 相比較,相同則爲PLL鎖定狀態。


PLL_SETUP       EQU     1
PLLCFG_Val      EQU     0x00000024 ;表示向CFG配置寄存器寫入的值爲0 01 00100,跟系統所需的頻率有關。
     ;LPC2119的主頻最高是60MHz,振盪器的主頻是10MHz
     ;分頻值爲1,倍頻值爲4,所以主頻爲40Mhz。

;-------------------------------------------------------------------------------------
; 存儲器加速模塊
;
;-------------------------------------------------------------------------------------

; Memory Accelerator Module (MAM) definitions
MAM_BASE        EQU     0xE01FC000      ; MAM Base Address
MAMCR_OFS       EQU     0x00            ; MAM Control Offset
MAMTIM_OFS      EQU     0x04            ; MAM Timing Offset

MAM_SETUP       EQU     1
MAMCR_Val       EQU     0x00000002
MAMTIM_Val      EQU     0x00000004


;---------------------------------------------------------------------------
; 外部存儲器擴展
;
;---------------------------------------------------------------------------
; External Memory Controller (EMC) definitions
EMC_BASE        EQU     0xFFE00000      ; EMC Base Address
BCFG0_OFS       EQU     0x00            ; BCFG0 Offset
BCFG1_OFS       EQU     0x04            ; BCFG1 Offset
BCFG2_OFS       EQU     0x08            ; BCFG2 Offset
BCFG3_OFS       EQU     0x0C            ; BCFG3 Offset

;// <e> External Memory Controller (EMC)
EMC_SETUP       EQU     0


BCFG0_SETUP EQU         0
BCFG0_Val   EQU         0x0000FBEF


BCFG1_SETUP EQU         0
BCFG1_Val   EQU         0x0000FBEF


BCFG2_SETUP EQU         0
BCFG2_Val   EQU         0x0000FBEF


BCFG3_SETUP EQU         0
BCFG3_Val   EQU         0x0000FBEF

;// </e> End of EMC


; External Memory Pins definitions
PINSEL2         EQU     0xE002C014      ; PINSEL2 Address
PINSEL2_Val     EQU     0x0E6149E4      ; CS0..3, OE, WE, BLS0..3, 
                                        ; D0..31, A2..23, JTAG Pins


                PRESERVE8 ;彙編僞指令,堆棧8字節對準
                
;-------------------------------------------------------------------------------
; 前面都是對寄存器位置的聲明,以下是具體代碼。定義了一個代碼段
;
;-------------------------------------------------------------------------------
;
; Area Definition and Entry Point
; Startup Code must be linked first at Address at which it expects to run.

;定義個名爲RESET的代碼段
                AREA    RESET, CODE, READONLY
                ARM

; 中斷向量表的異常入口共8條語句32字節,在鏈接的時候保證在0地址處
Vectors         LDR     PC, Reset_Addr        ;將Reset_Addr加載到PC中,程序就跳到reset_addr所指位置。 
                LDR     PC, Undef_Addr
                LDR     PC, SWI_Addr
                LDR     PC, PAbt_Addr
                LDR     PC, DAbt_Addr
                NOP                            ; Reserved Vector 
;               LDR     PC, IRQ_Addr
                LDR     PC, [PC, #-0x0FF0]     ; Vector from VicVectAddr
                LDR     PC, FIQ_Addr

Reset_Addr      DCD     Reset_Handler ;分配一段字內存單元給程序段Reset_Handler
Undef_Addr      DCD     Undef_Handler
SWI_Addr        DCD     SWI_Handler
PAbt_Addr       DCD     PAbt_Handler
DAbt_Addr       DCD     DAbt_Handler
                DCD     0                      ; Reserved Address 
IRQ_Addr        DCD     IRQ_Handler
FIQ_Addr        DCD     FIQ_Handler

;
Undef_Handler   B       Undef_Handler
SWI_Handler     B       SWI_Handler
PAbt_Handler    B       PAbt_Handler
DAbt_Handler    B       DAbt_Handler
IRQ_Handler     B       IRQ_Handler
FIQ_Handler     B       FIQ_Handler


;-----------------------------------------------------------------------------------
;
;
;-----------------------------------------------------------------------------------
; Reset Handler

                EXPORT Reset_Handler
Reset_Handler  

;設置擴展存儲的引腳
; Setup External Memory Pins
                IF      :DEF:EXTERNAL_MODE ;判斷 EXTERNAL_MODE 是否定義,如果定義了就設置響應的管腳。見某論壇上的一個人問,外部存儲器設置了但是不能工作,就是這裏的 EXTERNAL_MODE 沒有被定義導致擴展 存儲的引腳的代碼沒有被編譯所以沒有被初始化,EXTERNAL_MODE EQU 1,應該就可以了 ,還沒測試。
                LDR     R0, =PINSEL2
                LDR     R1, =PINSEL2_Val ;前面 PINSEL2_Val 被初始化爲0x0E6149E4,完成一系列管腳的初始化
                STR     R1, [R0]
                ENDIF

;設置擴展存儲器的控制寄存器,分別檢測幾個bank是否存在,分別進行設置
; Setup External Memory Controller
                IF      EMC_SETUP <> 0
                LDR     R0, =EMC_BASE

                IF      BCFG0_SETUP <> 0
                LDR     R1, =BCFG0_Val
                STR     R1, [R0, #BCFG0_OFS]
                ENDIF

                IF      BCFG1_SETUP <> 0
                LDR     R1, =BCFG1_Val
                STR     R1, [R0, #BCFG1_OFS]
                ENDIF

                IF      BCFG2_SETUP <> 0
                LDR     R1, =BCFG2_Val
                STR     R1, [R0, #BCFG2_OFS]
                ENDIF

                IF      BCFG3_SETUP <> 0
                LDR     R1, =BCFG3_Val
                STR     R1, [R0, #BCFG3_OFS]
                ENDIF

                ENDIF   ; EMC_SETUP

;設置VPB總線的分頻因子,這裏分頻因子被設置爲0
; Setup VPBDIV
                IF      VPBDIV_SETUP <> 0
                LDR     R0, =VPBDIV
                LDR     R1, =VPBDIV_Val
                STR     R1, [R0]
                ENDIF

;設置鎖相環
; Setup PLL
                IF      PLL_SETUP <> 0
                LDR     R0, =PLL_BASE
                MOV     R1, #0xAA
                MOV     R2, #0x55

; Configure and Enable PLL
                MOV     R3, #PLLCFG_Val   
                STR     R3, [R0, #PLLCFG_OFS]    ;PLLCFG_Val = 0x00000024
                MOV     R3, #PLLCON_PLLE   ;R3 = 1
                STR     R3, [R0, #PLLCON_OFS]   ; PLLCON = 1,PLL 使能
                STR     R1, [R0, #PLLFEED_OFS]   ; 寫 饋送寄存器命令序列一次是10101010一次01010101,0xAA,0x55。規定的。
                STR     R2, [R0, #PLLFEED_OFS]
;等待PLL穩定
; Wait until PLL Locked
PLL_Loop        LDR     R3, [R0, #PLLSTAT_OFS]   ;將狀態寄存器裝載到R3中
                ANDS    R3, R3, #PLLSTAT_PLOCK   ;PLLSTAT_OFS 與1<<10 進行與且影響 CPSR 的Z位,
                BEQ     PLL_Loop    ;Z位爲1 跳到PLL_Loop

; Switch to PLL Clock
                MOV     R3, #(PLLCON_PLLE:OR:PLLCON_PLLC)
                STR     R3, [R0, #PLLCON_OFS]
                STR     R1, [R0, #PLLFEED_OFS]
                STR     R2, [R0, #PLLFEED_OFS]
                ENDIF   ; PLL_SETUP

;-----------------------------------------------------------------------------
; 存儲器加速模塊
; Setup MAM
                IF      MAM_SETUP <> 0
                LDR     R0, =MAM_BASE
                MOV     R1, #MAMTIM_Val
                STR     R1, [R0, #MAMTIM_OFS] 
                MOV     R1, #MAMCR_Val
                STR     R1, [R0, #MAMCR_OFS] 
                ENDIF   ; MAM_SETUP

;--------------------------------------------------------------------------
;內存映射,結構有點複雜額,總之就是根據不同的情況去設置存儲器映射控制寄存器,
; 00 Boot裝載,中斷向量從BootBlock重新映射
; 01 用戶FLASH模式,中斷向量不重新映射,就在FLASH裏面
; 10 用戶RAM模式,中斷向量從靜態RAM重新映射
; 11 用戶外部存儲器模式,中斷向量從外部存儲器重新映射。
; Memory Mapping (when Interrupt Vectors are in RAM)
;----------------------------------------------------------------------------

MEMMAP          EQU     0xE01FC040      ; Memory Mapping Control ;
                IF      :DEF:REMAP
                LDR     R0, =MEMMAP
                IF      :DEF:EXTMEM_MODE ;判斷是不是擴展模式 是就往R1裏寫3
                MOV     R1, #3
                ELIF    :DEF:RAM_MODE ;如果是RAM中,往R1裏寫2
                MOV     R1, #2
                ELSE
                MOV     R1, #1   ;否則R1裏寫1,唉彙編的編譯判斷真夠煩的。
                ENDIF
                STR     R1, [R0] ;寫到MEMMAP寄存器。
                ENDIF


; Initialise Interrupt System
; ...

;爲處理器的每種處理模式初始化棧空間

; Setup Stack for each mode

                LDR     R0, =Stack_Top

; Enter Undefined Instruction Mode and set its Stack Pointer
                MSR     CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit ;CPSR_c = 0x1B|0x80|0x40 = 意思爲禁止IRQ和FIQ,ARM狀態,處理

器進入了未定義模式
                MOV     SP, R0     ;棧指針指向了Stack_Top
                SUB     R0, R0, #UND_Stack_Size   ;Stack_Top = Stack_Top - ABT_Stack_Size

; Enter Abort Mode and set its Stack Pointer
                MSR     CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #ABT_Stack_Size

; Enter FIQ Mode and set its Stack Pointer
                MSR     CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #FIQ_Stack_Size

; Enter IRQ Mode and set its Stack Pointer
                MSR     CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #IRQ_Stack_Size

; Enter Supervisor Mode and set its Stack Pointer
                MSR     CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #SVC_Stack_Size
; 進入用戶模式,並且設置棧空間指針
; Enter User Mode and set its Stack Pointer
                MSR     CPSR_c, #Mode_USR
                IF      :DEF:__MICROLIB   ;支持 MICROLIB庫,如果C程序的運行庫是MICROLIB 則將__initial_sp 導出

                EXPORT __initial_sp

                ELSE

                MOV     SP, R0
                SUB     SL, SP, #USR_Stack_Size

                ENDIF

;進入C代碼的執行,爲C代碼的執行創造一個運行環境
; Enter the C code

                IMPORT __main   ;導入外部符號
                LDR     R0, =__main ;將main的地址加載到r0中
                BX      R0   ;帶狀態的跳到main 去執行


                IF      :DEF:__MICROLIB ;還是有關使用MICROLIB庫的,如果使用了該庫就要導出下面連個符號。

                EXPORT __heap_base
                EXPORT __heap_limit

                ELSE
; User Initial Stack & Heap
                AREA    |.text|, CODE, READONLY

                IMPORT __use_two_region_memory
                EXPORT __user_initial_stackheap
__user_initial_stackheap

                LDR     R0, = Heap_Mem
                LDR     R1, =(Stack_Mem + USR_Stack_Size)
                LDR     R2, = (Heap_Mem +      Heap_Size)
                LDR     R3, = Stack_Mem
                BX      LR
                ENDIF


                END


一直對底層的東西不太懂,總是朦朦朧朧的感覺,索性拿啓動代碼看一下吧,指望着能學一下彙編。週末的學習效率是在太低了,一個小小的啓動文件竟然費了兩天功夫。費了牛勁了看是看完了,還是有好多地方一頭霧水。因爲認識的深度有限,錯誤的地方肯定少不了,所以還請您校正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章