四、第二阶段

news/2024/5/4 23:16:46/文章来源:https://blog.csdn.net/liutit/article/details/130034421

全局数据

声明

# < lib_arm\board.c >

DECLARE_GLOBAL_DATA_PTR;

定义

# < include\asm\global_data.h >

typedef struct global_data {

bd_t *bd;

unsigned long flags;

unsigned long baudrate;

unsigned long have_console; /* serial_init() was called */

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;

// 申明一个gd_t类型的指针gd,存于寄存器r8

#define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")

字段说明

bd_t *bd:board info数据结构定义,位于文件 include/asm-arm/u-boot.h定义,主要是保存开发板的相关参数。

    typedef struct bd_info {

        int bi_baudrate; /* serial console baudrate */

        unsigned long bi_ip_addr; /* IP Address */

        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];

    } bd_t;

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:当前使用的串口设备。

初始化序列(板子初始化函数序列)

原型

# < lib_arm\board.c >

typedef int (init_fnc_t) (void);

int print_cpuinfo (void);

init_fnc_t *init_sequence[] = {

#if defined(CONFIG_ARCH_CPU_INIT)

arch_cpu_init, /* basic arch cpu dependent setup */

#endif

board_init, /* basic board dependent setup */

#if defined(CONFIG_USE_IRQ)

interrupt_init, /* set up exceptions */

#endif

timer_init, /* initialize timer */

env_init, /* initialize environment */

init_baudrate, /* initialze baudrate settings */

serial_init, /* serial communications setup */

console_init_f, /* stage 1 init of console */

display_banner, /* say that we are here */

#if defined(CONFIG_DISPLAY_CPUINFO)

print_cpuinfo, /* display cpu info (and speed) */

#endif

#if defined(CONFIG_DISPLAY_BOARDINFO)

checkboard, /* display board info */

#endif

#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)

init_func_i2c,

#endif

dram_init, /* configure available RAM banks */

#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)

arm_pci_init,

#endif

display_dram_config,

NULL,

};

结果

init_fnc_t *init_sequence[] = {

board_init, /* basic board dependent setup */

timer_init, /* initialize timer */

env_init, /* initialize environment */

init_baudrate, /* initialze baudrate settings */

serial_init, /* serial communications setup */

console_init_f, /* stage 1 init of console */

display_banner, /* say that we are here */

dram_init, /* configure available RAM banks */

display_dram_config,

NULL,

};

入口函数

入口

# < lib_arm\board.c >

void start_armboot (void)

申请gd全局数据

gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));

防止高版本gcc优化产生错误

    _asm__ __volatile__("": : :"memory");

说明:

1)   __asm__用于指示编译器在此插入汇编语句。

2)    __volatile__用于告诉编译器,严禁将此处的汇编语句与其它的语句重组合优化。即:原原本本按原来的样子处理这这里的汇编。

3)    memory强制gcc编译器假设RAM所有内存单元均被汇编指令修改,这样cpu中的registers和cache中已缓存的内存单元中的数据将作废。cpu将不得不在需要的时候重新读取内存中的数据。这就阻止了cpu又将registers,cache中的数据用于去优化指令,而避免去访问内存。

4)      "":::表示这是个空指令。barrier()不用在此插入一条串行化汇编指令。

清空全局数据

    memset ((void*)gd, 0, sizeof (gd_t));

    gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));

    memset (gd->bd, 0, sizeof (bd_t));

设置标志位(当前代码在RAM)

    gd->flags |= GD_FLG_RELOC;

获取整个uboot长度

monitor_flash_len = _bss_start - _armboot_start;

说明:

_bss_start是bss的开始地址,_armboot_start是Uboot的开始代码地址,这里monitor_flash_len得到的是整个Uboot的长度

使用初始化函数序列初始化

    for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr)

    {

        if ((*init_fnc_ptr)() != 0) //函数返回值不为零,直接进入死循环

        {

            hang ();    //死循环 { for(;;); }

        }

    }

初始化内存堆区

mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN, CONFIG_SYS_MALLOC_LEN);

说明:

_armboot_start = TEXT_BASE = 0x33F80000

# < common\dlmalloc.c >

void mem_malloc_init(ulong start, ulong size)

{

mem_malloc_start = start;

mem_malloc_end = start + size;

mem_malloc_brk = start;

memset((void *)mem_malloc_start, 0, size);

}

flash驱动器初始化

#ifndef CONFIG_SYS_NO_FLASH

    /* configure available FLASH banks */

    display_flash_config (flash_init ());

#endif /* CONFIG_SYS_NO_FLASH */

说明:

# < lib_arm\board.c >

static void display_flash_config (ulong size)

{

puts ("Flash: ");

print_size (size, "\n");

}

初始化Nand驱动器

#if defined(CONFIG_CMD_NAND)

    puts ("NAND:  ");

    nand_init(); /* go init the NAND */

#endif

说明:

# < include\configs\mini2440.h >

#define CONFIG_SYS_MAX_NAND_DEVICE 1

# < drivers\mtd\nand\nand.c >

void nand_init(void)

{

int i;

unsigned int size = 0;

for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {

nand_init_chip(&nand_info[i], &nand_chip[i], base_address[i]);

size += nand_info[i].size / 1024;

if (nand_curr_device == -1)

nand_curr_device = i;

}

printf("%u MiB\n", size / 1024);

#ifdef CONFIG_SYS_NAND_SELECT_DEVICE

/*

* Select the chip in the board/cpu specific driver

*/

board_nand_select_device(nand_info[nand_curr_device].priv, nand_curr_device);

#endif

}

环境变量初始化

    env_relocate ();

从环境变量获取ip

    gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");

说明:

IPaddr_t getenv_IPaddr (char *var)

{

return (string_to_ip(getenv(var)));

}

char *getenv (char *name)

{

int i, nxt;

WATCHDOG_RESET();

        // 便利所有字符串

for (i=0; env_get_char(i) != '\0'; i=nxt+1)

        {

int val;

                // 查找出一个字符串(以'\0'结束)

for (nxt=i; env_get_char(nxt) != '\0'; ++nxt)

                {

if (nxt >= CONFIG_ENV_SIZE)

                        {

return (NULL);

}

}

if ((val=envmatch((uchar *)name, i)) < 0) // 判断名称

continue;

return ((char *)env_get_addr(val));

}

return (NULL);

}

uchar env_get_char_memory (int index)

{

if (gd->env_valid) {

return ( *((uchar *)(gd->env_addr + index)) );

} else {

return ( default_environment[index] );

}

}

uchar *env_get_addr (int index)

{

if (gd->env_valid) {

return ( ((uchar *)(gd->env_addr + index)) );

} else {

return (&default_environment[index]);

}

}

标准输入、标准输出、标准错误初始化("stdin", "stdout", "stderr")

    stdio_init()

int stdio_init (void)

{    //其余代码由于宏被屏蔽

drv_system_init ();

return (0);

}

static void drv_system_init (void)

{

struct stdio_dev dev;

memset (&dev, 0, sizeof (dev));

strcpy (dev.name, "serial");

dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;

dev.putc = serial_putc;

dev.puts = serial_puts;

dev.getc = serial_getc;

dev.tstc = serial_tstc;

stdio_register (&dev);

}

struct stdio_dev {

int flags; /* Device flags: input/output/system */

int ext; /* Supported extensions */

char name[16]; /* Device name */

/* GENERAL functions */

int (*start) (void); /* To start the device */

int (*stop) (void); /* To stop the device */

/* OUTPUT functions */

void (*putc) (const char c); /* To put a char */

void (*puts) (const char *s); /* To put a string (accelerator) */

/* INPUT functions */

int (*tstc) (void); /* To test if a char is ready... */

int (*getc) (void); /* To get that char */

/* Other functions */

void *priv; /* Private extensions */

struct list_head list;

};

int stdio_register (struct stdio_dev * dev)

{

struct stdio_dev *_dev;

_dev = stdio_clone(dev);

if(!_dev)

return -1;

list_add_tail(&(_dev->list), &(devs.list));

return 0;

}

struct stdio_dev* stdio_clone(struct stdio_dev *dev)

{

struct stdio_dev *_dev;

if(!dev)

return NULL;

_dev = calloc(1, sizeof(struct stdio_dev));

if(!_dev)

return NULL;

memcpy(_dev, dev, sizeof(struct stdio_dev));

strncpy(_dev->name, dev->name, 16);

return _dev;

}

跳转表初始化

    jumptable_init ();

void jumptable_init (void)

{    //函数地址

int i;

gd->jt = (void **) malloc (XF_MAX * sizeof (void *));

for (i = 0; i < XF_MAX; i++)

gd->jt[i] = (void *) dummy;

gd->jt[XF_get_version] = (void *) get_version;

gd->jt[XF_malloc] = (void *) malloc;

gd->jt[XF_free] = (void *) free;

gd->jt[XF_getenv] = (void *) getenv;

gd->jt[XF_setenv] = (void *) setenv;

gd->jt[XF_get_timer] = (void *) get_timer;

gd->jt[XF_simple_strtoul] = (void *) simple_strtoul;

gd->jt[XF_udelay] = (void *) udelay;

gd->jt[XF_simple_strtol] = (void *) simple_strtol;

gd->jt[XF_strcmp] = (void *) strcmp;

#if defined(CONFIG_I386) || defined(CONFIG_PPC)

gd->jt[XF_install_hdlr] = (void *) irq_install_handler;

gd->jt[XF_free_hdlr] = (void *) irq_free_handler;

#endif /* I386 || PPC */

#if defined(CONFIG_CMD_I2C)

gd->jt[XF_i2c_write] = (void *) i2c_write;

gd->jt[XF_i2c_read] = (void *) i2c_read;

#endif

#ifdef CONFIG_CMD_SPI

gd->jt[XF_spi_init] = (void *) spi_init;

gd->jt[XF_spi_setup_slave] = (void *) spi_setup_slave;

gd->jt[XF_spi_free_slave] = (void *) spi_free_slave;

gd->jt[XF_spi_claim_bus] = (void *) spi_claim_bus;

gd->jt[XF_spi_release_bus] = (void *) spi_release_bus;

gd->jt[XF_spi_xfer] = (void *) spi_xfer;

#endif

}

终端设备第二阶段初始化

    console_init_r ();

中断初始化

    enable_interrupts ();

说明:

根据宏:CONFIG_USE_IRQ,该函数功能被屏蔽

void enable_interrupts (void)

{

return;

}

从环境变量获取加载地址(未使用,环境变量没有该参数)

    if ((s = getenv ("loadaddr")) != NULL) {

        load_addr = simple_strtoul (s, NULL, 16);

    }

主循环

    for (;;)

    {

        main_loop ();

    }

滞后说明

各种初始化(init_sequence)

nand初始化(nand_init)

环境变量初始化(env_relocate)

终端初始化(console_init_r)

主循环(main_loop )

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_283711.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用adb 命令删除手机预装app

1. 手机开启开发者选项&#xff0c;允许usb调试&#xff1b; 2.pc 安装adb&#xff0c; 1&#xff09;Windows版本&#xff1a;https://dl.google.com/android/repository/platform-tools-latest-windows.zip 2&#xff09;按键windowsr打开运行&#xff0c;输入sysdm.cpl&a…

Go 语言安装部署,两分钟让你写`上Hello World`(包含 goland 开发工具)

Go 语言安装部署&#xff0c;两分钟让你写上Hello World&#xff08;包含 goland 开发工具&#xff09; 第一步下载 Go 安装包 官网 https://golang.google.cn/dl/ 根据自己使用电脑平台选择安装版本 第二步 安装 GO 打开安装包直接点击next下一步 勾选协议&#xff0c;继…

10 kafka生产者发送消息的原理

1.发送原理&#xff1a; 在消息发送的过程中&#xff0c;涉及到了两个线程——main 线程和 Sender 线程。在 main 线程 中创建了一个双端队列 RecordAccumulator。main 线程将消息发送给 RecordAccumulator&#xff0c; Sender 线程不断从 RecordAccumulator 中拉取消息发送到…

CTFHub | 00截断

0x00 前言 CTFHub 专注网络安全、信息安全、白帽子技术的在线学习&#xff0c;实训平台。提供优质的赛事及学习服务&#xff0c;拥有完善的题目环境及配套 writeup &#xff0c;降低 CTF 学习入门门槛&#xff0c;快速帮助选手成长&#xff0c;跟随主流比赛潮流。 0x01 题目描述…

IDEA修改主题 设置背景图片

IDEA修改主题 设置背景图片 目录IDEA修改主题 设置背景图片1.修改IDEA默认主题2.修改IDEA背景图片2.1 打开设置界面2.2 下载插件很多小白在刚刚使用IDEA的时候还不是很熟练本文主要给大家提供一些使用的小技巧&#xff0c;希望能帮助到你1.修改IDEA默认主题 IDEA的默认主题是黑…

Jmeter 工具测试 websocket

WebSocket 是一种基于在单个 TCP 连接上进行全双工通信的协议&#xff0c;是从HTML5开始提供的一种浏览器与服务器之间进行全双工通讯的网络技术。相较于 HTTP 协议&#xff0c;WebSocket 协议实现了持久化网络通信&#xff0c;可以实现客户端和服务端的长连接&#xff0c;能够…

对Javascript中作用域的理解?

一、作用域 作用域&#xff0c;即变量&#xff08;变量作用域又称上下文&#xff09;和函数生效&#xff08;能被访问&#xff09;的区域或集合 换句话说&#xff0c;作用域决定了代码区块中变量和其他资源的可见性 举个例子 function myFunction() {let inVariable "…

C/C++中文参考手册离线最新版

最近又用回C/C刷题&#xff0c;回想上一年还在用Java&#xff0c;C/C才是世界上最好的语言&#xff08;纯属调侃&#xff09;。哼哼&#xff0c;不许反驳。 想分享我正在使用的C/C中文参考手册离线最新版给大家&#xff0c;需要的朋友们可以自行下载&#xff08;free的哦&#…

造型别致的耳夹式耳机,听出新色彩,塞那Z50上手

蓝牙耳机这几年发展很快&#xff0c;市面上的选择特别丰富&#xff0c;其中还有不少设计、音质都特别出彩的产品&#xff0c;像是我最近在用的这款sanag塞那Z50&#xff0c;就采用了一种很新颖的设计&#xff0c;带来了更加舒适的佩戴体验&#xff0c;而且音质表现也很出色。 s…

Redis 如何使用 Sentinel 构建主从复制的高可用架构?

文章目录Redis 如何使用 Sentinel 构建主从复制的高可用架构&#xff1f;什么是 Sentinel 服务&#xff1f;如何配置 Sentinel 集群服务&#xff1f;启动 Sentinel 服务配置说明测试主节点失效查看 Sentinel 主节点服务状态查看 Sentinel 从节点服务状态模拟主节点失效观察各个…

Unity实战篇 | 使Unity打包的exe程序始终保持屏幕最前端【文末送书】

&#x1f3ac; 博客主页&#xff1a;https://xiaoy.blog.csdn.net &#x1f3a5; 本文由 呆呆敲代码的小Y 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f384; 学习专栏推荐&#xff1a;Unity系统学习专栏 &#x1f332; 游戏制作专栏推荐&#xff1a;游戏制作 &…

Winform控件开发(28)——ToolTip(史上最全)

前言: 该控件的作用是在鼠标移动到控件上方时,弹出一个提示框,效果如下: 利用方法SetToolTip将工具提示和控件绑定 toolTip1.SetToolTip(button1 ,"提示1");一、属性 1、Name 获取控件对象 2、Active 为true时,工具提示才有效 3、AutomaticDelay 设置该…

第一章:part1监督学习:回归

线性回归&#xff08;linear regression model&#xff09; 线性回归模型 回归&#xff1a;可以预测数字作为输出 是一种特殊的监督学习模型 例&#xff1a;通过已知的房价来拟合曲线 可以求得英尺的价格 区别回归与分类&#xff1a;分类的输出结果一般为离散的&#xff0c;并…

Python第二章---列表简介

1、列表是什么&#xff1f; 在Python中用 [ ] 表示列表&#xff0c;用 逗号 , 分隔元素 每个元素用对应类型的方法标注&#xff0c;如字符串类型用单引号‘ ’标注 形如 list1 [a,b,c] print(list1); 输出时&#xff0c;会打印全部内容&#xff0c;包括符号 访问列表元…

Linux系统操作命令

1.linux目录结构 不同于 Windows 系统的⽂件路径的起点是盘符, Linux 系统的路径起点是/(根⽬录) 注意: - 1. / 为根⽬录, 是所有⽂件的路径的起点 - 2. 根⽬录下的所有第⼀层级的⽂件夹, 均不能随意进⾏修改操作 - 3. 掌握常⽤⽬录的作⽤即可 - 4. / 根⽬录, /home 普通⽤户…

AI助手帮你轻松做好Imagenet数据集重命名与复制

AI助手帮你轻松做好Imagenet数据集重命名与复制 任务需求 我们对Imagenet数据集进行了水下的退化处理&#xff0c;保存的数据集所有图片的深度图&#xff0c;格式为.npy。但是命名存在一些问题&#xff0c;现有格式为&#xff1a;n02009912_1916.JPEG.npy&#xff0c;需要更改…

哪个网站的电子书最多?

程序员宝藏库&#xff1a;https://gitee.com/sharetech_lee/CS-Books-Store 随便找一个电子书导航&#xff0c;就会给你提供几十个电子书下载网站。 然而&#xff0c;当真正用到时会发现&#xff0c;质量层次不齐&#xff0c;在绝大多数时候试遍几十个网站都找不到自己想要的书…

【蓝桥杯算法模板题--蓝桥题库Java】

PDF下载地址&#xff1a;点击即可 文章目录算法模板1 排序&#xff08;ArrayList&#xff0c;sort&#xff09;题目描述输入描述输出描述输入输出样例示例 1运行限制2 小明的彩灯&#xff08;差分&#xff09;输入输出样例示例 1运行限制3 绝世武功&#xff08;二阶差分算法&am…

「STM32入门」TIM输出比较

输出比较的简介 输出比较英文写作OC (Output Compare) 输出比较可以通过比较CNT和CCR寄存器值的关系&#xff0c;来对输出电平进行置高或者置低或者翻转的操作&#xff0c;用于输出一定频率和占空比的PWM波形常见应用例子如&#xff1a;呼吸灯&#xff0c;调速电机等CCR&#x…

2023年第十四届蓝桥杯javaB组省赛真题

&#x1f468;‍&#x1f4bb;作者简介&#xff1a;练习时长两年半的java博主 &#x1f4d6;个人主页&#xff1a;君临๑ &#x1f39e;️文章介绍&#xff1a;2023年第十四届蓝桥杯javaB组省赛真题 &#x1f389;所属专栏&#xff1a;算法专栏 &#x1f381; ps&#xff1a;点…