您的位置:首页 > 其它

nand fllash的选中/取消,发地址、发命令、空闲等待、读取数据功能的程序编写

2016-08-05 21:38 344 查看
1、所有相关的nand flash寄存器构成一个结构体,便于操作

typedef struct {

    S3C24X0_REG32   NFCONF;

    S3C24X0_REG32   NFCONT;

    S3C24X0_REG32   NFCMD;

    S3C24X0_REG32   NFADDR;

    S3C24X0_REG32   NFDATA;

    S3C24X0_REG32   NFMECCD0;

    S3C24X0_REG32   NFMECCD1;

    S3C24X0_REG32   NFSECCD;

    S3C24X0_REG32   NFSTAT;

    S3C24X0_REG32   NFESTAT0;

    S3C24X0_REG32   NFESTAT1;

    S3C24X0_REG32   NFMECC0;

    S3C24X0_REG32   NFMECC1;

    S3C24X0_REG32   NFSECC;

    S3C24X0_REG32   NFSBLK;

    S3C24X0_REG32   NFEBLK;

} S3C2440_NAND;

2、发出片选信号

 void s3c2440_nand_select_chip(void)

{

    int i;

 //s3c2440nand是自定义的结构体指针,首地址是nand flash寄存器的首寄存器的地址。(S3C2440_NAND *)是将地址0x4e000000强制转换成结构体S3C2440_NAND的指针。

S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;

// 下面一句程序是指将s3c2440nand结构体指针下的NFCONT成员的第11位取0,查阅2440手册可知此位为片选位,低电平有效。

    s3c2440nand->NFCONT &= ~(1<<1);

    for(i=0; i<10; i++);    

}
3、取消片选信号
 void s3c2440_nand_deselect_chip(void)

{

S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;

与发出片选信号函数不同的地方在于把NFCONT寄存器的第1位设为1.

    s3c2440nand->NFCONT |= (1<<1);

}

4、发命令

static void s3c2440_write_cmd(int cmd)

{
S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;

//定义一个无符号字符型指针指向s3c2440nand结构体指针的数据成员NFCMD的地址

    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFCMD;

//把传进来的命令值写到NFCMD寄存器中

    *p = cmd;

}

5、发地址

(1)以下是本芯片手册的5个周期的地址,列(column)地址是寄存器的开始地址,里面的*L必须设置为低电平。

本nand flash芯片忽略任何额外的输入地址周期,也就是说地址大于5个周期,都以5个周期地址取值。






(2)程序

 void s3c2440_write_addr_lp(unsigned int addr)

{
int i;
S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;

//无符号字符型指针p指向NFADDR寄存器的地址。
volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR;
int col, page;

//这里NAND_BLOCK_MASK_LP取2047,由于&是按位与的意思,取得列地址,也就是对应nand flash某一页的某个地址。
col = addr & NAND_BLOCK_MASK_LP;

//这里NAND_SECTOR_SIZE_LP取2048,地址值求比值,也就是要知道此地址对应nand flash的第几页。

page = addr / NAND_SECTOR_SIZE_LP;
//第1和第二周期用于提取列地址(对应nand flash 的某一页的某个地址),由于是12位数据,因而第一个周期先取第八位值,第二个周期把col向右移8位,再进行与运算,也就是取高四位值。
*p = col & 0xff;/* Column Address A0~A7 */
for(i=0; i<10; i++);
*p = (col >> 8) & 0x0f;
/* Column Address A8~A11 */
for(i=0; i<10; i++);

//第3~5周期用于提取行地址(对应nand flash的哪一页),第3个周期先取页地址的低8位数据,第4个周期再取页地址的次高8位数据,第五个周期再取高8位数据的最后两位值。
*p = page & 0xff;/* Row Address A12~A19 */
for(i=0; i<10; i++);
*p = (page >> 8) & 0xff;/* Row Address A20~A27 */
for(i=0; i<10; i++);
*p = (page >> 16) & 0x03;/* Row Address A28~A29 */
for(i=0; i<10; i++);

}

6、空闲等待

static void s3c2440_wait_idle(void)

{

    int i;
S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;

//定义一个无符号字符型指针指向状态寄存器NFSTAT的地址。

    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFSTAT;

//BUSY定义为1,要退出while循环,需要!(*p & BUSY)取0,也就是(*p & BUSY)取1,由于&是按位与运算,因而*p值必须为1,也就是说指针p对应的内容必须为1,联系上面的语句可知,状态寄存器NFSTAT的第0位为1。

    while(!(*p & BUSY))

        for(i=0; i<10; i++);

}

7、读取数据寄存器的值

static unsigned char s3c2440_read_data(void)
{
S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;

//读取数据寄存器NFDATA的值

    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFDATA;

    return *p;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: