你們要的Linux系統移植來了,本章主要講解系統啟動 bootloader ,涉及ADS命令行、內存映射的內容。
本人也是一名程序員,給大家挑選的都是IT編程相關的精品資料,希望對大家的學習有幫助。
另外,本人近期會陸續上傳這些資料和視頻教程,可以關注一下互相交流:C C++ Java python linux ARM 嵌入式 物聯網等。
1 工具介紹
1.1 ADS 命令行命令介紹
1.1.1 armasm
1.1.2 armcc, armcpp
1.1.3 armlink
2 基本原理
2.1 可執行文件組成及內存映射
2.1.1 可執行文件的組成
2.1.2 裝載過程
2.1.3 啟動過程的彙編部分
2.1.4 啟動過程的 C 部分
3 AXD 的使用以及源代碼說明
3.1 源代碼說明
3.1.1 彙編源代碼說明
3.1.2 C 語言源代碼說明
3.1.3 源代碼下載
3.2 AXD 的使用
3.2.1 配置仿真器
3.2.2 啟動 AXD 配置開發板
3 AXD 的使用以及源代碼說明
3.1 源代碼說明
3.1.1 彙編源代碼說明
;===============================================================================
; 引用頭文件
;===============================================================================
get bdinit.h
;===============================================================================
; 引用標準變量
;===============================================================================
IMPORT |Image$$RO$$Base| ; Base address of RO section
IMPORT |Image$$RO$$Limit| ; End address of RO section
IMPORT |Image$$RW$$Base| ; Base address of RW section
IMPORT |Image$$RW$$Limit| ; End address of RW section
IMPORT |Image$$ZI$$Base| ; Base address of ZI section
IMPORT |Image$$ZI$$Limit| ; End addresss of ZI section
IMPORT bdmain ; The entry function of C program
;===============================================================================
; 宏定義
;===============================================================================
; macro HANDLER
MACRO
$HandlerLabel HANDLER $HandleLabel
$HandlerLabel
sub sp,sp,#4 ;Decrement sp (to store jump address)
stmfd sp!,{r0} ;PUSH the work register to stack
ldr r0,=$HandleLabel;Load the address of HandleXXX to r0
ldr r0,[r0] ;Load the contents(service routine start address) of HandleXXX
str r0,[sp,#4] ;Store the contents(ISR) of HandleXXX to stack
ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR)
MEND
;===============================================================================
; 彙編語言的入口代碼
;===============================================================================
AREA Init,CODE,READONLY
CODE32
ENTRY
;=====================
; 建立中斷向量表
;===================== b reset_handler ;0x00000000: Reset (SVC)
b undef_handler ;0x00000004: Undefined instruction (Undef)
b swi_handler ;0x00000008: Software Interrupt (SVC)
b iabr_handler ;0x0000000C: Instruction Abort (Abort)
b dabr_handler ;0x00000010: Data Abort (Abort)
b no_handler ;0x00000014:
b irq_handler ;0x00000018: IRQ (IRQ)
b fiq_handler ;0x0000001C: FIQ (FIQ)
LTORG
undef_handler HANDLER HandleUndef
swi_handler HANDLER HandleSWI
iabr_handler HANDLER HandlePabort
dabr_handler HANDLER HandleDabort
no_handler HANDLER HandleReserved
irq_handler HANDLER HandleIRQ
fiq_handler HANDLER HandleFIQ
;=============================
; 復位時運行的主程序
;=============================
reset_handler
;Set the cpu to SVC32 mode
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr_cxsf,r0
;Turn off watchdog
ldr
r0,=WTCON
ldr
r1,=0x0
str
r1,[r0]
;Disable all the first level interrupts
ldr
r0,=INTMSK
ldr
r1,=0xffffffff
str
r1,[r0]
;Disable all the second level interrupts
ldr
r0,=INTSUBMSK
ldr
r1,=0x7ff
str
r1,[r0]
;Configure MPLL
ldr
r0,=MPLLCON
ldr
r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV) ;Fin=12MHz,Fout=200MHz
str
r1,[r0]
;Set FCLK:HCLK:PCLK = 1:2:4
ldr
r0, =CLKDIVN
mov
r1, #3
str
r1, [r0]
;Set memory control registers
ldrr0,=SMRDATAldr
r1,=BWSCON
add
r2, r0, #52
;End address of SMRDATA
0
ldr
r3, [r0], #4
str
r3, [r1], #4
cmp
r2, r0
bne
%B0
;Initialize stacks
bl
InitStacks
;Setup IRQ handler
ldr
r0,=HandleIRQ
;This routine is needed
ldr
r1,=IsrIRQ
str
r1,[r0]
;Copy RW/ZI section into RAM
ldr
r0, =|Image$$RO$$Limit|;Get pointer to ROM data
ldr
r1, =|Image$$RW$$Base| ;and RAM copy
ldr
r3, =|Image$$ZI$$Base|
cmp
r0, r1
; Check that they are different
beq
%F2
1
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
2
ldr
r1, =|Image$$ZI$$Limit| ; Top of zero init segment
mov
r2, #0
3
cmp
r3, r1
; Zero init
strcc
r2, [r3], #4
bcc
%B3
bl bdmain
;Jump to the main function
;Dead loop
1
nop
b
%B1
;===============================================================================
; 初始中斷處理程序
;===============================================================================
IsrIRQ
sub
sp,sp,#4 ;reserved for PC
stmfd
sp!,{r8-r9}
ldr
r9,=INTOFFSET
ldr
r9,[r9]
ldr
r8,=HandleEINT0
add
r8,r8,r9,lsl #2
ldr
r8,[r8]str
r8,[sp,#8]
ldmfd
sp!,{r8-r9,pc}
;===============================================================================
; 初始化各個模式下堆棧
;===============================================================================
InitStacks
mrs
r0,cpsr
bic
r0,r0,#MODEMASK
orr
r1,r0,#UNDEFMODE|NOINT
msr
cpsr_cxsf,r1
;UndefMode
ldr
sp,=UndefStack
orr
r1,r0,#ABORTMODE|NOINT
msr
cpsr_cxsf,r1
;AbortMode
ldr
sp,=AbortStack
orr
r1,r0,#IRQMODE|NOINT
msr
cpsr_cxsf,r1
;IRQMode
ldr
sp,=IRQStack
orr
r1,r0,#FIQMODE|NOINT
msr
cpsr_cxsf,r1
;FIQMode
ldr
sp,=FIQStack
bic
r0,r0,#MODEMASK|NOINT
orr
r1,r0,#SVCMODE
msr
cpsr_cxsf,r1
;SVCMode
ldr
sp,=SVCStack
mov
pc,lr
;Return the call routine
LTORG
;===============================================================================
; 內存區控制寄存器值表; 你可根據需要修改 bdinit.h 文件, 下面代碼不用做任何改動
;===============================================================================
SMRDATA DATA
DCD
(0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(
B7_BWSCON<<28))
DCD
((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC)) ;GCS0
DCD
((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC)) ;GCS1
DCD
((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC)) ;GCS2
DCD
((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC)) ;GCS3
DCD
((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC)) ;GCS4
DCD
((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC)) ;GCS5
DCD ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN)) ;GCS6
DCD ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) ;GCS7
DCD ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
DCD 0x32 ;SCLK power saving mode, BANKSIZE 128M/128M
DCD 0x30 ;MRSR6 CL=3clk
DCD 0x30 ;MRSR7
ALIGN
;===============================================================================
; 異常及中斷向量表空間; 安裝異常或中斷處理程序在 bdisr.c 中,isr_setup()來完成.
;===============================================================================
AREA RamData, DATA, READWRITE
^ _ISR_STARTADDRESS ;表示下面數據區從_ISR_STARTADDRESS 指定的位置開始
HandleReset
# 4
HandleUndef
# 4
HandleSWI
# 4
HandlePabort # 4
HandleDabort # 4
HandleReserved # 4
HandleIRQ
# 4
HandleFIQ
# 4
;=============================
; The Interrupt table
;=============================
HandleEINT0 # 4
HandleEINT1 # 4
HandleEINT2 # 4
HandleEINT3 # 4
HandleEINT4_7 # 4
HandleEINT8_23 # 4
HandleRSV6
# 4
HandleBATFLT # 4
HandleTICK # 4
HandleWDT
# 4
HandleTIMER0 # 4
HandleTIMER1 # 4
HandleTIMER2 # 4
HandleTIMER3 # 4
HandleTIMER4 # 4
HandleUART2 # 4
HandleLCD
# 4
HandleDMA0
# 4
HandleDMA1
# 4
HandleDMA2
# 4
HandleDMA3
# 4
HandleMMC
# 4
HandleSPI0
# 4
HandleUART1
# 4
HandleRSV24
# 4
HandleUSBD
# 4
HandleUSBH
# 4
HandleIIC
# 4
HandleUART0
# 4
HandleSPI1
# 4HandleRTC
# 4
HandleADC
# 4
END
3.1.2 C 語言源代碼說明
void bdmain(void)
{
/* 禁止 Cache 和 MMU */
cache_disable();
mmu_disable();
/* 端口初始化 */
port_init();
/* 中斷處理程序 */
isr_init();
/* 串口初始化 */
serial_init(0, 115200);
/* 輸出信息進行主循環 */
serial_printf("is ok!\\n");
while(1) {
}
}
通常基本 ADS 的測試程序都可以在這個架構上加入自己的代碼.
3.2 AXD 的使用
3.2.1 配置仿真器
1. 為仿真器安裝 Server
一般的仿真器都對應有一個 Server 程序,所以在使用在線仿真之前,必須先安裝這個 Server 程序。我使用
是 DragonICE 仿真器, 所以先要安裝 DragonICE Server 程序。
2. 連接仿真器
把 dragonICE 仿真器的 JTAG 口連接上 ARM 板(注意:ARM 板要斷電連接), 另一端通過並口連接到 PC 上,
有的仿真器是通過 USB 口連接到 PC 上, 這與仿真器的硬件相關。連接好後, 打開 ARM 電源,啟動 ARM 板。
當 ARM 通電啟動後,啟動 DragonICE Server 檢測 ARM 板,詳細步驟及設置參見對應的仿真器手冊。我的
dragonICE Server 啟動, 按”自動檢測”可以檢測到 ARM920T。
3.2.2 啟動 AXD 配置開發板
1. 啟動 AXD
先啟動 DragonICE Server 程序.
按如下步聚啟動 AXD:
開始>所有程序>ARM Developer Suite v1.2>AXD Debugger
2. 裝載仿真器庫文件
從 AXD 菜單的 Options> Configure Target...啟動”Choose Target”目標板配置窗口.
在”Choose Target”窗口中,點擊”Add”按鈕,選擇仿真器的庫文件. 我的仿真器服務器程序安裝在
c:\\DragonICE 下,所以選擇項 c:\\DragonICE\\dragonice.dll 文件.3. 為 AXD 在線仿真配置仿真器
在"Target Environments"中選中 DragonICE 中,點擊右邊的"Configure"按鈕.
在”FJB DragonICE Release v1.2”窗口點擊"This computer..."按鈕,再點擊"OK"按鈕。
回到”Choose Target”窗口,點擊"OK"按鈕。完成配置.
回到主界面, 在右邊的”Target”窗口會出現 ARM920T_0.這表明 AXD 已經進入 ARM 板的在線仿真狀態.
點擊菜單"System Views">"Controls Monitors".會出現"ARM920TRegister"窗口.此時,會顯示當前 ARM 板上所
有寄存器的狀態。
4. 配置 ARM 板
如果 ARM 板通電後,沒有程序運行並把內存區控制寄存器配置好的說,外部 RAM 是不能使用的. 所以必須
通過仿真器來設置這些寄存器. 如果 ARM 板已經有啟動程序並且已經配置好, 這一步可以省略.
首先把 2410cfg.txt 拷貝到 c:\\下.
回到 AXD 主界面, 從菜單”System Views” > “Command Line Interface”。會出現一個 Command Line
Interface 的調試命令行窗口,並顯示如下提示符:
Debug >
輸入 obey c:\\2410cfg.txt 裝載所有配置命令.
Debug >obey c:\\2410cfg.txt
5. 2410cfg.txt 文件說明
sreg psr, 0x00000013
;設置當前 CPSR 的值, 把 CPU 的模式切換到 SVC 模式和 32 位指令集, 關閉 IRQ 和 FIQ。
smem 0x53000000,0,32
;設置看門狗控制寄存器 WTCON
;禁止看門狗定時器
smem 0x4C000004,((0x74<<12)+(0x3<<4)+0x1),32
;設置主頻率設置寄存器 MPLLCON
;目前 CPU 的工作頻率 FCLK 是 124.00MHz
smem 0x4C000014,0x3,32
;設置時鐘分頻寄存器 CLKDIVN
;設置 FCLK/HCLK/PCLK 的頻率比例 1:2:4
smem 0x48000000,((2<<28)+(2<<24)+(1<<20)+(1<<16)+(1<<12)+(1<<8)+(1<<4)+0),32
;設置內存總線控制 BWSCON
;SDRAM BANK 6&7 is 32 位
;其它 BANK is 16 位
smem 0x48000004,((3<<13)+(3<<11)+(7<<8)+(3<<6)+(3<<4)+(3<<2)+3),32
;設置寄存器區 0 控制寄存器:BANKCON0
smem 0x4800001c,((3<<15)+(1<<2)+1),32
;設置寄存器區 6 控制寄存器: BANKCON6(SDRAM)
;RAS to CAS 延時 3 時鐘週期
;列地址是 9 位
smem 0x48000020,((3<<15)+(1<<2)+1),32
;設置寄存器區 7 控制寄存器: BANKCON7(SDRAM)
;RAS to CAS 延時 3 時鐘週期
;列地址是 9 位
smem 0x48000024,((1<<23)+(3<<18)+(2<<16)+1113),32
;set 外部 RAM 刷新寄存器:REFRESH
;允許自刷新
;HCLK=FCLK/2, 60MHz,刷新計算器是 1113
smem 0x48000028,0x31,32;設置寄存器的大小
;禁止 burst 操作
;允許 SDRAM power down 模式
;SCLK 在訪問期間仍在活動狀態
;SDRAM 模式寄存器設置
smem 0x4800002c,0x30,32
smem 0x48000030,0x30,32
3.2.3 使用 AXD 在線仿真調試程序
1. 裝載可執行的文件
AXD 只支持.axf 格式的可執行文件.
啟動 AXD, 在菜單的 File 中,選擇 Load Image..., 選擇 c:\\adsbloadter\\prj\\prj_Data\\DebugRel\\prj.axf 加載執行
image. 就可以執行並調試了. AXD 提供了非常方便的調試手段, 包括在線單步, 自由設置斷點等.
閱讀更多 IT百科 的文章