3分钟理解bootloader的流程

首先说明一下,本人是一个刚刚入行的新手。第一次写这样的博客可能有很多不足之处,还望各位同僚能够包容。不喜勿喷

那么现在就开始进入今天的重头戏,bootloader的启动流程以及VIVI的源码分析。

什么是Bootloader :

     Bootloader 是嵌入式系统的引导加载程序,它是系统上电后运行的第一段程序,其作用类似于 PC 机上的 BIOS。在完成对系统的初始化任务之后,它会将Linux 内核拷贝到 RAM 中去,然后跳转到内核的第一条指令处继续执行,从而启动 Linux 内核。        

Bootloader的启动流程 :

一般来说bootloader的启动分为两大阶段:

  第一阶段:第一阶段主要包含依赖于CPU的体系结构硬件初始化的代码,通常都用汇编语言来实现。在这个阶段的中它初始化基本的硬件设备(关闭看门狗、屏蔽所有的中断、关闭处理器内部指令/数据Cache等)。初始化SDRAM为第二阶段准备RAM空间,如果是从某个固态存储媒质中,则复制Bootloader的第二阶段代码到RAM。设置堆栈跳转到第二阶段的C程序入口点,在C程序中完成更多的初始化设置。

  第二阶段:第二阶段通常用C语言完成,以便实现更复杂的功能,也使程序有更好的可读性和可移植性。这个阶段的任务有:
  1.初始化本阶段要使用到的硬件设备。
  2.检测系统内存映射。
  3.将内核映像和根文件系统映像从Flash读到RAM。
  4.为内核设置启动参数。调用内核。

下面一起来看看VIVI的源码 :

VIVI源码分析:

head.S

关闭看门狗

    mov r1, #0x53000000
    mov r2, #0x0
    str r2, [r1]

关闭所有中断

    mov r1, #INT_CTL_BASE
    mov r2, #0xffffffff
    str r2, [r1, #oINTMSK]
    ldr r2, =0x7ff
    str r2, [r1, #oINTSUBMSK]   

初始化SDRAM

    mov r1, #MEM_CTL_BASE
    adrl    r2, mem_cfg_val
    add r3, r1, #52
1:  ldr r4, [r2], #4
    str r4, [r1], #4
    cmp r1, r3
    bne 1b
    mov pc, lr

跳转到main

    mrs r0, cpsr
    bic r0, r0, #0x1f
    orr r1, r0, #(0x12|0xc0)    
    msr cpsr_c, r1
    msr     cpsr_c,#0xd2
    ldr sp, IRQ_STACK_START

    msr     cpsr_c,#0xdf
    @ get read to call C functions
    ldr sp, DW_STACK_START  @ setup stack pointer
    mov fp, #0          @ no previous frame, so fp=0
    mov a2, #0          @ set argv to NULL 

    bl  main            @ call main 

main.c

1.打印版本信息

putstr(vivi_banner);
const char *vivi_banner =
                       "VIVI version " VIVI_RELEASE " (" VIVI_COMPILE_BY "@"
                       VIVI_COMPILE_HOST ") (" VIVI_COMPILER ") " UTS_VERSION "\r\n";

2.初始化板子相关的时钟和默认GPIO

ret = board_init();
    init_time();  
    set_gpios();

3.MMU初始化

mem_map_init();
    mem_map_nand_boot();
    cache_clean_invalidate();
    tlb_invalidate();
mmu_init();
    arm920_setup();

4.分配堆栈空间

ret = heap_init();
    mmalloc_init((unsigned char *)(HEAP_BASE), HEAP_SIZE);

5.MTD初始化

ret = mtd_dev_init();
    ret = mtd_init();
    add_command(&flash_cmd);

6.改变系统倍频进入shell

ChangeUPllValue(56,2,2);
boot_or_vivi();

7.Shell中启动内核

exec_string("boot");

猜你喜欢

转载自blog.csdn.net/arm_flying/article/details/73793657