[uboot] (番外篇)global_data介绍

本文介绍了U-Boot中的global_data,用于在只读存储器运行时传递数据。内容包括global_data的功能、数据结构、存放位置及获取方式,详细讲解了其在内存中的布局和使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以下例子都以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

typedef struct global_data {
    bd_t *bd;
    unsigned long flags;
    unsigned int baudrate;
    unsigned long cpu_clk;  /* CPU clock in Hz!     */
    unsigned long bus_clk;
    /* We cannot bracket this with CONFIG_PCI due to mpc5xxx */
    unsigned long pci_clk;
    unsigned long mem_clk;
    unsigned long have_console; /* serial_init() was called */
    unsigned long env_addr; /* Address  of Environment struct */
    unsigned long env_valid;    
<think>嗯,用户之前已经问过关于U-Boot中gd->fdt_blob参数的问题,现在他们想进一步了解global_data结构体及其成员的作用。这说明用户可能在进行U-Boot的移植、调试或开发工作,需要深入理解U-Boot的内部机制。 首先,我需要确认用户对U-Boot的基础知识是否了解。考虑到他们之前的问题,可能已经有一定的背景,但可能需要更详细的解释。用户可能是嵌入式系统开发者或爱好者,正在处理与启动流程、设备树或硬件初始化相关的问题。 接下来,我需要整理global_data结构体的相关信息。这个结构体在U-Boot中非常重要,存储了全局数据,包括启动参数、设备树信息、内存布局等。需要逐一介绍主要成员,比如fdt_blob、baudrate、env_addr、ram_top等,并解释它们的作用。 还要注意用户之前的问题中提到的系统级指令,比如使用正确的LaTeX格式和中文回答。需要确保回答结构清晰,分点说明,可能还需要代码示例来辅助解释。 用户可能想知道每个成员的具体用途,以及它们如何影响U-Boot的运行流程。例如,env_addr指向环境变量的存储位置,relocaddr与重定位相关,ram_top表示可用内存的顶部。这些信息对调试和配置U-Boot非常有帮助。 此外,需要强调global_data在不同架构中的差异,以及如何访问这些成员(比如通过gd指针)。可能还需要提到实际应用中的例子,如设备树操作或环境变量处理,以帮助用户更好地理解。 最后,总结部分要突出global_data的重要性,并提醒用户在实际开发中需要注意的问题,比如内存覆盖和地址有效性。这些细节能帮助用户避免常见错误,提升他们的开发效率。</think>在 U-Boot 中,`global_data`(简称 **gd**)是一个全局数据结构体,用于存储系统运行时的核心数据和状态。它贯穿整个 U-Boot 生命周期,是**硬件抽象层**与**软件功能模块**之间的桥梁。以下是详细解析: --- ### 一、**`global_data` 的定位** - **存储位置** 在大多数架构中,`gd` 的指针会被保存在寄存器中(如 ARM 的 `r9` 或 `r18`),确保全局快速访问。 - **生命周期** 从 U-Boot 初始化开始,到操作系统内核启动后销毁,全程有效。 - **核心作用** 统一管理硬件配置、启动参数、内存布局、设备树、环境变量等关键信息。 --- ### 二、**`global_data` 结构体成员详解** 以下是常见成员及其作用(不同架构可能略有差异): #### 1. **基础配置** - **`void *fdt_blob`** 指向**设备树二进制(DTB)**在内存中的地址,用于解析硬件配置(如[前一问题](link)所述)。 - **`unsigned long baudrate`** 串口波特率,决定 U-Boot 控制台的通信速率(例如 `115200`)。 #### 2. **内存管理** - **`ulong ram_size`** 系统物理内存总大小(单位:字节)。 - **`ulong ram_top`** 可用内存的顶部地址,用于动态内存分配(如 `malloc`)。 - **`ulong relocaddr`** U-Boot 自身重定位后的基地址(在支持重定位的系统中使用)。 #### 3. **启动参数** - **`boot_params *bd`** 指向 `boot_params` 结构体,存储启动参数(如内核地址、根文件系统类型等)。 - **`char *env_addr`** 环境变量存储区的起始地址(例如 Flash 或内存中的位置)。 #### 4. **硬件状态** - **`unsigned long cpu_clk`** CPU 主频(单位:Hz)。 - **`unsigned long bus_clk`** 总线时钟频率(单位:Hz)。 - **`int arch_number`** 硬件平台 ID(用于 Linux 内核匹配机器类型,如 ARM 的 `MACH_TYPE`)。 #### 5. **运行时状态** - **`unsigned long flags`** 状态标志位,例如 `GD_FLG_RELOC` 表示 U-Boot 已完成重定位。 - **`struct device *cur_serial_dev`** 当前使用的串口设备指针,用于控制台输出。 #### 6. **设备与驱动** - **`struct udevice *dm_root`** 设备模型(Driver Model)的根设备节点。 - **`struct list_head uclass_root`** 设备类链表的头部,管理所有已注册的设备类。 --- ### 三、**关键成员的实际应用** #### 1. **访问 `gd` 的宏定义** 代码中通常通过宏 `DECLARE_GLOBAL_DATA_PTR` 声明 `gd` 指针: ```c DECLARE_GLOBAL_DATA_PTR; // 声明 gd 指针 printf("Baudrate: %lu\n", gd->baudrate); // 访问成员 ``` #### 2. **设备树操作** 通过 `gd->fdt_blob` 解析硬件信息: ```c int node = fdt_path_offset(gd->fdt_blob, "/soc/uart"); const char *name = fdt_getprop(gd->fdt_blob, node, "compatible", NULL); ``` #### 3. **环境变量处理** 读写环境变量存储区: ```c char *env = (char *)gd->env_addr; if (env != NULL) { printf("Environment starts at 0x%p\n", env); } ``` --- ### 四、**典型初始化流程** 1. **早期初始化** 在 `board_init_f()` 中初始化 `gd` 的基础成员(如 `ram_size`)。 2. **重定位** 将 U-Boot 自身代码和数据重定位到新地址,更新 `gd->relocaddr`。 3. **设备树加载** 从存储介质加载 DTB 到内存,赋值 `gd->fdt_blob`。 4. **驱动探测** 通过 `gd->dm_root` 遍历并初始化所有设备驱动。 --- ### 五、**调试与注意事项** - **查看 `gd` 内容** 使用 U-Boot 命令 `bdinfo` 可打印 `gd` 的部分成员(如内存布局、时钟频率)。 - **内存保护** 确保 `gd` 指向的内存区域不被意外覆盖(尤其是在动态内存分配时)。 - **架构差异** 不同 CPU 架构(ARM、RISC-V、MIPS)的 `gd` 成员可能扩展不同字段。 --- ### 六、**代码片段示例** ```c // 在 board_init_f() 中初始化 gd int board_init_f(void) { gd->ram_size = PHYS_SDRAM_SIZE; // 设置内存大小 gd->flags |= GD_FLG_RELOC; // 标记重定位状态 return 0; } ``` --- ### 总结 `global_data` 是 U-Boot 的“全局数据中心”,其成员涵盖了从硬件配置到运行时状态的所有关键信息。理解其结构对以下场景至关重要: 1. **移植 U-Boot** 到新硬件平台。 2. **调试启动故障**(如内存分配错误)。 3. **扩展自定义功能**(如添加新设备驱动或启动参数)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值