以下例子都以project X项目tiny210(s5pv210平台,armv7架构)为例
[uboot] uboot流程系列:
[project X] tiny210(s5pv210)上电启动流程(BL0-BL2)
[uboot] (第一章)uboot流程——概述
[uboot] (第二章)uboot流程——uboot-spl编译流程
===================================================================================
一、global_data功能
1、global_data存在的意义
在某些情况下,uboot是在某些只读存储器上运行,比如ROM、nor flash等等。
在uboot被重定向到RAM(可读可写)之前,我们都无法写入数据,更无法通过全局变量来传递数据。
而global_data则是为了解决这个问题。
这里顺便一下,后续的uboot的relocation操作,也就是uboot的重定向操作,最主要的目的也是为了解决这个问题,后续会专门说明。
2、 global_data简单介绍
global_data又称之为GD.
简单地说,uboot把global_data放在RAM区,并且使用global_data来存储全局数据。由此来解决上述场景中无法使用全局变量的问题。
二、global_data数据结构
1、数据结构说明
global_data数据结构结构体定义为struct global_data,被typedef为gd_t。
也就是说可以直接通过struct global_data或者gd_t来进行声明。
struct global_data定义如下(过滤掉一些被宏定义包含的部分):
include/asm-generic/global_data.h
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
2、成员说明
- 重点说明
- bd_t *bd:board info数据结构定义,位于文件 include/asm-arm/u-boot.h定义,主要是保存开发板的相关参数。
- unsigned long env_addr:环境变量的地址。
- unsigned long ram_top:RAM空间的顶端地址
- unsigned long relocaddr:UBOOT重定向后地址
- phys_size_t ram_size:物理ram的size
- unsigned long irq_sp:中断的堆栈地址
- unsigned long start_addr_sp:堆栈地址
- unsigned long reloc_off:uboot的relocation的偏移
- struct global_data *new_gd:重定向后的struct global_data结构体
- const void *fdt_blob:我们设备的dtb地址
- void *new_fdt:relocation之后的dtb地址
- unsigned long fdt_size:dtb的长度
- struct udevice *cur_serial_dev:当前使用的串口设备。
其他成员在后续时候到的时候在进行说明。
三、global_data存放位置以及如何获取其地址
1、global_data区域设置代码
(1)首先参考一下分配global_data的代码。
common/init/board_init.c
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
(2)然后看一下初始化global_data区域的代码。
common/init/board_init.c
去除无关代码的部分
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
(3)arm平台如何分配global_data区域,并保存其地址。
代码如下,去除掉被宏定义包含的无关代码部分
arch/arm/lib/crt0.S
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
注意:最终global_data的地址存放在r9中了。
2、global_data内存分布
内存分布如下:
———————-CONFIG_SYS_LOAD_ADDR —————————–高地址
…………………………….. early malloc 内存池
————————-early malloc 内存池基地址 —————————
………………………………… global_data区域
—————-global_data基地址(r9), 也是堆栈的起始地址————-
………………………………………堆栈空间
————————————–堆栈结束—————————————-低地址
注意:最终global_data的地址存放在r9中了。
四、global_data使用方式
1、原理说明
前面我们一直强调了global_data的地址存放在r9中了。
所以当我们需要global_data的时候,直接从r9寄存器中获取其地址即可。
uboot中定义了一个宏DECLARE_GLOBAL_DATA_PTR,使我们可以更加简单地获取global_data。
定义如下:
arch/arm/include/asm/global_data.h
- 1
DECLARE_GLOBAL_DATA_PTR定义了gd_t *gd,并且其地址是r9中的值。
一旦使用了DECLARE_GLOBAL_DATA_PTR声明之后,后续就可以直接使用gd变量,也就是global_data了。
2、使用示例
DECLARE_GLOBAL_DATA_PTR定义了gd_t *gd,并且其地址是r9中的值。
一旦使用了DECLARE_GLOBAL_DATA_PTR声明之后,后续就可以直接使用gd变量,也就是global_data了。
简单例子如下:
common/board_r.c
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
global_data相对比较简单,也就不多说了。