NAND flash 介绍
关于NAND flash 的介绍:https://www.linuxidc.com/Linux/2012-10/73065.htm
NAND flash 寻址
NAND flash内部结构:
NAND flash存储结构:
NandFlash的存储单元是由Block组成的,Block又是由Page组成的,数据就是存储在Page上。
K9F2G08X0M的总容量是2112M,由图可以看出,它一共有2048块,每一块有64页,每一页有(2K+64)Bytes。其中2K为我们平时使用的存储区,64bytes用于校验、ECC等特殊功用,不做常用地址。
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地址映射图。