DECLARE_GLOBAL_DATA_PTR、gd_t、bd_t及uboot中 start_armboot 代码分析

2024-08-28 12:18

本文主要是介绍DECLARE_GLOBAL_DATA_PTR、gd_t、bd_t及uboot中 start_armboot 代码分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、Uboot中DECLARE_GLOBAL_DATA_PTR 只是一个定义的宏,这个宏定义了一个gd_t全局数据结构的指针,这个指针存放在指定的寄存器中(386体系结构没有放到指定寄存器中)。这个宏定义在\include\asm-arm\globe_data.h文件中
#define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm("r8")
声明一个寄存器变量 gd 占用r8。这个宏在所有需要引用全局数据指针gd_t *gd的源码中都有申明。

这个申明也避免编译器把r8分配给其它的变量. 所以gd就是r8,用r8来保存内存地址,达到全局使用目的,这个指针变量不占用内存。


二、gd_t和bd_t是u-boot中两个重要的数据结构,在初始化操作很多都要靠这两个数据结构来保存或传递.分别定义在./include/asm/global_data.h和./include/asm/u_boot.h
1.gd_t: global data数据结构定义,位于文件 include/asm-arm/global_data.h。其成员主要是一些全局的系统初始化参数。需要用到时用宏定义:DECLARE_GLOBAL_DATA_PTR,指定占用寄存器R8。

2.bd_t : board info数据结构定义,位于文件 include/asm-arm/u-boot.h。保存板子参数。


三、
#ifndef __ASM_GBL_DATA_H
#define __ASM_GBL_DATA_H
/*
* The following data structure is placed in some memory wich is
* available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
* some locked parts of the data cache) to allow for a minimum set of
* global variables during system initialization (until we have set
* up the memory controller so that we can use RAM).
*下面的数据结构在引导后放在内存里,在系统初始化期间给全局变量进行最小化设置。
* Keep it *SMALL* and remember to set CFG_GBL_DATA_SIZE > sizeof(gd_t) 保持简单且不要忘了使CFG_GBL_DATA_SIZE 大于gd_t的大小
*/


typedef struct global_data
{
bd_t  *bd;                                   //开发板相关参数,结构体变量,参考u-boot.h
unsigned long flags;                     //指示标志,如设备已经初始化标志等
unsigned long baudrate;               //串行口通讯速率
unsigned long have_console;       /* serial_init() was called console_init()中使用控制台*/
unsigned long reloc_off;             /* Relocation Offset 重定位偏移,就是实际定向的位置与编译连接时
                                                    指定的位置之差,一般为0 */
unsigned longenv_addr;              /* Address of Environment struct 环境参数地址*/
unsigned longenv_valid;             /* Checksum of Environment valid? 环境参数CRC检验有效标志*/
unsigned longfb_base;                /* base address of frame buffer 帧缓冲区基地址*/

#ifdef CONFIG_VFD
unsigned charvfd_type;              /* display type 显示类型*/
#endif

#if  0     
unsigned long cpu_clk;               /*  CPU clock in Hz!   cpu时钟  */
unsigned long bus_clk;               // 总线时钟
unsigned long ram_size;             /*  RAM  size  of ram大小 */
unsigned long reset_status;      /* reset status register at boot */
#endif

void   **jt;                                /* jump table 跳转表,用来"函数调用地址登记" */
}gd_t;
/*
* Global Data Flags   全局数据标志
*/
#define GD_FLG_RELOC 0x00001            /* Code was relocated to RAM   代码装载到RAM里*/
#define GD_FLG_DEVINIT 0x00002         /* Devices have been initialized 设备已经初始化*/
#define GD_FLG_SILENT 0x00004           /* Silent mode     */
#define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")
#endif /* __ASM_GBL_DATA_H */

typedef struct bd_info {
int                                       bi_baudrate;        /* serial console baudrate    串口波特率 */
unsigned long                      bi_ip_addr;          /* IP Address    IP 地址 */
unsigned char                      bi_enetaddr[6];     /* Ethernet adress    MAC地址*/
struct environment_s        *bi_env;                //结构体变量定义见46行
ulong                                   bi_arch_number;   /* unique id for this board    板子的id*/
ulong                                   bi_boot_params;   /* where this board expects params 启动参数*/
struct     /* RAM configuration    RAM 配置*/
{
ulong start;
ulong size;
}     bi_dram[CONFIG_NR_DRAM_BANKS];
}bd_t;
=====================================================================
=====================================================================


下面是lib_arm\board.c文件分析  
/*
* Breathe some life into the board...           //给开发板注入些活力
*
* Initialize a serial port as console, and carry out some hardware
* tests.
*         初始化串口作为控制台并实现硬件测试
* The first part of initialization is running from Flash memory;
* its main purpose is to initialize the RAM so that we
* can relocate the monitor code to RAM.
 初始化的第一个阶段是在flash中运行,主要目的是初始化ram以便于可以重载监控代码到ram里
*/
/* All attempts to come up with a "common" initialization sequence
* that works for all boards and architectures failed: some of the
* requirements are just _too_ different. To get rid of the resulting
* mess of board dependent #ifdef'ed code we now make the whole
* initialization sequence configurable to the user.
*试图提出一个公共的初始化序列应用于所有开发板和体系结构几乎是不可能的。为避免开发板混乱需要依赖条件编译代码。
* The requirements for any new initalization function is simple: it
* receives a pointer to the "global data" structure as it's only
* argument, and returns an integer return code, where 0 means
* "continue" and != 0 means "fatal error, hang the system".
任何新的初始化函数的要求都是简单的:函数接受一个指针参数作为全局数据结构,返回整型数据类型,为0表示继续,非0表示致命错误,系统挂起*/
typedef int (init_fnc_t) (void); //自定义数据类型
/*初始化函数序列init_sequence[]
init_sequence[]数组保存着基本的初始化函数指针。这些函数名称和实现的程序文件在下列注释中。*/

init_fnc_t   *init_sequence[]= {
cpu_init,               /* basic cpu dependent setup 基本的处理器相关配置-- cpu/s3c44b0/cpu.c */
board_init,           /* basic board dependent setup 基本的板级相关配置-- board/hfrk/hfrks3c44b0/hfrks3c44b0.c*/
interrupt_init,    /* set up exceptions 初始化例外处理-- cpu/s3c44b0/interrupt.c*/
env_init,               /* initialize environment 初始化环境变量-- common/env_flash.c*/
init_baudrate,      /* initialze baudrate settings 初始化波特率设置-- lib_arm/board.c*/
serial_init,          /* serial communications setup串口通讯设置 -- cpu/s3c44b0/serial.c*/
console_init_f,    /* stage 1 init of console控制台初始化阶段1 -- common/console.c*/
display_banner,    /* say that we are here 打印u-boot信息 -- lib_arm/board.c*/
dram_init,            /* configure available RAM banks 配置可用的DRAM-- board/hfrk/hfrks3c44b0/hfrks3c44b0.c*/
display_dram_config,                   //显示RAM的配置大小 -- lib_arm/board.c 

#if defined(CONFIG_VCMA9)
checkboard,
#endif

NULL,
};

//整个u-boot的执行就进入等待用户输入命令,解析并执行命令的死循环中。
//start_armboot是U-Boot执行的第一个C语言函数,完成系统初始化工作,进入主循环,处理用户输入的命令。

void start_armboot (void)
{
DECLARE_GLOBAL_DATA_PTR;   
/*DECLARE_GLOBAL_DATA_PTR 只是一个定义的宏,这个宏定义了一个gd_t全局数据结构的指针,
         这个指针存放在指定的寄存器中(386体系结构没有放到指定寄存器中)。
这个宏定义在\include\asm-arm\globe_data.h文件中
#define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm("r8")
声明一个寄存器变量 gd 占用r8。这个宏在所有需要引用全局数据指针gd_t *gd的源码中都有申明。
这个申明也避免编译器把r8分配给其它的变量. 所以gd就是r8,用r8来保存内存地址,达到全局使用目的,这个指针变量不占用内存。
         总结:gd指向一个数据结构,用于保存参数。。*/
        ulong size;
init_fnc_t**init_fnc_ptr;            //这个是函数的指针,指向==>硬件初始化的函数
char *s;

#if defined(CONFIG_VFD)
unsigned long addr;
#endif

#if CFG_LED_FLASH
LED();
#endif
/* gd指针可写,因为已经分配一个寄存器给它作为变量。
这里就相当于把后面算出来的地址保存到r8寄存器.
*/
/* Pointer is writable since we allocated a register for it */
gd = (gd_t*)(_armboot_start -CFG_MALLOC_LEN-sizeof(gd_t));                 //计算出gd在RAM中的地址
memset ((void*)gd, 0, sizeof (gd_t));                   //给全局数据变量gd安排空间,用0填充全局数据表*gd

gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));                    //给板子数据变量gd->bd安排空间
memset (gd->bd, 0, sizeof (bd_t));                                   //gd区包含了bd区,gd_t,bd_t都是结构体变量,
//用0填充(初始化) *gd->bd board info数据结构定义,位于文件 include/asm-arm/u-boot.h
monitor_flash_len = _bss_start - _armboot_start;      // 取u-boot的长度

/* 顺序执行init_sequence数组中的初始化函数 */
for (init_fnc_ptr = init_sequence;    *init_fnc_ptr;     ++init_fnc_ptr)
{
if ((*init_fnc_ptr)() != 0) {
hang ();      //打印错误信息并死锁
}
}
/* configure available FLASH banks   配置可用的Flash */
size = flash_init ();                      //drivers/cfi_flash.c或自定义
display_flash_config (size);
#ifdef CONFIG_VFD                        //如果定义了VFD(真空荧光显示),就定义页面大小为4096B
# ifndef PAGE_SIZE
#   define PAGE_SIZE 4096
# endif

/*
* reserve memory for VFD display (always full pages)给VFD保留内存空间,以页为单位
*/
/* armboot_end is defined in the board-specific linker script */

addr = (_bss_start + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
size = vfd_setmem (addr);
gd->fb_base = addr;     //全局数据gd中定义的帧缓冲区的基地址
#endif /* CONFIG_VFD */

/* armboot_start is defined in the board-specific linker script初始化堆空间*/
mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);            //malloc使用的内存空间地址0x0c700000-129k(0x00080400)
#if (CONFIG_COMMANDS & CFG_CMD_NAND)              //如果有nandflash的话就在下面的代码中进行初始化
puts ("NAND:");
nand_init();           /* go init the NAND */
#endif
#ifdef CONFIG_HAS_DATAFLASH
AT91F_DataflashInit();
dataflash_print_info();
#endif
/* initialize environment 重新初始化环境,重新定位环境变量参数区,它在/common/env_common.c文件中定义*/
env_relocate ();
#ifdef CONFIG_VFD
/* must do this after the framebuffer is allocated */
drv_vfd_init();           //vfd初始化,在分配帧缓冲区之后必须的
#endif /* CONFIG_VFD */
/* IP Address 从环境变量中获取IP地址*/
gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
/* MAC Address 以太网接口MAC 地址*/
{
int       i;
ulong    reg;
char      *s,    *e;
uchar    tmp[64];
         i = getenv_r ("ethaddr", tmp, sizeof (tmp));
s =  (i  >  0)  ?  tmp  :  NULL;
         for (reg = 0;   reg < 6;   ++reg){
gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
if (s)
s = (*e) ? e + 1 : e;          
}
}
devices_init ();              /* get the devices list going.设备初始化*/
jumptable_init ();          //跳转表初始化
console_init_r ();          /* fully init console as a device 完整地初始化控制台设备*/
#if defined(CONFIG_MISC_INIT_R)
/* miscellaneous platform dependent initialisations */
misc_init_r ();
#endif
/* enable exceptions 使能中断处理*/
enable_interrupts ();
。。。。。。
/* main_loop() can return to retry autoboot, if so just run it again. 循环不断执行*/
for  ( ;  ; ){
main_loop ();      //主循环函数处理执行用户命令 -- common/main.c
}
/* NOTREACHED - no way out of command loop except booting */
}
void hang (void)
{
puts ("### ERROR ### Please RESET the board ###\n");     //输出错误信息需要reset,进入死循环
for (  ;  ;  );
}

这篇关于DECLARE_GLOBAL_DATA_PTR、gd_t、bd_t及uboot中 start_armboot 代码分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1114741

相关文章

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者

MOLE 2.5 分析分子通道和孔隙

软件介绍 生物大分子通道和孔隙在生物学中发挥着重要作用,例如在分子识别和酶底物特异性方面。 我们介绍了一种名为 MOLE 2.5 的高级软件工具,该工具旨在分析分子通道和孔隙。 与其他可用软件工具的基准测试表明,MOLE 2.5 相比更快、更强大、功能更丰富。作为一项新功能,MOLE 2.5 可以估算已识别通道的物理化学性质。 软件下载 https://pan.quark.cn/s/57

代码随想录冲冲冲 Day39 动态规划Part7

198. 打家劫舍 dp数组的意义是在第i位的时候偷的最大钱数是多少 如果nums的size为0 总价值当然就是0 如果nums的size为1 总价值是nums[0] 遍历顺序就是从小到大遍历 之后是递推公式 对于dp[i]的最大价值来说有两种可能 1.偷第i个 那么最大价值就是dp[i-2]+nums[i] 2.不偷第i个 那么价值就是dp[i-1] 之后取这两个的最大值就是d

pip-tools:打造可重复、可控的 Python 开发环境,解决依赖关系,让代码更稳定

在 Python 开发中,管理依赖关系是一项繁琐且容易出错的任务。手动更新依赖版本、处理冲突、确保一致性等等,都可能让开发者感到头疼。而 pip-tools 为开发者提供了一套稳定可靠的解决方案。 什么是 pip-tools? pip-tools 是一组命令行工具,旨在简化 Python 依赖关系的管理,确保项目环境的稳定性和可重复性。它主要包含两个核心工具:pip-compile 和 pip

衡石分析平台使用手册-单机安装及启动

单机安装及启动​ 本文讲述如何在单机环境下进行 HENGSHI SENSE 安装的操作过程。 在安装前请确认网络环境,如果是隔离环境,无法连接互联网时,请先按照 离线环境安装依赖的指导进行依赖包的安装,然后按照本文的指导继续操作。如果网络环境可以连接互联网,请直接按照本文的指导进行安装。 准备工作​ 请参考安装环境文档准备安装环境。 配置用户与安装目录。 在操作前请检查您是否有 sud

论文翻译:arxiv-2024 Benchmark Data Contamination of Large Language Models: A Survey

Benchmark Data Contamination of Large Language Models: A Survey https://arxiv.org/abs/2406.04244 大规模语言模型的基准数据污染:一项综述 文章目录 大规模语言模型的基准数据污染:一项综述摘要1 引言 摘要 大规模语言模型(LLMs),如GPT-4、Claude-3和Gemini的快