NanoPC-T2 Uboot启动过程分析 - 2-5 board_init_r() part 1

本文详细分析了NanoPC-T2在Uboot启动过程中board_init_r()的执行流程,包括init_sequence_r[]函数调用、串口初始化、环境变量加载等关键步骤,揭示了Uboot启动过程中的内存配置和寄存器状态变化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在继续分析之前,先回顾一下当前相关寄存器的值、内存空间的使用情况和相关变量的值的情况。


r0 = 0x42BF_FF60 @ &gd

r1 = 0x42C0_0000

r2 = 0x42BF_FF10 @ &sp

r9 = 0x42BF_FF60 @ &gd

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

sp = 0x42BF_FF10

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

RAM:

0xC000_0000

 -

0x5000_0000(RAM_TOP)

 -

0x4FFE_F800

 UBOOT(Reserve 478K)

0x4FF7_8000

 -

0x4FFF_4000

 TLB table

0x4FFF_0000

 -

0x4DF9_8000

 malloc(Reserve 32768K)

0x4DF7_8000

 Board Info(Reserve 80B) = gd->bd

0x4DF7_7FB0

 New GD

0x4DF7_7F10

 IRQ

0x4DF7_7F00(IRQ_SP)

 -

0x4DF7_7EF0

 -

0x4500_0000

 Heap

0x4300_0000

 -

0x42C8_C000

 Page

0x42C8_0000

 -

0x42C7_7988

 UBOOT

0x42C0_0000

 GD

0x42BF_FEB8

 BD Info

0x42BF_FE68(START_ADDR_SP)

 UBoot-Stack

0x4000_0000

gd内容:


bd_t *bd = 0x42BF_FF10

{

unsigned long bi_memstart = 0

phys_size_t bi_memsize = 0

unsigned long bi_flashstart = 0

unsigned long bi_flashsize = 0

unsigned long bi_flashoffset = 0

unsigned long bi_sramstart = 0

unsigned long bi_sramsize = 0

unsigned long bi_bootflags = 0

unsigned long bi_ip_addr = 0

unsigned char bi_enetaddr[6] = 0

unsigned short bi_ethspeed = 0

unsigned long bi_intfreq = 0

unsigned long bi_busfreq = 0

ulong bi_arch_number = 4330

ulong bi_boot_params = 0x4000_0100

struct bi_dram[1]

{

ulong start = 0x4000_0000

ulong size = 0x4000_0000

}

}

unsigned long flags = 0

unsigned int baudrate = 115200

unsigned long cpu_clk = 0

unsigned long bus_clk = 0

unsigned long pci_clk = 0

unsigned long mem_clk = 0

unsigned long have_console = 1

unsigned long env_addr = &default_environment[0]

unsigned long env_valid = 1

unsigned long ram_top = 0x5000_0000

unsigned long relocaddr = 0x4500_0000

phys_size_t ram_size = 0x1000_0000

unsigned long mon_len = 0x0007_7988

unsigned long irq_sp = 0x4DF7_7F00

unsigned long start_addr_sp = 0x42BF_FF10

unsigned long reloc_off = 0

struct global_data *new_gd = 0x4df7_7f10

const void *fdt_blob = 0

void *new_fdt = 0

unsigned long fdt_size = 0

void **jt = 0

char env_buf[32] = 0

unsigned long timebase_h = 0

unsigned long timebase_l = 0

struct arch_global_data arch

{

unsigned long timer_rate_hz = 0

unsigned long tbu = 0

unsigned long tbl = 0

unsigned long lastinc = 0

unsigned long long timer_reset_value = 0

unsigned long tlb_addr = 0x4fff_0000

unsigned long tlb_size = 0x0000_4000

}

现在继续分析,目前已经执行到 /uboot-root/arch/arm/cpu/slsiap/s5p4418/start.S 的第153行,代码如下所示:


    /* call board_init_r(gd_t *id, ulong dest_addr) */

    mov r0, r9 /* gd_t */

    ldr r1, =(CONFIG_SYS_MALLOC_END) /* dest_addr for malloc heap end */

    /* call board_init_r */

    ldr pc, =board_init_r /* this is auto-relocated! */

这里是为调用 board_init_r() 作参数准备。在调用到最后一句指令时,相关寄存器的值如下:


r0 = 0x42BF_FEB8 @ &gd

r1 = 0x4500_0000

r2 = 0x42BF_FF10 @ &sp

r9 = 0x42BF_FEB8 @ &gd

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

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

由于最后一句指令是使用 ldr 进行跳转,因此 lr 寄存器不受影响。board_init_r()位于 /uboot-root/common/board_r.c 中。其代码如下:


void board_init_r(gd_t *new_gd, ulong dest_addr)

{

 gd = new_gd;

 if (initcall_run_list(init_sequence_r))

 hang();

 /* NOTREACHED - run_main_loop() does not return */

 hang();

}

这里的重点还是在于 initcall_run_list()。与之前的 board_init_f()一样,这里也有一个函数指针数组 init_sequence_r[]。以下是它的内容:


init_fnc_t init_sequence_r[] = {

 initr_trace,

 initr_reloc,

 initr_caches,

 board_init, /* Setup chipselects */

 initr_reloc_global_data,

 initr_serial,

 initr_announce,

 initr_barrier,

 initr_malloc,

 bootstage_relocate,

 power_init_board,

 initr_mmc,

 initr_env,

 initr_secondary_cpu,

 stdio_init,

 initr_jumptable,

 console_init_r, /* fully init console as a device */

 arch_misc_init, /* miscellaneous arch-dependent init */

 interrupt_init,

 board_late_init,

 run_main_loop,

};

首先调用的是 initr_trace(),该函数什么东西都没做,忽略。

接下来调用的是 initr_reloc(),该函数更新了gd->flags和标识了一下UBoot所在的阶段。

接下来调用的是 initr_caches(),该函数什么都没做,忽略。

接下来调用的是位于 /uboot-root/board/s5p4418/nanopi2/board.c 中的 board_init(),这里主要是设置LCD的,不再详细展开。

接下来调用的是 initr_reloc_global_data(),该函数也是什么都没做,忽略。

接下来调用的是 initr_serial(),里面调用了位于/uboot-root/drivers/serial/serial.c中的serial_initialize()。在这个函数中,有很多个板子初始化串口的函数,但经过宏定义的过滤,真正有效的是里面的pl01x_serial_initialize(),以及最后一行的serial_assign()。代码如下所示:


void serial_initialize(void)

{

 pl01x_serial_initialize();

 serial_assign(default_serial_console()->name);

}

先看pl01x_serial_initialize(),代码如下所示:


void pl01x_serial_initialize(void)

{

 serial_register(&pl01x_serial_drv);

}

这里的serial_register()是一个注册过程,说白了就是维护一条链表。代码如下所示:


void serial_register(struct serial_device *dev)

{

 dev->next = serial_devices;

 serial_devices = dev;

}

serial_devices定义如下:


static struct serial_device *serial_devices;

由于这个指针到现在才出现,并未使用过,而且它属于在bss段里的,所以初始值为0,即为NULL。另外,分析注册过程可以得出serial_devices始终指向链表头。所以上面注册完后,该链表如下所示:


serial_devices = pl01x_serial_drv -> NULL

执行完注册过程后,又返回调用的serial_assign()。调用时以pl01x_serial_drv->name为参数,其代码如下:


int serial_assign(const char *name)

{

 struct serial_device *s;

 for (s = serial_devices; s; s = s->next) {

 if (strcmp(s->name, name))

 continue;

 serial_current = s;

 return 0;

 }

 return -EINVAL;

}

从代码可以看出,这里为变量serial_current赋值。该变量用于指示当前使用的输出串口设备,也有用于指定默认串口设备。

接下来调用的是 initr_announce(),这里只是输出一些调试信息。

接下来调用的是 initr_barrier(),该函数什么都没做,忽略。

接下来调用的是 initr_malloc()。这里主要是初始化位于0x4300_0000至0x4500_0000的堆空间为0。

接下来调用的是位于 /uboot-root/common/bootstage.c 中的bootstage_relocate()。这里只是初始化启动记录标志而已,与整体流程并没有大的影响,因此不详细展开。

接下来调用的是 power_init_board()。该函数什么都没做,忽略。

接下来调用的是 initr_mmc()。由于这里是初始化mmc设备的,具体与CPU设置有关,这里就不详细展开了。

接下来调用的是 initr_env()。这里是通过读取MMC将环境变量读取出来,并更新当前的环境变量。更新后的环境变量如下:


baudrate=115200

bloader=ext4load mmc 0:1

bootcmd=$bloader 0x48000000 $kernel;$bloader 0x49000000 root.img.gz;bootm 0x48000000

bootdelay=0

bootfile=uImage

ethaddr=00:e2:1c:ba:e8:60

firstboot=0

gatewayip=192.168.1.254

ipaddr=192.168.1.165

kernel=uImage

netmask=255.255.255.0

serverip=192.168.1.164

stderr=serial

stdin=serial

stdout=serial

接下来调用的是 initr_secondary_cpu()。该函数什么都没做,忽略。

由于篇幅原因,本节暂告一段落。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值