uboot启动流程详解(4)-cpu_init_crit

1、源码及注释

cpu_init_crit标号对应的源码:

/*************************************************************************
 *
 * CPU_init_critical registers
 *
 * setup important registers
 * setup memory timing
 *
 *************************************************************************/
ENTRY(cpu_init_crit)
    /*
     * Jump to board specific initialization...
     * The Mask ROM will have already initialized
     * basic memory. Go here to bump up clock rate and handle
     * wake up conditions.
     */
    b   lowlevel_init       @ go setup pll,mux,memory
ENDPROC(cpu_init_crit)

lowlevel_init标号对应的源码:(这个代码要初始化内存等,是和具体平台有关的,所以应该去对应平台的目录下找lowlevel_init.S文件)

ENTRY(lowlevel_init)
    /*
     * Setup a temporary stack
     */
    /**
    为调用c函数准备一个临时堆栈而已,这个堆栈在cpu的片上内存!
    **/
    ldr sp, =CONFIG_SYS_INIT_SP_ADDR
    bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
#ifdef CONFIG_SPL_BUILD
    ldr r9, =gdata
#else
    sub sp, sp, #GD_SIZE
    bic sp, sp, #7
    mov r9, sp
#endif
    /*
     * Save the old lr(passed in ip) and the current lr to stack
     */
    push    {ip, lr} /*将ip和lr寄存器压入堆栈保存*/

    /*
     * go setup pll, mux, memory
     */
    bl  s_init  /*针对相应的平台设置系统时钟,这是c函数,结合cpu的datasheet阅读即可*/
    pop {ip, pc}   /*将ip和lr寄存器从堆栈弹出*/
ENDPROC(lowlevel_init)

2、相关指令介绍

  1. ldr
    ARM指令集中,LDR通常都是作加载指令的,但是它也可以作伪指令。
    (1)LDR r0,=name,像这种带等号的是伪指令,而不是ARM指令,LDR 伪指令用于加载立即数或一个地址值到指定寄存器。
      如果name是立即数的话:LDR R0,=0X123;//将0X123存入R0
       如果name是个标识符:LDR R0,=NAME;//将NAME的地址存入R0
       相当于:
      LDR R0,LABEL;
      LABEL DCB NAME;//分配内存并用NAME初始化(LABEL为内存的起始地址?)
    (2)LDR R1,[R0] ;如果没有等号,LDR 指令用于从内存中读取数据放入寄存器中.该指令是 将R0 地址处的数据读出,保存到R1 中(零偏移)。

3、代码流程走读

  1、lowlevel_init
  CONFIG_SYS_INIT_SP_ADDR该宏定义在文件include/configs/mx6slevk.h文件中(因为我自己用的CPU是飞思卡尔的MX6SL)

#define CONFIG_SYS_INIT_SP_ADDR \
    (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)

#define CONFIG_SYS_INIT_RAM_ADDR    IRAM_BASE_ADDR
#define CONFIG_SYS_INIT_SP_OFFSET \
    (CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)

#define IRAM_BASE_ADDR          0x00900000
#define CONFIG_SYS_INIT_RAM_SIZE    IRAM_SIZE
#define GENERATED_GBL_DATA_SIZE 176 /* (sizeof(struct global_data) + 15) & ~15  @ */

#define IRAM_SIZE                    0x00040000

  根据以上定义,计算得CONFIG_SYS_INIT_SP_ADDR = 0x00900000 + 0x00040000 - 176。查看该cpu的内存分布可知,0x00900000处是该cpu的片上内存(on chip ram),大小有256K。所以在进入s_init函数之前,SP指针如下图所示:
这里写图片描述
  

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
uboot是一种常用的开源引导加载程序,用于嵌入式系统的引导启动。其中,board_init_r和board_init_f是uboot中的两个重要函数。 board_init_r函数是在uboot启动过程中执行的第一个函数。它负责执行一系列的初始化工作,例如初始化系统时钟、设置内存映射等。此函数被用于配置和初始化各个硬件模块,包括中断控制器、串口控制器、定时器等,以确保系统正常运行。该函数还读取并解析配置文件,加载设备树等操作,为后续的引导加载准备好必要的条件。 board_init_f函数是在board_init_r函数之后调用的。它用于进一步初始化系统,并执行一些与硬件相关的操作。例如,该函数可能会初始化网络接口、USB接口、存储设备等,并设置系统的默认环境变量。此外,board_init_f函数还负责将uboot的控制权交给操作系统的引导加载程序,从而完成uboot的使命。 通过调用board_init_r和board_init_f函数,uboot能够在系统启动时完成各种硬件的初始化和配置工作。这两个函数是uboot启动过程中的重要环节,确保系统能够顺利地加载操作系统并运行。同时,它们也为开发者提供了扩展uboot的接口,可以在这两个函数中添加自定义的初始化代码,以满足系统特定的需求。 总结来说,board_init_r和board_init_f是uboot中两个重要的函数,用于初始化和配置嵌入式系统的硬件,并为操作系统的加载做好准备。它们是uboot启动过程中不可或缺的一部分,保证系统的正常启动和运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值