⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nand.c

📁 s3c2440bootloader的stepldr修改版
💻 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 + -