原创文章版权所有!如需转载,请注明出处: http://hi.baidu.com/liushuiyue1/myhome谢谢合作!!!!!
六.对Nor flash的支持:
从上图的启动信息可以看到flash:0kb。Uboot还没有添加对Nor flash的支持。我们使用的nor flash型号是EN29LV160AB,与AMD的兼容,所以添加对Nor flash的支持。
#cd include/configs/// #gedit smdk6410.h // /*----------------------------------------------------------------------- * FLASH and environment organization */ #define CONFIG_SYS_FLASH_BASE 0x00000000//0x10000000Flash的基地址 #define CONFIG_SYS_MONITOR_BASE 0x00000000
#define CONFIG_SYS_MAX_FLASH_BANKS 1 /* max number of memory banks */ //一定要定义为>0 /* AM29LV160B has 35 sectors, AM29LV800B - 19 */ #define CONFIG_SYS_MAX_FLASH_SECT 35//40硬件得来
#define CONFIG_AMD_LV800 //#define CONFIG_SYS_FLASH_CFI 1 /* Use CFI parameters (needed?) */ #define PHYS_FLASH_SIZE 0x200000 //2M Flash的大小 #define PHYS_FLASH_1 0x00000000 /* Use drivers/cfi_flash.c, even though the flash is not CFI-compliant */ //CFI相关的屏蔽掉 //#define CONFIG_FLASH_CFI_DRIVER 1 //#define CONFIG_SYS_FLASH_CFI_WIDTH FLASH_CFI_16BIT //#define CONFIG_FLASH_CFI_LEGACY //#define CONFIG_SYS_FLASH_LEGACY_512Kx16
/* timeout values are in ticks */ #define CONFIG_SYS_FLASH_ERASE_TOUT (5 * CONFIG_SYS_HZ) /* Timeout for Flash Erase */ #define CONFIG_SYS_FLASH_WRITE_TOUT (5 * CONFIG_SYS_HZ) /* Timeout for Flash Write */ #define CONFIG_ENV_ADDR 0x00000 #define CONFIG_ENV_SIZE 0x4000 /* Total Size of Environment Sector */ |
说明:Uboot2010.03中支持Nor flash的两种读写方式:CFI和JEDEC。本文章采用JEDEC的方式。因为S3C2440和S3C6410的nor flash接口兼容,所以将S3C2440目录下的flash.c复制到./board/samsung/s3c6410/下,并修改Makefile文件。
#cd board/samsung/s3c6410/Makefile// #gedit Makefile // COBJS-y := smdk6410.o flash.o |
重新编译Uboot并下载到Nand Flash中,串口打印信息如下。说明板子已经能检测到Nor flash。
七.Uboot支持yaffs2文件的读写
由于Uboot本身支持yaffs2文件的读写直接修改./include/configs/smdk6410.h的配置文件,使得uboot支持yaffs2的读写,重新编译Uboot并下载到Nand Flash中,串口打印信息如下,uboot已经支持yaffs2烧写到nand flash(由于本人对于此uboot中指令不熟悉,所以至今还未写yaffs2文件成功,如有知道的可告知,谢谢)。
于是又重新手动yaffs2文件的烧写指令。首先修改./include/configs/smdk6410.h
#cd include/configs/smdk6410.h// #define CONFIG_YAFFS2 |
于是又重新手动yaffs2文件的烧写指令。
1) 修改./include/configs/smdk6410.h
注意一定要屏蔽掉CONFIG_YAFFS2,否则yaffs文件读写有冲突。
#cd include/configs/smdk6410.h// //#define CONFIG_YAFFS2 #define CONFIG_SYS_NAND_YAFFS_WRITE 1 /* support yaffs write EN */ #define CONFIG_MTD_NAND_ECC_YAFFS 1 |
2)修改common/cmd_nand.c
在373行,红色字体为添加部分 if (!s || !strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i")) { if (read) ret = nand_read_skip_bad(nand, off, &size, (u_char *)addr); else ret = nand_write_skip_bad(nand, off, &size, (u_char *)addr); } #if defined(ENABLE_CMD_NAND_YAFFS) }else if ( s != NULL && (!strcmp(s, ".yaffs") || !strcmp(s, ".yaffs1"))){ if(read) { printf("nand read.yaffs[1] is not provide temporarily!"); } else { nand->rw_oob = 1; #if defined(ENABLE_CMD_NAND_YAFFS_SKIPFB) nand->skipfirstblk = 1; #else nand->skipfirstblk = 0; #endif ret = nand_write_skip_bad(nand,off,&size,(u_char *)addr); #if defined(ENABLE_CMD_NAND_YAFFS_SKIPFB) nand->skipfirstblk = 0; #endif nand->rw_oob = 0; } #endif } else if (!strcmp(s, ".oob")) { /* out-of-band data */ mtd_oob_ops_t ops = { .oobbuf = (u8 *)addr, .ooblen = size, .mode = MTD_OOB_RAW }; 在505行添加,红色字体为添加部分 "nand erase [clean] [off size] - erase 'size' bytes from/n" " offset 'off' (entire device if not specified)/n" #if defined(CONFIG_SYS_NAND_YAFFS_WRITE) "nand read[.yaffs[1]] is not provide temporarily/n" "nand write[.yaffs[1]] addr off size -write the 'size' byte yaffs image starting/n" "at offset 'off' from memory address 'addr' (.yaffs for 512+16 Nand)" #endif "nand bad - show bad blocks/n"
|
3)drivers/mtd/nand/nand_base.c
在2095行处红色字体为修改部分: static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const uint8_t *buf) { struct nand_chip *chip = mtd->priv; int ret;
#if defined(CONFIG_SYS_NAND_YAFFS_WRITE) int oldopsmode = 0; if(mtd->rw_oob==1) { size_t oobsize =mtd->oobsize; size_t datasize = mtd->writesize; int i=0; uint8_t oobtemp[oobsize]; int datapages = 0; datapages = len/(datasize); for(i=0;i<(datapages);i++) { memcpy((void *)oobtemp,(void *)(buf+datasize*(i+1)),oobsize); memmove((void *)(buf+datasize*(i+1)),(void *)(buf+datasize*(i+1)+oobsize),(datapages-(i+1))*(datasize)+(datapages-1)*oobsize); memcpy((void *)(buf+(datapages)*(datasize+oobsize)-oobsize),(void *)(oobtemp),oobsize); } } #endif
/* Do not allow reads past end of device */ if ((to + len) > mtd->size) return -EINVAL; if (!len) return 0; nand_get_device(chip, mtd, FL_WRITING); chip->ops.len = len; chip->ops.datbuf = (uint8_t *)buf; #if !defined(CONFIG_SYS_NAND_YAFFS_WRITE) chip->ops.oobbuf = NULL; #endif #if defined(CONFIG_SYS_NAND_YAFFS_WRITE) if(mtd->rw_oob!=1) { chip->ops.oobbuf = NULL; } else { chip->ops.oobbuf = (uint8_t*)(buf+len); chip->ops.ooblen = mtd->oobsize; oldopsmode = chip->ops.mode; chip->ops.mode = MTD_OOB_RAW; } #endif ret = nand_do_write_ops(mtd, to, &chip->ops);
*retlen = chip->ops.retlen;
nand_release_device(mtd); #if defined(CONFIG_SYS_NAND_YAFFS_WRITE) chip->ops.mode = oldopsmode; #endif
return ret; } |
4)修改drivers/mtd/nand/nand_util.c
int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, u_char *buffer) { int rval; size_t left_to_write = *length; size_t len_incl_bad; u_char *p_buffer = buffer;
#if defined(CONFIG_SYS_NAND_YAFFS_WRITE) if(nand->rw_oob==1) { size_t oobsize=nand->oobsize; size_t datasize = nand->writesize; int datapages = 0;
if(((*length)%(nand->oobsize+nand->writesize))!=0) { printf("Attempt to write error lenght data!/n"); return -EINVAL; } datapages = *length/(datasize+oobsize); *length = datapages*datasize; left_to_write = *length; } #endif /* Reject writes, which are not page aligned */ if ((offset & (nand->writesize - 1)) != 0 || (*length & (nand->writesize - 1)) != 0) { printf ("Attempt to write non page aligned data/n"); return -EINVAL; }
len_incl_bad = get_len_incl_bad (nand, offset, *length);
if ((offset + len_incl_bad) > nand->size) { printf ("Attempt to write outside the flash area/n"); return -EINVAL; }
#if !defined(CONFIG_SYS_NAND_YAFFS_WRITE) if (len_incl_bad == *length) { rval = nand_write (nand, offset, length, buffer); if (rval != 0) printf ("NAND write to offset %llx failed %d/n", offset, rval);
return rval; } #endif
while (left_to_write > 0) { size_t block_offset = offset & (nand->erasesize - 1); size_t write_size;
WATCHDOG_RESET ();
if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) { printf ("Skip bad block 0x%08llx/n", offset & ~(nand->erasesize - 1)); offset += nand->erasesize - block_offset; continue; } #if defined(CONFIG_SYS_NAND_YAFFS_WRITE) if (nand->skipfirstblk==1) { nand->skipfirstblk = 0; printf("Skip the first good block%llx/n",offset&~(nand->erasesize-1)); offset+=nand->erasesize-block_offset; continue; } #endif
if (left_to_write < (nand->erasesize - block_offset)) write_size = left_to_write; else write_size = nand->erasesize - block_offset; printf("/rWriting at 0x%llx--",offset);
rval = nand_write (nand, offset, &write_size, p_buffer); if (rval != 0) { printf ("NAND write to offset %llx failed %d/n", offset, rval); *length -= left_to_write; return rval; } left_to_write -= write_size; printf("%d%% is complete",100-(left_to_write/(*length/100))); offset += write_size;
// p_buffer += write_size; #if defined(CONFIG_SYS_NAND_YAFFS_WRITE) if(nand->rw_oob==1) { p_buffer+=write_size+(write_size/nand->writesize*nand->oobsize); } else { p_buffer+=write_size; } #else p_buffer += write_size; #endif } return 0; }
|
5)修改include/linux/mtd/mtd.h
在131行添加红色字体部分 #if defined(CONFIG_SYS_NAND_YAFFS_WRITE) u_char rw_oob; u_char skipfirstblk; #endif |
重新编译uboot并下载到Nand Flash中,使用nand指令烧写yaffs2文件到nand中如下图所示,至此uboot已支持yaffs的烧写。
对于uboot的yaffs2文件的烧写一定要是2048+64个字节的整数倍,否则烧写将出错,说明页面烧写不成功。
八.支持串口xmodem协议
U-Boot默认支持的loadb命令需要配合Linux下的kermit工具来使用,loady命令通过串口ymodem协议来传输文件。Windows下的超级终端虽然支持ymodem,但是它的使用界面实在不友好。而SecureCRT只支持xmodem和zmodem。而上位机和开发板之间的文件传输又实在是一件非常重要的事,所以现在修改代码以增加对xmodem的支持,即增加一个命令loadx。
1)依照loady的实现来编写代码,首先使用U_BOOT_CMD宏来增加loadx命令(在文件common/cmd_load.c文件中):
U_BOOT_CMD( loadx, 3, 0, do_load_serial_bin, "load binary file over serial line (xmodem mode)", "[ off ] [ baud ]/n" " - load binary file over serial line" " with offset 'off' and baudrate 'baud'" ); |
2)依照loady在do_load_serial_bin函数中增加对loadx命令的处理分支。
else if(strcmp(argv[0],"loadx")==0) { printf ("## Ready for binary (xmodem) download " "to 0x%08lX at %d bps.../n", offset, load_baudrate); addr = load_serial_xmodem (offset); } |
3)由于addr行调用了load_serial_xmodem函数,依照load_serial_ymodem实现的一个函数。首先在文件开头增加loadx_serial_xmodem函数的声明,然后复制load_serial_ymodem函数为load_serial_xmodem,稍作修改:(1)、将局部数组ymodemBuf改名为xmodemBuf,并在后面使用到的地方统一修改,这只是为了与函数名称一致,可改可不改。(2)、info.mode的值从xyzModem_ymodem改为xyzModem_xmodem。
#if defined(CONFIG_CMD_LOADB) static ulong load_serial_ymodem (ulong offset); static ulong load_serial_xmodem (ulong offset); #endif |
重新编译,执行loadx,然后在secureCRT的Transfer菜单下点Send Xmodem(xxx已经放在了Upload目录里),完成对串口xmodem协议的支持。