NanoPC-T2 Uboot启动过程分析 - 2-2 board_init_f

在本节继续之前,先回顾相关寄存器的内容与内存空间的使用情况:

寄存器:


r13 = &( bl mmu_turn_on ) @ /uboot-root/arch/arm/cpu/slsiap/s5p4418/start.S

sp = 0x42C0_0000

lr = &( bl mmu_on ) @ /uboot-root/arch/arm/cpu/slsiap/s5p4418/mmu_asm.S

内存空间:


0xC000_0000

    UBoot

0x42C0_0000

    UBoot-Stack

0x4000_0000

接下来继续从 \/uboot-root\/arch\/arm\/cpu\/slsiap\/s5p4418\/start.S 的第134行代码分析,如下述所示:


    ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)

    bic sp, sp, #7 /* 8-byte alignment for ABI compliance */

    sub sp, #GD_SIZE /* allocate one GD above SP */

    bic sp, sp, #7 /* 8-byte alignment for ABI compliance */

    mov r9, sp /* GD is above SP */

    mov r0, #0

    bl board_init_f

这是为调用 board_init_f 标签前做准备。包括了三件事,一是为全局变量gd预留空间,二是重新设置UBoot栈,三是准备好调用参数。

首先,UBoot先在 0x42C0_0000 (CONFIG_SYS_INIT_SP_ADDR) 前160个字节处开始往后预留空间。GD_SIZE宏可以在 \/uboot-root\/include\/generated\/generic-asm-offsets.h 处可以找到。即新的内存空间使用情况如下:


0xC000_0000

    UBoot

0x42C0_0000

    GD (struct global_data)

0x42BF_FF60

    UBoot-Stack

0x4000_0000

此时在最后一条指令执行时,相关寄存器如下:


r0 = 0

r9 = 0x42BF_FF60 @ &gd

r13 = &( bl mmu_turn_on ) @ /uboot-root/arch/arm/cpu/slsiap/s5p4418/start.S

sp = 0x42BF_FF60

lr = &( bl board_init_f ) @ /uboot-root/arch/arm/cpu/slsiap/s5p4418/start.S

到这里,有几个地方值得关注。首先是 board_init_f 位于 /uboot-root/common/board.c,是一个由c语言编写的函数。因此在调用前要准备好UBoot栈。第二,该函数有一个形参 ulong boot_flags,该参数的值由寄存器r0来传递,其值为0。第三,r9是全局变量gd的首地址。全局变量gd长160个字节,首地址定义在 \/uboot-root\/arch\/sh\/include\/asm\/global_data.h 中。定义如下:


#define DECLARE_GLOBAL_DATA_PTR register gd_t *gd asm ("r13")

变量gd是一个gd_t结构的类型,结构定义在 \/uboot-root\/include\/asm-generic\/global_data.h 中,定义如下:


typedef struct global_data {

 bd_t *bd;

 unsigned long flags;

 unsigned int baudrate;

 unsigned long cpu_clk; /* CPU clock in Hz! */

 unsigned long bus_clk;

 /* We cannot bracket this with CONFIG_PCI due to mpc5xxx */

 unsigned long pci_clk;

 unsigned long mem_clk;

 unsigned long have_console; /* serial_init() was called */

 unsigned long env_addr; /* Address of Environment struct */

 unsigned long env_valid; /* Checksum of Environment valid? */

 unsigned long ram_top; /* Top address of RAM used by U-Boot */

 unsigned long relocaddr; /* Start address of U-Boot in RAM */

 phys_size_t ram_size; /* RAM size */

 unsigned long mon_len; /* monitor len */

 unsigned long irq_sp; /* irq stack pointer */

 unsigned long start_addr_sp; /* start_addr_stackpointer */

 unsigned long reloc_off;

 struct global_data *new_gd; /* relocated global data */

 const void *fdt_blob; /* Our device tree, NULL if none */

 void *new_fdt; /* Relocated FDT */

 unsigned long fdt_size; /* Space reserved for relocated FDT */

 void **jt; /* jump table */

 char env_buf[32]; /* buffer for getenv() before reloc. */

 unsigned long timebase_h;

 unsigned long timebase_l;

 struct arch_global_data arch; /* architecture-specific data */

} gd_t;

gd_t结构还包含了两个变量,分别是位于 \/uboot-root\/include\/asm-generic\/u-boot.h 中的bd_t和位于 \/uboot-root\/arch\/arm\/include\/asm\/global_data.h 中的arch_global_data。经过整理后,变量gd包含的内容如下:


bd_t *bd

{

unsigned long bi_memstart

phys_size_t bi_memsize

unsigned long bi_flashstart

unsigned long bi_flashsize

unsigned long bi_flashoffset

unsigned long bi_sramstart

unsigned long bi_sramsize

unsigned long bi_bootflags

unsigned long bi_ip_addr

unsigned char bi_enetaddr[6]

unsigned short bi_ethspeed

unsigned long bi_intfreq

unsigned long bi_busfreq

ulong bi_arch_number

ulong bi_boot_params

struct bi_dram[1]

{

ulong start;

ulong size;

}

}

unsigned long flags

unsigned int baudrate

unsigned long cpu_clk

unsigned long bus_clk

unsigned long pci_clk

unsigned long mem_clk

unsigned long have_console

unsigned long env_addr

unsigned long env_valid

unsigned long ram_top

unsigned long relocaddr

phys_size_t ram_size

unsigned long mon_len

unsigned long irq_sp

unsigned long start_addr_sp

unsigned long reloc_off

struct global_data *new_gd

const void *fdt_blob

void *new_fdt

unsigned long fdt_size

void **jt

char env_buf[32]

unsigned long timebase_h

unsigned long timebase_l

struct arch_global_data arch

{

unsigned long timer_rate_hz

unsigned long tbu

unsigned long tbl

unsigned long lastinc

unsigned long long timer_reset_value

unsigned long tlb_addr

unsigned long tlb_size

}

言归正传,下面来看一下函数 board_init_f 的函数,其代码如下:


void board_init_f(ulong boot_flags)

{

 gd->flags = boot_flags;

 gd->have_console = 0;

 if (initcall_run_list(init_sequence_f))

 hang();

}

这里有三个值得关注的地方,一是设置了gd两个成员的值,二是执行了一个 initcall_run_list 的函数,第三是 hang() 是一个死循环的函数,用于造成CPU空转。

首先先更新一下gd的内容:


unsigned long flags = 0

unsigned long have_console = 0

接下来看看位于 /uboot-root/lib/initcall.c 中的initcall_runlist()的代码:


int initcall_run_list(const init_fnc_t init_sequence[])

{

 const init_fnc_t *init_fnc_ptr;

 for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {

 unsigned long reloc_ofs = 0;

 if (gd->flags & GD_FLG_RELOC)

 reloc_ofs = gd->reloc_off;

 debug("initcall: %p\n", (char *)*init_fnc_ptr - reloc_ofs);

 if ((*init_fnc_ptr)()) {

 printf("initcall sequence %p failed at call %p\n",

 init_sequence,

 (char *)*init_fnc_ptr - reloc_ofs);

 return -1;

 }

 }

 return 0;

}

在这段代码中,由于 gd->flags 的值为0,因此条件判断if (gd->flags & GD_FLG_RELOC)不成立。那么,该函数的作用就是不断地调用参数init_sequence[]中的函数。init_sequence[]是一个存放函数指针的数组,其实参为位于/uboot-root/common/board_f.c中的init_sequence_f[]。其内容如下:


static init_fnc_t init_sequence_f[] = {

 setup_mon_len,

 setup_fdt,

 trace_early_init,

 arch_cpu_init, /* basic arch cpu dependent setup */

 mark_bootstage,

 board_early_init_f,

 env_init, /* initialize environment */

 init_baud_rate, /* initialze baudrate settings */

 serial_init, /* serial communications setup */

 console_init_f, /* stage 1 init of console */

 display_options, /* say that we are here */

 display_text_info, /* show debugging info if required */

 print_cpuinfo, /* display cpu info (and speed) */

 init_func_i2c,

 announce_dram_init,

 /*

 * Now that we have DRAM mapped and working, we can

 * relocate the code and continue running from DRAM.

 *

 * Reserve memory at end of RAM for (top down in that order):

 * - area that won't get touched by U-Boot and Linux (optional)

 * - kernel log buffer

 * - protected RAM

 * - LCD framebuffer

 * - monitor code

 * - board info struct

 */

 setup_dest_addr,

 reserve_round_4k,

 reserve_mmu,

 reserve_trace,

 reserve_uboot,

 reserve_malloc,

 reserve_board,

 setup_machine,

 reserve_global_data,

 reserve_fdt,

 reserve_stacks,

 setup_dram_config,

 show_dram_config,

 display_new_sp,

 reloc_fdt,

 setup_reloc,

 NULL,

};

由于篇幅问题,本小节暂告一段落。之后会继续分析init_sequence[]中每一个函数的作用。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值