全部博文(11)
分类: LINUX
2009-05-21 02:30:43
1.2.5 修改u-boot支持烧写yaffs映像文件
(1) 在/common/cmd_nand.c中do_nand函数中,加入代码,实现对nand write.yaffs命令的支持。在对jffs2操作的下面加入,如下:
在else if (s != NULL && !strcmp(s, ".oob"))前加入
else if(s != NULL && !strcmp(s, ".yaffs"))
{
if(read)
{
printf("nand read.yaffs is not provide!"); /*不支持读取yaffs*/
}
else
{
nand->writeoob = 1;
ret = nand_write_skip_bad(nand,off,&size,(u_char *)addr); //写入yaffs
nand->writeoob = 0;
}
}
在 nand 的命令中加入对 nand write.yaffs 的描述,加入如下3行:
" to/from memory address 'addr', skipping bad blocks.\n"
"nand write.yaffs - addr off|partition size\n"
" write 'size' bytes starting at offset 'off'\n"
" to/from yaffs image in memory address 'addr', skipping bad blocks.\n"
"nand erase [clean] [off size] - erase 'size' bytes from\n"
(2) 在include/linux/mtd/mtd.h的 mtd_info 结构体定义中加入两个变量如下:
struct mtd_info {
u_char writeoob;
u_char skipfirstblock;
u_char type;
u_int32_t flags;
u_int32_t size; /* Total size of the MTD */
(3) 在drivers/mtd/nand/nand_util.c的nand_write_skip_bad函数中加两段程序,一段是为了计算正常数据的长度,一段是为了在写入一段数据后,数据指针能正常跳到下一段数据,修改如下:
size_t left_to_write = *length;
size_t len_incl_bad;
u_char *p_buffer = buffer;
/*这段程序主要是从yaffs映像中提取要写入的正常数据的长度,即不包括oob数据的数据长度*/
if(nand->writeoob==1)
{
size_t oobsize = nand->oobsize; //定义oobsize的大小
size_t datasize = nand->writesize;
int datapages = 0;
//长度不是528整数倍,认为数据出错。
if (((*length)%(nand->oobsize+nand->writesize)) != 0) {
printf ("Attempt to write error length data!\n");
return -EINVAL;
}
datapages = *length/(datasize+oobsize);
*length = datapages*datasize;
left_to_write = *length;
nand->skipfirstblock=1;
}
/* Reject writes, which are not page aligned */
以下的程序程序本意是没有坏块时,不进行坏块检查直接写,但没有达到目的,所以注释掉:
/*if (len_incl_bad == *length) {
printf("first write\n");
rval = nand_write (nand, offset, length, buffer);
if (rval != 0) {
printf ("NAND write to offset %x failed %d\n",
offset, rval);
return rval;
}
}*/
在while(left_to_write>0)循环中添加:
offset += nand->erasesize - block_offset;
continue;
}
if(nand->skipfirstblock==1) //如需跳过第一个好块,则跳过第一个好块。
{
nand->skipfirstblock=0;
printf ("Skip the first good block 0x%08x\n",
offset & ~(nand->erasesize - 1));
offset += nand->erasesize - block_offset;
continue;
}
if (left_to_write < (nand->erasesize - block_offset))
write_size = left_to_write;
修改p_buffer处的代码如下:
left_to_write -= write_size;
printf("%ld%% is complete.",100-(left_to_write/(*length/100)));
offset += write_size;
//p_buffer += write_size;
if(nand->writeoob==1)
{
p_buffer += write_size+(write_size/nand->writesize*nand->oobsize);
}
else
{
p_buffer += write_size;
}
(4)在/drivers/mtd/nand/nand_base.c的nand_write函数中,加入一段把正常数据与oob数据分离的代码,再加入页写时的模式设置为MTD_OOB_RAW,在页写时,不进行ECC的校验,ECC的校验在yaffs的oob数据中已自带了,不能重写。此模式下,写入正常数据后,会把oob的数据写入nand的oob区。修改后如下:
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;
//printf("0 len is %d ",len);
//此段数据是将要写入的数据中的正常数据移到buf中的前段,把oob数据移到后段。
int oldopsmode = 0;
if(mtd->writeoob==1)
{
size_t oobsize = mtd->oobsize; //定义oobsize的大小
size_t datasize = mtd->writesize;
int i = 0;
uint8_t oobtemp[16];
int datapages = 0;
datapages = len/(datasize); //传进来的len是没有包括oob的数据长度
for(i=0;i<(datapages);i++)
{
memcpy(oobtemp,buf+datasize*(i+1),oobsize);
memmove(buf+datasize*(i+1),buf+datasize*(i+1)+oobsize,(datapages-(i+1))*(datasize)+(datapages-1)*oobsize);
memcpy(buf+(datapages)*(datasize+oobsize)-oobsize,oobtemp,oobsize);
}
}
//printf("1 len is %d ",len);
/* Do not allow reads past end of device */
if ((to + len) > mtd->size)
return -EINVAL;
if (!len)
//return 0;
{printf("Write data length is %d ",len);return 0;}
nand_get_device(chip, mtd, FL_WRITING);
chip->ops.len = len;
chip->ops.datbuf = (uint8_t *)buf;
//chip->ops.oobbuf = NULL;
if(mtd->writeoob!=1)
{
chip->ops.oobbuf = NULL;
}
else
{
chip->ops.oobbuf = (uint8_t *)(buf+len); //将oob缓存的指针指向buf的后段,即oob数据区的起始地址。
chip->ops.ooblen = mtd->oobsize;
oldopsmode = chip->ops.mode;
chip->ops.mode = MTD_OOB_RAW; //将写入模式改为直接书写oob区,即写入数据时,不进行ECC校验的计算和写入。(yaffs映像的oob数据中,本身就带有ECC校验)
}
ret = nand_do_write_ops(mtd, to, &chip->ops);
*retlen = chip->ops.retlen;
nand_release_device(mtd);
chip->ops.mode = oldopsmode; //恢复原模式
return ret;
}
/* Do not replace user supplied command function ! */
if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
chip->cmdfunc = nand_command_lp;
//MTDDEBUG (MTD_DEBUG_LEVEL0, "NAND device: Manufacturer ID:"
// " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id,
// nand_manuf_ids[maf_idx].name, type->name);
printf("NAND device: Manufacturer ID:"
" 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id,
nand_manuf_ids[maf_idx].name, type->name);
return type;
}
1.2.6 修改DM9000驱动
修改文件 u-boot-2008.10/drivers/net/dm9000x.c
/* Enable TX/RX interrupt mask */
DM9000_iow(DM9000_IMR, IMR_PAR);
/* 注释掉与MII接口相关的语句----*/
#if 0
i = 0;
while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */
udelay(1000);
……
break;
}
printf("mode\n");
#endif
return 0;
}