当前位置: 代码迷 >> 综合 >> s3c2410/s3c2440对nandflash的读写操作
  详细解决方案

s3c2410/s3c2440对nandflash的读写操作

热度:33   发布时间:2023-12-09 03:20:14.0

折腾了两三天终于搞定了s3c2440对nandflash的读写操作,s3c2410对nandflash的读写操作资料比较多而s3c2440的资料比较少,两款芯片在nandflash寄存器上有较大的变化,不能通用,需对照datasheet修改。  

 下面讲一下实验过程:

试验目的:使nandflash开始4k代码完成将4k以后代码copy到sdram内运行的功能。

试验内容:采用朗成AT2440EVB-I型开发板,nandflash启动跳线1,3,4在on位置,将head.s和init.c(主要完成初始化,nandflash读写,从nandflash到sdram的代码copy)写入nandflash起始地址(启动地址0x0000),将main.c(完成点亮LED的功能)存放到nandflash的4096地址,但使其在0x30000000(就是sdram的首地址)运行,这就需要nandflash启动后4k的代码将4096起始的代码copy到0x30000000运行。

过程:本来是有源代码的,但那是用在s3c2410上的,将其直接用到AT2440EVB-I型开发板上,失败。将2410和2440datasheet对照一看才知道寄存器有了很大变化,直接用是肯定不行的。查资料才知道2440的nandflash操作资料很少(好像2440的资料都很少,2410比较多),最后查到两个,一个是u-boot在2440上的移植,其中有从nandflash启动的读写函数(copy自vivi),另一个就是AT2440EVB-I型开发板自带的ATBOOT中nand_read.c,对照看了一下差不多,根据这两个资料改写init.c之后还是失败。只好又找资料将“nandflash读写操作”的原理搞清楚了(之前一直没搞清楚代码,只是拿过来用)。再看2410上的代码,发现2440上的少了nandflash的初始化函数,对照datasheet改写寄存器后,led终于亮了。^_^

s3c2410对nandflash读写操作寄存器配置的流程:

1.初始化   

                NFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);或NFCONF = 0xf830;

(1)enable NAND flash controller(15位)

(2)initialize ECC(12位)

(3)chip disable(11位),使用时再chip enable

(4)设置TACLS=0、TWRPH0=3、TWRPH1=0 //2440采用默认值即可

2.复位     

 (1)NFCONF &= ~0x800;//chip enable

 (2)NFCMD = 0xff; //reset command

(3)while(!(NFSTAT & BUSY))等待NAND flash memory ready to operate

3.读写函数

(1)NFCONF &= ~0x800;/* chip Enable */   

(2)NFCMD = 0;//read0

(3)NFADDR = i & 0xff;      NFADDR = (i >> 9) & 0xff;      NFADDR = (i >> 17) & 0xff;      NFADDR = (i >> 25) & 0xff;/* Write Address */

(4)while(!(NFSTAT & BUSY))等待NAND flash memory ready to operate

(5)*buf = (NFDATA & 0xff);//读数据线

(6)NFCONF |= 0x800; /* chip disable */

 s3c2440对nandflash读写操作寄存器配置的流程:

1.初始化

(1)NFCONT = (1<<0) //enable NAND flash controller

(2)NFCONT |= (1<<1)/* chip disable */

2.复位

(1)NFCONT &= ~(1<<1) /* chip enable */

(2)NFCMD = 0xff; //reset command

(3)while(!(NFSTAT & BUSY))等待NAND flash memory ready to operate

3.读函数

(1)NFCONT &= ~(1<<1) /* chip enable */

(2)NFSTAT |= (1<<2) //NAND_CLEAR_RB ,RnB transition is detected

(3)NFCMD = 0; //READ0,读上半叶

(4) /* Write Address */
             NFADDR = i & 0xff;
             NFADDR = (i >> 9) & 0xff;
             NFADDR = (i >> 17) & 0xff;
             NFADDR = (i >> 25) & 0xff;

(5)while(! (NFSTAT&(1<<0)) );   /*NAND_DETECT_RB,等待NAND flash memory ready to operate*/

(6)*buf = (NFDATA & 0xff);  //读数据线

(7)NFCONT |= (1<<1)/* chip disable */

s3c2440对nandflash读写操作部分源码(仅供学习使用):

/* NAND Flash registers 2440*/
#define NFCONF    (*(volatile unsigned int *)0x4e000000)
#define NFCONT    (*(volatile unsigned int *)0x4e000004)
#define NFCMD    (*(volatile unsigned char *)0x4e000008)
#define NFADDR    (*(volatile unsigned char *)0x4e00000c)
#define NFDATA    (*(volatile unsigned char *)0x4e000010)
#define NFSTAT    (*(volatile unsigned char *)0x4e000020)

#define NAND_CHIP_ENABLE (NFCONT &= ~(1<<1))
#define NAND_CHIP_DISABLE (NFCONT |= (1<<1))
#define NAND_CLEAR_RB (NFSTAT |= (1<<2))
#define NAND_DETECT_RB { while(! (NFSTAT&(1<<0)) );}


/* 在第一次实用NAND Flash前,复位一下NAND Flash */

void reset_nand()
{
 int i=0;
// NFCONF &= ~0x800;
//     for(; i<10; i++);

 NAND_CHIP_ENABLE;

 NFCMD = 0xff; //reset command
 wait_idle();
}

/* 初始化NAND Flash */

void init_nand()
{
// NFCONF = 0xf830;
 NFCONT = (1<<0);
 NAND_CHIP_DISABLE;
 reset_nand();
}

#define BUSY 1
inline void wait_idle(void) {
    while(!(NFSTAT & BUSY));
    NFSTAT |= BUSY;
}

#define NAND_SECTOR_SIZE 512
#define NAND_BLOCK_MASK  (NAND_SECTOR_SIZE - 1)

/* low level nand read function */
int
nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
{
    int i, j;

    if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {
        return -1; /* invalid alignment */
    }

    NAND_CHIP_ENABLE;

    for(i=start_addr; i < (start_addr + size);) {
        /* READ0 */
        NAND_CLEAR_RB;
        NFCMD = 0;

        /* Write Address */
        NFADDR = i & 0xff;
        NFADDR = (i >> 9) & 0xff;
        NFADDR = (i >> 17) & 0xff;
        NFADDR = (i >> 25) & 0xff;

        NAND_DETECT_RB;

        for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {
            *buf = (NFDATA & 0xff);
            buf++;
        }
    }
    NAND_CHIP_DISABLE;
    return 0;
}

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zhao207/archive/2008/05/25/2480367.aspx

补充:

1.1.3 寻址方式

Samsung K9F1208U0B Nand Flash 片内寻址采用26位地址形式。从第0位开始分四次通过I/O0I/O7进行

传送,并进行片内寻址。具体含义如下:

07位:字节在上半部、下半部及OOB内的偏移地址

8位:值为0代表对一页内前256个字节进行寻址

值为1代表对一页内后256个字节进行寻址

913位:对页进行寻址

1425位:对块进行寻址

当传送地址时,从位0开始

1.1.4 Nand flash 主要内设命令详细介绍

Nand Flash命令执行是通过将命令字送到Nand Flash控制器的命令寄存器来执行。

Nand Flash的命令是分周期执行的,每条命令都有一个或多个执行周期,每个执行周期都有相映代码表示该周期将要执行的动作。

主要命令有:Read 1Read 2Read IDResetPage ProgramBlock EraseRead Status

详细介绍如下:

1. Read 1

功能:表示将要读取Nand flash存储空间中一个页的前半部分,并且将内置指针定位到前半部分的第一个字节。

命令代码:00h

2. Read 2

功能:表示将要读取Nand flash存储空间中一个页的后半部分,并且将内置指针定位到后半部分的第一个字节。

命令代码:01h

3. Read ID

功能:读取Nand flash芯片的ID

命令代码:90h

4. Reset

功能:重启芯片。

命令代码:FFh

5. Page Program

功能:对页进行编程命令用于写操作。

命令代码:首先写入00h(A)/01h(B)/05h(C), 表示写入那个区再写入80h开始编程模式(写入模式),接

下来写入地址和数据最后写入10h表示编程结束.

6. Block Erase

功能:块擦除命令。

命令代码:首先写入60h进入擦写模式,然后输入块地址接下来写入D0h, 表示擦写结束.

7. Read Status

功能:读取内部状态寄存器值命令。

命令代码:70h

  相关解决方案