bootloader的核心初始化forARM11

来源:互联网 发布:php程序员的发展方向 编辑:程序博客网 时间:2024/06/05 06:53
今天刚学习完bootloader的核心初始化,趁早记下,免得忘记
关于ARM11的bootloader核心初始化,通过对u-boot的分析,主要有以下6步
1设置异常向量表
2设置CPU到svc模式
3关闭看门狗
4关闭所有中断
5关闭mmu和cache
6外设基地址初始化(这里先不讨论)

明确目标之后就可以开始了,先构造脚本文件
OUTPUT_ARCH(arm)
ENTRY(_start) //标记文件入口处
SECTIONS{
. = 0x50008000;

. = ALIGN(4); //对齐
.text : //执行代码
{
start.o(.text)
*(.text)
}

. = ALIGN(4);
.data : //数据
{
*(.data)
}
. = ALIGN(4);
bss_start = .;
.bss :
{
*(.bss)
}
bss_end = .;
}

然后转到.text文件写执行代码,创造start.S汇编文件,
.text
.global _start
_start: #以上都是规定,表示从_start处开始进入程序,下面是为了方便起见,进行了一下类似宏定义的操作

_undefined_instruction: .word undefined_instruction
_software_interrupt: .word software_interrupt
_prefetch_abort: .word prefetch_abort
_data_abort: .word data_abort
_not_used: .word not_used
_irq: .word irq
_fiq: .word fiq

设置中断向量表,说白了就是在程序发生异常时,你要去这几个地址执行对应的异常处理
bootloader的核心初始化forARM11

b reset #初始化
ldr pc,_undefined_instruction #未定义的指令发生对应的处理
ldr pc,_software_interrupt #软件中断处理
ldr pc,_prefetch_abort #从内存中取指令失败
ldr pc,_data_abort #从内存中取数据失败
ldr pc,_not_used #这个我也不知道是干嘛的,但老师就是写了
ldr pc,_irq #一般中断
ldr pc,_fiq #快速中断

按照上面顺序,先去执行reset,也就是说为的BL的核心初始化
reset:
bl set_svc #设置cpu到SVC模式
bl disable_watchdog #关闭看门狗
bl disable_interrupt #关闭所有中断
bl disable_mmu #关闭mmu

关于设置CPU到SVC模式,先看看手册
bootloader的核心初始化forARM11
写着我们只要把cpsr寄存器配置成0B10011就可以了,来看看cpsr寄存器
bootloader的核心初始化forARM11
bootloader的核心初始化forARM11

我们就是要配置最后5位,但是发现前面两位正好是中断和快速中断的关闭,那就顺便关了吧
所以
set_svc:
mrs r0, cpsr
bic r0, r0,#0x1f
orr r0, r0,#0xd3
msr cpsr, r0
mov pc, lr #返回到reset那里

接下来关闭看门狗
bootloader的核心初始化forARM11
#define pwTCON 0x7E004000
disable_watchdog:
ldr r0, =pwTCON
mov r1, #0x0
str r1, [r0]
mov pc, lr

关闭所有中断,这里有点不同,关闭在一个寄存器里,开启又在另一个寄存器里
bootloader的核心初始化forARM11

bootloader的核心初始化forARM11
disable_interrupt:
mvn r1, #0x0
ldr r0, =0x71200014
str r1, [r0]

ldr r0, =0x71300014
str r1, [r0]
mov pc, lr

失效mmu和cache,然后关闭mmu和cache
disable_mmu:
mcr p15,0,r0,c7,c7,0
mrc p15,0,r0,c1,c0,0
bic r0,r0,#0x00000007
mcr p15,0,r0,c1,c0,0
mov pc, lr




所以整个.text里面是这样的
.text
.global _start
_start:
b reset
ldr pc,_undefined_instruction
ldr pc,_software_interrupt
ldr pc,_prefetch_abort
ldr pc,_data_abort
ldr pc,_not_used
ldr pc,_irq
ldr pc,_fiq

_undefined_instruction: .word undefined_instruction
_software_interrupt: .word software_interrupt
_prefetch_abort: .word prefetch_abort
_data_abort: .word data_abort
_not_used: .word not_used
_irq: .word irq
_fiq: .word fiq


undefined_instruction:
nop
software_interrupt:
nop
prefetch_abort:
nop
data_abort:
nop
not_used:
nop
irq:
nop
fiq:
nop
reset:
bl set_svc
bl disable_watchdog
bl disable_interrupt
bl disable_mmu

set_svc:
mrs r0, cpsr
bic r0, r0,#0x1f
orr r0, r0,#0xd3
msr cpsr, r0
mov pc, lr

#define pwTCON 0x7E004000
disable_watchdog:
ldr r0, =pwTCON
mov r1, #0x0
str r1, [r0]
mov pc, lr

disable_interrupt:
mvn r1, #0x0
ldr r0, =0x71200014
str r1, [r0]

ldr r0, =0x71300014
str r1, [r0]
mov pc, lr
disable_mmu:
mcr p15,0,r0,c7,c7,0
mrc p15,0,r0,c1,c0,0
bic r0,r0,#0x00000007
mcr p15,0,r0,c1,c0,0
mov pc, lr


在编写makefile文件
all : start.o //最终要生成的文件start.o
arm-linux-ld -Tgboot.lds -o gboot.elf $^ //链接成可执行文件
arm-linux-objcopy -O binary gboot.elf gboot.bin//生成二进制.bin文件


%.o : %.S //.o文件可以由.S汇编文件编译得到
arm-linux-gcc -g -c $^
%.o : %.c //.o文件也可以由.c文件汇编得到
arm-linux-gcc -g -c $^


这样BL的核心初始化就完成了
原创粉丝点击