2012年(135)
分类:
2012-09-19 11:32:21
开发板: 飞凌6410 256M DDR 2G nand (4K pagesize)
需要csdn帐号和资源分才可以下载,其它朋友有需要可以QQ 67016879 或 lxj_com@163.com
移植好的uboot下载地址:
三星IROM boot 文档:
烧录工具下载:
Raw data bmp 转换工具(PIC2RAW):
http://www.mculee.cn/post/%E5%9B%BE%E7%89%87,bmp,raw,%E8%BD%AC%E6%8D%A2.html
移植说明:
1.支持SD/SDHC启动,相关文件:
include/confisg/smdk6410.h 定义 #define CONFIG_BOOT_MOVINAND 关掉 //#define CONFIG_BOOT_NAND
其它参考: cpu/s3c64xx/movi.c 主要功能是通过三星IROM code 函数CopyMMCtoMem(z,a,b,c,e) 拷贝BL2到DDR内存,
前8K(BL1)由CPU上电时自行拷贝,需要设置CPU启动跳线;
内存已经配置成256M了,飞凌提供的mmc.bin只支持128M(浪费了128M),烧大于126M的文件几乎很难烧录。
一般在加入越来越多的应用后,文件系统会越来越大,
最大文件支持为253M,uboot 2M(地址0x5FE00000) framebuffer 1M(0x5FD00000),
超过的话,可能需要改程序分块烧(目前uboot FAT不支持分块读文件)。
2.烧录bin到SD卡:
SD启动的bin文件会被分成BL1,BL2两块,移植好的uboot目录下有mkmovi脚本工具可以生成u-boot-movi.bin可供SD_Write.exe烧录;
也可以使用三星提供的IROM_Fusing_Tool工具(网上可以下载到源码,可以自己修改)烧录;
如果没有工具也可以使用WinHex工具直接写SD卡,注意SD ,SDHC写入的偏移不一样,都是写在SD尾部,
卡的块大小可通过IROM code 全局变量globalBlockSizeHide得到,
具体看三星IROM boot文档,这些uboot代码已经写好了;
到此,sd uboot 应该可以跑起来了,注意飞凌256M内存uboot中,include/configs/smdk6410.h文件
改了CFG_ENV_SIZE 的大小需要改回到0x4000,这个值会在include/movi.h中参与BL2地址的计算;
3.SD卡驱动:
cpu/s3c64xx/hs_mmc.c 此驱动文件比较旧,不支持SDHC卡和SD2.0协议,SD/MMC(2G或以下)可以;
需要修改初始化函数hsmmc_init(),
SD2.0初始化卡顺序
SD rest CMD0 -> SD_SEND_IF_COND CMD8 -> 选中SD ... 具体参考移植好的代码,
更详细可以搜索SD2.0协议
SDMA也有问题,它是大块一次读完,我测试当文件大于16M时,读取的数据就不正确了。需要修改movi_read()函数,
改成每次按512Byte字节读,直到把block num读完为止,为什么要这样,我仔细看过datasheet,
原本程序应该也是没有问题,估计三星的SDMA没有做好或有BUG,网上也可以搜到,但不多。
4.uboot1.1.6的FAT文件系统支持:
fs/fat/fat.c 此文件也有BUG,读文件目录时有问题,去uboot官网下载最新代码,
替换fs/fat/fat.c 应该可以直接替换,我是用比较工具替换的;
支持FAT文件系统后,就可以将编译好的u-boot.bin,zImage,rootfs.yaffs2文件直接复制SD卡中(将SD卡格式化为FAT32),
可以使用 fatload mmc 0:1 0x50008000 u-boot.bin ; 首先将文件放到内存,再用 nand.write 命令烧写。
5.支持yaffs2烧录:
加入了nand write.yaffs 命令,这里一定要注意,yaffs文件直接烧录到nand中, kernel是不识别的(根本没有检测到文件数据),
因为yaffs文件是按 PageSize + OOB 格式存储的,OOB是用来识别文件信息的,直接烧录所以找不到文件。
还要注意mkyaffs2image工具生成的pagesize和oob一定要和uboot的对上,否则烧进去,也是白搭。
飞凌用的是K9GAG08U0D_2G 4K pagesize的nand,
需要修改 kernel/fs/yaffs2/utils/ mkyaffs2image.c
#define chunkSize 4096//2048
#define spareSize 128//64如果使用其它mkyaffs2image.c版本,注意oob格式
关掉内核nand驱动ECC硬件检测
6.烧录uboot:
三星6410从nand启动时,控制器只支持2K pagesize,所以换成4K pagesize nand后,直接烧uboot后,
导致uboot跑不起来,可以将uboot分成每2K分别烧录4K page size的每页,
可以参考这个牛人的方法:
本来想用IROM boot启动nand(直接支持4K Pagesize),
可是bin文件需要ECC校验(其实完全不需要的,nand第1个block是有保证的),否则启动不了,取消ECC也设置不了,
还没有找到写ECC的资料,就没有搞定;
后来还是增加了 nand write.uboot 命令,也是2K一烧,4K 一跳;
修改 commom/cmd_nand.c do_nand() 函数
7.LCD显示支持:
实际生产中,不可能每个工作人员接一台电脑用串口看烧录状态,
加入了 LCD显示烧录状态(6410支持5层windows framebuffer,我用了2层,0层背景,1层OSD同时显示串口打印信息,颜色用的565),
烧录状态显示的图片存放在SD卡中(burnIcon.bin 565 raw data bmp),因为uboot很难存下480*272*2Byte的图片,烧录前nand也没法存图片,
存在SD卡是最好的。
烧录完成蜂呜器响10声。
common/lcd.c
include/confisg/smdk6410.h 定义 #define CONFIG_LCD
修改void lcd_ctrl_init(void *lcdbase) LCD控制器时序
注意:图片的字节序,我用的565是小端(低字节在前),6410 LCD控制器默认是大端(高字节在前),所以要倒序否则图片显示有些不正常:
S3C_WINCON0 = S3C_WINCONx_BPPMODE_F_16BPP_565 | S3C_WINCONx_HAWSWP_ENABLE;
8.修改开机白屏,默认背光是关闭的,framebuffer写好后,再开背光;
我们修改了LCD电路板(加一个三极管和GPIO控制LT1937 SHDN (PIN4) ,上电时自动拉低,关背光)
图片显示后再开背光(GPIO拉高),主要是防闪,平滑过渡
9.u-boot自动执行烧录命令:
在include/configs/smdk6410.h中修改 CONFIG_BOOTCOMMAND 宏,让u-boot自动执行命令
#define CONFIG_BOOTCOMMAND "fatload mmc 0:1 0x5FD00000 burnIcon.bin; "\
"nand scrub 0x00000000 0x00100000; "/*u-boot*/\
"nand erase 0x00000000 0x00100000; "\
"fatload mmc 0:1 0x50008000 u-boot.bin; "\
"nand write.uboot 0x50008000 0x00000000 $filesize; "\
"nand scrub 0x00100000 0x00300000; "\
"nand erase 0x00100000 0x00300000; "\
"fatload mmc 0:1 0x50008000 zImage; "/*kernel zImage*/\
"nand write.e 0x50008000 0x00100000 $filesize; "\
"nand scrub 0x00400000; "\
"nand erase 0x00400000; "\
"fatload mmc 0:1 0x50008000 rootfs.yaffs2; "/*root filesystem yaffs2*/\
"nand write.yaffs 0x50008000 0x00400000 $filesize; "\
"nand ok "/*beep sound ok*/
0x5FD00000 为背景层windows framebuffer的地址, burnIcon.bin为565 raw data bmp图片,直接丢到framebuffer就可以显示图片了。
注意: $filesize 代表文件的大小,所以文件大小不要超过kernel nand分区表,否则会错误。
飞凌烧cramfs时烧写大小直接写的是32M,所以大于32M时,就容易出错,并且飞凌烧yaffs2还要跑到内核去烧,不实用。
补充:之前版本是按512字节每块读的,现在改为256K每块读,速度从读100M文件需要100秒提升到只需20秒,进5倍提示,
但是我设置成512K每块读,会出现数据丢失现象。
更新代码 cpu/s3c64xx/hs_mmc.c
void movi_read (uint addr, uint start_blk, uint blknum)