uboot启动流程

自我要求:

  1. 熟悉uboot启动流程
  2. cmd命令执行过程(能添加一个命令:显示产品信息)
  3. 熟悉uboot的flash读写指令过程
  4. 熟悉引导内核的过程
  5. 另外看看lds链接脚本,重定位的用处

https://pan.baidu.com/s/14aZPVbq5c1LRq-x2qVLkFA 提取码: h7ai

flash读写指令过程:
sf.c
最底下注册了U_BOOT_CMD(sf, 5, 1, do_spi_flash,…
)
do_spi_flash函数可以进行读写flash指令
如果要读flash到某个地址
do_spi_flash() // sf.c
do_spi_flash_probe()
spi_flash_probe() //注册
do_spi_flash_read_write() // sf.c
spi_flash_read() //spi_flash.h
flash->read() //需要知道在哪注册了这个函数
spi_flash_scan() //可能在这注册的spi_flash.c(不对)
flash->read = spi_flash_cmd_read_ops; // spi_flash.c
if(flash->memory_map)
spi_xfer(spi, 0, NULL, NULL, SPI_XFER_MMAP);
spi_flash_copy_mmap(data, flash->memory_map + offset, len);
spi_xfer(spi, 0, NULL, NULL, SPI_XFER_MMAP_END);
spi_release_bus(spi);
//感觉应该是如果结构体flash中存放了flash的地址,就用这样的方式去里面读取flash的数据。
spi_flash_read_common()//不然就用这样的方法
spi_flash_cmd_read //sf.c
spi_flash_read_write //sf.c
spi_xfer //sf.c

spi_flash_probe() //在这注册的 hisi_spi_nor.c
hifmc100_spi_nor_probe()//hifmc100.c
hifmc100_spi_nor_scan()//hifmc100.c
spi_nor_flash->read = hifmc100_dma_read //在这注册的
hifmc100_dma_transfer()

Uboot命令执行过程;
执行前,命令初始化方法:
command.h中定义了cmd_tbl_s结构体,
每个命令行,在.C文件中定义U_BOOT_CMD,就是注册了一个这样的结构体。

执行:
run_command()函数
解析参数
find_cmd函数
作用:__uboot_cmd_start开始根据第一个参数寻找uboot_cmd_stop,找到名字相同的cmd_tbl_t结构体,并返回。
最后就是执行找到的这个结构体中的执行动作函数,就是do_xxx函数

增加了一个uboot命令的方法:
在cmd文件夹下面添加一个mycmd.c
编写一个U_BOOT_CMD结构体,里面包含了命令名字,函数名do_mycmd等参数
接着再写do_mycmd函数的内容。
在include/config目录下hifm.h中#define CONFIG_CMD_MYCMD
再cmd文件夹下面的makefile里面obj-$(CONFIG_CMD_MYCMD) += sf.o

Uboot启动流程:
从arch/arm/cpu/armv7/start.S开始,(因为一般程序都是从0地址开始的,所以用链接脚本lds去看0地址放的东西,比较方便看得到启动的第一段程序)
在此处应该是设置中断向量表,
_start会跳转到start_code处(还是汇编)
CPU进入管理模式,关看门狗,关中断,设置时钟频率,关闭mmu
.然后进入第一个C函数:
board_init_f()初始化一个序列,序列里面包含了初始化函数
初始化定时器,GPIO,串口等,划分内存区域,初始化 gd 的各个成员变量, uboot 会将自己重定位到 DRAM 最后面的地址区域,也就是将自己拷贝到 DRAM 最后面的内存区域中。这么做的目的是给 Linux 腾出空间,防止 Linuxkernel 覆盖掉 uboot,将 DRAM 前面的区域完整的空出来

重定位 复制uboot,然后修改SDRAM上的uboot链接地址进入 board_init_r()函数 再初始化各种复杂的外设
run_main_loop()
for (;😉
main_loop();
return 0;
autoboot_command(s)//进行倒计时,如果没有输入则执行
run_command_list,此函数会执行参数 s 指定的一系列命令,也就是环境变量 bootcmd 的命令,bootcmd 里面保存着默认的启动命令,因此 linux 内核启动
否则向下执行到cli_loop();进行命令控制台的程序
先进行解析,然后cmd_process()执行命令,会去具体的列表cmd_tbl_t中找到对应的命令名字。
在编译链接的时候,应该是根据传入的产生确认了编译哪个start.S,后面的board_init_f函数都是在board/cpu/具体的芯片名/board.c中定义的,所以能确认只编译这么一个board_init_f函数,其他的函数也是一样的。
在汇编start.S

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值