s3c2440 CPU内置NAND FLASH控制器。相关寄存大器起始地址为0x4e000000。
通过设置NFCONF寄存器,设置NAND FLASH 时序。
通过设置NFCONT寄存器,使能NAND FLASH、初始化ECC等。
代码:
#define GSTATUS1 (*(volatile unsigned int *)0x560000B0) //读此寄存器可以知道CPU芯片型号#define BUSY 1
#define NAND_SECTOR_SIZE_LP 2048 //大页每页2048字节#define NAND_BLOCK_MASK_LP (NAND_SECTOR_SIZE_LP - 1) //大页掩码???
typedef unsigned int S3C24X0_REG32;
//s3c2440 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;
static S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;//s3c2440 Nand flash 相关寄存器起始地址
//供外部调用的函数声明void nand_init(void); //初始化void nand_read(unsigned char *buf, unsigned long start_addr, int size);//读取数据到缓冲区
/* S3C2440的NAND Flash处理函数 */static void s3c2440_nand_reset(void);static void s3c2440_wait_idle(void);static void s3c2440_nand_select_chip(void);static void s3c2440_nand_deselect_chip(void);static void s3c2440_write_cmd(int cmd);static void s3c2440_write_addr_lp(unsigned int addr);static unsigned char s3c2440_read_data(void);
//复位static void s3c2440_nand_reset(void){ s3c2440_nand_select_chip();//选片选 s3c2440_write_cmd(0xff); //复位命令 s3c2440_wait_idle(); //等待就绪 s3c2440_nand_deselect_chip(); //取消片选}
//等待就绪信号static void s3c2440_wait_idle(void){ int i; volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFSTAT; //最后一位为1表示忙,忙就一直等 while (!(*p & BUSY)) for (i = 0; i < 10; i++);}
//片选static void s3c2440_nand_select_chip(){ s3c2440nand->NFCONT &= ~(1 << 1); //NFCONT寄存器[1]位Reg_nCE置0 int i ; for (i = 0; i < 10; i++); //等待片选?}
//取消片选static void s3c2440_nand_deselect_chip(){ s3c2440nand->NFCONT |=(1<<1); //NFCONT寄存器[1]位Reg_nCE置1 }
//发送命令static void s3c2440_write_cmd(int cmd){ volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFCMD; //p指向NFCMD寄存器 *p = cmd; //命令写入命令寄存器}
//发送地址static void s3c2440_write_addr_lp(unsigned int addr){ int i; volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR; int col, page; col = addr & NAND_BLOCK_MASK_LP; //得到页内地址。 每页2K,页内地址为bit[0-10] page = addr / NAND_SECTOR_SIZE_LP; //得到页号。256M为2的28次方,地址总位数为27,即bit[11-27]为页号,共17位 *p = col & 0xff; //地址后8位 ,A0-A7; for (i = 0; i < 10; i++); *p = (col >> 8) & 0x0f; //A8-A10 for (i = 0; i < 10; i++); *p = page & 0xff; //页号后后位 A11-A18 for (i = 0; i < 10; i++); *p = (page >> 8) & 0xff;//A19-A26 for (i = 0; i < 10; i++); *p = (page >> 16) & 0x1; //A27 for (i = 0; i < 10; i++);}
//读数据static unsigned char s3c2440_read_data(void){ volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFDATA; return *p;}
//初始化Nand Flashvoid nand_init(void){ //设置时序 //这里假设cpu频率100MHz,即一个时钟周期为10ns #define TACLS 0 #define TWRPH0 3 //nand flash手册 twp最低要求12ns,即2个时钟周期以上,所以这里可以取1的,3可以保证400MHz时可用 #define TWRPH1 0 //nand flash手册 tCLH最低要求5ns,取值0要求CPU频200Mhz以下 s3c2440nand->NFCONF = (TACLS << 12) | (TWRPH0 << 8) | (TWRPH1 << 4); //使能Nand Flash,禁止片选,初始化ECC s3c2440nand->NFCONT = (1 << 4) | (1 << 1) | (1 << 0); s3c2440_nand_reset(); //复位}
//读数据void nand_read(unsigned char *buf, unsigned long start_addr, int size){ //Nand Flash的读取单位最小是page,长度必须是page的整数倍。所以必须对齐 if ((start_addr & NAND_BLOCK_MASK_LP)||(size & NAND_BLOCK_MASK_LP)) { return; } s3c2440_nand_select_chip();//发出片选信号
int i, j; for (i = start_addr; i < (start_addr+size);) { s3c2440_write_cmd(0); //发出READ0命令 s3c2440_write_addr_lp(i); s3c2440_write_cmd(0x30); s3c2440_wait_idle(); //读取页数据 for ( j = 0; j <NAND_SECTOR_SIZE_LP;j++,i++) { *buf = s3c2440_read_data(); buf++; }
}
s3c2440_nand_deselect_chip();//取消片选}
转载于:https://www.cnblogs.com/sekon/p/6443402.html
相关资源:JAVA上百实例源码以及开源项目