本文主要探讨210Nand和iNand相关知识。
NandFlash
型号与命
K9F2G08:K9F为发行商,2G为Nand大小是2Gbit(256MB),08为Nand是8位(8数据线即接口为8位:传输数据,地址,命令)
功能
Nand是矩阵式存储,每块可存1bit位
Nand单次访问最小单元为Page,Page大小是2KB+64B,每次读写n*2KB,random read模式可读1字节
210中 1 block = 64 page,1 Device = 2028 block = 2048 × 64 × 2K = 256MB
Page是读写最小单位,Block是擦除最小单位
Nand芯片:Nand存储 + Nand接口
Nand读写时地址通过IO线发送,地址有30位而IO只有8位,需要多个cycle才能完成
SoC通过发送命令、地址、数据等信给Nand控制器来访问Nand(接口)
I/O8~15用在X16设备且仅用于输入命令和地址,用于数据输入和接口输出





ECC(软件或硬件寄存器)
2KB存储数据,64用于管理功能(存储ECC数据、存储坏块标志···),
读取或写入前后会做校验,校验不通过则证明已损坏,会将坏块信息存储信息到Nand时会产生
ECC(校验信息)存储到64字节内,下次读写跳过坏块
Nand操作流程
坏块检查
nand使用前要擦除(块单位),擦除完后全是1,擦除后检测是否为0xff可知是否为坏块

页写
写前需要擦除
SoC写Flash通过命令线在IO线依次发送写入开始命令、要写入的页地址、要写入数据,写入结束命令
SOC与Nand建立写入连接后,写入一页数据发给Nand接口,接口接收数据缓冲区,再写入Nand存储区
nand接收和写入数据需要延时,通过状态寄存器判断是否写完,写完后再发送写入结束命令,再做ECC校验写入是否正常

擦除
擦除读写要发送对齐地址

页读

210Nand相关寄存器


gpio





nand configure







demo1:
nand功能
nand.h
void nand_init(void);
void nand_read_id(void);
int nand_block_erase(unsigned long block_num);
int copy_nand_to_sdram(unsigned char *sdram_addr, unsigned long nand_addr, unsigned long length);
int copy_sdram_to_nand(unsigned char *sdram_addr, unsigned long nand_addr, unsigned long length);
int nand_page_read(unsigned int pgaddr, unsigned char *buf, unsigned int length);
int nand_page_write(unsigned int pgaddr, const unsigned char *buf, unsigned int length);
int nand_random_read(unsigned long pgaddr,unsigned short offset, unsigned char *data);
int nand_random_write(unsigned long pgaddr,unsigned short offset,unsigned char wrdata);
nand.c
#include "nand.h"
#include "stdio.h"
#define rNFCONF ( *((volatile unsigned long *)0xB0E00000) )
#define rNFCONT ( *((volatile unsigned long *)0xB0E00004) )
#define rNFCMMD ( *((volatile unsigned long *)0xB0E00008) )
#define rNFADDR ( *((volatile unsigned long *)0xB0E0000C) )
#define rNFDATA ( *((volatile unsigned long *)0xB0E00010) )
#define rNFDATA8 ( *((volatile unsigned char *)0xB0E00010) )
#define rNFSTAT ( *((volatile unsigned long *)0xB0E00028) )
#define rMP0_1CON ( *((volatile unsigned long *)0xE02002E0) )
#define rMP0_2CON ( *((volatile unsigned long *)0xE0200300) )
#define rMP0_3CON ( *((volatile unsigned long *)0xE0200320) )
#define MAX_NAND_BLOCK 8192
#define NAND_PAGE_SIZE 2048
#define NAND_BLOCK_SIZE 64
//dealy time(12ns)
#define TACLS 1
#define TWRPH0 4
#define TWRPH1 1
//command
#define NAND_CMD_READ_1st 0x00
#define NAND_CMD_READ_2st 0x30
#define NAND_CMD_READ_CB_1st 0x00
#define NAND_CMD_READ_CB_2st 0x35
#define NAND_CMD_RANDOM_WRITE 0x85
#define NAND_CMD_RANDOM_READ_1st 0x05
#define NAND_CMD_RANDOM_READ_2st 0xe0
#define NAND_CMD_READ_ID 0x90
#define NAND_CMD_RESET 0xff
#define NAND_CMD_READ_STATUS 0x70
#define NAND_CMD_WRITE_PAGE_1st 0x80
#define NAND_CMD_WRITE_PAGE_2st 0x10
#define NAND_CMD_BLOCK_ERASE_1st 0x60
#define NAND_CMD_BLOCK_ERASE_2st 0xd0
#define ECC_EN (1<<4)
#define CONTROL_EN (1<<0)
static void nand_reset(void);
static void nand_wait_idle(void);
static void nand_select_chip(void);
static void nand_deselect_chip(void);
static void nand_send_cmd(unsigned long cmd);
static void nand_send_addr(unsigned long addr);
static unsigned char nand_read8(void);
static void nand_write8(unsigned char data);
static unsigned int nand_read32(void);
static void nand_write32(unsigned int data);
typedef struct nand_id_info
{
//marker code
unsigned char IDm;
//device code
unsigned char IDd;
unsigned char ID3rd;
unsigned char ID4th;
unsigned char ID5th;
}nand_id_info;
//reset
void nand_reset(void)
{
nand_select_chip();
nand_send_cmd(NAND_CMD_RESET);
nand_wait_idle();
nand_deselect_chip();
}
//waite busy or read status over
void nand_wait_idle(void)
{
unsigned long i;
while( !(rNFSTAT & (1<<4)) )
for(i=0; i<10; i++);
}
//connect nand
void nand_select_chip(void)
{
unsigned long i;
rNFCONT &= ~(1<<1);
for(i=0; i<10; i++);
}
//disconnect nand
void nand_deselect_chip(void)
{
unsigned long i = 0;
rNFCONT |= (1<<1);
for(i=0; i<10; i++);
}
//send command
void nand_send_cmd(unsigned long cmd)
{
unsigned long i = 0;
rNFCMMD = cmd;
for(i=0; i<10; i++);
}
//send address
void nand_send_addr(unsigned long addr)
{
unsigned long i;
unsigned long col, row;
//address of interior page
col = addr % NAND_PAGE_SIZE;
//address of page
row = addr / NAND_PAGE_SIZE;
//write Column Address A0~A7
rNFADDR = col & 0xff;
for(i=0; i<10; i++);
//write Column Address A8~A11
rNFADDR = (col >> 8) & 0x0f;
for(i=0; i<10; i++);
//write Row Address A12~A19
rNFADDR = row & 0xff;
for(i=0; i<10; i++);
//write Row Address A20~A27
rNFADDR = (row >> 8) & 0xff;
for(i=0; i<10; i++);
//write Row Address A28~A30(A28,low level)
rNFADDR = (row >> 16) & 0xff;
for(i=0; i<10; i++);
}
//read nand(word)
unsigned int nand_read32(void)
{
return rNFDATA;
}
//write nand(word)
void nand_write32(unsigned int data)
{
rNFDATA = data;
}
//read nand(half word)
unsigned char nand_read8(void)
{
return rNFDATA8;
}
//write nand(half word)
void nand_write8(unsigned char data)
{
rNFDATA8 = data;
}
//get nand status
unsigned char nand_read_status(void)
{
unsigned char ch;
int i;
//connect nand
nand_select_chip();
//get nand status
nand_send_cmd(NAND_CMD_READ_STATUS);
for(i=0; i<10; i++);
//read nand
ch = nand_read8();
//disconnect nand
nand_deselect_chip();
return ch;
}
// nand init
void nand_init(void)
{
//set read nand signal dealy
rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(

本文聚焦210Nand和iNand相关知识。介绍了NandFlash的型号命名、功能、操作流程及相关寄存器,如Nand是矩阵式存储,Page是读写最小单位,Block是擦除最小单位。还阐述了iNand/eMMC/SDCard/MMCCard的特点,以及210SD/iNand寄存器的设置等内容。
最低0.47元/天 解锁文章
847

被折叠的 条评论
为什么被折叠?



