博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
uboot重定位后初始化
阅读量:4056 次
发布时间:2019-05-25

本文共 5585 字,大约阅读时间需要 18 分钟。

本文接博文《uboot启动之第一次运行C函数到uboot重定位》,从relocate_done处开始。

relocate_done之后,就是跳转到lr处执行。

这个lr在relocate_code之前就设置好了,为uboot/arch/arm/lib/crt0.S中的here:

114行使用bl跳转到c_runtime_cpu_setup,这样就吧116行指令地址传给了lr寄存器(r14)。

c_runtime_cpu_setup定义在uboot/arch/arm/cpu/arm1176/start.S:

247行直接将lr给了pc,于是程序就回到了uboot/arch/arm/lib/crt0.S中的116行。

116-124行,就是将__bss_start  -  __bss_end这一段内存清零。

126行跳转到coloured_LED_init, 这个C函数定义在uboot/common/board_f.c中。

uboot/common/board_f.c:

这是个空函数。返回后,程序来到127行,跳转到red_led_on。

和coloured_LED_init一样,这也是个空函数。定义在uboot/common/board_f.c

程序返回uboot/arch/arm/lib/crt0.S继续执行。

130行,r8保存的是relocate之后的gd的地址。

131行r1为uboot image relocate之后的地址。

133行,将PC指向board_init_r,即下一条指令就是运行board_init_r,有两个参数r0和r1,

r0为新gd地址, r1为image的新地址。

board_init_r定义在uboot/common/board_r.c中。

uboot/common/board_r.c

925行循环调用init_sequence_r list中的函数。

initr_reloc:

设置relocate flags,mark boot stage为uboot_r.

initr_caches:

使能指令和数据cache.

uboot/arch/arm/cpu/astcommon/cache.c(CONFIG_SYS_ICACHE_OFF未定义,但是CONFIG_SYS_DCACHE_OFF定义了,故这里只有icache_enable做了)

uboot/arch/arm/lib/cache_cp15.c

board_init:

板子初始化,定义在uboot/board/ast2500evb/ast2500evb.c

97行使能icache多余,前面已经做过了。之后,配置GPIO寄存器。

105行disable watch dog.

initr_reloc_global_data:

 

只是记录下uboot image size。

CONFIG_SYS_SYM_OFFSETS在uboot/include/asm-generic/sections.h

initr_serial:

初始化串口。

271行调用serial_assign,设置当前串口UART为ns16550 COM5.

initr_malloc:

初始化malloc zone为uboot image前面的128K, 并初始化为0.

uboot/common/dlmalloc.c

power_init_board:

ast2500evb没有这个函数,使用uboot/common/board_r.c中默认的。

initr_flash:

初始化flash.

首先向串口打印”Flash: ”, 然后调用board_flash_wp_on. ast2500evb使用默认的__board_flash_wp_on,返回0.

故直接进入了flash_init(), 该函数定义在uboot/drivers/spiflash/spiflash.c

flash_init调用SPI_CTRL_DIRVER_INIT()去初始化spi driver. SPI_CTRL_DRIVER_INIT定义在uboot/arch/arm/cpu/astcommon/ast_spiflash.c

SPI_CTRL_DRIVER_INIT做两件事:

  1. 调用ast_spiflash_init()去配置Firmware spi Memory Controller(FMC, 基址0x1E620000)。

  1. 调用register_spi_ctrl_driver()注册驱动到spi_ctrl_drvs_list.

之后,flash_init通过register_spi_chip_driver()注册各种不同spi chip(芯片)的驱动, 比如atmel, m25pxx, spansion, micron等。

并清空flash_info.( CONFIG_SYS_MAX_FLASH_BANKS为5,定义在uboot/include/configs/ast.cfg)

然后调用probe_spi_chips去探测系统中存在的spi存储芯片。

我们的系统中使用的是美光Micron N25Q00A存储芯片,我们来看一下micron_init()时注册的probe函数:micron_probe()

uboot/drivers/spiflash/micron.c

micron_probe() 调用  spi_generic_probe()去探测芯片。

spi_generic_probe打开write enable, 写入spi_read命令来读取前3个字节的设备数据。

然后用这3个字节的设备数据去匹配已知的设备list,来确定是哪个设备。

uboot/dribers/spiflash/generic.c

这里的ctrl_drv->spi_transfer()为uboot/arch/arm/cpu/astcommon/ast_spiflash.c中的ast_spiflash_transfer().

uboot/arch/arm/cpu/astcommon/ast_spiflash.c

spi_generic_probe得知是什么micron芯片后,设置IO read/write模式到ctrl_drv->fast_read/ctrl_drv->fast_write,并将flash chip信息拷贝到出参chip_info, 最后通过串口打印部分芯片信息。

这里printk() -> printf(), printf()在uboot/common/console.c中,它将调用puts() -> putc()将信息向串口ns16550 COM5输出。

initr_mmc:

先向串口输出“MMC:     ”,然后调用mmc_initialize()。

uboot/drivers/mmc/mmc.c

对于ast2500evb,board_mmc_init未定义,使用默认的,返回-1,cpu_mmc_init()就是去配置sd寄存器。

uboot/arch/arm/cpu/astcommon/ast_mmc.c

initr

_env:

初始化环境变量env,我们在uboot relocate之前,也初始化了一个default ENV(uboot/common/board_f.c),并保存到gd->env_addr。现在relocate之后,我们要使用特定的ENV,不使用default ENV。这个特定的ENV是烧写在flash上的,即地址0x20040000(512M).

init_env() -> env_relocate()

uboot/common/board_r.c

uboot/common/env_common.c

由于在uboot image relocate之前设置了default ENV,这个gd->env_valid被设置为1了,故env_relocate() 调用env_relocate_spec(). Env_relocate_spec()从flash ENV烧写地址0x20040000处读取环境变量,然后import()。

uboot/common/env_spi.c

flash_read()最终通过调用micron驱动read来读取micron flash上的ENV数据。

从flash上读取的ENV数据存放在buf中,然后调用env_import()进一步处理。

uboot/common/env_common.c

env_import()在himport_r()是会从malloc区申请一块内存来存放ENV数据,在190行由gd->env_addr来指向。

这里使用的malloc函数在uboot/include/malloc.h定义:

uboot/include/malloc.h

uboot/common/dlmalloc.c

stdio_init:

stdio设置。

uboot/common/stdio.c

drv_system_init()注册两个stdio设备: serial 和 nulldev.

serial_stdio_init()将之前的ns16550 COM5设备注册未stdio设备。

uboot/drivers/serial/serial.c

console_init_r:

控制台初始化,将之前配置的stdio devices之一设置为stdin, stdout, stderr设备。

uboot/common/console.c

779行获取之前通过stdio_register()注册的stdio设备,如下:

uboot/common/stdio.c

797-808行便利stdio device list找出第一个可input&output的device,从之前的stdio_init()看,第一个设备为serial,这里找到的肯定就是这个设备。

812行将找到的设备serial设置为stdout/stderr设备。

822行将找到的设备serial设置为stdin设备。

uboot/common/console.c

834行设置三个env变量:stdin, stdout, stderr,值均为找到设备serial.

uboot/common/stdio.c

misc_init_r:

通过配置SCU和LPC寄存器来控制各种设备。

uboot/board/ast2500evb/ast2500evb.c

initr_enable_interrupts:

enable中断。

uboot/common/board_r.c

enable_interruptes()通过配置cprs寄存器来enable中断。

uboot/arch/arm/lib/interrupts.c

61行将bit7清零。

62行将temp设置为cpsr_c(cpsr的低8bits), 由于61行将bit7(I)清零,故这里就enable IRQ了。

initr_ethaddr:

从环境变量中

拿出ethaddr地址(MAC地址)。

uboot/common/board_r.c

initr_net:

初始化net。

uboot/common/board_r.c

605行先向串口ns16550 COM5输出”Net:         ”, 然后调用eth_initialize();

uboot/net/eth.c

eth_initialize()在316行调用cpu_eth_init去初始化eth,在333行将该设备的name向串口输出,344行去从ENV变量中取出ethxaddr=<MAC>, 并将MAC地址写入eth设备(x表示eth的index,比如eth1, eth2…, 如果是eth0,则为ethaddr=<MAC>).

我们来看一下cpu_eth_init().

uboot/arch/arm/cpu/astcommon/ast_eth.c

ast_eth_initialize()主要是配置SCU相关寄存器以配置eth。然后申请eth_device内存,并通过eth_register注册上去。最后enable MII管脚,注册miiphy.

uboot/net/eth.c

run_main_loop:

uboot/common/board_r.c

uboot/common/main.c

process_boot_delay(),处理auto boot kernel之前的delay时间,如果delay时间内,用户输入任意键,则auto boot kernel停止,进入和用户的交互程序。

387行,在我的环境上, bootdelay=3。

417行,获取环境变量bootcmd的值。

441行,打印输出”DRAM ECC disabled”。

444行,调用abortboot() -> abortboot_normal()。

225行,打印提示”Hit key ‘b’ or ‘B’ to stop autoboot: 3 ”.

234行,测试控制台console的stdin是否有输入,如果有输入,则236行获取该输入的字符。

247-271行,每1s检查一次是否console的stdin有输入,有则停止auto boot;否则每过1s打印一下剩余bootdelay时间。

如果在这期间,我们中断了auto boot,则uboot进入交互式cli界面了,可以使用uboot提供的cli命令。

转载地址:http://gvlci.baihongyu.com/

你可能感兴趣的文章
通过C++反射实现C++与任意脚本(lua、js等)的交互(二)
查看>>
利用清华镜像站解决pip超时问题
查看>>
微信小程序开发全线记录
查看>>
CCF 分蛋糕
查看>>
解决python2.7中UnicodeEncodeError
查看>>
小谈python 输出
查看>>
Django objects.all()、objects.get()与objects.filter()之间的区别介绍
查看>>
python:如何将excel文件转化成CSV格式
查看>>
机器学习实战之决策树(一)
查看>>
机器学习实战之决策树二
查看>>
[LeetCode By Python]7 Reverse Integer
查看>>
[LeetCode By Python]121. Best Time to Buy and Sell Stock
查看>>
[LeetCode By Python]136. Single Number
查看>>
Android/Linux 内存监视
查看>>
Android2.1消息应用(Messaging)源码学习笔记
查看>>
计算机网络复习要点
查看>>
Variable property attributes or Modifiers in iOS
查看>>
NSNotificationCenter 用法总结
查看>>
C primer plus 基础总结(一)
查看>>
剑指offer算法题分析与整理(三)
查看>>