裸机NAND flash

NAND flash 介绍

关于NAND flash 的介绍:https://www.linuxidc.com/Linux/2012-10/73065.htm

NAND flash 寻址

NAND flash内部结构:
裸机NAND flash
NAND flash存储结构:
裸机NAND flash
NandFlash的存储单元是由Block组成的,Block又是由Page组成的,数据就是存储在Page上。
K9F2G08X0M的总容量是2112M,由图可以看出,它一共有2048块,每一块有64页,每一页有(2K+64)Bytes。其中2K为我们平时使用的存储区,64bytes用于校验、ECC等特殊功用,不做常用地址。

NAND flash地址组成:
裸机NAND flash
column address:列地址,用于访问页内地址,相当于存储单元相对于所在页的偏移量。
row address:行地址(页地址),相当于存储单元所在行(页)的地址。

nandflash的大小=块总数x每块的页总数x每页的大小(如存储结构图中1 device的容量算法)
下面以韦东山嵌入是开发视频源码中读操作例子说明地址转化过程(个人理解,不一定正确):

#define NAND_SECTOR_SIZE_LP    2048
#define NAND_BLOCK_MASK_LP     (NAND_SECTOR_SIZE_LP - 1)

typedef unsigned int S3C24X0_REG32; //寄存器大小

/* NAND FLASH (see S3C2440 manual chapter 6, www.100ask.net) */
typedef struct {
    S3C24X0_REG32   NFCONF;
    S3C24X0_REG32   NFCONT;
    S3C24X0_REG32   NFCMD;
    S3C24X0_REG32   NFADDR;
    S3C24X0_REG32   NFDATA;
    S3C24X0_REG32   NFMECCD0;
    S3C24X0_REG32   NFMECCD1;
    S3C24X0_REG32   NFSECCD;
    S3C24X0_REG32   NFSTAT;
    S3C24X0_REG32   NFESTAT0;
    S3C24X0_REG32   NFESTAT1;
    S3C24X0_REG32   NFMECC0;
    S3C24X0_REG32   NFMECC1;
    S3C24X0_REG32   NFSECC;
    S3C24X0_REG32   NFSBLK;
    S3C24X0_REG32   NFEBLK;
} S3C2440_NAND;	//结构体中包涵所有与NAND FLASH 设置、操作相关寄存器

typedef struct {
    void (*nand_reset)(void);
    void (*wait_idle)(void);
    void (*nand_select_chip)(void);
    void (*nand_deselect_chip)(void);
    void (*write_cmd)(int cmd);
    void (*write_addr)(unsigned int addr);
    unsigned char (*read_data)(void);
}t_nand_chip;	//函数指针结构体,方便调试、调用。

//通过将结构体初值初始化为0x4e000000,可通过指针访问结构体内所有寄存器。
static S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;	

static void s3c2440_write_addr_lp(unsigned int addr)
{
	int i;
	//通过这样设置,使用时,*p可表示NFADDR寄存器低八位的值。
	volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR; 
	
	int col, page;

	/*
	本人理解:
	此处可看成行列地址分割界
	NAND_BLOCK_MASK_LP为page的容量(2k = 2048)。
	page为页(行)地址,计算出地址所在页数。
	col为列地址,计算出地址所在位置相对本页偏移量。
	*/
	col = addr & NAND_BLOCK_MASK_LP;
	page = addr / NAND_SECTOR_SIZE_LP;
	
	*p = col & 0xff;			/* Column Address A0~A7 */
	for(i=0; i<10; i++);		
	*p = (col >> 8) & 0x0f; 	/* Column Address A8~A11 */
	for(i=0; i<10; i++);
	*p = page & 0xff;			/* Row Address A12~A19 */
	for(i=0; i<10; i++);
	*p = (page >> 8) & 0xff;	/* Row Address A20~A27 */
	for(i=0; i<10; i++);
	*p = (page >> 16) & 0x03;	/* Row Address A28~A29 */
	for(i=0; i<10; i++);
}

注:本人查阅K9F2G08U0M芯片手册没有找到有关地址转换的规则(不知道是没有还是理解不够)。
在网上搜索资料时很多人的物理地址算法都是通过 块地址+页地址+页内偏移量 来计算。

以下是2440芯片手册nand flash地址映射图。
裸机NAND flash