硬件配制内存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就可以完成烧写.