IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> 自己写bootloader------编写第2阶段 -> 正文阅读

[游戏开发]自己写bootloader------编写第2阶段

我们的bootloader要实现以下功能,

  • 初始化硬件:关看门狗,设置时钟,设置SDRAM,初始化nand falsh,
  • 如果bootloader比较大,要把它重定位到SDRAM。
  • 把内核从nandflash读到SDRAM
  • 设置"要传给内核的参数"
  • 跳转到内核

在第一阶段我们实现了初始化以及重定位,并且封装了nandread函数,接下来实现后面三项功能,我们将新建一个boot.c,在里面的main函数中实现这三个功能。

1 从nandflash里把内核读入内存

那么我们从哪个地址开始读,读到哪里,读多大,我们在开发板的uboot命令行用mtd命令看一下,得到

?我们可以看到kernal存在0x0060000这个地方,还有一个问题就是我们烧写的内核是uImage,uImage=64字节的头部 + zImage。我们的uImage存在0x0060000这里,那么我们的zImage存在0x0060000 + 64这里。

那么读到哪里呢,我们再uboot里面用boot命令启动看一下,得到

?可以看到内核是放到内存的30008000这里,于是我们用如下代码将内核从nandflash读到SDRAM里面。

nand_read(0x60000+64, (unsigned char *)0x30008000, 0x200000);

2 设置参数

我们的uboot要告诉内核我们的内存有多大,告诉内核启动的命令行参数,这些参数都是通过tag进行传递的,就是在某一块内存上保存着这些参数,然后内核直接去这个内存读取参数,我们一共需要四个tag

	/* 2. 设置参数 */
	puts("Set boot params\n\r");
	setup_start_tag();
	setup_memory_tags();
	setup_commandline_tag("noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0");
	setup_end_tag();
  • setup_start_tag()表示设置参数开始的地方,
  • setup_memory_tags()高速内核我们的内存有多大;
  • setup_commandline_tag("noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0");命令行参数tag
  • setup_end_tag();表示参数结束的地方。

2.1 setup_start_tag()

我们首先看一下uboot的start_tag是怎么写的,

?这里面有一个参数param,我们看一下param的定义

?那我们在自己的bootloader里面也定义这么一个结构体,其中的tag是这么一个结构体

?tag结构体是在uboot的setup.h里面声明的,我们直接把这个setup.h复制过来用,然后这个setup.h里面的u32 u16 u8没有定义,我们在里面定义一下。

然后我们开始写setup_start_tag,我们直接把uboot里面的setup_start_tag函数复制过来,

void setup_start_tag(void)
{
	params = (struct tag *)0x30000100;

	params->hdr.tag = ATAG_CORE;
	params->hdr.size = tag_size (tag_core);

	params->u.core.flags = 0;
	params->u.core.pagesize = 0;
	params->u.core.rootdev = 0;

	params = tag_next (params);
}

经过setup_start_tag之后得到

其中params = tag_next (params);的意思是指向下一个tag,这个宏定义是当前tag+size也就是指向了下一个tag。???????

?2.2 setup_memory_tag

我们同样模仿uboot里面的写法,我们先看一下uboot里面的

?我们的内存起始地址是0x30000000,大小是64M,因此得到

void setup_memory_tags(void)
{
	params->hdr.tag = ATAG_MEM;
	params->hdr.size = tag_size (tag_mem32);
	
	params->u.mem.start = 0x30000000;
	params->u.mem.size  = 64*1024*1024;
	
	params = tag_next (params);
}

2.3 setup_commandline_tag

视频到24分钟了。

3 跳转

我们参考uboot的代码,uboot启动主要执行bootm命令

于是我们去uboot代码中搜一下bootm这个命令,在cmd_bootm.c这个文件中的do_bootm函数,在do_bootm这个函数中调用了do_bootm_linux函数,在这里面定义了一个函数指针,

我们也仿照着定义一个函数指针,

void (*theKernel)(int zero, int arch, unsigned int params);

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-03-21 21:25:48  更:2022-03-21 21:27:14 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/16 18:49:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码