六:mini2440实现自己写bootloader

本文介绍了作者在实现从NAND Flash启动内核的过程中,如何编写简单的Bootloader。涉及到的关键步骤包括初始化NAND Flash,读取内核到SDRAM,设置内存标记和命令行参数,并传递机器ID。作者还分享了在NAND Flash初始化时遇到的问题及解决思路,以及启动内核时的注意事项。
摘要由CSDN通过智能技术生成

自己实现Uboot启动:

前言:

想想 uboot 的代码量,我们说自己写一个 bootloader 是不是口出狂言了?然而并没有,bootloader 的唯一目的只有一个,那便是启动内核。内核就是一大段可执行程序,我们只要跳转到它的入口地址去执行不就OK? 所以,写一个简单的 bootloader 并不困难。
现在来思考一下,目的是启动内核,那么内核在哪里?刚上电的时候,内核肯定是位于 nandflash 里的,我们得具备初始化 nandflash 并读取的功能。那么,我们将内核去读到 sdram 然后跳转到入口地址去执行就够了么?然而还不行,bootloader 启动内核时还需要给内核传递一些信息(tag),两个必不可少的信息是 内存标记和命令行参数。信息传递完,那么内核就一定能起得来么?未必,启动内核时,我们还会传递一个机器ID,如果Uboot传递进去的机器ID和内核支持的机器ID不匹配,那么内核也无法启动。想必,分析过 uboot 的同学对这个并不陌生。

一、自己写 bootloader ,或者移植 uboot ,需要知道的一些信息
1、内核在 nandflash 中的地址,是 uImage 还是 zImage ,我这里用的是 uImage ,在 nandflash 里的 0x60000处,uImage 是用来支持 uboot 启动的,不过我们自己写的话用 uImage 也没关系,因为 uImage 就是在 zImage 的基础上加了一个 64 字节的头部,用来告诉 uboot 内核的信息,比如版本号、加载地址、链接地址、编译时间等。uboot 会获取到这个头部,干一些事情。我们自己写的话,就不需要头部了,从NAND FLASH里把内核读入内存,直接跳到 uImage 启示地址 + 64 的地方去读就OK 。
2、内核的链接地址:0x30008000 ,这个连接地址实际上应该说是“真正”内核的链接地址,如果是 uImage ,不应该包含它的头部。知道什么意思了吧,使用 uImage 时,我们应当将整个 uImage 拷贝到 0x30008000 - 64 的地方去,也就是 0x30007fc0 。使用uImage的时候就是0x30008000 。

3、bootloader 的连接地址:uboot的链接地址一般为 0x3ff80000 处,内存是64M的,最大地址为0x3ff80000 ,我们自己写的也用这个地址好了。说到这里,必须得提一下,对于2440来说,不管是 nand 启动,还是 nor 启动,刚上电的时候我们的 bootloader 并不是运行在链接地址处,那么这时候跑在非链接地址处的这些指令就得有特殊要求——位置无关码。我们要在将自身代码拷贝到链接地址处之前,能用汇编写的尽量不用C写,因为用汇编我们自己可以分得清哪些是位置无关码,迫不得已的情况下用C写,写完看反汇编,看看那些跳转指令是否依赖于当前PC值。

4、标记 tag 的地址,2440 常用的做法是放在 0x30000100 处,我们同样也放在这里。其实放那都行,地址会作为参数传递给内核的。tag的放置方法,可以参考 uboot ,必须以 ATAG_CORE 类型的开头,以 ATAG_NONE 类型的结尾。
5、启动内核时传递给内核的参数,3个,第一个默认0,第三个是前边提到的 tag 的地址,第二个是机器ID。内核中所有支持的“机器”或者称作开发板、单板都用一个 MACHINE_START 宏来定义,这个宏的作用就是填充一个 machine_desc 类型的结构体,填充的过程中会对它的 .nr 成员赋值,这个 nr 就是所谓的机器ID。
6、内核刚启动时会打印一些信息,但是那时候内核自己并不会初始化串口,也为了方便自己调试,bootloader里需要初始化串口。

前面的是引用的一篇总结的好的博文

我主要写我自己遇到的问题:

在这里插入图片描述
Uboot基本实现的是:关闭看门狗,设置时钟,初始化SDRAM,代码重定位,执行main。
在这里插入图片描述
在这里插入图片描述
Sdram_config:中记录的是每一个寄存器所需要的值,依次赋给内存控制器的寄存器。
Bne 1b 的b的意思是back ,向后跳转,所以可以有很多个1标号。1f是向前跳转。
但是我自己写用的是以前调试好的C函数。这里注意了要用到函数一定要先设置堆栈。

现在lyboot是实现启动内核功能,那么就需要将nandflash里面的内核拷贝到sdram里面启动起来,就要做nand初始化,nand读操作。初始化nand,需要对照nand芯片手册进行时序的设置。只需要去看CPU能设置的时序就行了。这里写nand初始化的时候我还没有看裸机的nand分析,但是跟到韦老师仍然是可以实现的,但是遇到了很大一个问题,在后面会说明。先看nand的时序:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.根据nand芯片查到的twp间隔最小是15/12ns,设置TWRPH0在寄存器NFCONF里面。
在这里插入图片描述
HCLK为100MHZ,则10ns*(TWRPH0+1)>15/12ns,TWRPH0可以设置为1以上。
2.根据nand芯片查到的tcls间隔最小也是15/12ns,对应的TACLS可以为0表示同时发出,那么设置TACLS在寄存器NFCONF里面。
3.根据nand芯片查到的tclh间隔最小是5ns,那么设置TWRPH1在寄存器NFCONF里面。
HCLK为100MHZ,则10ns*(TWRPH0+1)>10/5ns,TWRPH0可以设置为0以上。
这样初始化的代码基本可以确定了:

void Nand_init(void)
{
	#define TACLS  0
	#define TWRPH0 2
	#define TWRPH1 0
	/*设置时序*/
	NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
	/*使能Nand控制器,初
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值