接触嵌入式一段时间以来,总是不断的在寻找一个正确的学习方式,寻找一个既有前途又有钱途的方向,并没有认真的去做好手上的事情。而近段时间的生活很学习也让我悟出了一个道理:认真做好现在手头上的每一件事情,才是目前最重要的事情。妄想着寻找一个最火的方向,不脚踏实地的走路,只会跌倒的更痛。

所以我决定,细心的学习一些简单,但又必须懂的知识,写一些简单的代码。努力的将自己的缺点和错过的知识补上去。KEEP IT SIMPLE AND STUPID 是当务之急。

导师总是喜欢讲嵌入式分三个层面,应用层、硬件支撑层、硬件层。我更喜欢纵向的去学习一个方面的知识,从一个硬件的说明书,到驱动,到应用。

下面是NAND FLASH 学习笔记:

从main函数开始分析,VIVI支持写FLASH 功能,所以在进入VIVI的时候肯定是实现了NAND FLASH 的读写的功能。Main函数的第五步里对内存技术设备进行了初始化,代码为:ret = mtd_dev_init();

/*
 * Initialise
 */
extern int mtd_init(void);

int mtd_dev_init(void)
{
	int ret = 0;

#ifdef CONFIG_DEBUG
	printk("Initialize MTD device\n");
#endif
	ret = mtd_init();

#ifdef CONFIG_MTD_CFI
	add_command(&flash_cmd);
#endif
	return ret;
}

这个函数在Mtdcore.c中,对MTD进行初始化.mtd_init()的实现和开发板相关,在s3c2410_flash.c中。代码如下:
int mtd_init(void)
{
	int ret;

#ifdef CONFIG_MTD_CFI
	ret = cfi_init();
#endif
#ifdef CONFIG_MTD_SMC
	ret = smc_init();
#endif
#ifdef CONFIG_S3C2410_AMD_BOOT
	ret = amd_init();
#endif

	
	//add by threewater
	UpdateMtd();

	if (ret) {
		mymtd = NULL;
		return ret;
	}
	return 0;


其中真正执行的有smc_init()  UpdateMtd();
smc应该是samsung manufactory chip.

static int
smc_init(void)
{
	struct nand_chip *this;
	u_int16_t nfconf;

	/* Allocate memory for MTD device structure and private data */
	mymtd = mmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip));

	if (!mymtd) {
		printk("Unable to allocate S3C2410 NAND MTD device structure.\n");
		return -ENOMEM;
	}

	/* Get pointer to private data */
	this = (struct nand_chip *)(&mymtd[1]);

	/* Initialize structures */
	memset((char *)mymtd, 0, sizeof(struct mtd_info));
	memset((char *)this, 0, sizeof(struct nand_chip));

	/* Link the private data with the MTD structure */
	mymtd->priv = this;

	/* set NAND Flash  controller */
	nfconf = NFCONF;
	/* NAND Flash controller enable */
	nfconf |= NFCONF_FCTRL_EN;

	/* Set flash memory timing */
	nfconf &= ~NFCONF_TWRPH1;	/* 0x0 */
	nfconf |= NFCONF_TWRPH0_3;	/* 0x3 */
	nfconf &= ~NFCONF_TACLS;	/* 0x0 */

	NFCONF = nfconf;

	/* Set address of NAND IO lines */
	this->hwcontrol = smc_hwcontrol;
	this->write_cmd = write_cmd;
	this->write_addr = write_addr;
	this->read_data = read_data;
	this->write_data = write_data;
	this->wait_for_ready = wait_for_ready;

	/* Chip Enable -> RESET -> Wait for Ready -> Chip Disable */
	this->hwcontrol(NAND_CTL_SETNCE);
	this->write_cmd(NAND_CMD_RESET);
	this->wait_for_ready();
	this->hwcontrol(NAND_CTL_CLRNCE);

	smc_insert(this);

	return 0;
}


该段代码是对mtd结构体的初始化。包括了:结构体空间分配,结构体中元操作的定义。注意最后一个函数的调用不可忽视,其实smc_insert函数的作用不容小觑,它扫描了预先定义好的一些数据,并对MTD结构体的成员进行赋值。

inline int
smc_insert(struct nand_chip *this) {
	/* Scan to find existance of the device */
    if (smc_scan(mymtd)) {
		return -ENXIO;
    }
    /* Allocate memory for internal data buffer */
    this->data_buf = mmalloc(sizeof(u_char) *
			     (mymtd->oobblock + mymtd->oobsize));

    if (!this->data_buf) {
		printk("Unable to allocate NAND data buffer for S3C2410.\n");
		this->data_buf = NULL;
		return -ENOMEM;
    }

    return 0;
}

上面的smc_scan代码如下,与FLASH芯片代码有关的代码,除了在s3c2410_flash.c中,还在smc_core.c中。该函数的功能根据预定义好的nand_flash_dev结构体扫描,当扫描出来的制造商ID ,设备ID 和预定义的值一样时,就对MTD结构体进行赋值。这样基本上一个flash的属性描述就到此结束了。

int
smc_scan(struct mtd_info *mtd)
{
	int i, nand_maf_id, nand_dev_id;
	struct nand_chip *this = mtd->priv;

	/* Select the device */
	nand_select();

	/* Send the command for reading device ID */
	nand_command(mtd, NAND_CMD_READID, 0x00, -1);

	this->wait_for_ready();

	/* Read manufacturer and device IDs */
	nand_maf_id = this->read_data();
	nand_dev_id = this->read_data();

	/* Print and sotre flash device information */
	for (i = 0; nand_flash_ids[i].name != NULL; i++) {
		if (nand_maf_id == nand_flash_ids[i].manufacture_id &&
		    nand_dev_id == nand_flash_ids[i].model_id) {
#ifdef USE_256BYTE_NAND_FLASH
			if (!mtd->size) {
				mtd->name = nand_flash_ids[i].name;
				mtd->erasesize = nand_flash_ids[i].erasesize;
				mtd->size = (1 << nand_flash_ids[i].chipshift);
				mtd->eccsize = 256;
				if (nand_flash_ids[i].page256) {
					mtd->oobblock = 256;
					mtd->oobsize = 8;
					this->page_shift = 8;
				} else {
					mtd->oobblock = 512;
					mtd->oobsize = 16;
					this->page_shift = 9;
				}
				this->dev = &nand_smc_info[GET_DI_NUM(nand_flash_ids[i].chipshift)];
			}
#else
			if (!(mtd->size) && !(nand_flash_ids[i].page256)) {
				mtd->name = nand_flash_ids[i].name;
				mtd->erasesize = nand_flash_ids[i].erasesize;
				mtd->size = (1 << nand_flash_ids[i].chipshift);
				mtd->eccsize = 256;
				mtd->oobblock = 512;
				mtd->oobsize = 16;
				this->page_shift = 9;
				this->dev = &nand_smc_info[GET_DI_NUM(nand_flash_ids[i].chipshift)];
			}
#endif
			printk("NAND device: Manufacture ID:" \
				" 0x%02x, Chip ID: 0x%02x (%s)\n",
				nand_maf_id, nand_dev_id, mtd->name);
			break;
		}	    
	}

	/* De-select the device */
	nand_deselect();

	/* Print warning message for no device */
	if (!mtd->size) {
		printk("No NAND device found!!!\n");
		return 1;
	}

	/* Fill in remaining MTD driver data */
	mtd->type = MTD_NANDFLASH;
	mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC;
	mtd->module = NULL;
	mtd->ecctype = MTD_ECC_SW;
	mtd->erase = nand_erase;
	mtd->point = NULL;
	mtd->unpoint = NULL;
	mtd->read = nand_read;
	mtd->write = nand_write;
	mtd->read_ecc = nand_read_ecc;
	mtd->write_ecc = nand_write_ecc;
	mtd->read_oob = nand_read_oob;
	mtd->write_oob = nand_write_oob;
	mtd->lock = NULL;
	mtd->unlock = NULL;

	/* Return happy */
	return 0;
}
TO BE CONTINUE,下面讲下操作代码。
posted on 2009-11-28 20:49  灰太狼大王  阅读(722)  评论(0编辑  收藏  举报