专题5-核心初始化

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lvjianxin6015/article/details/54142750

一、异常向量表

1.1 异常定义–execption
因为内部或外部的一些事件,导致处理器停下正在处理的工作,转而去处理发生的事件。

1.2 异常类型
7种异常:复位异常、未定义指令异常、软中断异常(SWI)、预取失败异常、数据存储异常、IRQ、FIQ。
这里写图片描述

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

1.4 异常向量表
这里写图片描述

2、手把手教你写代码
start.S的代码如下(先写异常向量表

.text
.global _start
_start:
                b reset
                ldr pc, _undifined_instruction
                ldr pc, _software_interrupt
                ldr pc, _prefetch_abort
                ldr pc, _data_abort
                ldr pc, _not_used
                ldr pc, _irq
                ldr pc, _fiq

#采用宏的方式,否则上面可以写为 eg:ldr pc, =undifined_instruction,此时ldr是一个伪指令
_undifined_instruction: .word undifined_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


undifined_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{  #注意这里是{}不是()
                . = 0x30008000;#2440

                . =ALIGN(4);#4字节对齐,c语言中是用#pragma pack(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 $^         #-o 不要忘记了
    arm-linux-objcopy -O binary gboot.elf gboot.bin

%.o : %.S
    arm-linux-gcc -g -c $^

%.0 : %.c
    arm-linux-gcc -g -c $^

210处理器BL1头信息添加:(2440和6410不用加头)
这里写图片描述
这里写图片描述

二、设置svc模式

通过程序状态寄存器来设置:
这里写图片描述
这里写图片描述
设置方法:因为状态寄存器是不能直接01操作的,要先将其复制到通用寄存器(指令:mrs),再对通用寄存器进行01操作(清零:bic 置1:orr),再复制到状态寄存器(指令:msr)。

扫描二维码关注公众号,回复: 3775537 查看本文章

备注:bl是一个分支指令,在分支之前,在寄存器14中装载寄存器15中的内容。即会将链接寄存器lr的值赋给pc指针。

reset:
    bl set_svc

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

上面置1操作时,对最后5位进行操作可以写为:orr r0,r0,#0x13(10011),之所以写为0xd3(11010011),最后5位是一样的,同时对I、F位进行了置1操作(目的:关闭中断)。
这里写图片描述

三、关闭看门狗

这里写图片描述
3.1 原理:
这里写图片描述

3.2 看门狗控制寄存器:
这里写图片描述
这里写图片描述

#define pwTCON 0x53000000
disable_watchdog:
    ldr r0,=pwTCON
    mov r1,#0x0     #干脆全赋值为0
    str r1,[r0]     #把寄存器的值赋给内存,str为存储器访问指令
    mov pc,lr

四、关闭中断

首先:cpsr寄存器的 I 、F为设置为1(在设置处理器的工作模式时已经完成)
其次:设置中断屏蔽寄存器(MASK),设为全1
2440:
这里写图片描述

reset:
    bl disable_interrupt
#define inmask 0x4A000008
disable_interrupt:
    mvn r1,#0x0    #先取反再赋值,写入全1
    ldr r0,=inmask
    str r1,[r0]
    mov pc,lr

6410:
这里写图片描述

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

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

210:
这里写图片描述

reset:
    bl disable_interrupt
disable_interrupt:
    mvn r1,#0x0
    ldr r0,=0xf2000014
    str r1,[r0]

    ldr r0,=0xf2100014
    str r1,[r0]

    ldr r0,=0xf2200014
    str r1,[r0]

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

五、关闭mmu和cache

5.1 cache:
这里写图片描述

5.2 mmu之前,先介绍虚拟地址
这里写图片描述
那么谁来帮助系统完成虚拟地址物理地址之间的转化呢?—-mmu来完成
(在arm11及以后,访问cache要经过mmu)

5.3 为什么要关闭?
在arm初始化的时候并没有正确的去配置mmu,所以在使用之前要关闭它,防止一些意想不到的错误。后面再使用的时候,会配置好再打开。

5.4 怎么关闭?—通过协处理器cp15来关闭
第一步:使Icache和Dcache失效
这里写图片描述
第二步:关闭IDcache、mmu
先将控制寄存器(control register)读到r0寄存器
这里写图片描述
这里写图片描述

reset:
    bl disable_mmu
disable_mmu:
    mcr p15,0,r0,c7,c7,0  #第一步:使Icache和Dcache失效

    #第二步:关闭Dcache、mmu
    mrc p15,0,r0,c1,c0,0
    bic r0,r0,#0x00000007
    mcr p15,0,r0,c1,c0,0
    mov pc,lr

猜你喜欢

转载自blog.csdn.net/lvjianxin6015/article/details/54142750