因为要找工作了我准备把以前做的东西再看一下,感觉以前学的不是很扎实,很多东西都不明白,所以我参考网上的视频再看了一下。
http://study.163.com/course/courseMain.htm?courseId=890008(韦东山的感觉讲得很细,特别是做过之后带着问题去看的话应该收获不少)
由于本人能力有限,只解决一下我力所能及的问题。
首先我们还是看一下我们s3c2440的存储控制器的地址空间分布图吧。
***************************************************************************************************************************************************************************************
我们主要是看右边,因为我fl2440的开发板是只支持nand flash的不支持nor flasn.
首先来2个小问题来压压惊~
*********************************************************************************************************************************************************************************
问题一:如果换一块开发板有可能改哪些东西?
首先,cpu的运行模式,如果需要对cpu进行设置那就设置,关看门狗,关中断不用改,时钟有可能要改,如果能正常使用则不用改,关闭catch和MMU不用改,设置bank有可能要改。最后一步拷贝时看地址会不会变,如果变化也要改,执行内存中代码,地址有可能要改。
红色字体的原因是:
因为我们sdram是64M的,你可以从图中看出来它是挂载BANK6上的,我们用JLINK第一次烧uboot的时候setpc的地址是33f80000,这个地址看得出来是在sdram的地址范围里面,因为我们留了512K给uboot运行,如果你的uboot大于了 512K,你在烧的时候是可以把这个地址往下拉一点的。
问题二:Nor Flash和Nand Flash本质区别:(nor flash不存在坏块,nand flash存在坏块所以放在上面的文件系统也都不同)
就在于是否进行代码拷贝,也就是下面代码所表述:无论是Nor Flash还是Nand Flash,核心思想就是将uboot代码搬运到内存中去运行,但是没有拷贝bss后面这段代码,只拷贝bss前面的代码,bss代码是放置全局变量的。Bss段代码是为了清零,拷贝过去再清零重复操作(nor flash支持XIP,片上执行,不用将代码搬到内存中去,直接在nor flash运行)
因为我们的nand flash是没有地址线的,不是直接接在cpu上的,我们是通过nand flash控制器用命令来控制nand flsh的数据传输,比如什么时候传地址,什么时候传数据,是读还是写,我们都是先通过命令来设置,然后再传输数据。
**********************************************************************************************************************************************************************************
言归正传:我们看图,因为每个BANK的地址空间是128MB,有8个BANK所以总的地址空间是1GB,上面这个地址空间是用来连接外设的。我们的BANK0-BANK6分别连接了如下设备:NOR FLASH,IDE接口,10M网卡CS8900A,100M网卡DM9000,扩展串口芯片16C2550,SDRAM。
s3c2440作为32位的CPU,可以使用的地址范围理论上达到了4GB。除去上面用于连接外设的1GB地址空间外,还有一部分是CPU内部寄存器的地址,剩下的地址空间还没使用。 s3c2440的寄存器的地址范围处于0X4800000----0X5FFFFFFF,我们的NAND FLASH控制器地址就在里面。
下面是我烧写uboot进开发板的步骤(开发板什么都没有,全部清除了)
1.首先是用JLINK烧写bootstrap 到0地址,这个地址是SRAM的地址,SRAM是不需要启动的,上电就有,不过只有4K,这个程序用来启动我们的SDRAM。
2.继续用JLINK烧写我们的uboot.bin文件到0x33f80000这个地址(前面这个地址说过了SDRAM的地址范围,我们用来存放uboot的),然后打开我们的CRT,我们可以看见UBOOT启动的信息了(能够在CRT上看到这些信息也是uboot里面设置的,为了开发方便)。
3.进入了我们的uboot,我们就需要用tftp命令将我们的uboot放到我们的0x30008000这个地址,可以看出,这个地址也是在SDRAM里面,我们用tftp 30008000 offset filesize这个命令将uboot传到30008000这个地址,偏移地址是offset,大小是filesize。 OK,到现在为止我们都还只是将uboot放到了SDRAM中启动,并没有将其放到nand flsh中存储起来,这样一掉电,我们的uboot就没了。
4.使用nand write命令将uboot写进我们的nand flash中去,这样就大功告成了,再重启开发板就能直接启动了,看得到uboot的信息,当然你要把jlink拔掉,不然不能启动!
其实上面还是没有说到uboot的作用是啥,上面只是一个流程,第一步。
我再说一下uboot到底干了什么事情。(在uboot已经烧进去,写 进了nand flash中后,我们上电后的情况)
大多数bootloader都分为stage1和stage2两部分,u-boot也不例外。依赖于CPU体系结构的代码(如设备初始化代码等)通常都放在stage1且可以用汇编语言来实现,而stage2则通常用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。
第一阶段用汇编的原因:因为c语言只能访问通用寄存器,第一阶段通常要配置特殊寄存器,通常用特殊汇编指令集来访问,C需要不支持,就只能用汇编了
我们可以将uboot分为2个部分:前4K和后面的内容
前4K:
PS:由于我们的nand flash的特性,它会将自己前4K的内容由硬件拷贝到sram(4K)中,因为我们的uboot是放在nand flash的最开头嘛,所以它前4K的内容也就是uboot的前4K内容,所以uboot前4K的内容是----------初始化CPU,初始化SDRAM,将UBOOT搬到SDRAM中运行。
u-boot的stage1代码通常放在start.S文件中,他用汇编语言写成,其主要代码部分如下:
(1)定义入口。由于一个可执行的Image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在ROM(Flash)的0x0地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本来完成。
(2)设置异常向量(Exception Vector)。
(3)设置CPU的速度、时钟频率(一上电的频率是12M,最大能到400M,所以我们需要设置时钟频率让它工作快一点)及终端控制寄存器。
(4)初始化内存控制器。
(5)将ROM中的程序复制到RAM中。
(6)初始化堆栈。
(7)转到RAM中执行,该工作可使用指令ldr pc来完成。
后面的内容:
Stage2 C语言代码部分
lib_arm/board.c中的start arm boot是C语言开始的函数也是整个启动代码中C语言的主函数,同时还是整个u-boot(armboot)的主函数,该函数只要完成如下操作:
(1)调用一系列的初始化函数。
(2)初始化Flash设备。
(3)初始化系统内存分配函数。
(4)如果目标系统拥有NAND设备,则初始化NAND设备。
(5)如果目标系统有显示设备,则初始化该类设备。
(6)初始化相关网络设备,填写IP、MAC地址等。
(7)进去命令循环(即整个boot的工作循环),接受用户从串口输入的命令,然后进行相应的工作。
OK~上面就是uboot做的事情。
我们得先要了解最基本的工作原理,当初我在学的时候只是照着文档走了一遍,还不懂为什么这么做,当然上面写的只是一些很浅显的东西,具体对于文件的操作,还需要了解makefile,知道如何去修改,还要看得懂C语言,还要知道nand flasn存储结构,对了nand flash中的每页有一个OOB区,大小是64字节,是用来存放坏块信息,ECC校验信息的,一般情况下我们不会去用,我也没去看。
对了,还有一个很重要的就是脚本链接文件 .lds