U-boot 开始文件Start.s的异常向量表CONFIG_SPL_BUILD宏及VBAR地址映射

#include <asm-offsets.h>          /* 头文件在根目录下的include及根
#include <config.h>             目录下的arch/arm/include目录 */ 
#include <version.h>
#include <asm/system.h>
#include <linux/linkage.h>

.globl _start
_start: b   reset //跳转到reset 进行地址判断,设置SVC模式
    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                    //快中断
#ifdef CONFIG_SPL_BUILD
_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
_pad:           .word 0x12345678 /* now 16*4=64 */
#else
_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
_pad:           .word 0x12345678 /* now 16*4=64 */
#endif  /* CONFIG_SPL_BUILD */

.global _end_vect
_end_vect:

    .balignl 16,0xdeadbeef

CONFIG_SPL_BUILD宏

我们可以看到异常向量表有两个定义,多了宏:#ifdef CONFIG_SPL_BUILD
什么是SPL呢,我们需要从启动机制说起:
以S3C6410为例:
1、将uboot.bin前4K拷贝到片内内存SRAM中,进行初始化内存SDRAM
2、将uboot.bin的内容约为200k全部拷贝到SDRAM中,PC指针跳转到SDRAM开始运行(前4K内容会判断自身在哪个内存当中,判断在SDRAM中则直接跳过前4K到后续部分进行运行。)
3、将内核加载到SDRAM中运行。

有了这种情况,随着厂家处理器改进:增加了片内内存的大小约为96K左右,希望整个Uboot.bin全部在片内内存进行运行,然后把内核加载到片外内存SDRAM中运行。
但是呢,uboot整体编译出来至少100K-200K,这样就造成了没法执行上述方案,于是Uboot作者就把uboot设置成2个部分:
ubootspl.bin (16K)和 uboot.bin (210K)
ubootspl.bin放到片内SRAM运行,进行初始化内存,将uboot.bin拷贝到外存SDRAM中运行,然后PC指针直接跳转到SDRAM中进行运行。
这就是#ifdef CONFIG_SPL_BUILD 宏的由来。


异常向量的地址映射问题

根据ARM的手册我们知道,异常向量地址的入口为0x00000000或者0xffff0000然而片内内存中开始地址0x00000000为ROM区,开始地址不可写,处理器厂家知道这样设计有些问题,所以在片内内存开辟了一块新的区域专门用于放置异常向量表。这样做话我们就需要将异常向量表的地址重新定位到厂家的那块内存。
上述是uboot在片内内存中,如果是在SD卡运行,且启用了MMU,这时候就很麻烦,RAM公司也考虑到了这种情况,所以在CP15协处理器中设计了一个叫VBAR的寄存器,我们将异常向量表的地址放到VBAR寄存器,那么发生异常以后ARM处理器会自动的从VBAR寄存器寻到异常向量表的地址,跳转到该处进行运行。

uboot编译以后的文件

这里写图片描述
绿颜色的uboot 文件:是所有.o文件链接后的文件,很大约有900K,里面包含了很多的调试信息和注释信息,是不能放到板子里运行的,是用来调试的文件。(elf格式的image)
uboot.bin是uboot文件剥离掉调试信息和注释信息的文件,可以放置到板子中运行。(原始二进制文件(raw image))
uboot.map (符号表)
uboot.srec ( S-Record格式的image)
uboot.lds (uboot的链接脚本文件)
uboot.16K(ubootspl-16K 文件)

查看uboot反汇编指令:
  arm-linux-objdump -S u-boot | less
_pad:           .word 0x12345678 /* now 16*4=64 */
#endif  /* CONFIG_SPL_BUILD */

.global _end_vect
_end_vect:

    .balignl 16,0xdeadbeef

这段_pad标识占位
.global _end_vect 标识异常向量表结束
.balignl 16,0xdeadbeef 标识如果没有16字节对齐就填充0xdeadbeef 直到填充到下个标号16字节对齐为止。

利用cp15协处理器设置异常向量表地址

#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD))
    /* Set V=0 in CP15 SCTRL register - for VBAR to point to vector */
    mrc p15, 0, r0, c1, c0, 0   @ Read CP15 SCTRL Register
    bic r0, #CR_V       @ V = 0
    mcr p15, 0, r0, c1, c0, 0   @ Write CP15 SCTRL Register

    /* Set vector address in CP15 VBAR register */
    ldr r0, =_start
    mcr p15, 0, r0, c12, c0, 0  @Set VBAR
#endif

1、将cp15 SCTRL寄存器读出来
2、清零第13位(#CR_V在arch/arm/include/asm/system.h中定义 是1<<13bit)
3、写会SCTRL寄存器
该位意思是中断异常地址设置0x00000000,选择1是映射到0xffff0000
4、将异常向量表实际运行的地址放入r0
5、将r0的内容写入VBAR寄存器

VBAR寄存器:如果中断向量表的地址没有被映射到0xffff0000的话,有一种更好的方法,可以使用该寄存器将中断向量表的地址映射到任何地址。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值