硬件配制内存64M,nandflash 128M,我的u-boot版本为1.3.4
由于内存太小,无法下载大于60M的文件系统,我这里说下如何从TF更新大于60M的文件系统。
首先从TF卡 启动更新系统你需要移植fat,mmc相关支持,这里我已经移植好了具体过程我就不说了.这些移植完成后。
最开始是可以使用如下命令进行更新的:
fatload mmc 0 0xc0000000 /gzsd/u-boot.bin; nand erase bios; nand write.jffs2 0xc0000000 bios $(filesize)bios为u-boot分区信息。60M文件之所以无法下载是因为内存不够引起的,所以首先要找到读文件是在哪里,跟踪代码最后找到fat.c文件。
在函数get_contents中有这样几条代码:
/* get remaining clusters */ if (get_cluster(mydata, curclust, buffer, (int)actsize) != 0) { FAT_ERROR("Error reading cluster\n"); return -1; } /* get remaining bytes */ gotsize += (int)actsize; filesize -= actsize; buffer += actsize; actsize= filesize; if (get_cluster(mydata, endclust, buffer, (int)actsize) != 0) { FAT_ERROR("Error reading cluster\n"); return -1; }具体读的过程就是在get_cluster函数里
static int get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size) { int idx = 0; __u32 startsect; if (clustnum > 0) { startsect = mydata->data_begin + clustnum*mydata->clust_size; } else { startsect = mydata->rootdir_sect; } FAT_DPRINT("gc - clustnum: %d, startsect: %d\n", clustnum, startsect); if (disk_read(startsect, size/FS_BLOCK_SIZE , buffer) < 0) { FAT_DPRINT("Error reading data\n"); return -1; } if(size % FS_BLOCK_SIZE) { __u8 tmpbuf[FS_BLOCK_SIZE]; idx= size/FS_BLOCK_SIZE; if (disk_read(startsect + idx, 1, tmpbuf) < 0) { FAT_DPRINT("Error reading data\n"); return -1; } buffer += idx*FS_BLOCK_SIZE; memcpy(buffer, tmpbuf, size % FS_BLOCK_SIZE); return 0; } return 0; }接下来我主要对这两个函数进行修改,我的实现过程是将文件系统分次读写,先读20几M然后开始写到flash里,然后在读20几M写到flash里,反复这样的操作.
首先在文件前面增加向个全局变量和宏定义
#define BUF_SIZE (2112*1024*10) #define B_ADDR 0x0 #define K_ADDR 0x300000 #define R_ADDR 0x700000 static long nandaddr=0; static long memaddr=0xc0000000; static int wnandflags = 0;其中BUF_SIZE为每次读写的字节,有一点需要注意这里的大小不是可以任意修改。在写yaffs文件的时候有一个大小的判断。具体请看u-boot源码下的drivers/mtd/nand/nand_util.c
函数:
int nand_write_skip_bad_yaffs里面有如下代码:
if (*length % (nand->writesize + nand->oobsize)) { *length = (*length / (nand->writesize + nand->oobsize)+1)*(nand->writesize + nand->oobsize); }length为你写的文件的大小,而其中
nand->writesize + nand->oobsize就是2112字节
同时BUF_SIZE还必需满足以下两个条件:
1.必需是512的倍数,因为TF卡里一个扇区是512字节,如果不是512字节可能导致数据最后加起来不对
2.必需是2*1024的倍数,yaffs文件好像不需要满足这个,这个只针对u-boot和内核,因为nandflash是以2K对齐的,如果内核大于BUF_SIZE了这个就需要用到了。
B_ADDR u-boot在nand flash里的起始地址 K_ADDR内核在nand flash里的起始地址 R_ADDR为文件系统在nand flash里的起始地址.
这两个函数修改后如下:
static int gzsd_get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size) { int idx = 0; __u32 startsect; char cmd_buf[200]; unsigned long wsize; unsigned long tmpmem,tmpnand; int times,i,tmpsize; __u8 *dmem=(unsigned char *)0xc0000000; if (clustnum > 0) { startsect = mydata->data_begin + clustnum*mydata->clust_size; } else { startsect = mydata->rootdir_sect; } FAT_DPRINT("gc - clustnum: %d, startsect: %d\n", clustnum, startsect); if(size > BUF_SIZE) { times = size / BUF_SIZE; tmpmem = memaddr; tmpnand = nandaddr; tmpsize = BUF_SIZE; for(i=0;i<times;i++) { if (disk_read(startsect, tmpsize/FS_BLOCK_SIZE , dmem) < 0) { FAT_DPRINT("Error reading data\n"); return -1; } if(tmpsize % FS_BLOCK_SIZE) printf("*****************************\n"); if(wnandflags) { sprintf(cmd_buf, "nand write.yaffs 0x%x 0x%x 0x%x", tmpmem, tmpnand, tmpsize); printf("nand write.yaffs 0x%x 0x%x 0x%x", tmpmem, tmpnand, tmpsize); run_command(cmd_buf, 0); } else { sprintf(cmd_buf, "nand write.jffs2 0x%x 0x%x 0x%x", tmpmem, tmpnand, tmpsize); printf("nand write.jffs2 0x%x 0x%x 0x%x", tmpmem, tmpnand, tmpsize); run_command(cmd_buf, 0); } //buffer += BUF_SIZE; startsect += tmpsize/FS_BLOCK_SIZE; //tmpmem += tmpsize; tmpnand += tmpsize; } if(size % BUF_SIZE) { tmpsize = size % BUF_SIZE; if (disk_read(startsect, tmpsize/FS_BLOCK_SIZE , dmem) < 0) { FAT_DPRINT("Error reading data\n"); return -1; } if(tmpsize % FS_BLOCK_SIZE) { __u8 tmpbuf[FS_BLOCK_SIZE]; idx= tmpsize/FS_BLOCK_SIZE; if (disk_read(startsect + idx, 1, tmpbuf) < 0) { FAT_DPRINT("Error reading data\n"); return -1; } dmem += idx*FS_BLOCK_SIZE; memcpy(dmem, tmpbuf, tmpsize % FS_BLOCK_SIZE); } if(wnandflags) { wsize = tmpsize; sprintf(cmd_buf, "nand write.yaffs 0x%x 0x%x 0x%x", tmpmem, tmpnand, wsize); printf("nand write.yaffs 0x%x 0x%x 0x%x", tmpmem, tmpnand, wsize); run_command(cmd_buf, 0); } else { if(tmpsize % (2*1024) != 0) wsize = ((tmpsize/(2*1024)) + 1)*(2*1024); else wsize = tmpsize; sprintf(cmd_buf, "nand write.jffs2 0x%x 0x%x 0x%x", tmpmem, tmpnand, wsize); printf("nand write.jffs2 0x%x 0x%x 0x%x", tmpmem, tmpnand, wsize); run_command(cmd_buf, 0); } } } else { // < BUF_SIZE if (disk_read(startsect, size/FS_BLOCK_SIZE , dmem) < 0) { FAT_DPRINT("Error reading data\n"); return -1; } if(size % FS_BLOCK_SIZE) { __u8 tmpbuf[FS_BLOCK_SIZE]; idx= size/FS_BLOCK_SIZE; if (disk_read(startsect + idx, 1, tmpbuf) < 0) { FAT_DPRINT("Error reading data\n"); return -1; } dmem += idx*FS_BLOCK_SIZE; memcpy(dmem, tmpbuf, size % FS_BLOCK_SIZE); } if(wnandflags) { wsize = size; sprintf(cmd_buf, "nand write.yaffs 0x%x 0x%x 0x%x", memaddr, nandaddr, wsize); printf("nand write.yaffs 0x%x 0x%x 0x%x", memaddr, nandaddr, wsize); run_command(cmd_buf, 0); } else { if(size % (2*1024) != 0) wsize = ((size/(2*1024)) + 1)*(2*1024); else wsize = size; sprintf(cmd_buf, "nand write.jffs2 0x%x 0x%x 0x%x", memaddr, nandaddr, wsize); printf("nand write.jffs2 0x%x 0x%x 0x%x", memaddr, nandaddr, wsize); run_command(cmd_buf, 0); } } return 0; } /* * Read at most 'maxsize' bytes from the file associated with 'dentptr' * into 'buffer'. * Return the number of bytes read or -1 on fatal errors. */ static long get_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer, unsigned long maxsize) { unsigned long filesize = FAT2CPU32(dentptr->size), gotsize = 0; unsigned int bytesperclust = mydata->clust_size * SECTOR_SIZE; __u32 curclust = START(dentptr); __u32 endclust, newclust; unsigned long actsize; FAT_DPRINT("Filesize: %ld bytes\n", filesize); if (maxsize > 0 && filesize > maxsize) filesize = maxsize; FAT_DPRINT("Reading: %ld bytes\n", filesize); printf("Reading: %ld bytes\n", filesize); if(filesize < (1*1024*1024)) { nandaddr = B_ADDR; wnandflags = 0; } else if((filesize > (1*1024*1024)) && (filesize < (10*1024*1024))) { nandaddr = K_ADDR; wnandflags = 0; } else if(filesize > (10*1024*1024)) { nandaddr = R_ADDR; wnandflags = 1; } memaddr = 0xc0000000; actsize=bytesperclust; endclust=curclust; do { /* search for consecutive clusters */ while(actsize < filesize) { newclust = get_fatent(mydata, endclust); if((newclust -1)!=endclust) goto getit; if (CHECK_CLUST(newclust, mydata->fatsize)) { FAT_DPRINT("curclust: 0x%x\n", newclust); FAT_DPRINT("Invalid FAT entry\n"); return gotsize; } endclust=newclust; actsize+= bytesperclust; } /* actsize >= file size */ actsize -= bytesperclust; #if 1 #if 0 /* get remaining clusters */ if (gzsd_get_cluster(mydata, curclust, buffer, (int)actsize) != 0) { FAT_ERROR("Error reading cluster\n"); return -1; } /* get remaining bytes */ gotsize += (int)actsize; filesize -= actsize; //buffer += actsize; nandaddr += actsize; //memaddr += actsize; actsize= filesize; if (gzsd_get_cluster(mydata, endclust, buffer, (int)actsize) != 0) { FAT_ERROR("Error reading cluster\n"); return -1; } #else /* get remaining clusters */ if (gzsd_get_cluster(mydata, curclust, buffer, filesize) != 0) { FAT_ERROR("Error reading cluster\n"); return -1; } #endif #else /* get remaining clusters */ if (get_cluster(mydata, curclust, buffer, (int)actsize) != 0) { FAT_ERROR("Error reading cluster\n"); return -1; } /* get remaining bytes */ gotsize += (int)actsize; filesize -= actsize; buffer += actsize; actsize= filesize; if (get_cluster(mydata, endclust, buffer, (int)actsize) != 0) { FAT_ERROR("Error reading cluster\n"); return -1; } #endif gotsize+=actsize; return gotsize; getit: if (get_cluster(mydata, curclust, buffer, (int)actsize) != 0) { FAT_ERROR("Error reading cluster\n"); return -1; } gotsize += (int)actsize; filesize -= actsize; buffer += actsize; curclust = get_fatent(mydata, endclust); if (CHECK_CLUST(curclust, mydata->fatsize)) { FAT_DPRINT("curclust: 0x%x\n", curclust); FAT_ERROR("Invalid FAT entry\n"); return gotsize; } actsize=bytesperclust; endclust=curclust; } while (1); }get_cluster不作修改,因为还有一个地方需要用到,这里新增加一个gzsd_get_cluster函数,将nand的写操作也增加进去了,现在只需要执行:
fatload mmc 0 0xc0000000 /gzsd/root.bin就可以完成烧写.