Tekkaman Ninja 版本的uboot说明

来源:互联网 发布:python日期加减 编辑:程序博客网 时间:2024/06/05 10:04
Tekkaman Ninja的博客地址:http://blog.chinaunix.net/uid/20543672.html

已经移植最新的2010.12,此版本停止开发
u-boot-2010.09 for mini6410 (add MMC support)
在完成了LCD 控制器驱动之后,我决定搞定6410的MMC启动这一块,经过了我一个星期业余时间的努力,终于搞定了。这个的补丁包括
1、6410从SD/MMC启动
2、识别启动介质,自动跳转到Nandboot或者SD/MMC boot代码
3、进入uboot后的SD/MMC的读写,可以读取SD/MMC上的FAT32和EXT2文件系统中的文件。
4、支持在SD/MMC中存放ENV和LCD背景图片,自动读取背景文件。

注意:编译出的u-boot-nand.bin依然可以烧写到NAND中启动,因为是自动识别启动介质的。

注意配置文件中的
#define LCD_VIDEO_BACKGROUND_IN_NAND
#define CONFIG_ENV_IS_IN_NAND

#define LCD_VIDEO_BACKGROUND_IN_MMC
#define CONFIG_ENV_IS_IN_MMC

他们定义了背景图片和环境变量ENV的存放位置。
请确定你自己的背景图片和ENV存放位置,并对上面的配置作适当关闭和打开。

源码已经上传:我的Git代码仓库

为了部分无法下载git源码的朋友,上传了补丁(请先打上basic补丁和LCD补丁):
文件:u-boot-2010.09_mini6410_tekkaman_mmcboot_mmc.patch.tar.bz2大小:9KB下载:下载

对于三星针对6410的u-boot-1.6.1的MMC支持,代码不是现在uboot的MMC框架下的驱动,不具有移植性,所以这次我的MMC驱动是在现在uboot的MMC框架下的驱动,移植性好。
而这个驱动是基本复制了s5p芯片的驱动,因为这两个芯片的MMC模块是一样的,寄存器一模一样。我修复的一下其中的BUG,并在MMC上层代码中添加了SD卡的探测支持。

现在对这个补丁的一些设置进行解释:

关于SD/MMC的启动原理,请参考网上可以下载到的一份:《SMDK6410_IROM_APPLICATION NOTE_REV 1.00》的PDF文件(请在看下面的内容前阅读完),是三星的一份文档。看完了这份文档,你会对于6410的IROM启动有比较完全的了解。
在这份文档和网上的一份《使uboot支持S3C6410的SD启动》以及自己导出的可以启动的SD卡中的镜像,基本可以确定如何烧写编译好的镜像到SD卡:
现对于我的配置文件中:
#define MMC_UBOOT_POS_BACKWARD(0x300000)
#define MMC_ENV_POS_BACKWARD(0x280000)
#define MMC_BACKGROUND_POS_BACKWARD(0x260000)

我将编译好的代码了目录中的nand_spl/u-boot-spl-16k.bin烧写到BL1区(第一级引导,代码自拷贝部分),
将源码根目录下的u-boot.bin烧写到BL2(SD卡末尾向前3MB的位置)(0x300000)
ENV的位置是在SD卡末尾向前2.5MB的位置(在BL2后0.5MB)(0x280000)
背景图片的位置在SD卡末尾向前0x260000的位置。


对于从普通2G以下SD卡和2G以上的SDHC启动的区别:
其实在这两中SD卡中启动uboot的源码无须作任何修改,只是在烧写的时候位置不同而已。
为什么有这个区别呢?我猜想可能是IROM的bug,IROM在获取SDHC的总块数的时候会缺少1024块,也就是说在调用IROM的Device Copy Function的时候,IROM根本就不知道有最后的1024块,但是如果你自己去初始化SD/MMC控制器后去获取SDHC的总块数的时候就不会缺少这1024块。
所以如果在BL1中使用IROM的Device Copy Function中的CopyMMCtoMem去拷贝SDHC中的代码,你烧写的位置必须无视最后的1024块。但是在自己的uboot代码中SDHC最后的1024块是存在的。

关于镜像的烧写方法,uboot必须烧写到SD卡的最后,所以可能会破坏你的数据,请你保证SD卡最后的10M左右没有任何数据。
现在我的烧写暂时是使用Linux下的dd命令来实现的,比如一个8G的SD卡在Linux下的用fdisk读出的信息是

tekkaman@MAGI-Linux:~$ sudo fdisk /dev/sdb
[sudo] password for tekkaman:

Command (m for help): p

Disk /dev/sdb: 7969 MB,7969177600 bytes
246 heads, 62 sectors/track, 1020 cylinders
Units = cylinders of 15252 * 512 = 7809024 bytes
Disk identifier: 0x00000000

Device Boot Start End Blocks Id System
/dev/sdb1 * 1 6 45755+ b W95 FAT32
/dev/sdb2 * 7 1020 7732764 83 Linux

所以总块数是7969177600/512=15564800
IROM所认为的总块数15563776(15564800-1024)(仅在SDHC时需要减去1024)

所以nand_spl/u-boot-spl-16k.bin烧写的位置是15563758块(15563776-18
u-boot.bin烧写的位置是15557632块15563776-6144(3MB)(根据我的Uboot配置文件)

烧写命令:
sudo dd if='(Uboot源码)/nand_spl/u-boot-spl-16k.bin' of=/dev/(SD卡的设备节点) bs=512 seek=15563758
sudo dd if='/(Uboot源码)/u-boot.bin' of=/dev/(SD卡的设备节点) bs=512 seek=15557632
2010年11月16日 00:03 修复一个MMC 中存储ENV和背景图片数据位置的BUG
文件:u-boot-2010.09_mini6410_tekkaman_mmcboot_mmc_1.patch.tar.bz2大小:0KB下载:下载

u-boot-2010.09 for mini6410 (basic) (2010-10-24 00:50)
分类: Bootloader


已经移植最新的2010.12,此版本停止开发
u-boot-2010.09 for mini6410 Source release
(basic)

这是u-boot-2010.09 针对友善之臂MINI6410移植的最基础版本,只包含了就基本的系统引导,NAND读写,DM9000网卡等等。但是这个足够开发的方便使用。今后会陆续添加原先我为mini2440添加的所有功能。

但是此次移植并非我的功劳,首先基本的移植是由Alex Ling <kasimling at gmail.com>完成的,你可以在这里看到他提交的补丁,但是编译后无法使用,可能是因为host系统不同,对脚本的解析不同,使得spl部分的生成出现问题,只需修改一下nand_spl目录下目标板目录的中config.mk中的
PAD_TO:= $(shell expr $$[$(TEXT_BASE) + 4096])
即可。

DM9000的驱动没有太大的问题(修改了一点可能出现问题的地方,感谢肖工指教),但是原本的u-boot并没有调整所有SROM控制器的配置(其中包括连接DM9000所使用的bank1的总线),我使用了友善带的u-boot的参数配置了一下就好了。

源码的下载地址,和以前一样在我的git仓库中。
为了部分无法下载git源码的朋友,上传了补丁:
文件:u-boot-2010.09_mini6410_tekkaman.patch.tar.bz2大小:9KB下载:下载


u-boot-2010.09 for mini6410 (add LCD support ) (2010-11-01 00:04)
分类: Bootloader


已经移植最新的2010.12,此版本停止开发
u-boot-2010.09 for mini6410 (add LCD support)
在完成了基本移植之后,我决定现搞定LCD console的显示,玩一下。经过几天业余时间的努力,终于搞定了。期间也被透明参数搞郁闷了,本来早就弄好了,但是透明值理解反了,结果设成了全透明。我一直找原因:为什么会没有显示呢?最后参考nboot的参数设置才找到原因。
其实要在U-boot中添加LCD支持其实很简单,只要你的CPU支持类似framebuffer的机制,就只要添加一个初始化LCD 控制器和一个GraphicDevice *pGD结构体的代码就基本可以了。
在6410中,他的LCD 控制器可以显示5层的画面,我在uboot中使用了两层,一个作为console的显示,一个作为背景,可以拷贝一张BMP的图形到NAND Flash中,启动的时候代码会自动拷贝nand中特定地址的数据并显示为背景。具体的地址看下include/configs/mini6410.h的最后就知道了。(图片的制作请参考:对uboot移植的点滴记录。

所有的代码已经上传github,可以到这里下载。
为了部分无法下载git源码的朋友,上传了补丁(请先打上basic补丁):
文件:u-boot-2010.09_mini6410_tekkaman_lcd.patch.tar.bz2大小:10KB下载:下载

以下是显示效果,有图有真相:

同时支持3.5吋屏,只需要输入命令:setenv videomode 0x211 ;saveenv ,然后重启即可。其他的屏幕我没有,所有无法测试。

u-boot SD flasher for mini6410(测试版) (2011-02-15 16:59)
分类: Bootloader


在完成了2010.09版本的移植以后,我就想要做一个简单的u-boot启动SD卡的烧写工具。虽然我知道应该实现什么功能,但是我不会写界面,只好求助于我的好兄弟Amankwah。我告诉他所要实现的功能、界面布局和烧写的方法,他帮我实现具体的界面。

经过我们的沟通与合作,这个u-boot的SD卡烧写界面的雏形和基本的功能都已经实现了。在这里我要感谢Amankwah对我的无私的帮助。

这里是源码的下载地址。运行环境:Ubuntu。

如果你在使用中发现了bug,你可以发邮件给Amankwah,最好再抄送一份给我。


此工具是测试版本,功能还不完善:

erase还不能用(虽然没有什么必要)

没有烧写成功的提示(虽然已经成功了)


但是我们会慢慢的完善她。

以下是运行的效果图:

注意:此工具会改变你的可移动存储设备的内容,请小心使用!推荐使用测试用SD卡(里面没有重要数据),我们对使用此工具造成的一切数据丢失一概不负责。

关于u-boot for MINI6410自动识别内存大小的原理 (2011-03-12 23:56)
标签:MINI6410U-boot256MB DDRRAM 分类:Bootloader


昨天完成了MINI6410的u-boot自动识别256MB和128MB DDR 内存的功能,这里把其中的原理记录一下。

1、了解DDR SDRAM的原理

首先你必须了解一下DDR SDRAM的原理和外部接口,这些在网上有几篇比较经典的文章这里推荐一下:

专家详解:内存工作原理及发展历程

内存的原理和时序(SDRAM、DDR、DDR-Ⅱ、Rambus DRAM)

----------------------------------------------------------------------------------

2、MINI6410的内存硬件结构与寻址关系

在看过上面的文档之后,相信应该对DDR内存有了一个比较完整的认识和理解,下面我们就来讲讲在MINI6410上的内存硬件结构:

对于MINI6410的设计,用了两块引脚兼容的DDR内存芯片来实现128MB内存和256MB内存可共用一个PCB。

128MB内存使用的是两片K4X51163PG(32Mx16bit),形成一个32M×32bit(128MB)的内存。

256MB内存使用的是两片K4X1G163PE(64Mx16bit),形成一个64M×32bit(256MB)的内存。

这两款芯片在引脚上的差别就是K4X51163PG的F7是NC脚,而K4X1G163PE的F7脚是A13

这个F7引脚在128MB内存版本的MINI6410中这个引脚是不连接的,而256MB版本中是通过一个0欧电阻和S3C6410的Xm1ADDR13相连的

看了这两个内存芯片和S3C6410(DRAM控制器)的数据手册的朋友一定知道,这种连接形成一个这样的寻址关系:

128MB内存版本:Xm1ADDR[15:14](bank):Xm1ADDR[12:0](行地址):Xm1ADDR[9:0](列地址) 。一共25根地址线刚好可寻址32M空间

256MB内存版本:Xm1ADDR[15:14](bank):Xm1ADDR[13:0](行地址):Xm1ADDR[9:0](列地址) 。一共26根地址线刚好可寻址64M空间

这两种连接和芯片配置也要通过修改S3C6410的DRAM控制器的两个寄存器的参数来匹配。

----------------------------------------------------------------------------------

3、U-boot中内存自适应代码应处的位置

做好了以上的两个知识准备后,我们看看在u-boot中应该在什么位置来识别和自适应不同的内存大小。

首先我们在识别了内存大小之后可能需要重新配置S3C6410的内存控制器。这么一来,这些代码不能在DDR中运行。因为一旦重新配置内存控制器,必然导致内存暂时无法使用,如果代码在DDR中CPU可能无法得到下一步的代码。所以这些代码要放在u-boot实现自拷贝到内存之前的地方,其实最好的地方就是在u-boot的SPL部分中初始化内存控制器的代码段中。

这些代码就在:arch/arm/cpu/arm1176/s3c64xx/cpu_init.S

这个文件是汇编代码,其中的函数mem_ctrl_asm_init是通过start.S中的“bl lowlevel_init”------>/board/samsung/mini6410/lowlevel_init.S中的lowlevel_init ”bl mem_ctrl_asm_init”调用的。mem_ctrl_asm_init函数中的代码对S3C6410的DRAM控制器进行了初始化,并对外部的DDR内存也进行了初始化,所以内存的识别和自适应代码应该放在这些初始化之后。先识别内存的大小,如果内存大小和原先DRAM控制器的配置不相符,就修改DRAM控制器的配置。

----------------------------------------------------------------------------------

4、内存大小的识别

针对MINI6410的情况,我们只需要识别内存是128MB还是256MB。由于这两种内存大小关系到DRAM控制器的两个寄存器的参数,所有我们必须先假设我们的内存大小,再通过读写的方式来证明,如果证明我们的假设是错误的,再修改寄存器的参数。

我移植的U-boot代码中首先假设内存是256MB,并先配置DRAM控制器为256MB内存的参数。如果这时连接的是128MB内存,那么就会有这样一个有趣的现象:

由于Xm1ADDR[13]没有连接,所以DDR内存的第一个8M×32bit(32MB)和第二个8M×32bit(32MB)是镜像关系,第三个8M×32bit(32MB)和第四个8M×32bit(32MB)是镜像关系,以此类推。一共有四个这样的镜像关系,共256MB。如果连接的就是256MB的内存就不会有这样的现象。所以,只要我们证明了这种现象存在,就证明了我们其实连接的是128MB内存,然后重新配置DRAM控制器为128MB内存的参数就大功告成了。

所以我移植的U-boot代码中首先写一个32bit的测试数据到第一个8M×32bit(32MB)的某个位置(比如0x0地址),然后就去第二个8M×32bit(32MB)相应偏移位置读取,如果数据一致就可以证明镜像关系。但是还不保险,如果就是这么巧(在连接256MB的内存的情况下)第二个8M×32bit(32MB)相应位置本身就是这个数据怎么办?不要紧,我们再去第二个8M×32bit(32MB)同一位置写入另一个测试数据,然后去第一个8M×32bit(32MB)的那个位置(也就是一开始的那个写入位置)读取数据,如果数据一致就完全可以证明镜像关系。通过这样的两次测试,看看是否要重新配置DRAM控制器参数。

但是我们不能假设内存是128MB,并先配置DRAM控制器为128MB内存的参数。如果连接的是256MB的内存,没有任何特殊的现象可以测试到。通过上面的寻址关系,如果连接的是256MB的内存,只是第二、四、六、八(假设Xm1ADDR[13]一直是0)个8M×32bit(32MB)是没法访问的(可以说是内存空洞),这个无法通过读写证明。(通过寻址关系推断,未通过实验证明)

----------------------------------------------------------------------------------

5、关于内存控制器的重配置

如果上面的步骤中测试出了镜像的存在,我们必须重新配置两个寄存器的值,但是如何重新配置,这个三星的数据手册是没有讲的,我通过测试发现可以通过以下的步骤重新配置DRAM控制器:

1、将DRAM控制器设为暂停(Paused)状态;

2、检测P1MEMSTAT,直到确认了暂停(Paused)状态;

3、将DRAM控制器设为配置(Config)状态;

4、检测P1MEMSTAT,直到确认了配置(Config)状态;

5、修改需要重新配置的寄存器

6、将DRAM控制器设为启动(Go)状态;

7、检测P1MEMSTAT,直到确认了就绪(Ready)状态;

----------------------------------------------------------------------------------

所有的原理就总结到这里,具体的源码可以到这里下载、分析。

如果您认为我的方法不好,可以在评论中批评、指出。

如果有朋友有更好的办法来解决MINI6410内存的识别问题,也欢迎在评论中共享出来

u-boot-2010.12 for mini6410(128M/256M auto adapt) (2011-03-12 08:39)
标签:MINI6410U-boot256MB DDRRAM 分类:Bootloader


以前我移植的u-boot在启动的时候只支持128MB内存,因为最开始友善出的MINI6410只有128MB的DDR内存。但是后面他们升级为256MB的DDR了,我的U-boot一直没有修改,一直在凑合着用。最近几天,由于项目需要,看了一下DDR(1/2/3)的接口和相关的时序,就想到也让U-boot支持一下256MB的DDR,所有就稍微看了看S3C6410的DRAM控制器,调整了两个寄存器就实现了对256MB的支持。

但是对于两个内存版本的板子,如果要编译出两个u-boot,这肯定比较麻烦。要做就做完美来,自动适应两种RAM大小。友善的superboot支持,这说明技术上是绝对可行的。经过了我一两天业余时间的尝试,昨天晚上搞定了。
识别的原理是利用的在以265MBDDR模式下配置DRAM控制器后读写128MBDDR会出现32MB镜像内存的作用,具体的识别原理我会专门写一个文档来探讨。

所有的代码已经更新到github,可以到这里下载
---------------------------------------------------------------------------
2011.3.15更新:
只在u-boot的SPL中初始化DRAM控制器,在u-boot.bin中屏蔽了相关初始化代码。
在初始化开发板后往环境变量中添加了“ramsize”变量,记录了内存的大小,使得bootargs可以实现向内核传递启动参数的“mem=”的自动配置。比如,在uboot中加入命令:
  1. setenv bootcmd 'setenv bootargs noinitrd root=/dev/nfs rw nfsroot=192.168.1.2:/home/tekkaman/development/share/mini6410_rootfs ip=192.168.1.22:192.168.1.2::255.255.255.0 console=ttySAC0,115200 init=/linuxrc mem=$ramsize ; tftp 192.168.1.2:uImage ;bootm'
注意:上面bootcmd后面的是用单引号包括起来的,否则mem=$ramsize会变为mem=256M等,无法在启动是自动配置。


u-boot-2011.06 for mini6410 (2011-09-08 08:46)
标签:MINI6410U-boot 分类:Bootloader


好久都没有更新mini6410的u-boot了,前段时间仔细学习了git和quilt的使用,发现真的对开发有极大的帮助。这次将u-boot-2011.06移植到mini6410算是一个集中实习。

这次我使用原来u-boot-2009.12的补丁移植到2011.06上再做适当的修改,主要使用的是quilt,仅用两天的业余时间就完成,quilt真是功不可没。在处理补丁方面,quilt简直是神器,不愧是神人的作品。我分享了quilt的学习资料,请看:补丁工具quilt学习资源分享
此版本的源码照例发布在我的git仓库。

这里再上传补丁集,可以直接复制到u-boot-2011.06的源码根目录下,通过quilt管理。当然你也可以手工打补丁(自找麻烦)。
patches.zip
本次的移植功能和原来u-boot-2009.12最后一版的功能一样,但是对于第一级的引导的代码有较大变动,由于2011.06的代码多出了mmc_spl目录,专门用于编译mmc启动的第一级,所有我也将mmc启动放于此目录下。

编译命令:
  1. make CROSS_COMPILE=(你的编译器路径) mini6410_config
  2. make CROSS_COMPILE=(你的编译器路径)
编译好后,nand boot的bin文件依旧是根目录下的u-boot-nand.bin,
mmc boot的启动代码分别为mmc_spl/u-boot-spl.bin和根目录下的u-boot.bin。

当然如果你在nand_spl/board/samsung/mini6410中的Makefile文件中打开了CONFIG_BOOT_AUTODETECT = y,那么同样也可以和以前一样使用nand_spl/u-boot-spl.bin和根目录下的u-boot.bin烧写到SD卡。




原创粉丝点击