my uboot学习笔记

一、U-boot分析与使用

启动内核需要u-boot能做些什么

关闭看门狗
初始化时钟
初始化sdram
串口初始化、收、发
生产时烧写flash(usb、网卡方式等)
读flash写入sdram

u-boot 如何编译安装

1、网上下载、解压缩u-boot

2、打补丁,
linux 下 patch -px < 补丁文件(x代表忽略掉补丁目录的几个/)

3、配置
make xxxx_config

4、编译
make

5、烧录到裸板
oflash u-boot.bin

u-boot 的makefile 分析

首先要make xxx_config

make xxx_config的时候执行这个命令
@$(MKCONFIG) $(@: __config=) arm arm920t 100ask24x0 NULL s3c24x0
相当于
mkconfig 100ask24x0 arm arm920t 100ask24x0 NULL s3c24x0

mkconfig 是一个脚本文件

(个人理解,mkconfig里面的命令,指定了接下来makefile编译哪些文件,从而可以选择性的来编译符合当前硬件的程序文件)

下面对mkconfig进行分析

分析命令里面传入的参数

在这里插入图片描述

确定BOARD_NAMR

在这里插入图片描述
如果没有定义BOARD_NAMR,就认为$1为BOARD_NAMR
在这里插入图片描述

参数个数校验

$#代表参数的个数。如果参数小于4个大于6个就退出脚本
在这里插入图片描述

串口打印文字

在这里插入图片描述

建立新的asm文件

在这里插入图片描述
建立链接文件 asm 指向 asm-arm

(个人理解,makefile会去asm读取文件来编译,这里删除了原先的asm,然后建立链接文件 asm 指向 asm-arm,相当于编译的时候,就选择了asm-arm目录的文件来编译,这个arm($2)就是xxxconfig指定的)

建立新的asm-arm/arch

在这里插入图片描述
执行ln -s arch-s3c24x0 asm-arm/arch

asm-arm/arch 指向arch-s3c24x0
在这里插入图片描述

建立新的asm-arm/proc

在这里插入图片描述

为 make 生成一个配置文件

在这里插入图片描述
这里的 > 代表生成新文件
这里的 >>代表追加到文件
相当于:
ARCH = arm
CPU = arm920t
BOARD = 100ask24x0

如果第5个参数存在且不为空的话。。。

如果第6个参数存在且不为空的话
SOC = S3C24X0

(个人理解,是将参数保存在这个文件内,然后接下来的make还会使用到这些参数)

创建一个单板相关的头文件

在这里插入图片描述

新建一个config.h文件
追加一个注释:自动生成不可修改
追加#include <configs/100ask24x0.h>

(个人理解,100ask24x0.h根据某种规范编写,有统一的接口,为代码一致性方便维护,u-boot内很多文件会包含config.h这个文件,只要更换config.h内的包含,就可以改变很多文件的编译结果)

makefile编译过程分析

编译过程会使用到配置过程中生成的config.mk

ARCH = arm
CPU = arm920t
BOARD = 100ask24x0
SOC = S3C24X0
在这里插入图片描述

定义OBJS、以及LIBS

在这里插入图片描述

在这里插入图片描述

(个人理解,从这一步makefile就可以根据配置文件来选择CPU的启动文件以及库文件)

u-boot的目标文件

在这里插入图片描述

u-boot要用到哪些文件

小技巧:只需要执行make命令,查看最后面的链接命令用到了哪些文件


链接命令需要连接 脚本 和 链接的原材料 。

分析编译需要分析哪几个文件

1、cpu/arm920t/Start.S
2、链接脚本board/100ask24x0/u-boot.lds
链接命令的 0x33f80000在board/100ask24x0/mkconfig内定义

u-boot源码分析

第一阶段: start.S,硬件相关初始化

设置cpu为管理模式
关看门狗
关中断

查看当前程序所在位置
如果还在片内内存中,那么说明刚上电,
程序还没有进行初始化以及重定位

初始化(主要是sdram)

设置栈

初始化时钟

重定位:把代码复制到链接脚本指定的位置

清除bss段

调用strat_armboot

第二阶段:start_armboot

flash_init 初始化 norflash
堆的实现,初始化
初始化nandflash
环境变量初始化

。。。

main_loop循环主任务

怎么启动内核

1、依赖于bootcmd的环境变量
s = getenv(“bootcmd”)
run_command(s)

2、u-boot 界面
readline 读入串口的数据

u-boot 的核心是命令

命令是怎么实现的
解析输入的字符串命令,并执行对应的程序

命令与函数对应关系由一个结构体来储存

struct cmd_tbl_s
{
//名称
//最大参数
//是否可重复
//函数指针(命令调用的函数)
//短的帮助信息
//长的帮助信息
}

链接脚本里面,有一个ubootcmd段

在这里插入图片描述

搜索u_boot_cmd得到
在这里插入图片描述
在这里插入图片描述
所有的U_BOOT_CMD段的代码,都会以 cmd_tbl_s结构体的形式被储存到U_BOOT_CMD段

怎么自己增加一个命令

1、自己新建一个helloworld.c 文件,放在common目录下面
2、复制其他cmd的C文件的头文件到helloworld.c 文件
3、新建一个函数 :
在这里插入图片描述
4、定义一个U_BOOT_CMD,

在这里插入图片描述
(个人理解,这个U_BOOT_CMD 定义之后,链接的时候就会把括号内的内容放入U_BOOT_CMD段,然后uboot下输入命令后就会查找到这个命令,执行do_hello)

5、把helloworld.c加入u-boot

修改common目录的makefile
,在makefile的objs依赖文件变量里加入helloworld.o

6、测试命令

在这里插入图片描述
由测试可知,argc 是指参数个数
argv[]储存的是命令字符串
克制

uboot怎么启动内核

uboot启动内核依赖两条代码:
在这里插入图片描述
查找bootcmd命令,得到:
在这里插入图片描述
这两条命令第一条从nandflash上面把内核读到0x30007fc0,
第二条 是从0x30007fc0启动内核

从nand读出内核,从哪里读

从kernel分区读取

嵌入式分区的概念

与pc的分区不同,flash没有分区
为了体现分区,只能在源码(100ask24x0.h)里把分区写死
在这里插入图片描述

第一条命令解析

JFF2是文件格式,不用管
nand read.jff2 xxx yyy
把nandflash的yyy地址数据读到xxx上

第二条命令 bootm 0x30007fc0解析

这条命令主要是从0x30007fc0启动内核。

这个0x30007fc0 ,可以在未使用的空间随便取值,因为:

flash上存的内核:分为头部+真正的内核

头部结构体如下:
在这里插入图片描述
主要存放这些参数,
其中ih_load 代表加载地址
ih_ep 代表入口地址

在使用bootm的时候,会在0x30007fc0地方读取内核头部。
然后会根据读取的头部,把内核移动到ih_load(加载地址),再从ih_ep(入口地址)启动内核

启动内核上一步要告诉内核一些启动参数,还有机器ID

如何告诉内核、、?
1、在某个地址,(0x30000100)
2、按照某个格式,(tag结构体的格式)
在这里插入图片描述
3、保存数据

怎么启动内核?

1、定义一个函数指针
在这里插入图片描述
2、设置thekernel为入口地址
在这里插入图片描述

3、运行thekernel,把启动参数放到栈中?
在这里插入图片描述

从零开始写bootloader

总体需要做什么

1、从flash把内核读入内存
2、启动

猜你喜欢

转载自blog.csdn.net/tiantangmoke/article/details/102692337
my