首先查看芯片文档,s3c2410 用户手册.需要了解的资料有:
1.用户手册中关于NAND FLASH 操作的一章,详细相关寄存器的作用。
2.芯片文档:命令,地址,读写流程等。

用户手册上的寄存器的使用并不列出。这里根据学习目的,列出部分的芯片文档中的流程图。

下面是芯片操作的命令

command

通过在命令引脚上写命令来操作芯片。

写数据也称为编程数据。流程图如下:

 program

乘热看下编程函数的代码:这里注意在编程前应该先擦出原有位置的数据,而擦除操作一次根据具体的芯片而定。

/*
 * NAND write
 */
static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, 
			size_t *retlen, const u_char *buf)
{
	int i, page, col, cnt, status;
	struct nand_chip *this = mtd->priv;

	/* Do not allow write past end of page */
	if ((to + len) > mtd->size) {
		DEBUG(MTD_DEBUG_LEVEL0,
			__FUNCTION__"(): Attempted write past end of device\n");
		return -EINVAL;
	}

	/* Shift to get page */
	page = ((int)to) >> this->page_shift;

	/* Get the starting column */
	col = to & (mtd->oobblock - 1);

	/* Initialize return length value */
	*retlen = 0;

	/* Select the NAND device */
	nand_select();

	/* Check the WP bit */
	nand_command(mtd, NAND_CMD_STATUS, -1, -1);

	this->wait_for_ready();

	if (!(this->read_data() & SMC_STAT_NOT_WP)) {
		DEBUG(MTD_DEBUG_LEVEL0,
			__FUNCTION__"(): Device is write protected!!!\n");
		i = -EPERM;
		goto nand_write_exit;
	}

	/* Loop until all data is written */
	while (*retlen < len) {
		/* Write data into buffer */
		if ((col + len) >= mtd->oobblock)
			for (i = col, cnt = 0; i < mtd->oobblock; i++, cnt++)
				this->data_buf[i] = buf[(*retlen + cnt)];
		else
			for (i = col, cnt = 0; cnt < (len - *retlen); i++, cnt++)
				this->data_buf[i] = buf[(*retlen + cnt)];
		/* Write ones for partial page programming */
		for (i = mtd->oobblock; i < (mtd->oobblock + mtd->oobsize); i++)
			this->data_buf[i] = 0xff;
		
		/* Write pre-padding bytes into buffer */
		for (i = 0; i < col; i++)
			this->data_buf[i] = 0xff;

		/* Write post-padding bytes into buffer */
		if ((col + (len - *retlen)) < mtd->oobblock) {
			for (i = (col + cnt); i < mtd->oobblock; i++)
				this->data_buf[i] = 0xff;
		}

		/* Send command to begin auto page programming 
         这个地方其实就是写地址,也就是第一步。一次写的是一页。
         */
		nand_command(mtd, NAND_CMD_SEQIN, 0x00, page);

		/* Write out complete page of data */
		this->hwcontrol(NAND_CTL_DAT_OUT);
		for (i = 0; i < (mtd->oobblock + mtd->oobsize); i++)
			this->write_data(this->data_buf[i]);
		this->hwcontrol(NAND_CTL_DAT_IN);

		/* Send command to actually program the data */
		nand_command(mtd, NAND_CMD_PAGEPROG, -1, -1);

		this->wait_for_ready();

		/*
		 * Wait for program operation to complete. This could
		 * take up to 3000us (3ms) on some devices. so we try
		 * and exit as quickly as possible.
		 */
		status = 0;
		for (i = 0; i < 24; i++) {
			/* Delay for 125us */
			udelay(125);

			/* Check for status */
			nand_command(mtd, NAND_CMD_STATUS, -1, -1);
			status = (int)this->read_data();
			if (status & SMC_STAT_READY)
				break;
		}

		/* See if device thinks it succeeded */
		if (status & SMC_STAT_WRITE_ERR) {
			DEBUG(MTD_DEBUG_LEVEL0,
				__FUNCTION__"(): Failed write, page 0x%08x, " \
				"%6i bytes were sucesful\n", page, *retlen);
			i = -EIO;
			goto nand_write_exit;
		}

		if (col)
			col = 0x00;

		/* Update written bytes count */
		*retlen += cnt;

		/* Increment page address */
		page++;
		
	}

	/* Return happy */
	*retlen = len;
	i = 0;

nand_write_exit:
	/* De-select the NAND device */
	nand_deselect();

	return i;
}


关键部分在于while循环,注意一次写可能大于512个字节,每次只能写一个页,这也是为什么在写后需要填充前后空隙的原因。
nand_command(mtd, NAND_CMD_PAGEPROG, -1, -1); 这个就是就是写10到命令引脚,强制写入FLASH。属于流程图中的第三步。其中的ECC校验的部分被我省略了,主要想一步一步来。这个基本的读写完成了,再去考虑校验部分。

posted on 2009-11-28 22:14  灰太狼大王  阅读(1322)  评论(0编辑  收藏  举报