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

📄 nflash.c

📁 从指定缓冲区写入数据到nandflash一个页内,不可以跨页写
💻 C
字号:
/***
*   nflash.c    - Samsung nandflash driver
*               - modified by Feng Lie Bin 2006/12/12
***/
#include "PublHead.h"

#if (INCLUDE_ALLDATASAVE == 0)

//const define
#define MaxNandTypeNum      0x04    //定义型号种类
#define MaxWriteTryNum	    0x03    //重复写nandflash次数

//product ID
#define ProductID_SAMSUNG   0xec    //厂商代码

//nandflash command
#define NandReadCommand0    0x00     //读A区指令
#define NandReadCommand1    0x01     //读B区指令
#define NandReadCommand2    0x50     //读C区指令
#define NandWriteCommand    0x80     //写输入指令
#define NandWriteStartCom   0x10     //写开始指令
#define NandReadIDCom	    0x90     //读厂商指令
#define NandEraseCom	    0x60     //擦除建立指令
#define NandEraseStartCom   0xd0     //擦除开始指令
#define NandReadStatusCom   0x70     //读擦写是否成功标志

//定义常量
static U8 const NandTypeIdx[MaxNandTypeNum] = {0xE3,0xE6,0x73,0x75}; //nandflash型号列表
//                                                  4M         8M         16M        32M
static U32 const NandSizeIdx[MaxNandTypeNum] = {0x00400000,0x00800000,0x01000000,0x02000000}; //nandflash总容量列表
//                                                     8K     8K     16K    16K
static U16 const NandBlockSizeIdx[MaxNandTypeNum] = {0x2000,0x2000,0x4000,0x4000}; //nandflash块容量列表

//定义全局变量
U32 NandFlashSize;          //nandflash可使用全局容量
U16 NandBlockSize;          //nandflash全局块容量
BOOL NandFlashExist; //nandflash是否存在

// 读NandFlash厂商码
static void nf_ReadIDOneTime(U8 * id)
{
    NandSelect();
	NfMoveCToFlash(NandReadIDCom);
	NfMoveAToFlash(0x00);
	nf_MoveByteToRam(id,2);
    NandDeselect();
}

// NandFlash初始化
extern Boolean NF_DeviceInit(void)
{
	U8 id[2];
    Uchar i;
    Boolean ok;

    ok = 0;
    nf_ReadIDOneTime(id);
    for(i=0 ; i<MaxWriteTryNum ; i++)
    {
        U8 tmp[2];

        nf_ReadIDOneTime(tmp);
        if((id[0] == tmp[0]) && (id[1] == tmp[1]))
        {
            ok = 1;
            break;
        }
        else
        {
            id[0] = tmp[0];
            id[1] = tmp[1];
        }
    }
    if(ok)
    {
    	if(id[0] == ProductID_SAMSUNG)
    	{
    		for(i=0 ; i<MaxNandTypeNum ; i++)
    		{
    			if(id[1] == NandTypeIdx[i])
    			{
                    NandFlashSize = NandSizeIdx[i];
    				NandBlockSize = NandBlockSizeIdx[i];
    				NandFlashExist = TRUE;
    				return(TRUE);
    			}
    		}
    	}
    }
    NandFlashSize = 0xFFFFFFFF;
	NandBlockSize = 0xFFFF;
	NandFlashExist = FALSE;
	return(FALSE);
}

// 判断Nand Flash是否插入
extern Boolean NF_NoNandFlashErr(void)
{
	if(NandFlashExist == FALSE)
	{
		return(TRUE);
	}
	return(FALSE);
}

// 选择A,B,C区
static void nf_AreaSelect(Ulong nandadr,Boolean area)
{
    Uchar rdcmd;

	if(area == 1)
	{
        rdcmd = NandReadCommand2;
	}
	else
	{
        rdcmd = (nandadr & 0x00000100) ? NandReadCommand1 : NandReadCommand0;
	}
    NfMoveCToFlash(rdcmd);
}

// 地址输出
// 输入: RwOrErase  0:设置Erase的地址, 1:设置读写地址
static void nf_AddrOutput(Ulong nandadr,Boolean RwOrErase)
{
    UNION32 un_adr;

    un_adr.l = nandadr;
    if(RwOrErase)
    {
        NfMoveAToFlash(un_adr.b[0]);                // output address(a0~a7)
    }
	un_adr.l >>= 1;
	NfMoveAToFlash(un_adr.b[1]);                    // output address(a9~a16)
    NfMoveAToFlash(un_adr.b[2]);                    // output address(a17~a24)
	if(NandFlashSize > 0x02000000)                  //超过32M
	{
        NfMoveAToFlash(un_adr.b[3]);                // output address(a25~a26)
	}
}

// 向nandflash发送读命令
static void nf_SendReadCom(Ulong nandadr,Boolean area)
{
    nf_AreaSelect(nandadr,area);
    nf_AddrOutput(nandadr,1);
    nf_PollBusy(100);       //根据samsung数据手册进行延时
}

// 从nandflash一个页内读取数据到指定缓冲区,不可以跨页读
extern void NF_ReadDataInPage(Ulong nandadr,U8 * buf,Uint len,Boolean area)
{
    NandSelect();
    nf_SendReadCom(nandadr,area);
    nf_MoveByteToRam(buf,len);
    NandDeselect();
}

// 判断nandflash一个页内的数据是否可以写成指定缓冲区中的数据,不可以跨页判断
extern Boolean NF_CompAndDataInPage(Ulong nandadr,U8 * buf,Uint len)
{
    Boolean result;

    NandSelect();
    nf_SendReadCom(nandadr,0);
    result = nf_CompAndRamFlash(buf,len);
    NandDeselect();
    return(result);
}

//读擦写是否成功标志
static Uchar nf_ReadStatus(void)
{
    U8 status;

	NfMoveCToFlash(NandReadStatusCom);         //read status
	nf_MoveByteToRam(&status,1);
    return(status);
}

// 将NandFlash作块擦除
extern Boolean NF_EraseBlock(Ulong nandadr)
{
    Uchar i,status;

    for(i=0 ; i<MaxWriteTryNum ; i++)                               // retry 10 times
    {
        NandSelect();
        NandNoProtect();
        NfMoveCToFlash(NandEraseCom);
        nf_AddrOutput(nandadr,0);
        NfMoveCToFlash(NandEraseStartCom);
        nf_PollBusy(30000);
        status = nf_ReadStatus();
        NandProtect();
        NandDeselect();
        if((status & 0x01) == 0)
        {
            return(TRUE);
        }
    }
    return(FALSE);
}

// 从指定缓冲区写入数据到nandflash一个页内,不可以跨页写
extern Boolean NF_WriteDataInPage(Ulong nandadr,U8 * buf,Uint len,Boolean area)
{
    Uchar i;

    for(i=0 ; i<MaxWriteTryNum ; i++)                       // retry 3 times
    {
        Uchar status;

        NandNoProtect();
        NandSelect();
        nf_AreaSelect(nandadr,area);
        NfMoveCToFlash(NandWriteCommand);
        nf_AddrOutput(nandadr,1);
        nf_MoveByteToFlash(buf,len);
        NfMoveCToFlash(NandWriteStartCom);
        nf_PollBusy(5000);                             // check busy (spec: typ=200us, max=500us)
        status = nf_ReadStatus();                 // get status
        NandDeselect();
        NandProtect();                              // enable protect
        if(status & 0x01)
        {
            continue;
        }
//-------
        NandSelect();
        nf_SendReadCom(nandadr,area);
        status = nf_CompRamFlash(buf,len);
        NandDeselect();
        if(status == TRUE)
        {
            return(TRUE);                       // program ok
        }
    }
    return(FALSE);
}

#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -