加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

嵌入式学习之NandFlash控制器读写编程

发布时间:2020-12-15 18:06:06 所属栏目:百科 来源:网络整理
导读:S3C2440 NandFlash控制器介绍: ??????? NAND Flash控制器提供几个寄存器来简化对NAND Flash的操作。比如要发出读命令,只需往NFCMD寄存器写入0即可,NAND FLash控制器会自动发出各种控制信号。 1、操作方法概述 ??????? 访问NAND Flash时需要先发出命令,然

S3C2440 NandFlash控制器介绍:

??????? NAND Flash控制器提供几个寄存器来简化对NAND Flash的操作。比如要发出读命令,只需往NFCMD寄存器写入0即可,NAND FLash控制器会自动发出各种控制信号。

1、操作方法概述

??????? 访问NAND Flash时需要先发出命令,然后发出地址序列,最后读/写数据;需要使用各种使能信号来分辨是命令、地址还是数据。S3C2410的NAND Flash控制器提供了NFCONF、NFCMD、NFADDR、NFDATA、NFSTAT和NFECC等6个寄存器来简化这些操作。S3C2440的NAND Flash控制器则提供了NFCONF、NFCONT、NFCMMD、NFADDR、NFDATA、NFSTAT和其它与ECC有关的寄存器。对NAND Flash控制器的操作,S3C2410和S3C2440有一些小的差别:有些寄存器不一样,有些寄存器内容不一样,这在实例程序中会体现出来。

NAND Flash的读写操作次序如下:

????????

(1)设置NFCONF(对于S3C2440,还要设置NFCONT)寄存器,配置NAND Flash。

(2)向NFCMD寄存器写入命令,这些命令可以参考表8.2。

(3)向NFADDR寄存器写入地址。

(4)读/写数据:通过寄存器NFSTAT检测NAND Flash的状态,在启动某个操作后,应该检测R/nB信号以确定该操作是否完成、是否成功。

?

2.下面讲解这些寄存器的功能和用法:

?????????

1)NFCONF:NAND Flash配置寄存器

????? ? 这个寄存器在S3C2410、S3C2440上功能有所不同。S3C2410的NFCONF寄存器被用来使能禁止NAND Flash控制器、使能禁止控制引脚信号nFCE、初始化ECC,设置NAND Flash的时序参数等。

(2)NFCONT:NAND Flash控制寄存器,S3C2410没有这个寄存器。

??????? 被用来使能/禁止NAND Flash控制寄存器,使能/禁止控制引脚信号nFCE、初始化ECC。它还有其它功能,在一般的应用中用不到,比如锁定NAND Flash。

(3)NFCMD:NAND Flash命令寄存器

??????? 对于不同型号的Flash,操作命令一般不一样。对于本板使用的K9F1208U0M,可参考表8.2。

(4)NFADDR:NAND Flash地址寄存器。

??????? 当写这个寄存器时,它将对Flash发出地址信号。

(5)NFDATA:NAND Flash数据寄存器。

??????? 只用到低8位,读、写此寄存器将启动对NAND Flash的读数据、写数据操作。

(6)NFSTAT:NAND Flash状态寄存器

??????? 只用到位0,0:busy,1:ready

读NandFlash的步骤:

??????? ①设置NFCONF
??????? 在HCLK=100Mhz的情况下,TACLS=0,TWRPH0=3,TWRPH1=0,则
??????? NFCONF = 0x300
??????? 使能NAND Flash控制器、禁止控制引脚信号nFCE,初始化ECC
??????? NFCONT = (1<<4) | (1<<1) | (1<<0)
②操作NAND Flash前,复位
??????? NFCONT &= ~(1<<1)??????? 发出片选信号
??????? NFCMD = 0xff??????? reset命令
??????? 然后循环查询NFSTAT位0,直到等于1,处于就绪态
??????? 最后禁止片选信号,在实际使用时再使能
??????? NFCONT |= 0x2??????? 禁止NAND Flash
③发出读命令
??????? NFCONT &= ~(1<<1)??????? 发出片选信号
??????? NFCMD = 0??????? 读命令
④发出地址信号
⑤循环查询NFSTAT,直到等于1
⑥连续读NFDATA寄存器,得到一页数据
⑦最后禁止NAND Flash片选信号
??????? NFCONT |= (1<<1)

介绍几个Nand Flash初期化的函数:

?????

/* 初始化NAND Flash */
void nand_init(void)
{
#define TACLS   0
#define TWRPH0  3
#define TWRPH1  0

    /* 判断是S3C2410还是S3C2440 */
    if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
    {
        nand_chip.nand_reset         = s3c2410_nand_reset;
        nand_chip.wait_idle          = s3c2410_wait_idle;
        nand_chip.nand_select_chip   = s3c2410_nand_select_chip;
        nand_chip.nand_deselect_chip = s3c2410_nand_deselect_chip;
        nand_chip.write_cmd          = s3c2410_write_cmd;
        nand_chip.write_addr         = s3c2410_write_addr;
        nand_chip.read_data          = s3c2410_read_data;

		/* 使能NAND Flash控制器,初始化ECC,禁止片选,设置时序 */
        s3c2410nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);
    }
    else
    {
        nand_chip.nand_reset         = s3c2440_nand_reset;
        nand_chip.wait_idle          = s3c2440_wait_idle;
        nand_chip.nand_select_chip   = s3c2440_nand_select_chip;
        nand_chip.nand_deselect_chip = s3c2440_nand_deselect_chip;
        nand_chip.write_cmd          = s3c2440_write_cmd;
#ifdef LARGER_NAND_PAGE
        nand_chip.write_addr         = s3c2440_write_addr_lp;
#else
		nand_chip.write_addr		 = s3c2440_write_addr;
#endif
        nand_chip.read_data          = s3c2440_read_data;

		/* 设置时序 */
        s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
        /* 使能NAND Flash控制器,禁止片选 */
        s3c2440nand->NFCONT = (1<<4)|(1<<1)|(1<<0);
    }
    
    /* 复位NAND Flash */
    nand_reset();
}


Nand Flash 复位:

?

/* 复位 */
static void s3c2410_nand_reset(void)
{
    s3c2410_nand_select_chip();
    s3c2410_write_cmd(0xff);  // 复位命令
    s3c2410_wait_idle();
    s3c2410_nand_deselect_chip();
}


等待nand flash复位:

/* 等待NAND Flash就绪 */
static void s3c2410_wait_idle(void)
{
    int i;
    volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFSTAT;
    while(!(*p & BUSY))
        for(i=0; i<10; i++);
}


?

发出片选信号,选择芯片:

/* 发出片选信号 */
static void s3c2410_nand_select_chip(void)
{
    int i;
    s3c2410nand->NFCONF &= ~(1<<11);
    for(i=0; i<10; i++);    
}


取消片选:

/* 取消片选信号 */
static void s3c2410_nand_deselect_chip(void)
{
    s3c2410nand->NFCONF |= (1<<11);
}


发出命令、地址,读取数据:

/* 发出命令 */
static void s3c2410_write_cmd(int cmd)
{
    volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFCMD;
    *p = cmd;
}

/* 发出地址 */
static void s3c2410_write_addr(unsigned int addr)
{
    int i;
    volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFADDR;
    
    *p = addr & 0xff;
    for(i=0; i<10; i++);
    *p = (addr >> 9) & 0xff;
    for(i=0; i<10; i++);
    *p = (addr >> 17) & 0xff;
    for(i=0; i<10; i++);
    *p = (addr >> 25) & 0xff;
    for(i=0; i<10; i++);
}

/* 读取数据 */
static unsigned char s3c2410_read_data(void)
{
    volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFDATA;
    return *p;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读