DIY自己的arm11(6410)的bootloader

现我们仿照着uboot对ARM11所做的初始化操作,编写裸机bootloader。
1.首先编写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 $^  
      
%.o : %.c  
    arm-linux-gcc -g -c $^  
      
.PHONY: clean  
clean:  
    rm *.o *.elf *.bin

2.然后编写链接器脚本diyboot.lds

OUTPUT_ARCH(arm)//arm内核  
ENTRY(_start)//代码入口start  
SECTIONS {  
    . = 0x50008000;  
      
    . = ALIGN(4);  
    .text :  //代码段  
    {  
    start.o (.text) //start.s是初始化代码  
    *(.text)  
    }  
  
    . = ALIGN(4); //数据段,4字节对齐  
    .data :   
    {  
    *(.data)  
    }  
      
    . = ALIGN(4);  
    bss_start = .;  //当前代码所在地址  
    .bss :   
    {  
    *(.bss)   
    }  
    bss_end = .; //当前代码结束地址  
}  

3.  开始编写我们自己的start.S  
a. 添加向量表  
查看三星官方的ARM Architecture Reference Manual.pdf文件,可以看到ARM11共有七种模式  
设计代码如下:

.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:  
        nop

b. 设置SVC模式
如手册上表所示  
要把CSRP的后五位M[4:0]设置为10011
另外要屏蔽中断和快速中断,他们的屏蔽室I为和F位
要把I位和F位设置为1 因此CSRP的后8为设置为11010011即为0xD3  
因此修改代码如下: 

 
.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  
  
set_svc:  
        mrs r0, cpsr  //把CPSR导入到r0寄存器  
        bic r0, r0, #0x1f  //把CPSR的后五位清零  
        orr r0, r0, #0xd3//把CPSR的后八位设置为0XD3  
        msr cpsr, r0//把r0值导入到CPSR  
        mov pc, lr//退出CPSR寄存器

c.关闭看门狗  
在嵌入式领域,有些系统需要长期运行在无人看守的环境。在运行过程中,难免不出现系统死机的情况,这时就需要系统自身带有一种自动重启的功能。watchdog一般是一个硬件模块,其作用就是在系统死机时,帮助系统实现自动重启。Watchdog在硬件上实现了计时功能,启动计时后,用户(软件)必须在计时结束前重新开始计时,俗称“喂狗”,如果到超时的时候还没有重新开始计时,那么它就认为系统是死机了,就自动重启系统。
关闭看门狗和看门狗中断就是设置WTCON的0位和2位为0,修改代码如下:

.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  
  
set_svc:  
        mrs r0, cpsr  
        bic r0, r0, #0x1f  
        orr r0, r0, #0xd3  
        msr cpsr, r0  
        mov pc, lr  
   
#define pWTCON 0x7e004000   //定义WTCON的地址  
disable_watchdog:  
        ldr r0, =pWTCON  //把地址装入r0  
        mov r1, #0x0     //r1清零  
        str r1, [r0]      //把r1的0装入ro装入的WTCON所在的地址  
        mov pc, lr       //返回

d.关闭中断
中断使能寄存器如图所示:  
很简单只要把VIC0INTENABLE和VIC1INTENABLE全部设置为0即可,修改代码如下:

.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  
      
  
_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 reset  
  
undifined_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  
  
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:      //把VIC0INTENABLE和VIC1INTENABLE全部设置为0  
    mvn r1,#0x0  
    ldr r0,=0x71200014  
    str r1,[r0]  
  
    ldr r0,=0x71300014  
    str r1,[r0]  
    mov pc, lr

e.关闭MMU  
MMU作用就是把虚拟地址映射到物理地址上去。
初始化完成前必须先关掉。
关闭mmu按照CP15的寄存器说明进行:  
设计代码如下:

.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  
      
  
_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 reset  
  
undifined_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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值