u-boot第二阶段分析(一)
来源:互联网 发布:大闹天宫数据库修改 编辑:程序博客网 时间:2024/05/16 14:15
start_armboot函数的引入
注:本次分析的u-boot是九鼎官方的u-boot代码
下载地址:链接:http://pan.baidu.com/s/1gfpDZqj 密码:7cqe
一 start_armboot函数简介
start_armboot函数是一个长函数,在uboot/lib_arm/board.c的第444——908行,其中也调用了其他函数,共同构成了u-boot的第二阶段。
1.第二阶段的主要工作
我们之前已经分析过了第一阶段,主要是初始化了Soc内部的一些部件和初始化了DDR以及重定位,第二部分主要是初始化Soc外部的一些硬件设施(第一阶段没有初始化完生下来的)。
2.整个u-boot在什么地方结束
u-boot的目标是启动内核,我们在启动u-boot时,最后会出现倒数启动内核时间,如果用户没有干涉则会执行bootcmd进入自动启动内核流程;此时用户可以按下回车键打断uboot的自动启动进入u-boot的命令行下。
u-boot的命令行实际上是一个死循环,代码如下:
for (;;) { main_loop (); }
循环体内不断重复:接收命令、解析命令、执行命令。
接下来进行函数代码的分析;
二 变量的定义和初始化
1.init_fnc_t
代码为:init_fnc_t **init_fnc_ptr
其中init_fnc_ptr是一个二重指针,在c语言中二重指针有两个作用:一个是指向一个一重指针;第二个是指向一个指正数组,这里的init_fuc_ptr可以用来指向一个函数指针数组。
我们可以找到它的声明,typedef int (init_fnc_t) (void),这是一个函数类型。
2.DECLARE_GLOBAL_DATA_PTR
在变量的初始化过程中常见到“gd”和“bd”,那么是哪里来的呢?
在大部分的.c文件中,都有DECLARE_GLOBAL_DATA_PTR这个宏,这个宏的定义如下:
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")
定义了一个全局变量名字叫gd,这个全局变量是一个指针类型,占4字节。用volatile修饰表示可变的,用register修饰表示这个变量要尽量放到寄存器中,后面的asm(“r8”)是gcc支持的一种语法,意思就是要把gd放到寄存器r8中。
简而言之,DECLARE_GLOBAL_DATA_PTR就是定义了一个要放在寄存器r8中的全局变量,名字叫gd,类型是一个指向gd_t类型变量的指针。
(1)为什么要用register修饰?
因为这个全局变量gd(global data的简称)是uboot中很重要的一个全局变量(准确的说这个全局变量是一个结构体,里面有很多内容,这些内容加起来构成的结构体就是uboot中常用的所有的全局变量),这个gd在程序中经常被访问,因此放在register中提升效率。
(2)gd是一个结构体指针,这个结构体的定义如下:
typedef struct global_data { bd_t *bd; unsigned long flags;/*标志位*/ unsigned long baudrate; /控制台的波特率/ unsigned long have_console; /* 只有一位(bool类型),判断有没有concole(控制台)*/ unsigned long reloc_off; /* 重定位偏移量 */ unsigned long env_addr; /* Address of Environment struct */ unsigned long env_valid; /* Checksum of Environment valid? */ unsigned long fb_base; /* base address of frame buffer */#ifdef CONFIG_VFD unsigned char vfd_type; /* display type */#endif#if 0 unsigned long cpu_clk; /* CPU clock in Hz! */ unsigned long bus_clk; phys_size_t ram_size; /* RAM size */ unsigned long reset_status; /* reset status register at boot */#endif void **jt; /* jump table */} gd_t;
其中bd是一个bd_t类型的指针,指向的也是一个结构体,这个结构体里定义了开发板的板级信息,里面有不少硬件相关的参数,譬如波特率、IP地址、机器码、DDR内存分布。
代码如下:
typedef struct bd_info { int bi_baudrate; /* serial console baudrate */ unsigned long bi_ip_addr; /* IP Address */ unsigned char bi_enetaddr[6]; /* Ethernet adress */ struct environment_s *bi_env; ulong bi_arch_number; /* unique id for this board */ ulong bi_boot_params; /* where this board expects params */ struct /* RAM configuration */ { ulong start; ulong size; } bi_dram[CONFIG_NR_DRAM_BANKS];#ifdef CONFIG_HAS_ETH1 /* second onboard ethernet port */ unsigned char bi_enet1addr[6];#endif} bd_t;
三 内存排布
1.上一节定义了gd和bd这两个结构体指针,但是并没有分配内存,也就是说这两个指针还是野指针,下面就开始为它们分配内存。
注:u-boot还是裸机程序,所以没有操作系统管理内存,所以也就没法使用malloc等函数。
#ifdef CONFIG_MEMORY_UPPER_CODE /* by scsuh */ ulong gd_base; gd_base = CFG_UBOOT_BASE + CFG_UBOOT_SIZE - CFG_MALLOC_LEN - CFG_STACK_SIZE - sizeof(gd_t);#ifdef CONFIG_USE_IRQ gd_base -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ);#endif gd = (gd_t*)gd_base;#else gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));#endif
代码分析:
首先定义了一个ulong类型的变量gd_base,然后对其进行赋值,其中
CFG_UBOOT_BASE = 0x33e00000
CFG_UBOOT_SIZE = 2*1024*1024 = 2M
CFG_MALLOC_LEN = CFG_ENV_SIZE + 896*1024 = 912kb(分配的堆区大小)
CFG_STACK_SIZE = 512*1024 = 512kb
sizeof(gd_t) 大约36字节,算的时候可以忽略不计
所以gd_base的地址大约可以算出来,大约在0x33e00000网上624kb左右的位置处。
然后将gd指针给实例化:gd = (gd_t*)gd_base;
这是将gd_base指针强制类型转换为gd_t*类型。
2.内嵌汇编
/* compiler optimization barrier needed for GCC >= 3.4 */ __asm__ __volatile__("": : :"memory");
这行代码的作用是为了防止高版本的gcc的优化造成错误。
3.内存清零
memset ((void*)gd, 0, sizeof (gd_t));gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));memset (gd->bd, 0, sizeof (bd_t));
需要注意的是第二行代码中将指针gd强制类型转换为char*是因为指针相减的话,char减1就是减1,int减1就是减4。
- u-boot第二阶段分析(一)
- U-boot第二阶段分析
- U-boot第二阶段分析
- u-boot第二阶段分析(二)
- u-boot第二阶段分析(三)
- u-boot第二阶段分析(四)
- u-boot第二阶段分析(五)
- u-boot第二阶段源码分析
- U-boot第二阶段代码分析
- U-Boot 第二阶段代码分析
- U-Boot -第二阶段代码分析
- u-boot-1.1.6 源码分析(3)--第二阶段
- U-Boot启动过程源码分析(2)-第二阶段
- u-boot源码分析 --- 启动第二阶段001
- u-boot源码分析 --- 启动第二阶段002
- u-boot源码分析 --- 启动第二阶段003
- u-boot源码分析 --- 启动第二阶段004
- u-boot源码分析 --- 启动第二阶段005
- 流程的Python 第三章:字典和集合
- 定义一个ArrayList集合,存储一批书籍,书籍具有书名、作者、价格三个属性, 键盘录入一个书名时,显示该书籍的详细信息。
- Oracle之表的种类(heap,partition table,glable temp table,orgination index table,cluster sort hash table)
- mapreduce 统计流量
- spring之使用表达式定义切入点
- u-boot第二阶段分析(一)
- 判断IP合法性和纯数字合法性
- jqueryeasyui datagrid
- Vue.js学习系列六——Vue单元测试Karma+Mocha学习笔记
- (1) 初识birt(免费开源报表软件)-建立第一个birt report项目
- 日常linux使用笔记
- eclipse提交代码至GitHub
- 剑指offer--面试题3:数组中重复的数字
- Caffe在Ubuntu 14.04 64bit 下的安装------pycaffe 配置