uboot启动流程概述_海思uboot启动流程详细分析(一)

第一阶段 start.S

首先我们可以在u-boot.lds中看到ENTRY(_start),即指定了入口_start,_start也就是整个start.S的最开始;

1. reset

在arch\\arm\\cpu\\armv8\\hi3559av100中的start.S

reset:

/*

* Could be EL3/EL2/EL1, Initial State:

* Little Endian, MMU Disabled, i/dCache Disabled

*/

adr x0, vectors

switch_el x1, 3f, 2f, 1f

3: msr vbar_el3, x0

mrs x0, scr_el3

orr x0, x0, #0xf /* SCR_EL3.NS|IRQ|FIQ|EA */

msr scr_el3, x0

msr cptr_el3, xzr /* Enable FP/SIMD */

#ifdef COUNTER_FREQUENCY

ldr x0, =COUNTER_FREQUENCY

msr cntfrq_el0, x0 /* Initialize CNTFRQ */

#endif

b 0f

2: msr vbar_el2, x0

mov x0, #0x33ff

msr cptr_el2, x0 /* Enable FP/SIMD */

b 0f

1: msr vbar_el1, x0

mov x0, #3 << 20

msr cpacr_el1, x0 /* Enable FP/SIMD */

0:

/*

* Cache/BPB/TLB Invalidate

* i-cache is invalidated before enabled in icache_enable()

* tlb is invalidated before mmu is enabled in dcache_enable()

* d-cache is invalidated before enabled in dcache_enable()

*/

/*

* read system register REG_SC_GEN2

* check if ziju flag

*/

ldr x0, =SYS_CTRL_REG_BASE

ldr w1, [x0, #REG_SC_GEN2]

ldr w2, =0x7a696a75 /* magic for \"ziju\" */

cmp w1, w2

bne normal_start_flow

mov x1, sp /* save sp */

str w1, [x0, #REG_SC_GEN2] /* clear ziju flag */

adr x0, vectors,其中的vectors代表了异常向量表

主要做了如下事情:

1)reset SCTRL寄存器

具体可参考reset_sctrl函数,由CONFIG_SYS_RESET_SCTRL控制,一般不需要打开。该配置项的解释如下:

Reset the SCTRL register at the very beginning of execution to avoid interference from stale mappings set up by early firmware/loaders/etc.

2)根据当前的EL级别,配置中断向量、MMU、Endian、i/d Cache等。

3)配置ARM的勘误表

具体可参考apply_core_errata函数,由CONFIG_ARM_ERRATA_XXX控制,在项目的初期,可以不打开,后续根据实际情况打开)。

2. normal_start_flow流程

这里是正常启动流程

normal_start_flow:

/* set stack for C code */

ldr x0, =(CONFIG_SYS_INIT_SP_ADDR)

bic sp, x0, #0xf /* 16-byte alignment for ABI compliance */

bl uart_early_init

adr x0, Str_SystemSartup

bl uart_early_puts

ldr x0, =0x1202008c

ldr w0, [x0]

bl uart_early_put_hex

/* enable I-Cache */

bl icache_enable

1)设置代码的堆栈

2.)跳转到uart_early_init

因为uart_early_init是全局的伪汇编指令(在uart.S中定义),所以在start.S中也可以使用到

3)声明一个字符串Str_SystemSartup

4)使能icache

因为bne normal_start_flow是不跳转回来的,所以会继续向下执行

3. running_addr_check流程

判断是否进入not_ddr_init中,不需要DDR初始化,直接copy到DDR中

check_boot_mode:

ldr x0, =SYS_CTRL_REG_BASE

ldr w0, [x0, #REG_SYSSTAT]

lsr w6, w0, #4

and w6, w6, #0x3

cmp w6, #BOOT_FROM_EMMC //判断是不是EMMC启动

bne ufs_boot //如果不是,则进入ufs_boot

4. ziju_flow流程

自举模式从这里我可以推断出,芯片的启动分为两种,一种是自举模式也就是本地的spiflash或nand或emmc等启动,另一种就是pcie启动模式。不同启动模式对应不同的启动流程。但不同启动模式代码是相互交织的,需要分清楚!

1) 初始化PLL和DDRC控制器和管脚复用情况。

/* init PLL/DDRC/pin mux/... */

ldr r0, _blank_zone_start

ldr r1, _TEXT_BASE

sub r0, r0, r1

ldr r1, =RAM_START_ADRS

add r0, r0, r1

mov r1, #0x0 /* flags: 0->normal 1->pm */

bl init_registers /* init PLL/DDRC/... */

bl init_registers这个函数是初始化一些寄存器,这些寄存器分了很多,包括中断、网络、哈希功能形式的寄存器,初始化的意思就是给一个值,但这值一般没什么意义,具体的寄存器,后面会再进行配置!

2) start_ddr_training

/* DDR training:DR布线,完全按等长约束就没有ddr training的说法。

当布线去掉等长约束或放宽约束条件,就要做ddr training,以保证时序的完整性,使信号的建立&保持时间窗口一致。ddr training是调整Addr/Cmd信号对CLK,DQ信号对DQS的延时。由于没做等长约束,信号有长,有短,就会导致信号有快,慢之差(信号在1000mil走线耗时约160~180ps,相对FR-4的板材),ddr training就是找到一套参数,使信号的建立与保持时间充足。并保存且写到配置中。*/

3) pcie_slave_boot

6. jump_to_ddr

自举模式省略了一些PCIE判断的情况的解释,我也没怎么看懂

jump_to_ddr:

adr x0, _start_armboot

ldr x30,[x0]

ret

开始进入跳转到C语言阶段

总结

关cache,关mmu,SVC模式

检测是不是自举模式还是pcie启动,也包括是冷启动还是热启动

串口初始化

DDR初始化和DDR training

正常启动时,会检测启动方式,对代码进行相应的拷贝,重定位

设置堆栈

清bss段

跳转到第二阶段,即C语言阶段

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值