驱动K92G08U0B

在这里插入图片描述
这款芯片一页有(2048+64)个字节,一块有64页

原理图如下:
在这里插入图片描述
引脚介绍:
RnB: 就绪或者忙 FALE:地址锁存器
nFRE: 读使能 FCLE:命令所存器
nFCE: 片选使能 FWE:写使能

2416nand控制器时序图:
在这里插入图片描述
K92G08时序
在这里插入图片描述
查芯片手册得到TCS=20ns,Tch=5ns,twp=12ns,
所以
TACLS=tcs-twp=20-12=8;
TWRPH0=12ns:
TWRPH1=5ns;

初始化代码如下:

void nand_Init(void)
{
	rGPACON = (rGPACON &~(0x3f<<17)) | (0x3f<<17); 
	// 配置K9F2G08U0B timing(HCLK@133M)
	//1秒/133约为7纳秒
	// TACLS=1, (tALS或tCLS-tWP=0)(ALE或CLE有效后需保持才能发出写脉冲)
	// TWRPH0=2,tWP=12ns(最小写脉冲宽度)
	// TWRPH1=1,tALH或tCLH=5ns(写脉冲后ALE或CLE需保持有效时间)
	// 1-bit ECC
	rNFCONF = (1<<12)|(2<<8)|(1<<4)|(1<<1)|(0<<0);
	// 上升沿检查nand准备好信号线
	rNFCONT = (0<<12)|(0<<10)|(0<<9)|(0<<8)
				|(0x3<<6)|(0x3<<4)|(0x3<<1)|(1<<0);
}

芯片的读操纵:

在这里插入图片描述

static int Nand_ReadPage(unsigned int Block, unsigned int Page,unsigned char *Buffer)
{
	unsigned int i;
	unsigned int MECC, SECC;
	if (Buffer == (unsigned char *)0) {
		return 1; // 缓冲区为空,参数错误
	}
	Page &= (64-1); // 64 page in one block
	Page += (Block << 6); // Block转换为页数
	NF_INIT_MECC(); // main区ECC清空
	NF_INIT_SECC(); // spare区ECC清空
	NF_MECC_UNLOCK(); // main区ECC解锁,开始ECC计算
	NF_CE_ENABLE(); // 使能片选
	NF_CLEAR_RB(); // 清数据传输标志
	
	NF_CMD(NAND_CMD_READ0); // page read cycle 1
	NF_ADDR(0); // column address
	NF_ADDR(0); // columu address
	NF_ADDR(Page & 0xff); // 写入3字节的页地址
	NF_ADDR((Page>>8) & 0xff);
	NF_ADDR((Page>>16) & 0xff);	
	NF_CMD(NAND_CMD_READSTART); // page read cycle 2

	NF_WAIT_READY(); // 等待命令完成	
	for (i=0; i<2048; i++) { // 读取main区数据
		Buffer[i] = NF_READ_BYTE();
	}
	NF_MECC_LOCK(); // 锁定main ECC
	NF_SECC_UNLOCK(); // 解锁spare ECC

	MECC = NF_READ_WORD(); // spare区前4字节为main区ECC
	// main区的ECC放入到NFMECCD0/1中相应的位中
	rNFMECCD0=((MECC&0xff00)<<8) | (MECC&0xff);	
	rNFMECCD1=((MECC&0xff000000)>>8) | ((MECC&0xff0000)>>16);
	NF_SECC_LOCK(); // 锁定spare ECC
	// spare区第5,6这两字节为spare区ECC,剩下部分未使用
	SECC = NF_READ_WORD();
	// spare区的ECC放入到NFMECCD0/1中相应的位中	
	rNFSECCD=((SECC&0xff00)<<8)|(SECC&0xff);	
	NF_CE_DISABLE();
	// check whether spare/main area bit fail error occurred
	if ((rNFECCERR0 & 0xf) == 0) {
		return 0; // 数据读取正确
	} else {
		return 2; // ECC检验不一致,数据读取有误
	}
}

写操作也类是,只不过命令不一样
在这里插入图片描述

static int Nand_WritePage(unsigned int Block, unsigned int Page, unsigned char *Buffer)
{
	unsigned int i;
	unsigned char State;
	unsigned int MECC, SECC;
	if (Buffer == (unsigned char *)0) {
		return 1; // 数据缓存参数错误
	}
	if (Nand_IsBadBlock(Block)) {
		return 2; // 是坏块,返回坏块错误码
	}
	
	Page &= (64-1); // 1 block最大64页
	Page += (Block << 6); // block转换成页
	NF_INIT_MECC(); // main区ECC清空
	NF_INIT_SECC(); // spare区ECC清空
	NF_MECC_UNLOCK(); // main区ECC解锁,开始ECC计算
	NF_CE_ENABLE(); // 使能片选
	NF_CLEAR_RB(); // 清数据传输标志
	
	NF_CMD(NAND_CMD_SEQIN); // page program cycle 1
	NF_ADDR(0); // column address
	NF_ADDR(0); // columu address
	NF_ADDR(Page & 0xff); // 写入3字节页地址
	NF_ADDR((Page>>8) & 0xff);
	NF_ADDR((Page>>16) & 0xff);	
	
	for (i=0; i<2048; i++) { // 写入2k数据到main区
		NF_WRITE_BYTE(Buffer[i]);		
	}
	NF_MECC_LOCK(); // 锁定main ECC
	MECC = rNFMECC0; // 4字节写main区数据的ECC	
	NF_SECC_UNLOCK(); // 解锁spare ECC
	NF_WRITE_BYTE(MECC&0xff);// 写4字节main ECC到spare区
	NF_WRITE_BYTE((MECC>>8) & 0xff);	
	NF_WRITE_BYTE((MECC>>16) & 0xff);	
	NF_WRITE_BYTE((MECC>>24) & 0xff);
	NF_SECC_LOCK(); // 锁定spare ECC
	SECC = rNFSECC; // 2字节的spare写数据ECC
	NF_WRITE_BYTE(SECC & 0xff); // 继续写入SECC
	NF_WRITE_BYTE((SECC>>8) & 0xff);
	NF_CMD(NAND_CMD_PAGEPROG); // page program cycle 2
	
	NF_WAIT_READY(); // 等待写完
	NF_CMD(NAND_CMD_STATUS); // 发送命令读取状态
	do {
		State = NF_READ_BYTE();
	} while(!(State & (1<<6))); // 等待状态变成Ready
	
	NF_CE_DISABLE();
	
	// 是否写成功,第0位为0则pass,不然fail
	if (State & (1<<0)) {
		if (Nand_MarkBadBlock(Block)) { // 标志坏块
			return 3; // 写不成功并且坏块标记不成功
		} else {
			return 4; // 写不成功坏块标记成功
		}
	}
	return 0;
}

nandflash 8位ECC码写操作,如果2416的自动方式采用IROM启动的话,在将nandflash的8k数据复制到SRAM的过程中会进行校验,否则芯片是无法启动的

int32_t NandBoot_WritePage_8Bit(uint32_t Block, uint32_t Page, uint8_t *Buffer)
{
	uint8_t oob[64];
	uint8_t i;
	uint8_t State;
	uint8_t *poob;
	int32_t j;
	uint32_t eccprgecc0, eccprgecc1, eccprgecc2, eccprgecc3;
	
	Page &= (64-1); // 1 block最大64页
	Page += (Block << 6); // block转换成页	

	NF_CE_ENABLE(); // 使能片选
	NF_CLEAR_RB(); // 清数据传输标志
	
	NF_CMD(NAND_CMD_SEQIN); // page program cycle 1
	NF_ADDR(0); // column address
	NF_ADDR(0); // columu address
	NF_ADDR(Page & 0xff); // 写入3字节页地址
	NF_ADDR((Page>>8) & 0xff);
	NF_ADDR((Page>>16) & 0xff);		
	
	poob = oob;
	rNFCONF = (rNFCONF & ~(3<<23)) | (1<<23);
	for (i=0; i<4; i++) {
		// clear illegal access status bit
		rNFSTAT = rNFSTAT | ((1<<4)|(1<<5)|(1<<6)|(1<<7));	
		rNFCONT |= (1<<18) | (1<<11); // Encoding 8-bit ECC	
		NF_MECC_UNLOCK(); // main区ECC解锁,开始ECC计算	
		NF_INIT_MECC(); // main区ECC清空
		// Write buffer to main area
		for (j=0; j<512; j++) {
			NF_WRITE_BYTE(*Buffer++);
		}
		// 锁住校验码
		NF_MECC_LOCK();
		//等待校验码完成
		while (!(rNFSTAT & (1<<6))) {
			
		}
		// clear 8bit ecc encode done
		rNFSTAT |= (1<<6);
		eccprgecc0 = rNFM8ECC0;
		eccprgecc1 = rNFM8ECC1;	
		eccprgecc2 = rNFM8ECC2;		
		eccprgecc3 = rNFM8ECC3;
		
		*poob++ = eccprgecc0 & 0xff;
		*poob++ = (eccprgecc0 >> 8) & 0xff;
		*poob++ = (eccprgecc0 >> 16) & 0xff;
		*poob++ = (eccprgecc0 >> 24) & 0xff;
		*poob++ = eccprgecc1 & 0xff;
		*poob++ = (eccprgecc1 >> 8) & 0xff;
		*poob++ = (eccprgecc1 >> 16) & 0xff;
		*poob++ = (eccprgecc1 >> 24) & 0xff;
		*poob++ = eccprgecc2 & 0xff;
		*poob++ = (eccprgecc2 >> 8) & 0xff;
		*poob++ = (eccprgecc2 >> 16) & 0xff;
		*poob++ = (eccprgecc2 >> 24) & 0xff;
		*poob++ = eccprgecc3 & 0xff;	
	}
	// Reserved for OS(12 byte)
	*poob++ = 0xff;
	*poob++ = 0xff;
	*poob++ = 0xff;
	*poob++ = 0xff;
	*poob++ = 0xff;
	*poob++ = 0xff;
	*poob++ = 0xff;
	*poob++ = 0xff;
	*poob++ = 0xff;
	*poob++ = 0xff;
	*poob++ = 0xff;
	*poob++ = 0xff;	
	// 写完主数据区的数据之后,在写入ECC码
	for (j=0; j<64; j++) {
		NF_WRITE_BYTE(oob[j]);
	}
	
	NF_CMD(NAND_CMD_PAGEPROG); // page program cycle 2
	NF_WAIT_READY(); // 等待写完
	NF_CMD(NAND_CMD_STATUS); // 读取nand状态
	do {
		State = NF_READ_BYTE();
	} while(!(State & (1<<6))); // 等待状态变成Ready
	
	NF_CE_DISABLE();
	
	// 是否写成功,第0位为0则pass,不然fail
	if (State & (1<<0)) {		
		return -1; // 写不成功
	}
	return 0;
}

其他操作也一样,主要记住
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值