s3c2416解决无法下载大于60M文件系统

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

你可能感兴趣的:(s3c2416解决无法下载大于60M文件系统)