📄 k9f2808.c
字号:
/*
* DESC: K9F2808 NAND FLASH test program.
*
* AUTHOR: 余康华
*
* DATE: 2005-11-8 22:44
*
* Copyright (C) 2005 Hui Yuan Electronic Corp. Ltd.
*
* Historys
* 2005-11-8 22:45 .............. LCD 测试完成!
* 2005-11-10 11:39 .............. 内存分配测试完成!
*
*
* /WP --- 3.3V
* ALE --- ADDR2
* CLE --- ADDR1
* /CE --- GPC9
* RDY/B--- GPC8
*/
#include <string.h>
#include <stdio.h>
#include "Defs.h"
#include "44b0x.h"
// 读操作:任意大小
// 写操作:扇区大小(512字节)
// 擦除操作:快大小(16k字节)
#define BSZ 0x4000//16K
#define BMSK 0x3FFF
#define NC 10
// 实践证明对于快速CPU访问NAND FLASH,用下面的函数实现比宏定义实现要更可靠。
//
/*
#define NfReadData() *(volatile UCHAR *)0x02000000
#define NfWriteCmd(cmd) *(volatile UCHAR *)0x02000002= cmd
#define NfWriteAddr(addr) *(volatile UCHAR *)0x02000004= addr
#define NfWriteData(dat) *(volatile UCHAR *)0x02000000= dat
#define NfChipEnable() rPDATC &= ~0x200;
#define NfChipDisable() rPDATC |= 0x200
*/
// 数据读入
static UCHAR
NfReadData(void) {
return *(volatile UCHAR *)NAND_DAT;
}
// 写入数据
static void
NfWriteData(UCHAR dat) {
*(volatile UCHAR *)NAND_DAT = dat;
}
// 写入地址字段
static void
NfWriteAddr(UCHAR adr) {
*(volatile UCHAR *)NAND_ALE = adr;
}
// 命令写入
static void
NfWriteCmd(UCHAR cmd) {
*(volatile UCHAR *)NAND_CLE = cmd;
}
// 芯片使能
static void
NfChipEnable(void) {
rPDATC &= ~0x200;
}
// 芯片片选无效
static void
NfChipDisable(void) {
rPDATC |= 0x200;
}
#if 1
#define PSW int psw;
#define DISABLE psw = interrupts_disable()
#define ENABLE interrupts_enable(psw)
#else
#define PSW
#define DISABLE
#define ENABLE
#endif
void udelay(UINT us);
//
// 等待FLASH就绪
//
static void
NfWait(void) {
while(1) {
if(rPDATC & 0x100)
break;
}
}
//
// 读FLASH操作状态
//
static UCHAR
NfReadStatus(void) {
UCHAR st;
while(1) {
NfWriteCmd(0x70);
st = NfReadData();
if(st & 0x40)
break;
}
return st;
}
//
// 读出芯片ID标识
//
static ULONG
NfReadId(void) {
ULONG t;
PSW;
DISABLE;
NfChipEnable();
NfWriteCmd(0x90);
NfWriteAddr(0);
NfWait();
t = NfReadData() << 8;
t |= NfReadData();
NfChipDisable();
ENABLE;
return t;
}
/*
//
// Get bad block info
//
// OK!
static UCHAR
NfAnyBadBlock(ULONG offst) {
UCHAR t;
UCHAR cc;
PSW;
DISABLE;
cc = rSYSCFG;
rSYSCFG = 1 << 3;
NfChipEnable();
NfWriteCmd(0x50); // point to area C
NfWriteAddr(5);
NfWriteAddr(offst >> 9);
NfWriteAddr(offst >> 17);
NfWait();
t = NfReadData();
NfWriteCmd(0x0); // point to area A
NfChipDisable();
rSYSCFG = cc;
ENABLE;
return t;
}
*/
//
// 擦除若干块(每块32扇区)
//
// offst: 块首地址
// nr: 块数
ULONG
__NfErase(ULONG offst, ULONG nr) {
ULONG st;
PSW;
st = 0;
//DbgOut("Erase Page %u...\n", offst);
DISABLE;
NfChipEnable();
while(nr-- != 0) {
// 擦除扇区.
NfWriteCmd(0x60);
NfWriteAddr(offst >> 9); // Block Addr.: A9 ~ A23//row address page address,页地址实现了块跨越
NfWriteAddr(offst >> 17); // Only A14 - A23 is vaild//具体到快积存器
NfWriteCmd(0xd0);
st |= NfReadStatus();
offst += BSZ;//16K
}
NfChipDisable();
ENABLE;
return st;
}
//
// 读出若干扇区
//
// pgaddr: 扇区号。首地址
// buf: 数据存储位置
// nr: 扇区数
//
//COLUMN ADDRESS
//ROW ADDRESS
//达到对区的定位,具体化某扇区,起始单元
//ROW ADDRESS PAGE ADDRESS
// 512
//达到对块的定位
static void
__NfRead(ULONG pgaddr, UCHAR *buf, ULONG nr) {
ULONG i;
PSW;
while(nr-- != 0) {
DISABLE;
// 读入A区
NfChipEnable();
NfWriteCmd(0x0);
NfWriteAddr(0);//COLUMN ADDRESS
NfWriteAddr(pgaddr);
NfWriteAddr(pgaddr >> 8);//ROW ADDRESS
//I/O 0`7 三次写入。
NfWait();
for(i = 0; i < 256; i++)
*buf++ = NfReadData();
// 读入B区
NfWriteCmd(0x01);
NfWriteAddr(0);
NfWriteAddr(pgaddr);
NfWriteAddr(pgaddr >> 8);
NfWait();
for(; i < 512; i++)
*buf++ = NfReadData();
NfChipDisable();
ENABLE;
pgaddr++;
}
}
//
// 读FLASH
//
// offst: FLASH位置
// buf: 数据指针
// sz: 待读入数据长度
void
NfRead(ULONG offst, void *buf, ULONG sz) {
ULONG bsz;
static UCHAR tbuf[512];
while(sz != 0) {
// 扇区对齐
__NfRead(offst >> 9, tbuf, 1);
bsz = 512;
if(offst & 511)//不满511
bsz -= offst & 511;//操作的大小为OFFSET大小
if(bsz > sz)
bsz = sz;//不能 大于SZ
memcpy(buf, tbuf + (offst & 511), bsz);
offst += bsz;
buf = (char *)buf + bsz;
sz -= bsz;
}
}
//
// 写入若干扇区
//
// pgaddr: 块首地址
// buf: 数据存储位置
// nr: 块数
void
__NfWrite(ULONG pgaddr, void *buf, ULONG nr) {
ULONG i;
UCHAR *bp = (UCHAR *)buf;
UCHAR cc;
PSW;
CHECK_PTR(buf);
NfChipEnable();
while(nr-- != 0) {
DISABLE;
// 关闭CACHE
cc = rSYSCFG;
rSYSCFG = 1 << 3;
// 写入整个扇区
NfWriteCmd(0x80); // Prg0
NfWriteAddr(0);
NfWriteAddr(pgaddr);
NfWriteAddr(pgaddr >> 8);
for(i = 0; i < 512; i++)
NfWriteData(bp[i]);
NfWriteCmd(0x10); // Prg1
rSYSCFG = cc;
ENABLE;
NfWait();
pgaddr++;
bp += 512;
}
NfChipDisable();
}
//
// 复位FLASH, 检查FLASH标识。
//
//
// NAND FLASH 不用文件系统了!!!!
//
void
NfInit(void) {
ULONG t;
NfWriteCmd(0xFF);
t = NfReadId();
DBG1("NAND FLASH: 0x%X\n", t);
if(t != 0xEC73) {
internal_fatal("NAND FLASH 型号错误!");
}
}
// EOF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -