打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
uboot具体实现yaffs2深入学习.nand操作流程图

uboot具体实现yaffs2深入学习.nand操作流程图

初学嵌入式,初学uboot。之前移植过uboot一两次。第三次在实现yaffs2功能时,总是verify错误,我3天硬是没检查出来,

所以才深入学习了uboot实现yaffs2的过程。这是我的总结,画了nand处理yaffs2的流程图,供以后自己查阅,同时供入门网友们参考。

由于我没学到驱动编写,mtd结构还很多不懂,写的很肤浅,大家勿见怪,请多多指教,先谢! :D

ubootyaffs2移植时代码的更改,参见hbhuanggang老师:

http://blog.chinaunix.net/space.php?do=serial&id=3018&uid=22174347

-------------------------------------------------------------------------------------------------------------------------------

uboot输入例如 nand write.yaffs2 30008000 8000000 18c0的写yaffs2命令后.将进入do_nand()函数;

首先从argv[1]提取cmd=write.yaffs2;

内存地址addr=30008000;   nand地址off=800 0000;    yaffs2文件大小 size=18c0;

修改rw_oob=1 表示写nand时要写入oob数据.

skipfirstblk 表示跳过第一个好块.现在off=800 0000 +blocksize=802 0000.

然后进入第一个调用函数nand_write_skip_bad();

总结:do_nand()函数只简单读取输入参数,判断操作类型,调用对应函数;

 

进入nand_write_skip_bad():

首先计算数据将占用nand页数(datapage),然后是data长度(length).判断给入的地址是否合法.

计算跳过坏快后,数据实际会占用的长度len_incl_bad,这个变量加上offset检测写数据是否将超出nand容量.

然后进入写数据的循环,这里循环一次,写完一个block;

循环内:

首先判断将要操作的下一块是否坏块,若是坏快,继续判断之后一块.    若是好块,则开始写这一块;

第一次要跳过一个好块,修改offset,指向下一块(这里我图画得不好,skipfirstblk只会执行一次,而我画得每次都执行.注意);

下一步计算此次要写的数据量write_size,这里分两种情况,一是数据还很多,这次要写满一块.

另一种是数据快结束了,不足一块,此时write_size等于剩下的数据left_to_write;

然后将write_size传给下一个函数nand_write();

写完这一块之后,更新参数,off += write_size;   left_to_write -=write_size; P_buffer +=write_size+(write_size/pagesize*oob_size);

(这里为什么p_buffer要多加上一部份呢,我们不是只要求写了write_size个数据,而且给下一个函数传参也是write_size,为什么指针地址要

改变这么多呢.这是因为,我们是yaffs2数据,写模式为raw,后续的函数,会从buf里取出oob数据,一起写进页里.   所以虽然值要求写write_size,

但却多写了几个oob数据. 同时,以后要记住,如果我们要写oob数据,传参的长度,也应该只是data长度,不是总长度.)

本次写一块结束,开始下一次循环.....

总结:nand_write_skip_bad寻找好的块,把数据以块为单位,一块一块地写入nand flash.

nand_write_skip_bad进入到nand_write:

首先计算出此次要求写入的数据,将占用多少页.1~64.

然后整理此次传入的数据,因为yaffs2的数据里,含有oob数据,现在要把oob数据分离出来,集中到最后边.

2048+64 |2048+64 |2048+64 |2048+64|整理成:

2048+2048+2048+2048 |64+64+64+64|.

然后将NAND现在的结构情况写入struct nand_chip *chip, 这个结构体是用来描述NAND;

主要更新了chip->ops这个结构体的内容:

struct mtd_oob_ops {
    mtd_oob_mode_t    mode;      =  MTD_OOB_RAW;//
是在这里设置了模式
    size_t        len;                         =  len             //data
长度 (1~64)&2048
    size_t        retlen;                    
               //data区写入的长度,完成写时候,返回值存在这里
;
    size_t        ooblen;                   =  oobsize     //oob
长度
0~64
    size_t        oobretlen;              
                //oob区写入的长度,oob函数返回这个值
;
    uint32_t    ooboffs;                   0x0             //
但是没找到在哪赋值的
,    
    uint8_t        *datbuf;                 =  buf            //data
指针

    uint8_t        *oobbuf;                =  buf+len     //oob
数据的指针,因为上边整理了oob,就是这个位置了;
};

进入nand_do_write_ops();进行写数据;

总结:nand_write()还没真正的写nand,只是整理oob,更新data,oob数据指针,data,oob区长度.即为下个函数准备参数.

来到nand_do_write_ops:首先定义几个变量,存储几个熟悉的值.

ooboob指针,  bufbuf指针,  writelendata长度(1~64)&2048,  已写data长度ops->retlen归零.

检查to,   writelen是否对齐, 用的是这个宏来检测:
#define NOTALIGNED(x)    (x & (chip->subpagesize - 1)) != 0

开头例子:to等于802 0000&(512-1)=0writelen也对齐,因为正确的yaffs2格式数据是2048+64=2112的倍数(multiple of 2112)

其中writelendata长度,由page*2048算出,所以 page*2048 & (511-1) = 0

//subpagesize是什么意思?留一下.

计算,column = to & (mtd->writesize - 1) = 802 0000 & (2048-1) = 0;
        subpage = column||(writelen & (mtd->writesize - 1))         = 0 || (page*2048&(2048-1)) = 0;
这是或者|| 不是位或.

这里yaffs2 subpage肯定为0,因为yaffs2长度是2048+64,column0,subpage0;

if(subpage&oob)其他数据格式应该才有用.

chipnr=to>>28;  0;执行nand_select_chip() 320.但是chipnr=0,什么都没做?;

realpage=802 0000>>11 0x10040; page=10040&1FFFF=10040;确定数据要写在哪一页.

 blockmask = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1= 1<<(17-11)-1= 3F;

下面进入又一个while循环,每次循环写一页!(前面第一个while循环,把数据分成块来书写,这里再分成页来书写)

循环变量:

byte=mtd->writesize(2048), wbuf=buf.

cached = writelen > bytes && page != blockmask = 1 && 0  //变量意义不明.

if(partial wirite 写部分页),yaffs2不存在这种情况。

调用nand_fill_oob(),很简单,把当前要写这页的oob数据memcpychip->oob_poi+obboffs位置;

我不是很清楚为什么要这么个位置,chip->ops->oobbuf现成的不能用吗?

下面是google的一句话:

@oob_poi: poison value buffer

It seems like the oob_poi buffer is meant to be an intermediary(中间媒介) bufferfor

storing the laid-out OOB data; it's used by the NAND subsystem,especially in mode

MTD_OOB_AUTO, to layout data to be written. But this"documentation" means

absolutely nothing to me.

oob放到相应位置后,chip->nand_write(),这个函数真正开始写data+oob;

一页写完之后,更新变量,writelen -= bytes,buf += bytes, column = 0,realpage++;

判断数据写完没,写完则返回,没完就要判断下一个页号page,判断是否当前nand设备写完,取消始能,

再始能下一片nand.继续写下一页...直到写完0~64,nand_dowrite_ops()函数返回.

总结:nand_do_write_ops()函数首先始能nand,并把数据分成一页一页大小,把此页oob拷贝到chip->oob_opi,

下面的函数调用这个地址;


总于到了最内层一个函数,nand_write_page(),真正的写页;

第一,NFCMD寄存器发送写页命令0x80,并提供地址;

nand准备好后,cmdfunc函数返回,现在可以开始发送数据到NFDATA寄存器了;

调用ecc.write_page_raw(),可以看到就是先写data,再写oob,比较简单;

写完之后,发送命令0x10,表示写结束,然后马上进行校验是否写成功,读出此次写的数据,READ0指令.

然后读出数据,buf里的内容循环比较; if (buf[i] != readb(chip->IO_ADDR_R))

不同就返回verify错误,正确就返回0;

总结:nand_write_page(),先后写一页的data,oob,然后校验. 结束.

 

我这次移植结束,每次写yaffs2文件,总是遇到verify错误,也就是一直没写成功。直到把一个block写成坏块,跳到下一个好块去写数据,

就成功了。正是形成的这个坏块,我检查出了问题。

我把我的操作写出来,大家看看哪里错了。

tftp 30008000 testyaffs2.img

-ok,长度0x18c0

nand erase 8000000 20000

-ok

nand write.yaffs2 30008000 8000000 18c0;

-fail;

,就错在那个20000,虽然数据只有18c0,不足一块,我擦出了一块.

但是第一块,skipfirstblk跳过了,数据写在了下一块.由于没擦除,所以写不上,所以verify错误;

所以以后数据校验错误,首先检查擦出成功没。

 遗留问题:

0nand_write()函数有5个参数,怎么调用的时候只给了4???我添加了printf语句,程序的确跑到那里了,说明函数没找错,

       这里是直接调用函数名,少一个参数不知到怎么处理的.

解答: static inline int nand_write(nand_info_t *info, loff_t ofs, size_t *len, u_char *buf)
{
    return info->write(info, ofs, *len, (size_t *)len, buf);
}

1subpagesizeif(subpage&oob)什么含义。

2chip->cmdfuncNFCMD发送命令函数对0x80的处理没看到,函数可能找错了;

解答:nand_get_flash_type()函数查找id,进而决定chip->cmdfunc函数指针,大页指向:nand_command_lp(),小页指向:nand_command();

3chip->select_chip(mtd,chipnr); 函数实现里,chipnr -1,表示取消始能,0却没操作;是不是函数又找错了...

解答:nand的始能在nand_command()函数操作的,这里select_chip是空操作.这个函数只能传-1,取消片选;

4do_nand_write_opsnand始能后,没见取消片选.

解答:在上级函数nand_write()最后,用下边这个函数实现;

static void nand_release_device (struct mtd_info *mtd)
{
    struct nand_chip *this = mtd->priv;
    this->select_chip(mtd, -1);    /* De-select the NAND device */
}

 

 

 

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Nand flash uboot 驱动研究
u-boot-2010.03在tq6410上的移植详解(五)
S3C2440移植uboot之支持烧写yaffs映像及制作补丁
添加yaffs2文件下载功能
u-boot-2010.03在tq6410上的移植详解(六)
定位到oob
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服