优秀的编程知识分享平台

网站首页 > 技术文章 正文

Linux系统移植之——系统启动 bootloader 的编写、内存映射篇

nanyue 2024-11-10 10:17:53 技术文章 1 ℃

你们要的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 程序。我使用

是 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 提供了非常方便的调试手段, 包括在线单步, 自由设置断点等.

Tags:

最近发表
标签列表