📄 nand.c
字号:
#include <stdlib.h>
#include <string.h>
#include "def.h"
#include "s2440addr.h"
#include "option.h"
#include "nand.h"
#define NF_CMD(cmd) {rNFCMD=cmd;}
#define NF_ADDR(addr) {rNFADDR=addr;}
#define NEED_EXT_ADDR 1
#define NF_nFCE_L() {rNFCONT &= ~(1 << 1);}
#define NF_nFCE_H() {rNFCONT |= (1 << 1);}
#define NF_RSTECC() {rNFCONT |= (1 << 4);}
#define NF_MECC_UnLock() {rNFCONT &= ~(1<<5);}
#define NF_MECC_Lock() {rNFCONT |= (1<<5);}
#define NF_CLEAR_RB() {rNFSTAT |= (1 << 2);}
#define NF_DETECT_RB() {while(!(rNFSTAT&(1<<2)));}
#define NF_WAITRB() {while (!(rNFSTAT & (1 << 2)));}
#define NF_RDDATA() (rNFDATA)
#define NF_RDDATA32() (rNFDATA32)
#define NF_WRDATA(data) {rNFDATA=data;}
#define NF_RDMECC0() (rNFMECC0)
#define NF_RDMECC1() (rNFMECC1)
#define NF_RDMECCD0() (rNFMECCD0)
#define NF_RDMECCD1() (rNFMECCD1)
#define NF_WRMECCD0(data) {rNFMECCD0 = (data);}
#define NF_WRMECCD1(data) {rNFMECCD1 = (data);}
// HCLK=133Mhz
#define TACLS 0
#define TWRPH0 5
#define TWRPH1 3
void __RdPage512(volatile BYTE *bufPt);
int NF_ReadID()
{
UINT8 pMID;
UINT8 pDID;
UINT32 nCnt;
UINT16 nBuff;
UINT8 n4thcycle;
INT8 i;
FlashID = 0;
n4thcycle = nBuff = 0;
NF_nFCE_L();
NF_CLEAR_RB();
NF_CMD(CMD_READID); // read id command
NF_ADDR (CMD_READ);
for (i = 0; i < 100; i++)
{
;
}
/* tREA is necessary to Get a MID. */
for (nCnt = 0; nCnt < 5; nCnt++)
{
pMID = (BYTE) NF_RDDATA();
if (0xEC == pMID)
{
break;
}
}
pDID = (BYTE) NF_RDDATA();
nBuff = (BYTE) NF_RDDATA();
n4thcycle = (BYTE) NF_RDDATA();
NF_nFCE_H();
FlashID = pMID << 8 | pDID;
Uart_SendString("Nand Flash ID: ");
Uart_SendDWORD(FlashID, TRUE);
return (FlashID);
}
int NF_ReadPage(UINT32 block, UINT32 page, volatile BYTE *buffer)
{
volatile BYTE * bufPt = buffer;
UINT16 blockPage;
UINT32 MECC;
INT8 NewDataAddr;
BYTE iTemp;
switch (FlashID)
{
case 0xEC75:
iTemp = 5; // LSH 5 = 32Pages/Block
break;
case 0xEC76: // K9F1208, K9S1208
iTemp = 5; // LSH 5 = 32Pages/Block
break;
case 0xECA0:
iTemp = 8; // LSH 8 = 256Pages/Block
break;
default:
iTemp = 5;
}
if (FlashID > 0xECA0)
{
blockPage = (block << iTemp) + page/4;
NewDataAddr = 512*(page%4);
NF_RSTECC(); // Initialize ECC
NF_MECC_UnLock();
NF_nFCE_L();
NF_CMD(CMD_READ); // Read command
NF_ADDR((NewDataAddr)&0xff);
NF_ADDR(((NewDataAddr)>>8)&0xff);
NF_ADDR(blockPage&0xff);
NF_ADDR((blockPage>>8)&0xff); // Block & Page num.
if (LB_NEED_EXT_ADDR)
{
NF_ADDR((blockPage>>16)&0xff); // Block & Page num.
}
}
else
{
blockPage = (block << iTemp) + page;
NewDataAddr=0;
NF_RSTECC(); // Initialize ECC
NF_MECC_UnLock();
NF_nFCE_L();
NF_CMD(CMD_READ); // Read command
NF_ADDR((NewDataAddr)&0xff);
NF_ADDR(blockPage&0xff); //
NF_ADDR((blockPage>>8)&0xff); // Block & Page num.
if (SB_NEED_EXT_ADDR)
{
NF_ADDR((blockPage>>16)&0xff); // Block & Page num.
}
}
NF_CLEAR_RB();
NF_CMD(0x30);
NF_DETECT_RB();
__RdPage512(bufPt);
NF_MECC_Lock();
// no ecc check
return 1;
MECC = NF_RDDATA32();
MECC = NF_RDDATA32();
MECC = NF_RDDATA32();
NF_WRMECCD0(((MECC&0xff00)<<8) | (MECC&0xff));
NF_WRMECCD1(((MECC&0xff000000)>>8) | ((MECC&0xff0000)>>16));
NF_nFCE_H();
if (rNFESTAT0 & 0x3)
{
Uart_SendString("ECC ERROR block");
Uart_SendDWORD(block,0);
Uart_SendString("page");
Uart_SendDWORD(page,1);
return 0;
}
else
{
return 1;
}
}
void NF_Reset(void)
{
volatile int i;
NF_nFCE_L();
NF_CMD(CMD_RESET); // Reset command.
for (i=0 ; i<10 ; i++) // tWB = 100ns.
{
;
}
NF_WAITRB(); // wait 200~500us.
NF_nFCE_H();
}
void NF_Init(void)
{
rNFCONF = (TACLS << 12) | /* CLE & ALE = HCLK * (TACLS + 1) */
(TWRPH0 << 8) | /* TWRPH0 = HCLK * (TWRPH0 + 1) */
(TWRPH1 << 4) |
(0<<0);
rNFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(0<<6)|(0<<5)|(1<<4)|(1<<1)|(1<<0);
rNFSTAT = 0x4;
NF_Reset();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -