×
单片机 > 单片机程序设计 > 详情

ARM裸机开发bootloader核心初始化

发布时间:2020-06-08 发布时间:
|
一、异常向量表

1、异常的定义

异常:因为内部或者外部的一些事件,导致处理器停下正在处理的工作,转而去处理这些发生的事情。

2、异常的类型

ARM处理器有7种Exception type分别为:Reset、Undefined instructions、Software interrupt、Prefetch Abort、Data Abort、IRQ、FIQ

2、什么是异常向量

当一种异常发生的时候,ARM处理器会跳转到对应该异常的固定地址去执行异常处理程序,而这个固定的地址,就称为异常向量。

3、异常向量表

由七个异常向量及其处理函数跳转关系组成的表为异常向量表。

下面是一个例子:

 

start.S

.text
.global _start
_start:
		b reset
		ldr pc, _undefined_instruction
		ldr pc, _software_interrupt
		ldr pc, _prefetch_abort
		ldr pc, _data_abort
		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:
	nop	

 

 

gboot.lds

 

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 = .;
}


 

Makefile

 

all : start.o
	arm-linux-ld -Tgboot.lds -o gboot.elf $^
	arm-linux-objcopy -O binary gboot.elf gboot.bin
	
%.o : %.S
	arm-linux-gcc -g -c %.S 
%.o : %.c
	arm-linux-gcc -g -c %.c 
	
.PHONY: clean
clean:
	rm *.o *.elf *.bin
	
关于异常向量表,对于2440和6410以上就结束了,不过对于210还要添加BL1头

 

./mkv210_image led.bin 210.bin

/home/dnw 210.bin 0x50008000

如果不加头的话,就无法正常工作。原因是210在上电后会运行厂家已经固化在SRAM中的BL0,这个时候,由BL0来调用BL1,BL1运行会产生校验码(这个校验码就在添加的头里面)并与BL0里的校验码进行比对,确认是否为要运行的BL1。成功后就运行BL1.

Header Info (check sum(user writing)、BL1 size(user writing)).

二、设置SVC模式

此时设置ARM的工作模式为SVC(supervisor),这样可以使用更多的寄存器,同时拥有很大的操作权限。具体可以参考下图


 

通过上图对ARM的状态寄存器的解释,我们可以得知将CPSR的后五位设置为0b10011就可以使用SVC模式。同时我们还要关闭irq和fiq。

具体实现代码:

续上start.S

 

reset:
	bl set_svc
	
set_svc:
	mrs r0, cpsr
	bic r0, r0, #ox1f
	orr r0, r0, #oxd3
	msr cpsr, r0

三、关闭看门狗

1、什么是看门狗

有些嵌入式设备要长期工作在无人看管的情况下,这个时候就需要,当发生死机时,设备可以实现自启动。而watchdog就可以完成这样一种功能。watchdog模块是一硬件设备。其作用就是当系统发生死机时,帮助系统实现自启动。

2、看门狗如何工作

看门狗模块有三部分组成,分别为时钟产生器,计时器,重启器。当开启看门狗时,计时器就开始了计时,系统必须在计时结束前对看门狗重新设置使其重新计时,简称喂狗。否则它会认为系统发生了死机,就重启系统。

3、为什么要关闭看门狗

一般情况下,bootloader的运行过程中不会发生死机,所以我们就关闭看门狗。否则我们还要不断的喂狗,而占用系统时间。

下面是6410中的watchdog的解释


 

 

代码编写:

 

reset:
	bl set_svc
	bl disable_watchdog
	
set_svc:
	mrs r0, cpsr
	bic r0, r0, #0x1f
	orr r0, r0, #0xd3
	msr cpsr, r0
#define pWTCON 0x7E004000
disable_watchdog:
	ldr r0, =pWTCON	/*mov的操作数最多为8位*/
	mov r1, #0x0
	str r1, [r0]
注:我们这里把watchdog的控制寄存器直接清零,也可以达到效果。

四、关闭中断

关闭中断要两个环节:1、CPSR中的I F位 置1,在设置SVC时我们已经做过,所以这里就不做了。2、对中断屏蔽寄存器进行设置

2440的板子需要设置INTMSK寄存器

210的板子需要设置4组寄存器VICINTENCLEAR

6410的板子需要设置2组寄存器VIC0INTENCLEAR和VIC1INTENCLEAR

下面我们以6410为例子进行介绍:


 

编码如下

 

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

五、关闭MMU和Cache

1、前言


 

从ARM的存储体系,我们可以看到,位于金子塔顶端的是处理器的寄存器,后面依次为TCM和辅助存储器。显然从金子塔的底部到顶部存储器的存取速度愈来愈快,价格也越来越高,而数量却越来越少。

2、什么是Cache

我们都知道处理器的访问速度是非常快的,而内存的速度却慢的很。这样当处理器在访问内存时就出现了问题。而Cache恰恰就用来解决这个问题。从物理结构上来讲,Cache位于处理器与内存之间,cache中存储了处理器经常从内存访问的数据与指令,也就是cache是内存的部分拷贝。这时处理器往往先访问cache,如果cache中没有想要的数据,才去内存查找。而cache的访问速度要比内存大的多,这样就提高了整个的运行效率。

cache又分为:I-Cache和D-Cache

3、MMU

谈到MMU这个时候就要先说一下虚拟地址:作为一个程序员,大家都知道有逻辑地址和物理地址之分,如果我们不直接和硬件打交道,我们根本不用去管物理地址,只要用逻辑地址就可以了。而MMU就是把逻辑地址转换为物理地址的协议。

假如我们只使用物理地址就会出现两个问题要解决:1、地址冲突(两段程序使用同一物理地址)。2、范围小

我们使用了MMU就可以把逻辑地址映射到物理地址,再具体的说就是两段程序使用的是同一逻辑地址,而经过映射后,它们都被映射到不同的物理地址。还有就是地址空间变大了。具体的物理地址的分配不用程序员来管,都要MMU来分配,这样就可以更好的利用物理空间。

ARM11之间Cache位于MMU前面靠近处理器,也就是说cache使用的是虚拟地址(逻辑地址),而ARM11之后包括ARM11的MMU靠近内存,这个时候使用的是物理地址。

4、为什么要关闭MMU和Cache

MMU和Cache在使用之前要进行配置,在ARM初始化的时候还没有进行配置,所以这个时候要关闭它们。还有就是避免Bootloader将linux内核下载到D-cache中,而I-cache这个时候可以不管它。

关闭MMU和Cache的步骤:

1、使I-cache和D-cache失效

2、关闭I-Cache和D-Cache,关闭MMU

下面是cp15的寄存器解释:


 

 

代码如下:

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

2440、6410和210的cp15是一样的。所以这里的代码也是一样的。

 

整个核心初始化的代码为:

 

.text
.global _start
_start:
		b reset
		ldr pc, _undefined_instruction
		ldr pc, _software_interrupt
		ldr pc, _prefetch_abort
		ldr pc, _data_abort
		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的操作数最多为8位*/
	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



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
8051单片机的函数发生器的设计