本篇文章链接:http://blog.csdn.net/qqliyunpeng/article/details/51180276
引脚名字
引脚功能
RE#
读使能,低电平有效
WE#
写使能,上升沿有效
WP#
写保护,低电平有效
R/B#
READY/BUSY 输出,这个引脚表征设备操作的状态,低电平表示忙,高电平表示完成(状态包括:读、写、擦除)
PRE
POWER-ON READ 使能,高电平时上电时执行芯片的读操作
对 nandflash 的结构的几点说明:
寄存器
地址
R/W
描述
复位值
NFCONF
0x4E000000
R/W
Nandflash 的配置寄存器
0x0000100X
NFCONF
Bit
描述
初始值
Reserved
[15:14]
保留
-
TACLS
[13:12]
CLE & ALE duration setting value (0~3)
Duration = HCLK x TACLS
01
...
...
...
...
TWRPH0
[10:8]
TWRPH0 duration setting value (0~7)
Duration = HCLK x ( TWRPH0 + 1 )
000
...
...
...
...
TWRPH1
[6:4]
TWRPH1 duration setting value (0~7)
Duration = HCLK x ( TWRPH1 + 1 )
000
从这里之后的几个都是由硬件决定(就是上下拉)的不需要软件管。
原理图中的这个地方设置的是上表中 TWRPH1 之后的位:
#define NFCONF (*((volatile unsigned long *)0x4E000000))
void nand_init(void )
{
#define TACLS 0
#define TWRPH0 1
#define TWRPH1 0
/* 设置时序 */
NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
/* 使能 nandflash 控制器,初始化ECC,关片选 */
NFCONT = (1<<4)|(1<<1)|(1<<0);
}#define NFCONT (*((volatile unsigned long *)0x4E000004))
void nand_select(void )
{
NFCONT &= ~(1<<1);
}
void nand_deselect(void )
{
NFCONT |= (1<<1);
}// 写命令 注意是八位的命令
#define NFCMMD (*((volatile unsigned char *)0x4E000008))
void nand_cmd(unsigned char cmd)
{
volatile int i;
NFCMMD = cmd;
for (i = 0; i<10; i++); // 延时一段时间
}// 写地址
#define NFADDR (*((volatile unsigned char *)0x4E00000C))
#define NAND_SECTOR_SIZE 2048
#define NAND_BLOCK_MASK (NAND_SECTOR_SIZE_LP - 1)
void nand_addr(unsigned int addr)
{
// unsigned int col = addr % 2048;
// unsigned int page = addr / 2048;
col = addr & NAND_BLOCK_MASK;
page = addr / NAND_SECTOR_SIZE;
volatile int i;
NFADDR = col & 0xff; /* Column Address A0~A7 */
for (i = 0; i<10; i++);
NFADDR = (col>>8) & 0x0f; /* Column Address A8~A11 */
for (i = 0; i<10; i++);
NFADDR = page & 0xff; /* Row Address A12~A19 */
for (i = 0; i<10; i++);
NFADDR = (page>>8) & 0xff; /* Row Address A20~A27 */
for (i = 0; i<10; i++);
NFADDR = (page>>16) & 0x03; /* Row Address A28~A29 */
for (i = 0; i<10; i++);
}#define NFSTAT (*((volatile unsigned char *)0x4E000020))
#define NFDATA (*((volatile unsigned char *)0x4E000010))
void nand_wait_teady(void)
{
while(!(NFSTAT & 1))
for(i = 0; i < 10; i++);
}
unsigned char nand_data(void)
{
return NFDATA;
}
/*
* 参数的含义: addr 要读的地址,buf 读出来的数据存放的缓存,len 要读的长度
*/
void nand_read(unsigned int addr, unsigned char *buf, unsigned int len)
{
int col = addr % 2048;
int i = 0 ;
nand_select(); // 选中芯片
while(i < len)
{
nand_cmd(0x00); // 发出读命令 00h
nand_addr(addr); // 发送读的地址
nand_cmd(0x30); // 发出读命令 30h
nand_wait_ready(); // 等待不忙
for(;(col < 2048) && (i < len);col++)
{
buf[i] = nand_data(); // 读数据
i++;
addr++;
}
col = 0;
}
nand_deselect(); // 取消片选
}void nand_reset(void)
{
nand_select(); // 选中芯片
nand_cmd(0xff);
nand_read_ready();
nand_deselect();
}原文:http://blog.csdn.net/qqliyunpeng/article/details/51180276