標(biāo)題:
s3c2440啟動(dòng)代碼分析
[打印本頁]
作者:
xiaojuan
時(shí)間:
2014-9-17 22:55
標(biāo)題:
s3c2440啟動(dòng)代碼分析
本帖最后由 xiaojuan 于 2014-9-17 22:57 編輯
由于片面問題,所以可能會(huì)看起來不太美觀,可以看附件中的內(nèi)容。
ARM啟動(dòng)代碼相當(dāng)于我們電腦的BIOS,也就是ARM啟動(dòng)時(shí)對(duì)處理器的一些初始化及嵌入式系統(tǒng)硬件的一些初始化。由于它直接面對(duì)處理器內(nèi)核和硬件控制器進(jìn)行編程,一般都是用匯編語言。一般包括:中斷向量表,初始化存儲(chǔ)器系統(tǒng),初始化堆棧,初始化有特殊要求的斷口,設(shè)備初始化,變量初始化等。這幾天對(duì)著RealView MDK-ARM中自帶的啟動(dòng)代碼研究了一下,遇到問題又對(duì)著數(shù)據(jù)手冊(cè)和指令表看了一下,總算對(duì)S3C2440A的硬件有了一個(gè)大致的了解。學(xué)習(xí)嵌入式系統(tǒng)重在系統(tǒng),學(xué)習(xí)ARM只是為學(xué)習(xí)嵌入式系統(tǒng)鋪路,懶貓比較笨可能在上系統(tǒng)之前要裸奔幾天以強(qiáng)化以下對(duì)S3C2440A內(nèi)部結(jié)構(gòu)的了解。
把MDK自帶的S3C2440A.S文件的注釋發(fā)一下,這些是懶貓結(jié)合數(shù)據(jù)手冊(cè)與ARM指令表理解了,可能會(huì)有錯(cuò)誤,放在這里只是引導(dǎo)一下像我一樣還沒有入門的兄弟們,希望你們不要害怕ARM害怕嵌入式,老毛他老人家說的對(duì),世上無難事,只怕有心人,ARM指令就那么多,看一遍不會(huì)就多看幾遍,還有一定要學(xué)習(xí)看軟件自帶的幫助文件.
;/*****************************************************************************/
;/* S3C2440.S: Startup file for Samsung S3C440 */
;/*****************************************************************************/
;/* <<< Use Configuration Wizard in Context Menu >>> */
;/*****************************************************************************/
;/* This file is part of the uVision/ARM development tools. */
;/* Copyright (c) 2005-2008 Keil Software. All rights reserved. */
;/* This software may only be used under the terms of a valid, current, */
;/* end user licence from KEIL for a compatible version of KEIL software */
;/* development tools. Nothing else gives you the right to use this software. */
;/*****************************************************************************/
;下面這些參數(shù)是與CPSR狀態(tài)寄存器有關(guān)
;參數(shù)的由來:這里各個(gè)模式的參數(shù)是由寄存器CPSR的模式位設(shè)置M[4:0]得來的,
;比如這里的用戶模式,CPSR的M[4:0]設(shè)置為10000就是0x10。
;
;Mode_USR -- 用戶模式,正常程序執(zhí)行模式,用于應(yīng)用程序
;Mode_FIQ -- 快速中斷模式,用于高速數(shù)據(jù)傳輸和通道處理。
;Mode_IRQ -- 外部中斷模式,用于通用的中斷處理。
;Mode_SVC -- 管理模式,使用的一種保護(hù)模式。
;Mode_ABT -- 數(shù)據(jù)訪問中止模式,用于虛擬存儲(chǔ)用存儲(chǔ)保護(hù)
;Mode_UND -- 未定義指令中止模式,當(dāng)未定義指令執(zhí)行時(shí)進(jìn)入此模式。
;Mode_SYS -- 系統(tǒng)模式,用于特權(quán)級(jí)的操作系統(tǒng)任務(wù)。
;I_Bit -- 如果I位被置1,則外部中斷被禁止(IRQ is disabled)
;F_Bit -- 如果F位被置1,則快速中斷被禁止(FIQ is disabled)
;
;----------------------------------------------------------------------
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
I_Bit EQU 0x80 ; when I bit is set, IRQ is disabled
F_Bit EQU 0x40 ; when F bit is set, FIQ is disabled
;-----------------------------棧初始化定義-----------------------------------
;下面這些主要是棧配置,系統(tǒng)的?臻g設(shè)定
;
;UND_Stack_Size -- 未定義模式的棧大小
;SVC_Stack_Size -- 超級(jí)用戶模式的棧大小
;ABT_Stack_Size -- 數(shù)據(jù)訪問終止模式的棧大小
;FIQ_Stack_Size -- 快速中斷模式的棧大小
;IRQ_Stack_Size -- 外部中斷模式的棧大小
;USR_Stack_Size -- 用戶模式的棧大小
;ISR_Stack_Size -- 總堆棧的大小,也就是也有模式下堆棧相加
;
;-----------------------------------------------------------------------
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)
;-----------------------------------------------------------------------
;AREA -- 是一個(gè)偽指令,用于段定義。ARM的匯編程序由段組成,段是相對(duì)獨(dú)立
; 的指令或數(shù)據(jù)單位,每個(gè)段由AREA偽指令定義,并定義段的屬性。
; STACK -- AREA指令的一個(gè)參數(shù),定義段名稱
; NOINIT -- AREA指令的一個(gè)參數(shù),指定本數(shù)據(jù)段僅僅保留了內(nèi)在單元,而
; 將句初始值寫入內(nèi)存單元,也即將內(nèi)存單元值初始化為0
; READWRITE -- 指定本段為可讀可寫,數(shù)據(jù)段默認(rèn)為READWRITE。
; READWRITE(讀寫)、READONLY(只讀)
;ALIGN -- 也是一個(gè)偽指令,指定對(duì)齊方式。ALIGN n 指令的對(duì)齊值有兩種方案
; 即n 或 2^n,這里采用第二種方案即指定后面的指令8字節(jié)對(duì)齊。
;
;下面這句話的意思是:
;開辟一個(gè)堆棧段,段名字為STACK,定義為可讀可寫,將內(nèi)存單元初始化為0,
;-----------------------------------------------------------------------
AREA STACK, NOINIT, READWRITE, ALIGN=3
;-----------------------------------------------------------------------
;SPACE -- 偽指令,用于分配一塊內(nèi)存單元,并用0初始化,與%同義
;其指令格式為:
; {lable} SPACE expr
;lable -- 內(nèi)存起始地址標(biāo)號(hào) expr -- 所要分配的內(nèi)存字節(jié)數(shù)
;-----------------------------------------------------------------------
Stack_Mem SPACE USR_Stack_Size ;堆棧內(nèi)存起始地址標(biāo)號(hào)
__initial_sp SPACE ISR_Stack_Size ;匯編代碼的地址標(biāo)號(hào)
Stack_Top ;堆棧段內(nèi)容結(jié)束, 在這里放個(gè)標(biāo)號(hào),用來獲得堆棧頂部地址
Heap_Size EQU 0x00000000 ;定義堆大小設(shè)置
;開辟一個(gè)名字為HEAP可讀可寫,不初始化內(nèi)存單的內(nèi)存單元。
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base ;堆的基址
Heap_Mem SPACE Heap_Size ;堆內(nèi)存起始地址標(biāo)號(hào)
__heap_limit ;堆結(jié)束
;----------------------------內(nèi)存初始化定義-----------------------------
;在一些應(yīng)用系統(tǒng)中除了擴(kuò)展Flash,RAM掛接在外部存儲(chǔ)器接口上外,可能還有其它
;的外設(shè)掛接在外部存儲(chǔ)器接口上,不同外設(shè)的操作時(shí)序什么的都是不一樣的,所以
;在使用這些外設(shè)之前必須初始化連接這些外設(shè)存儲(chǔ)器接口。這里因?yàn)闆]擴(kuò)展,所以
;只定義一個(gè)片上內(nèi)存基地址。
;-----------------------------------------------------------------------
IRAM_BASE EQU 0x40000000 ;片上SRAM的基地址,即內(nèi)存基地址
;-------------------------看門狗初始化定義------------------------------
;看門狗在防止程序跑飛,進(jìn)入無限死循環(huán)時(shí)起著重要作用。有些應(yīng)用可能用不上
;看門狗功能,也可能有些應(yīng)用會(huì)用到外部看門狗。在這個(gè)時(shí)候內(nèi)部看門狗必須禁
;止,所以有時(shí)候會(huì)在初始化時(shí)將內(nèi)部看門狗禁止,當(dāng)以后應(yīng)用用到時(shí)再開啟它。
;看門狗定時(shí)器包括三個(gè)寄存器:
;WTCON -- 看門狗控制寄存器,設(shè)定看門狗定時(shí)器模式
;WTDAT -- 看門狗數(shù)據(jù)寄存器,用于設(shè)定超時(shí)寬度
;WTCNT -- 看門狗計(jì)數(shù)寄存器,里面存放的是看門狗定時(shí)器當(dāng)前值
;
;WT_BASE -- 看門狗定時(shí)器基地址
;WTCON_OFS -- 看門狗控制寄存器偏移地址,相對(duì)于基址
;WTDAT_OFS -- 看門狗數(shù)據(jù)寄存器偏移地址,相對(duì)于基址
;WTCNT_OFS -- 看門狗計(jì)數(shù)寄存器偏移地址,相對(duì)于基址
;WT_SETUP -- 看門狗設(shè)置
;WTCON_Val -- 看門狗控制寄存器設(shè)置,關(guān)閉看門狗
;WTDAT_Val -- 看門狗數(shù)據(jù)寄存器設(shè)置,初始值即為0x8000
;-----------------------------------------------------------------------
WT_BASE EQU 0x53000000 ; Watchdog Timer Base Address
WTCON_OFS EQU 0x00 ; Watchdog Timer Control Register Offset
WTDAT_OFS EQU 0x04 ; Watchdog Timer Data Register Offset
WTCNT_OFS EQU 0x08 ; Watchdog Timer Count Register Offset
WT_SETUP EQU 0
WTCON_Val EQU 0x00000000
WTDAT_Val EQU 0x00008000
;----------------------------時(shí)鐘與電源管理定義-------------------------
;S3C2440A中的時(shí)鐘控制邏輯可以產(chǎn)生必須的時(shí)鐘信號(hào),包括CPU的FCLK,AHB總線的
;HCLK 以及APB總線外設(shè)的PCLK3C2440A內(nèi)部有兩個(gè)鎖相環(huán)(PLL):一個(gè)提供FCLK,
;HCLK及PCLK,另一個(gè)專用于USB模塊(48MHz).
;
;CLOCK_BASE -- 時(shí)鐘基地址
;LOCKTIME_OFS -- 鎖相環(huán)鎖定時(shí)間計(jì)數(shù)寄存器偏移地址,相對(duì)于基址
;MPLLCON_OFS -- MPLL配置寄存器偏移地址,相對(duì)于基址,主時(shí)鐘源PLL
;UPLLCON_OFS -- UPLL配置寄存器偏移地址,相對(duì)于基址,USB時(shí)鐘源PLL
;CLKCON_OFS -- 時(shí)鐘控制寄存器偏移地址,相對(duì)于基址
;CLKSLOW_OFS -- 時(shí)鐘減慢控制寄存器偏移地址,相對(duì)于基址
;CLKDIVN_OFS -- 時(shí)鐘分頻器控制寄存器偏移地址,相對(duì)于基址
;CAMDIVN_OFS -- 攝像頭時(shí)鐘分頻器控制寄存器偏移地址,相對(duì)于基址,UPLL提供
;
;CLOCK_SETUP -- 時(shí)鐘設(shè)置
;LOCKTIME_Val -- PLL鎖定時(shí)間計(jì)數(shù)器值
;MPLLCON_Val -- MPLL配置寄存器值
;UPLLCON_Val -- UPLL配置寄存器值
;CLKCON_Val -- 時(shí)鐘配置寄存器值
;CLKSLOW_Val -- 時(shí)鐘減慢控制寄存器值
;CLKDIVN_Val -- 時(shí)鐘分頻控制寄存器值
;CAMDIVN_Val -- 攝像頭分頻控制寄存器值
;-----------------------------------------------------------------------
CLOCK_BASE EQU 0x4C000000 ; Clock Base Address
LOCKTIME_OFS EQU 0x00 ; PLL Lock Time Count Register Offset
MPLLCON_OFS EQU 0x04 ; MPLL Configuration Register Offset
UPLLCON_OFS EQU 0x08 ; UPLL Configuration Register Offset
CLKCON_OFS EQU 0x0C ; Clock Generator Control Reg Offset
CLKSLOW_OFS EQU 0x10 ; Clock Slow Control Register Offset
CLKDIVN_OFS EQU 0x14 ; Clock Divider Control Register Offset
CAMDIVN_OFS EQU 0x18 ; Camera Clock Divider Register Offset
CLOCK_SETUP EQU 0
LOCKTIME_Val EQU 0x0FFF0FFF
MPLLCON_Val EQU 0x00043011
UPLLCON_Val EQU 0x00038021
CLKCON_Val EQU 0x001FFFF0
CLKSLOW_Val EQU 0x00000004
CLKDIVN_Val EQU 0x0000000F
CAMDIVN_Val EQU 0x00000000
;--------------------存儲(chǔ)控制器設(shè)置定義---------------------------------
;下面這些都是一些關(guān)于存儲(chǔ)控制器的地址宏定義
;
;MC_BASE -- 存儲(chǔ)控制器基地址
;BWSCON_OFS -- 總線寬度和等待控制寄存器偏移地址
;BANKCON0_OFS -- BANK1控制寄存器偏移地址
; .
; .
;BANKCON7_OFS -- BANK7控制寄存器偏移地址
;REFRESH_OFS -- DRAM/SDRAM刷新控制寄存器偏移地址
;BANKSIZE_OFS -- 可調(diào)的bank大小寄存器偏移地址
;MRSRB6_OFS -- bank6模式控制寄存器偏移地址
;MRSRB7_OFS -- bank7模式控制寄存器偏移地址
;
;MC_SETUP -- 存儲(chǔ)器控制寄存器設(shè)置
;BWSCON_Val -- 寫入總線寬度和等待控制寄存值
;BANKCON0_Val -- 寫入Blank0的值
; .
; .
;BANKCON7_Val -- 寫入BANK7 的值
;REFRESH_Val -- 寫入DRAM/SDRAM刷新控制寄存的值
;BANKSIZE_Val -- 寫入可調(diào)的bank大小寄存的值
;MRSRB6_Val -- 寫入bank6模式控制寄存器的值
;MRSRB7_Val -- 寫入bank7模式控制寄存器的值
;-----------------------------------------------------------------------
MC_BASE EQU 0x48000000 ; Memory Controller Base Address
BWSCON_OFS EQU 0x00 ; Bus Width and Wait Status Ctrl Offset
BANKCON0_OFS EQU 0x04 ; Bank 0 Control Register Offset
BANKCON1_OFS EQU 0x08 ; Bank 1 Control Register Offset
BANKCON2_OFS EQU 0x0C ; Bank 2 Control Register Offset
BANKCON3_OFS EQU 0x10 ; Bank 3 Control Register Offset
BANKCON4_OFS EQU 0x14 ; Bank 4 Control Register Offset
BANKCON5_OFS EQU 0x18 ; Bank 5 Control Register Offset
BANKCON6_OFS EQU 0x1C ; Bank 6 Control Register Offset
BANKCON7_OFS EQU 0x20 ; Bank 7 Control Register Offset
REFRESH_OFS EQU 0x24 ; SDRAM Refresh Control Register Offset
BANKSIZE_OFS EQU 0x28 ; Flexible Bank Size Register Offset
MRSRB6_OFS EQU 0x2C ; Bank 6 Mode Register Offset
MRSRB7_OFS EQU 0x30 ; Bank 7 Mode Register Offset
MC_SETUP EQU 1
BWSCON_Val EQU 0x22000000
BANKCON0_Val EQU 0x00000700
BANKCON1_Val EQU 0x00000700
BANKCON2_Val EQU 0x00000700
BANKCON3_Val EQU 0x00000700
BANKCON4_Val EQU 0x00000700
BANKCON5_Val EQU 0x00000700
BANKCON6_Val EQU 0x00018005
BANKCON7_Val EQU 0x00018005
REFRESH_Val EQU 0x008404F3
BANKSIZE_Val EQU 0x00000032
MRSRB6_Val EQU 0x00000020
MRSRB7_Val EQU 0x00000020
;---------------------I/O端口宏定義--------------------------------------
;GPA_BASE -- 端口A基地址
; .
;GPJ_BASE -- 端口J基地址
;GPCON_OFS -- 端口配置寄存器偏移地址
;GPDAT_OFS -- 端口數(shù)據(jù)寄存器偏移地址
;GPUP_OFS -- 端口上拉寄存器偏移地址
;GP_SETUP -- 端口設(shè)置
;GPA_SETUP -- 端口A配置
;GPACON_Val -- 寫入端口A配置寄存器的值
; .
; .
;GPJ_SETUP -- 端口J配置
;GPJCON_Val -- 寫入端口J配置寄存器的值
;GPJUP_Val -- 寫入端口J上拉寄存器的值
;-----------------------------------------------------------------------
GPA_BASE EQU 0x56000000 ; GPA Base Address
GPB_BASE EQU 0x56000010 ; GPB Base Address
GPC_BASE EQU 0x56000020 ; GPC Base Address
GPD_BASE EQU 0x56000030 ; GPD Base Address
GPE_BASE EQU 0x56000040 ; GPE Base Address
GPF_BASE EQU 0x56000050 ; GPF Base Address
GPG_BASE EQU 0x56000060 ; GPG Base Address
GPH_BASE EQU 0x56000070 ; GPH Base Address
GPJ_BASE EQU 0x560000D0 ; GPJ Base Address
GPCON_OFS EQU 0x00 ; Control Register Offset
GPDAT_OFS EQU 0x04 ; Data Register Offset
GPUP_OFS EQU 0x08 ; Pull-up Disable Register Offset
GP_SETUP EQU 1
;-----------------------------------------------------------------------
;端口A配置
;-----------------------------------------------------------------------
GPA_SETUP EQU 0
GPACON_Val EQU 0x000003FF
;-----------------------------------------------------------------------
;端口B配置
;-----------------------------------------------------------------------
GPB_SETUP EQU 0
GPBCON_Val EQU 0x00000000
GPBUP_Val EQU 0x00000000
;-----------------------------------------------------------------------
;端口C配置
;-----------------------------------------------------------------------
GPC_SETUP EQU 0
GPCCON_Val EQU 0x00000000
GPCUP_Val EQU 0x00000000
;-----------------------------------------------------------------------
;端口D配置
;-----------------------------------------------------------------------
GPD_SETUP EQU 0
GPDCON_Val EQU 0x00000000
GPDUP_Val EQU 0x00000000
;-----------------------------------------------------------------------
;端口E配置
;-----------------------------------------------------------------------
GPE_SETUP EQU 0
GPECON_Val EQU 0x00000000
GPEUP_Val EQU 0x00000000
;-----------------------------------------------------------------------
;端口F配置
;-----------------------------------------------------------------------
GPF_SETUP EQU 0
GPFCON_Val EQU 0x00000000
GPFUP_Val EQU 0x00000000
;-----------------------------------------------------------------------
;端口G配置
;-----------------------------------------------------------------------
GPG_SETUP EQU 0
GPGCON_Val EQU 0x00000000
GPGUP_Val EQU 0x00000000
;-----------------------------------------------------------------------
;端口H配置
;-----------------------------------------------------------------------
GPH_SETUP EQU 0
GPHCON_Val EQU 0x00000000
GPHUP_Val EQU 0x00000000
;-----------------------------------------------------------------------
;端口J配置
;-----------------------------------------------------------------------
GPJ_SETUP EQU 0
GPJCON_Val EQU 0x00000000
GPJUP_Val EQU 0x00000000
;-----------------------------------------------------------------------
;PRESERVE8 -- 偽指令,指示當(dāng)前文件請(qǐng)求堆棧為8字節(jié)對(duì)齊。
; 匯編程序數(shù)據(jù)8字節(jié)對(duì)齊,c和匯編有8位對(duì)齊的要求.
;-----------------------------------------------------------------------
PRESERVE8
;-----------------------------------------------------------------------
;存儲(chǔ)區(qū)設(shè)定和程序入口點(diǎn)
;啟動(dòng)代碼必須連接到第一個(gè)地址才能運(yùn)行
;下面這句話的意思是:
; 聲明一個(gè)名為RESET的代碼段,屬性為只讀
;-----------------------------------------------------------------------
AREA RESET, CODE, READONLY
ARM ;ARM模式運(yùn)行程序
;-----------------------------------------------------------------------
;IMPORT -- 相當(dāng)于C語言中的關(guān)鍵字extern
; 指當(dāng)前的符號(hào)在其他源文件中定義的,在本源文件中可能引用該符號(hào).
;EXPORT -- 相當(dāng)于C語言中的關(guān)鍵字global
; 聲明一個(gè)符號(hào)可以被其它文件引用.相當(dāng)于聲明了一個(gè)全局變量
;下面這幾句話是的意思是:
; 如果定義了_EVAL這個(gè)變量,引用RO輸出區(qū)的字節(jié)長(zhǎng)度與RW輸出區(qū)的字節(jié)長(zhǎng)度
;注意:
;ARM連接器定義了一些包含$$的符號(hào)。這些符號(hào)及其他所有包含$$的名稱都是ARM的
;保留字。這些符號(hào)被用于指定域的基地址,輸出段的基地址和輸入段的基地址及其
;大小。我們可以自己的匯編語言程序中引用這些符號(hào)地址,把它們用作可重定位的
;地址,也可能在C或C++代碼中使用extern關(guān)鍵字來引用它們。這個(gè)可以查看uVision
;Help 的Region-related symbols這一節(jié)。
;-----------------------------------------------------------------------
IF :LNOT::DEF:__EVAL ;邏輯判斷是否定義了_EVAL這個(gè)變量
IMPORT ||Image$$ER_ROM1$$RO$$Length||
IMPORT ||Image$$RW_RAM1$$RW$$Length||
ENDIF
;-----------------------------------------------------------------------
; 異常向量,映射到地址0,必須使用絕對(duì)尋址方式,子程序用無限循環(huán)方式
;實(shí)現(xiàn)可以被修改。
;-----------------------------------------------------------------------
Vectors LDR PC, Reset_Addr ;將復(fù)位地址裝載到程序指針,即復(fù)位
LDR PC, Undef_Addr ;未定義指令
LDR PC, SWI_Addr ;軟件中斷
LDR PC, PAbt_Addr ;中止(預(yù)。
LDR PC, DAbt_Addr ;中止(數(shù)據(jù))
IF :DEF:__EVAL ;如果定義了__EVAL 變量
DCD 0x4000 ;分配2k空間
ELSE ;否則分配空間大小為RO輸出區(qū)的字節(jié)
;長(zhǎng)度與RW輸出區(qū)的字節(jié)長(zhǎng)度之和
DCD ||Image$$ER_ROM1$$RO$$Length||+\
||Image$$RW_RAM1$$RW$$Length||
ENDIF
LDR PC, IRQ_Addr ;外部中斷
LDR PC, FIQ_Addr ;快速中斷
IF :DEF:__RTX ;如果定義了__RTX
IMPORT SWI_Handler ;則定義中斷子程序
IMPORT IRQ_Handler_RTX ;定義快速中斷子程序
ENDIF
;-----------------------------------------------------------------------
;下面這幾句的任務(wù)是把各個(gè)子程序的入口地址分配給相應(yīng)的地址變量
;-----------------------------------------------------------------------
Reset_Addr DCD Reset_Handler ;復(fù)位子程序入口地址賦值給Reset_Addr
Undef_Addr DCD Undef_Handler ;未定義子程序入口地址賦值給Undef_Addr
SWI_Addr DCD SWI_Handler ;中斷子程序入口地址賦值給SWI_Addr
PAbt_Addr DCD PAbt_Handler ;中止(預(yù)存)子程序入口地址賦給PAbt_Addr
DAbt_Addr DCD DAbt_Handler ;中止(數(shù)據(jù))子程序入口地址賦給DAbt_Addr
DCD 0 ;保留地址
IF :DEF:__RTX ;如果定義了__RTX
IRQ_Addr DCD IRQ_Handler_RTX ;快速中斷子程序入口地址給IRQ_Addr
ELSE
IRQ_Addr DCD IRQ_Handler ;否則把IRQ_Handler入口地址給IRQ_Addr
ENDIF
FIQ_Addr DCD FIQ_Handler ;快速中斷入口地址給FIQ_Addr
;-----------------------------------------------------------------------
;這些子程序都是用無限循環(huán)方式實(shí)現(xiàn)的可以被修改。
;-----------------------------------------------------------------------
Undef_Handler
B Undef_Handler ;跳轉(zhuǎn)到Undef_Handler,還是在這個(gè)地方
IF :DEF:__RTX ;如果定義了DEF:__RTX,在此等待中斷
ELSE
SWI_Handler
B SWI_Handler ;否則跳轉(zhuǎn)到軟件中斷
ENDIF
PAbt_Handler
B PAbt_Handler ;中止(預(yù)存)子程
DAbt_Handler
B DAbt_Handler ;中止(數(shù)據(jù))子程
;-----------------------------------------------------------------------
;外部中斷子程序
; 如果函數(shù)標(biāo)有PROC與ENDP,但沒有FRAME PUSH 或 FRAME POP,則堆棧作用量
;假定為0.這意味著無需手動(dòng)添加FRAME PUSH 0或FRAME POP 0
;-----------------------------------------------------------------------
IRQ_Handler
PROC
EXPORT IRQ_Handler [WEAK] ;聲明一個(gè)全局變量,并且其它
;同名符優(yōu)先于本符號(hào)被引用
B . ;跳轉(zhuǎn)到當(dāng)前地址即在此等待“.”代表當(dāng)前指令地址
ENDP
FIQ_Handler ;快速中斷子程序
B FIQ_Handler
;-----------------------------------------------------------------------
;復(fù)位子程序
;-----------------------------------------------------------------------
EXPORT Reset_Handler ; 聲明一個(gè)全局變量
Reset_Handler
;-----------------------------------------------------------------------
;配置看門狗
;前面已經(jīng)初始化 WT_SETUP == 0,要想執(zhí)行下面的程序需將WT_SETUP置1
;-----------------------------------------------------------------------
IF WT_SETUP != 0
LDR R0, =WT_BASE ;加載看門狗基址
LDR R1, =WTCON_Val ;加載看門狗控制寄存器數(shù)據(jù)
LDR R2, =WTDAT_Val ;加載看門狗數(shù)據(jù)寄存器數(shù)據(jù)
STR R2, [R0, #WTCNT_OFS] ;將WTDAT_Val配置給看門狗
;計(jì)數(shù)寄存器
STR R2, [R0, #WTDAT_OFS] ;將WTDAT_Val 配置給看門狗
;數(shù)據(jù)寄存器
STR R1, [R0, #WTCON_OFS] ;將WTCON_Val配置給看門狗
;控制寄存器
ENDIF
作者:
xiaojuan
時(shí)間:
2014-9-17 22:56
;-----------------------------------------------------------------------
;配置時(shí)鐘
;如果邏輯上沒有定義 NO_CLOCK_SETUP并且 CLOCK_SETUP != 0執(zhí)行下面程序
;-----------------------------------------------------------------------
IF (:LNOT:(:DEF:NO_CLOCK_SETUP)):LAND:(CLOCK_SETUP != 0)
LDR R0, =CLOCK_BASE ;加載時(shí)鐘基址
LDR R1, =LOCKTIME_Val ;加載PLL鎖定時(shí)間計(jì)數(shù)值
STR R1, [R0, #LOCKTIME_OFS] ;并將該值配置到PLL鎖定時(shí)間計(jì)數(shù)器
MOV R1, #CLKDIVN_Val
STR R1, [R0, #CLKDIVN_OFS] ;配置時(shí)鐘分頻器
LDR R1, =CAMDIVN_Val
STR R1, [R0, #CAMDIVN_OFS] ;配置攝像頭分頻控制寄存器
LDR R1, =MPLLCON_Val
STR R1, [R0, #MPLLCON_OFS] ;配置MPLL配置寄存器
LDR R1, =UPLLCON_Val
STR R1, [R0, #UPLLCON_OFS] ;配置UPLL配置寄存器
MOV R1, #CLKSLOW_Val
STR R1, [R0, #CLKSLOW_OFS] ;配置時(shí)鐘減慢控制寄存器
LDR R1, =CLKCON_Val
STR R1, [R0, #CLKCON_OFS] ;配置時(shí)鐘配控制寄存器
ENDIF
;-----------------------------------------------------------------------
;存儲(chǔ)器設(shè)定
;如果沒有定義NO_MC_SETUP且CLOCK_SETUP != 0則執(zhí)行下面的程序
;-----------------------------------------------------------------------
IF (:LNOT:(:DEF:NO_MC_SETUP)):LAND:(CLOCK_SETUP != 0)
LDR R0, =MC_BASE ;加載存儲(chǔ)控制器基址
LDR R1, =BWSCON_Val
STR R1, [R0, #BWSCON_OFS] ;配置總線寬度和等待控制寄存器
LDR R1, =BANKCON0_Val
STR R1, [R0, #BANKCON0_OFS] ;配置BLANK0控制寄存器
LDR R1, =BANKCON1_Val
STR R1, [R0, #BANKCON1_OFS] ;配置BLANK1控制寄存器
LDR R1, =BANKCON2_Val
STR R1, [R0, #BANKCON2_OFS] ;配置BLANK2控制寄存器
LDR R1, =BANKCON3_Val
STR R1, [R0, #BANKCON3_OFS] ;配置BLANK3控制寄存器
LDR R1, =BANKCON4_Val
STR R1, [R0, #BANKCON4_OFS] ;配置BLANK4控制寄存器
LDR R1, =BANKCON5_Val
STR R1, [R0, #BANKCON5_OFS] ;配置BLANK5控制寄存器
LDR R1, =BANKCON6_Val
STR R1, [R0, #BANKCON6_OFS] ;配置BLANK6控制寄存器
LDR R1, =BANKCON7_Val
STR R1, [R0, #BANKCON7_OFS] ;配置BLANK7控制寄存器
LDR R1, =REFRESH_Val
STR R1, [R0, #REFRESH_OFS] ;配置DRAM/SDRAM刷新控制寄存器
MOV R1, #BANKSIZE_Val
STR R1, [R0, #BANKSIZE_OFS] ;配置可調(diào)的bank大小寄存器
MOV R1, #MRSRB6_Val
STR R1, [R0, #MRSRB6_OFS] ;配置bank6模式控制寄存器
MOV R1, #MRSRB7_Val
STR R1, [R0, #MRSRB7_OFS] ;配置bank7模式控制寄存器
ENDIF
;-----------------------------------------------------------------------
;IO端口配置
;如果沒有定義NO_GP_SETUP并且GP_SETUP != 0則執(zhí)行下面的程序
;-----------------------------------------------------------------------
IF (:LNOT:(:DEF:NO_GP_SETUP)):LAND:(GP_SETUP != 0)
IF GPA_SETUP != 0
LDR R0, =GPA_BASE ;配置端口A功能
LDR R1, =GPACON_Val ;A口有25個(gè)口,做IO時(shí)只能做輸出口
STR R1, [R0, #GPCON_OFS]
ENDIF
IF GPB_SETUP != 0
LDR R0, =GPB_BASE ;配置端口B功能
LDR R1, =GPBCON_Val
STR R1, [R0, #GPCON_OFS]
LDR R1, =GPBUP_Val ;配置端口B上拉寄存器
STR R1, [R0, #GPUP_OFS]
ENDIF
IF GPC_SETUP != 0
LDR R0, =GPC_BASE ;配置端口C功能
LDR R1, =GPCCON_Val
STR R1, [R0, #GPCON_OFS]
LDR R1, =GPCUP_Val ;配置端口C上拉寄存器
STR R1, [R0, #GPUP_OFS]
ENDIF
IF GPD_SETUP != 0
LDR R0, =GPD_BASE ;配置端口D功能
LDR R1, =GPDCON_Val
STR R1, [R0, #GPCON_OFS]
LDR R1, =GPDUP_Val ;配置端口D上位寄存器
STR R1, [R0, #GPUP_OFS]
ENDIF
IF GPE_SETUP != 0
LDR R0, =GPE_BASE
LDR R1, =GPECON_Val ;配置端口E功能
STR R1, [R0, #GPCON_OFS]
LDR R1, =GPEUP_Val ;配置端口E上位寄存器
STR R1, [R0, #GPUP_OFS]
ENDIF
IF GPF_SETUP != 0
LDR R0, =GPF_BASE
LDR R1, =GPFCON_Val ;配置端口F功能
STR R1, [R0, #GPCON_OFS]
LDR R1, =GPFUP_Val ;配置端口F上位寄存器
STR R1, [R0, #GPUP_OFS]
ENDIF
IF GPG_SETUP != 0
LDR R0, =GPG_BASE
LDR R1, =GPGCON_Val ;配置端口G功能
STR R1, [R0, #GPCON_OFS]
LDR R1, =GPGUP_Val ;配置端口G上位寄存器
STR R1, [R0, #GPUP_OFS]
ENDIF
IF GPH_SETUP != 0
LDR R0, =GPH_BASE
LDR R1, =GPHCON_Val ;配置端口H功
STR R1, [R0, #GPCON_OFS]
LDR R1, =GPHUP_Val ;配置端口H上位寄存器
STR R1, [R0, #GPUP_OFS]
ENDIF
IF GPJ_SETUP != 0
LDR R0, =GPJ_BASE
LDR R1, =GPJCON_Val ;配置端口J功
STR R1, [R0, #GPCON_OFS]
LDR R1, =GPJUP_Val ;配置端口J上位寄存
STR R1, [R0, #GPUP_OFS]
ENDIF
ENDIF
;-----------------------------------------------------------------------
;拷貝異常向量到內(nèi)部RAM
;如果定義了RAM_INTVEC就執(zhí)行下面一段程序
;-----------------------------------------------------------------------
IF :DEF:RAM_INTVEC
ADR R8, Vectors ; 讀取向量源地址
LDR R9, =IRAM_BASE ; 讀取片上SRAM的基地址
LDMIA R8!, {R0-R7} ; 批量加載異常向量
STMIA R9!, {R0-R7} ; 批量存儲(chǔ)向量
LDMIA R8!, {R0-R7} ; 加載程序入口地址(Load Handler Addresses )
STMIA R9!, {R0-R7} ; 存儲(chǔ)程序入口地址(Store Handler Addresses)
ENDIF
;-----------------------------------------------------------------------
;配置相應(yīng)模式棧的大小(Setup Stack for each mode )
;下面這一段主要是設(shè)置各個(gè)異常模式的堆棧,注意在設(shè)置的時(shí)候需要禁止IRQ和FIQ.
;這段代碼也是系統(tǒng)復(fù)位后執(zhí)行的第一段代碼。執(zhí)行完這段代碼后系統(tǒng)處于系統(tǒng)模
;式,并且IRQ和FIQ都是禁止的。
;-----------------------------------------------------------------------
LDR R0, =Stack_Top ;加載棧頂指針地址
;-----------------------------------------------------------------------
;進(jìn)入未定義模式,并設(shè)定其棧指針
;-----------------------------------------------------------------------
;將(Mode_UND | I_Bit | F_Bit)賦值給 CPSR_c即CPSR[7:0]
MSR CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit
MOV SP, R0 ;棧頂指針地址賦值給SP指針
SUB R0, R0, #UND_Stack_Size ;分其棧指針
;-----------------------------------------------------------------------
;進(jìn)入異常中斷模式,并設(shè)定其棧指針
;下面這三句話與上面原理一樣
;-----------------------------------------------------------------------
MSR CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #ABT_Stack_Size
;-----------------------------------------------------------------------
;進(jìn)入FIQ模式,并設(shè)定其棧指針
;下面這三句話與上面原理一樣
;-----------------------------------------------------------------------
MSR CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #FIQ_Stack_Size
;-----------------------------------------------------------------------
;進(jìn)入IRQ模式,并設(shè)定其棧指針
;下面這三句話與上面原理一樣
;-----------------------------------------------------------------------
MSR CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #IRQ_Stack_Size
;-----------------------------------------------------------------------
;進(jìn)入Supervisor模式,并設(shè)定其棧指針
;下面這三句話與上面原理一樣
;-----------------------------------------------------------------------
MSR CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #SVC_Stack_Size
;-----------------------------------------------------------------------
;進(jìn)入用戶模式,并設(shè)定其棧指針
;下面這三句話與上面原理一樣
;-----------------------------------------------------------------------
; Enter User Mode and set its Stack Pointer
MSR CPSR_c, #Mode_USR
MOV SP, R0
SUB SL, SP, #USR_Stack_Size
;-----------------------------------------------------------------------
;進(jìn)入用戶模式
;-----------------------------------------------------------------------
MSR CPSR_c, #Mode_USR
IF :DEF:__MICROLIB ;如果定義了__MICROLIB
EXPORT __initial_sp ;那么就聲明__initial_sp
ELSE
MOV SP, R0 ;否則就設(shè)定用戶模式棧指針
SUB SL, SP, #USR_Stack_Size
ENDIF
;-----------------------------------------------------------------------
;些處開始正式進(jìn)入C代碼區(qū)
;反匯編以后C程序中的main函數(shù)名就變成了__main
;-----------------------------------------------------------------------
IMPORT __main ;聲明__main 函數(shù)
LDR R0, =__main ;加載__main 函數(shù)入口地址
BX R0 ;跳轉(zhuǎn)到__main處
IF :DEF:__MICROLIB ;如果定義了__MICROLIB
EXPORT __heap_base ;則聲明__heap_base
EXPORT __heap_limit ;聲明__heap_limit
ELSE
;-----------------------------------------------------------------------
;用戶初始化堆與棧,用于動(dòng)態(tài)申請(qǐng)內(nèi)存使用
;__use_two_region_memory這是MDK的庫函
;__user_initial_stackheap也是一個(gè)庫函數(shù),它的返回值有
; * 堆基址(heap base) --> R0
; * ;(stack base) --> R1 一般為棧的最高地址
; * 堆頂(heap limit) --> R2
; * 棧頂(stack limit) --> R3
;
;-----------------------------------------------------------------------
AREA |.text|, CODE, READONLY
IMPORT __use_two_region_memory
EXPORT __user_initial_stackheap
__user_initial_stackheap
LDR R0, = Heap_Mem ;堆內(nèi)存起始地址 -->R0
LDR R1, =(Stack_Mem + USR_Stack_Size) ;棧起始地址 -->R1
LDR R2, = (Heap_Mem + Heap_Size) ;堆頂 -->R2
LDR R3, = Stack_Mem ;棧頂?shù)刂?--> R3
BX LR ;子程序返回
ENDIF
END
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1