如何正确nandflash的块地址和页地址

[初级知识]如何正确nandflash的块地址和页地址

结论

  • 块地址 从1开始,其范围位于1~2048(以2Gb nandflash为例)
  • 页地址 从0到63, 其范围位于0~63(以2Gb nandflash为例)

背景

对于初次接触nandflash的新手而言,不管是做裸机的驱动还是复杂的Linux下的nand驱动,能看懂nandflash的数据手册中给出的时序图,已经是不错的,但要想正确的去实现功能,恐怕是还是有一道拦路虎的,当然,弄懂了,就一纸老虎,这老虎就是我们要说的 nandflash操作中的块地址跟页地址的正确设置。

块地址

nandflash中有块和页的概念,常见的表述如,

nandflash的大小=块总数x每块的页总数x每页的大小

这里的块大小和页大小,均会在相应的数据手册中查到,那么,我们关系的擦除、读写这几个重要的操作而言,其中的块地址该如何计算而来?

比如说,我们常在控制台上用nand erase addr size,而这个命令通常是直接传入addr,我们怎么从addr中解析出块地址呢?下面给出一份正确的实现代码

int addr = 0x0ffc0000 ; 
int block_addr = 0;
int page_size = 2048;
int page_count_per_block= 64;

block_addr = addr/(page_size*page_count_per_block) ;    //小问号认为按照这句命令的理解:块地址就是块数,                                                        //求得块的数量就是块的地址,这个数量是一个块的总数量,                                                        //块总数量等于块的最大数,并且把最大块数定为块地址,                                                       //这与我们平常理解的定义地址一般是最小数(值)有些不                                                       //同,这一点要注意这一点。
                                                  

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

有的时候,我们看网上有的人说,nandflash的块地址等于页地址,其实这句话说的是有前提条件的,那就是第0块第0页的时候满足这个说法,其他的一概不满足

页地址

还是用上面的nand erase addr size,而这个命令通常是直接传入addr,我们怎么从addr中解析出页地址呢?下面给出一份正确的实现代码

int addr = 0x0ffc0000 ; 
int block_addr = 0;
int page_size = 2048;
int page_addr = 0;

page_addr = addr/page_size; //小问号同样认为,此语句可以理解为页地址就是在给定Nand的某个地址后,求得页的数量就是
                            //页的地址,这个数量是一个页的总数量,总数量等于页的最大数,并且把最大页数定为页地址,                            //这与我们平常理解的定义地址一般是最小数(值)有些不同,要注意这一点。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

有的时候,我们看网上有的人说,nandflash的块地址等于页地址,其实这句话说的是有前提条件的,那就是第0块第0页的时候满足这个说法,其他的一概不满足

实现nandflash的擦除

给出的已知条件为要擦除的地址,以及大小,要去实现擦除的伪代码 
- 页大小page_size 
- 每块的页总数page_count_per_block

int nand_erase_one_block(int addr, int size)
{
    int page_addr = 0;

    page_addr = addr/(page_size);

    伪代码:
    reset_nand();
    write_erase_cmd();
    write_addr(page_addr&0xff);
    write_addr(page_addr>>8&0xff);
    write_addr(page_addr>>16&0xff); 
    write_erase_cmd();

    wait_dev_ready();
    check_nand_erase_stat();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

有人或许会很好奇,你这写法为什么跟我在数据手册上看到的不一样,数据手册明明跟这不一样,而且你这种写法如何对得上数据手册中的地址周期值呢?我们不妨先解决这个疑问,用数据手册上的地址周期写法来实现一组代码,我们就按照下面的5个地址周期的数据手册写法来实现一组: 
5个地址周期图

因为我们都知道,在擦除程序时,只需要写三个行地址(为啥?因为数据手册的擦除时序图要求的,不会的看下面这张图) 
nand erase时序图

int nand_erase_one_block(int addr, int size)
{
    int block_addr = 0;

    block_addr = addr/(page_size*page_count_per_block);

    伪代码:
    reset_nand();
    write_erase_cmd();
    write_addr((block_addr << 6) & 0xff);//按照5个地址周期值,我们来填充数据
    write_addr((block_addr >> 2) & 0xff);
    write_addr((block_addr >> 10) & 0x01); 
    write_erase_cmd();

    wait_dev_ready();
    check_nand_erase_stat();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

以上这两种实现方法其实大同小异,第一种方法是用page_addr来实现的,而第二种方法是用block_addr的方法实现的,这两种方法实现其实是一模一样的,并没有什么差别。(小问号认为这里为何出现了页擦除和块擦除两种方法?,老师不是讲擦除只能是块擦除吗?)

  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值