自己动手写bootloader


原创作品,允许转载,转载时请务必以超链接形式标明文章  原始出处  、作者信息和本声明。否则将追究法律责任。 http://doublewen.blog.51cto.com/3097132/802508

                                           

    为了写一个bootloader让板子跑起来,首先我们要知道bootloader是个什么东东才行。简单的说,bootloader就是一个引导内核启动的一段小代码,也就是说当启动完内核之后,它的使命就已经结束。

bootloader生命周期:初始化硬件==》设置启动参数==》跳到Linux内核的首地址==》消亡。那么它是怎么启动内核的呢或者说在启动内核之前它究竟完成了哪些工作呢?

写代码之前还是先了解下内核启动的硬性条件:

    1.CPU寄存器的设置: r0=0,r1=机器类型ID(linux/arch/arm/tools/mach-types),r2=启动参数标记列表在RAM中的基地址。

    2.CPU工作模式:设置为管理模式(因为SUV模式的权限最大),且必须禁止中断IRQ、FIQ。

    3.cache和MMU的设置:MMU必须关闭,数据cache必须关闭,指令cache可以开启可以关闭,不过建议开启,因为可以加快bootloader的运行速度

    bootloader的工作分为两个阶段,由汇编语言和C语言各自掌管:

    第一阶段完成功能(汇编语言):包括模式设置,关闭看门狗(防止系统定时重启),关闭中断,关cache,设置时钟频率,初始化硬件(nand flash和sdram),初始化堆栈(因为要进入到C语言中执行),跳转到第二阶段代码的C入口点。

    第二阶段完成功能(C语言):重定位从flash里把程序本身复制到sdram里去,清bss段,为内核设置启动参数,调用内核。

注释:bootloader的代码分为前4K和4K后,bootloader运行时前4K代码会由硬件自动的拷贝到sram中,然后前4K代码需要将bootloader拷贝到sdram中运行(拷贝4K后的代码还是全部分具体情况而定),因为nand flash是不能直接运行代码的。

完成一个简单的具有基本功能的bootloader

start.S(bootloader入口)
.globl _start
_start:
    
        mrs r0 , cpsr
        bic r0 , r0 , #0x1f
        orr r0 , r0 , #0xd3 
        msr cpsr , r0
    
        ldr r0,  =0x53000000
        ldr r1,  = 0
        str r1, [r0]
    
        ldr r0 ,  =0x4a000008
        ldr r1 ,  =0xffffffff
        str r1 , [r0]
        ldr r0 ,  =0x4a00001c
        ldr r1 ,  =0x7fff
        str r1 , [r0] 
    
        mrc p15,  0, r2, c1, c0,  0
        orr r2, r2, #( 1 << 12)
        mcr p15,  0, r2, c1, c0,  0
    
        mrc p15,0,r0,c1,c0,0
        bic r0,r0,#0x00002300 @clear bits 13,9:8(--V- --RS)
        bic r0,r0,#0x00000087 @clear bits 7,2:0(B--- -CAM)
        orr r0,r0,#0x00000002 @set bit 1(A)Align
        orr r0,r0,#0x00001000 @set bit 12(I)I-Cache
        mcr p15,0,r0,c1,c0,0
    
    
    
    
 
        ldr r1 , = 0 
        str r1, [r1] 
        ldr r1, [r1] 
        cmp r1, # 0
        ldreq sp,  = 4096
        ldrne sp,  =(0x40000000 + 4096)
 
       
    *1.7 时钟初始化,主要是MPLLCON、CLKDIVN寄存器的设置,特别注意将总线模式改为异步总线模式*/
        bl clock_init
    
        bl sdram_init
    
        bl nand_init
    

    
    
      
        bl CopyCode2Ram
    
        ldr r0, =  __bss_start
        ldr r1,  =__bss_end
        cmp r0, r1
        beq setup_stack
        mov r2, # 0
        clear_loop :
        str r2, [r0], # 4
        cmp r0, r1
        bne clear_loop
    
 

relocate :   
        mov r0, # 0
        ldr r1,  =__start
        ldr r2,  =__bss_start
        sub r2, r2, r1
        setup_stack:
         
        ldr pc,  =main 
main.c
int  main( void)
{
  void  ( *theKernel)( int  zero,  int  machine_id,  int  params_addr);
 
  uart_init();
  puts( "============BOOT for S3C2440=============\n\rCopy kernel for flash to sdram ...\n\r");
 
  nand_read(0x30108000, 0x60000, 0x300000);
  puts( "OK\n\r"); 
   
  puts( "Set parametes ...");
  set_params();
  puts( "OK\n\r"); 
   
  puts( "Boot kernel ...\n\r");
  theKernel  =  0x30108040;
  theKernel( 0 362, 0x30000100 ); 
  puts( "\nerror!\n\r");
  return  0;
}

 

 

本文出自 “D.C_LOOK” 博客,请务必保留此出处http://doublewen.blog.51cto.com/3097132/802508

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值