Linux系統移植之——系統啟動 bootloader 的編寫、內存映射篇

你們要的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 配置開發板


Linux系統移植之——系統啟動 bootloader 的編寫、內存映射篇


Linux系統移植之——系統啟動 bootloader 的編寫、內存映射篇


Linux系統移植之——系統啟動 bootloader 的編寫、內存映射篇


Linux系統移植之——系統啟動 bootloader 的編寫、內存映射篇


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 程序。我使用

是 Dragon­ICE 仿真器, 所以先要安裝 Dragon­ICE Server 程序。

2. 連接仿真器

把 dragon­ICE 仿真器的 JTAG 口連接上 ARM 板(注意:ARM 板要斷電連接), 另一端通過並口連接到 PC 上,

有的仿真器是通過 USB 口連接到 PC 上, 這與仿真器的硬件相關。連接好後, 打開 ARM 電源,啟動 ARM 板。

當 ARM 通電啟動後,啟動 Dragon­ICE Server 檢測 ARM 板,詳細步驟及設置參見對應的仿真器手冊。我的

dragon­ICE Server 啟動, 按”自動檢測”可以檢測到 ARM920T。

3.2.2 啟動 AXD 配置開發板

1. 啟動 AXD

先啟動 Dragon­ICE Server 程序.

按如下步聚啟動 AXD:

開始­>所有程序­>ARM Developer Suite v1.2­>AXD Debugger

2. 裝載仿真器庫文件

從 AXD 菜單的 Options­­> Configure Target...啟動”Choose Target”目標板配置窗口.

在”Choose Target”窗口中,點擊”Add”按鈕,選擇仿真器的庫文件. 我的仿真器服務器程序安裝在

c:\\Dragon­ICE 下,所以選擇項 c:\\Dragon­ICE\\dragon­ice.dll 文件.3. 為 AXD 在線仿真配置仿真器

在"Target Environments"中選中 Dragon­ICE 中,點擊右邊的"Configure"按鈕.

在”FJB Dragon­ICE Release v1.2”窗口點擊"This computer..."按鈕,再點擊"OK"按鈕。

回到”Choose Target”窗口,點擊"OK"按鈕。完成配置.

回到主界面, 在右邊的”Target”窗口會出現 ARM920T_0.這表明 AXD 已經進入 ARM 板的在線仿真狀態.

點擊菜單"System Views"­­>"Controls Monitors".會出現"ARM920T­Register"窗口.此時,會顯示當前 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 提供了非常方便的調試手段, 包括在線單步, 自由設置斷點等.


分享到:


相關文章: