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

📄 nandflsh.c

📁 Cirrus Logic EP7312处理器部分控制程序。
💻 C
📖 第 1 页 / 共 2 页
字号:
//****************************************************************************
//
// NANDFLSH.C - Routines to access the NAND FLASH and SmartMedia
//
// Copyright (c) 1999 - 2001 Cirrus Logic, Inc.
//
//****************************************************************************
#include "ep7312.h"
#include "lib7312.h"

//****************************************************************************
//
// The following table contains the mapping from the NAND device ID to the
// physical layout of the NAND memory array.
//
//****************************************************************************
#define NOP __asm { nop }
#define NUMIDS 7
static const struct
{
    unsigned char ucID;
    unsigned char ucPageSize;
    unsigned char ucPagesPerBlock;
    unsigned char ucBlocks;
} sNANDMap[NUMIDS] =
{
    { 0xEA, 0, 16, 1 }, // 256bytes * 16pages * 512blocks = 2Meg
    { 0xE3, 1, 16, 1 }, // 512bytes * 16pages * 512blocks = 4Meg
    { 0xE5, 1, 16, 1 }, // 512bytes * 16pages * 512blocks = 4Meg
    { 0xE6, 1, 16, 2 }, // 512bytes * 16pages * 1024blocks = 8Meg
    { 0x73, 1, 32, 2 }, // 512bytes * 32pages * 1024blocks = 16Meg
    { 0x75, 1, 32, 4 }, // 512bytes * 32pages * 2048blocks = 32Meg
    { 0x76, 1, 32, 8 }, // 512bytes * 32pages * 4096blocks = 64Meg
};

//****************************************************************************
//
// The layout of the on-board NAND FLASH.
//
//****************************************************************************
static unsigned long ulNANDReadID = 0;
static unsigned long ulNANDPageSize;
static unsigned long ulNANDPagesPerBlock;
static unsigned long ulNANDNumBlocks;

//****************************************************************************
//
// The layout of the SmartMedia card.
//
//****************************************************************************
static unsigned long ulSMPageSize;
static unsigned long ulSMPagesPerBlock;
static unsigned long ulSMNumBlocks;

//****************************************************************************
//
// NANDGetSize determines the size and layout of the on-board NAND FLASH based
// on the device ID read from the NAND FLASH.
//
//****************************************************************************
long
NANDGetSize(unsigned long *pulDeviceSize, unsigned long *pulPageSize,
            unsigned long *pulPagesPerBlock, unsigned long *pulNumBlocks)
{
    unsigned long * volatile pulPtr = (unsigned long *)HwNANDAddress;
    unsigned char * volatile pucPortB = (unsigned char *)(HwBaseAddress +
                                                          HwPortB);
    unsigned char * volatile pucPortBdir = (unsigned char *)(HwBaseAddress + 
                                                            HwDdrB);
    unsigned long * volatile pulMemPtr = (unsigned long *)(HwBaseAddress +
                                                           HwMemConfig1);
    unsigned char volatile ucTemp;
    long lIdx;

    //
    // Set up chip select 1 for bus width of 32 bits
    //
    *pulMemPtr |= 0x1900;

    //
    // Set the port B data direction register.
    //
    *pucPortBdir = 0xFA;

    //
    // Set the initial value of port B, with both the NAND and Smart
    // Media chip selects set to 0.
    //
    *pucPortB = 0x00;

    //
    // Select the NAND FLASH.
    //
    *pucPortB |= HwPortBNANDCS;

    //
    // Assert CLE.
    //
    *pucPortB |= HwPortBCLE;

    //
    // Write the read id command.
    //
    *pulPtr = 0x00000090;

    //
    // Deassert CLE.
    //
    *pucPortB &= ~HwPortBCLE;

    //
    // Assert ALE.
    //
    *pucPortB |= HwPortBALE;

    //
    // Write the address.
    //
    *pulPtr = 0x00000000;

    //
    // Deassert ALE.
    //
    *pucPortB &= ~HwPortBALE;

    //
    // Read the maker ID.
    //
    ucTemp = *pulPtr;

    //
    // Read the device ID.
    //
    ucTemp = *pulPtr;

    //
    // Deassert the NAND FLASH.
    //
    *pucPortB &= ~HwPortBNANDCS;

    //
    // Find this device ID in our table.
    //
    for(lIdx = 0; lIdx < NUMIDS; lIdx++)
    {
        if((ucTemp & 255) == sNANDMap[lIdx].ucID)
        {
            break;
        }
    }

    //
    // Return an error if we could not find this device ID.
    //
    if(lIdx == NUMIDS)
    {
        return(0);
    }

    //
    // Fill in the NAND FLASH globals based on the physical layout of the NAND
    // devices on the board.
    //
    ulNANDPageSize = sNANDMap[lIdx].ucPageSize ? 512 : 256;
    ulNANDPagesPerBlock = sNANDMap[lIdx].ucPagesPerBlock;
    ulNANDNumBlocks = (unsigned long)sNANDMap[lIdx].ucBlocks << 9;
    ulNANDReadID = 1;

    //
    // If requested, return the size of the NAND memory.
    //
    if(pulDeviceSize)
    {
        *pulDeviceSize = ulNANDPageSize * ulNANDPagesPerBlock *
                         ulNANDNumBlocks * 4;
        *pulPageSize = ulNANDPageSize;
        *pulPagesPerBlock = ulNANDPagesPerBlock;
        *pulNumBlocks = ulNANDNumBlocks;
    }

    //
    // Success.
    //
    return(1);
}

//****************************************************************************
//
// NANDReadPage reads data from the specified page of the on-board NAND FLASH.
//
//****************************************************************************
void
NANDReadPage(unsigned long ulPage, int bReadSpare, unsigned char *pucBuffer)
{
    unsigned long * volatile pulPtr = (unsigned long *)HwNANDAddress;
    unsigned char * volatile pucPortB = (unsigned char *)(HwBaseAddress +
                                                          HwPortB);
    long lIdx;

    //
    // Make sure that we know the layout of the on-board NAND FLASH.
    //
    if(!ulNANDReadID)
    {
        NANDGetSize(0, 0, 0, 0);
    }

    //
    // Select the NAND FLASH.
    //
    *pucPortB |= HwPortBNANDCS;

    //
    // Assert CLE.
    //
    *pucPortB |= HwPortBCLE;

    //
    // Write the read1 command.
    //
    *pulPtr = 0x00;

    //
    // Deassert CLE.
    //
    *pucPortB &= ~HwPortBCLE;

    //
    // Assert ALE.
    //
    *pucPortB |= HwPortBALE;

    //
    // Write the address.
    //
    *pulPtr = 0x00;
    lIdx = ulPage & 0xFF;
    *pulPtr = lIdx;
    lIdx = (ulPage >> 8) & 0xFF;
    *pulPtr = lIdx;
    
    //
    // Deassert ALE.
    //
    *pucPortB &= ~HwPortBALE;

    //
    // Wait for at least 7uS for the row to copy from the cell array.
    //
    for(lIdx = 0; lIdx < 256; lIdx++)
    {
    }

    //
    // Read the data from this page.
    //
    for(lIdx = 0; lIdx < ulNANDPageSize; lIdx++)
    {
        pucBuffer[lIdx] = *pulPtr;
    }

    //
    // Read the spare area if requested.
    //
    if(bReadSpare)
    {
        for(lIdx = 0; lIdx < (ulNANDPageSize / 32); lIdx++)
        {
            pucBuffer[ulNANDPageSize + lIdx] = *pulPtr;
        }
    }

    //
    // De-select the NAND FLASH.
    //
    *pucPortB &= ~HwPortBNANDCS;
}

//****************************************************************************
//
// NANDEraseBlock erases the specified block of the on-board NAND FLASH.
//
//****************************************************************************
void
NANDEraseBlock(unsigned long ulBlock)
{
    unsigned long * volatile pulPtr = (unsigned long *)HwNANDAddress;
    unsigned char * volatile pucPortB = (unsigned char *)(HwBaseAddress +
                                                          HwPortB);
    long lIdx;

    //
    // Make sure that we know the layout of the on-board NAND FLASH.
    //
    if(!ulNANDReadID)
    {
        NANDGetSize(0, 0, 0, 0);
    }

    //
    // Convert the block number into the page number of the first page of the
    // block.  This is dependent on the number of pages per block.
    //
    switch(ulNANDPagesPerBlock)
    {
        case 16:
        {
            ulBlock <<= 4;
            break;
        }

        case 32:
        {
            ulBlock <<= 5;
            break;
        }
    }

    //
    // Select the NAND FLASH.
    //
    *pucPortB |= HwPortBNANDCS;

    //
    // Assert CLE.
    //
    *pucPortB |= HwPortBCLE;

    //
    // Write the auto block erase setup command.
    //
    *pulPtr = 0x60;

    //
    // Deassert CLE.
    //
    *pucPortB &= ~HwPortBCLE;

    //
    // Assert ALE.
    //
    *pucPortB |= HwPortBALE;

    //
    // Write the address.
    //
    lIdx = ulBlock & 0xFF;
    *pulPtr = lIdx;
    lIdx = (ulBlock >> 8) & 0xFF;
    *pulPtr = lIdx;
    
    //
    // Deassert ALE.
    //
    *pucPortB &= ~HwPortBALE;

    //
    // Assert CLE.
    //
    *pucPortB |= HwPortBCLE;

    //
    // Write the erase command.
    //
    *pulPtr = 0xd0;

    //
    // Write the read status command.
    //
    *pulPtr = 0x70;

    //
    // Deassert CLE.
    //
    *pucPortB &= ~HwPortBCLE;

    //
    // Wait until the erase has completed.
    //
    while((*pulPtr & 0x40) != 0x40)
    {
        for(lIdx = 0; lIdx < 1024; lIdx++)
        {
        }
    }

    //
    // Deselect the NAND FLASH.
    //
    *pucPortB &= ~HwPortBNANDCS;
}

//****************************************************************************
//
// NANDWritePage writes data to the specified page of the on-board NAND FLASH.
//
//****************************************************************************
void
NANDWritePage(unsigned long ulPage, int bWriteSpare, unsigned char *pucBuffer)
{
    unsigned long * volatile pulPtr = (unsigned long *)HwNANDAddress;
    unsigned char * volatile pucPortB = (unsigned char *)(HwBaseAddress +
                                                          HwPortB);
    long lIdx;

    //
    // Make sure that we know the layout of the on-board NAND FLASH.
    //
    if(!ulNANDReadID)
    {
        NANDGetSize(0, 0, 0, 0);
    }

    //
    // Select the NAND FLASH.
    //
    *pucPortB |= HwPortBNANDCS;

    //
    // Assert CLE.
    //
    *pucPortB |= HwPortBCLE;

    //
    // Write the sequential data input command.
    //
    *pulPtr = 0x80;

    //
    // Deassert CLE.
    //
    *pucPortB &= ~HwPortBCLE;

    //
    // Assert ALE.
    //
    *pucPortB |= HwPortBALE;

    //
    // Write the address.
    //
    *pulPtr = 0x00;
    lIdx = ulPage & 0xFF;
    *pulPtr = lIdx;
    lIdx = (ulPage >> 8) & 0xFF;
    *pulPtr = lIdx;

    //
    // Deassert ALE.
    //
    *pucPortB &= ~HwPortBALE;

    //
    // Write the data to this page.
    //
    for(lIdx = 0; lIdx < ulNANDPageSize; lIdx++)
    {
        *pulPtr = pucBuffer[lIdx];
    }

    //
    // Write data for the spare area if requested.
    //
    if(bWriteSpare)
    {
        for(lIdx = 0; lIdx < (ulNANDPageSize / 32); lIdx++)
        {
            *pulPtr = pucBuffer[ulNANDPageSize + lIdx];
        }
    }

    //
    // Assert CLE.
    //
    *pucPortB |= HwPortBCLE;

    //
    // Write the program command.
    //
    *pulPtr = 0x10;

    //
    // Write the read status command.
    //
    *pulPtr = 0x70;

    //
    // Deassert CLE.
    //
    *pucPortB &= ~HwPortBCLE;

    //
    // Wait until the program has completed.
    //
    while((*pulPtr & 0x40) != 0x40)
    {
        for(lIdx = 0; lIdx < 1024; lIdx++)
        {
        }
    }

    //
    // Deselect the NAND FLASH.
    //
    *pucPortB &= ~HwPortBNANDCS;
}

//****************************************************************************
//
// SMGetSize determines the size and layout of the SmartMedia card based on
// the device ID read from the SmartMedia card.  If an invalid ID is read, or
// the Smart Media card is not inserted, an error will be returned.
//
//****************************************************************************
long
SMGetSize(unsigned long *pulDeviceSize, unsigned long *pulPageSize,
            unsigned long *pulPagesPerBlock, unsigned long *pulNumBlocks)
{
    unsigned long * volatile pulPtr = (unsigned long *)HwNANDAddress;
    unsigned char * volatile pucPortB = (unsigned char *)(HwBaseAddress +
                                                          HwPortB);
    unsigned char * volatile pucPortBdir = (unsigned char *)(HwBaseAddress + 
                                                            HwDdrB);
    
    
    unsigned char volatile ucTemp;
    long lIdx;

    //
    // Set the port B data direction register.
    //
    *pucPortBdir = 0xFA;

    //
    // Set the initial value of port B, with both the NAND and Smart
    // Media chip selects set to 0.
    //
    *pucPortB = 0x00;

    //
    // Select the SmartMedia card.
    //
    *pucPortB |= HwPortBSMCS;

    //
    // Assert CLE.
    //
    *pucPortB |= HwPortBCLE;

    //
    // Write the read id command.
    //
    *pulPtr = 0x90;

    //
    // Deassert CLE.
    //
    *pucPortB &= ~HwPortBCLE;

    //
    // Assert ALE.
    //
    *pucPortB |= HwPortBALE;

    //
    // Write the address.
    //
    *pulPtr = 0x00;

    //
    // Deassert ALE.
    //
    *pucPortB &= ~HwPortBALE;

    //
    // Read the maker ID.
    //
    ucTemp = *pulPtr;

    //
    // Read the device ID.
    //
    ucTemp = *pulPtr;

    //
    // Deassert the SmartMedia card.
    //
    *pucPortB &= ~HwPortBSMCS;

    //
    // Find this device ID in our table.
    //
    for(lIdx = 0; lIdx < NUMIDS; lIdx++)
    {
        if(ucTemp == sNANDMap[lIdx].ucID)
        {
            break;
        }
    }

    //
    // Return an error if we could not find this device ID.
    //
    if(lIdx == NUMIDS)
    {
        return(0);
    }

    //
    // Fill in the SmartMedia globals based on the physical layout of the
    // SmartMedia card.
    //
    ulSMPageSize = sNANDMap[lIdx].ucPageSize ? 512 : 256;
    ulSMPagesPerBlock = sNANDMap[lIdx].ucPagesPerBlock;
    ulSMNumBlocks = (unsigned long)sNANDMap[lIdx].ucBlocks << 9;

    //
    // If requested, return the size of the SmartMedia card.
    //
    if(pulDeviceSize)
    {
        *pulDeviceSize = ulSMPageSize * ulSMPagesPerBlock * ulSMNumBlocks;
        *pulPageSize = ulSMPageSize;
        *pulPagesPerBlock = ulSMPagesPerBlock;
        *pulNumBlocks = ulSMNumBlocks;
    }

    //
    // Success.
    //
    return(1);
}

//****************************************************************************
//
// SMReadPage reads data from the specified page of the SmartMedia card.
//
//****************************************************************************
#if 0
long
SMReadPage(unsigned long ulPage, int bReadSpare, unsigned char *pucBuffer)
{
    unsigned long * volatile pulPtr = (unsigned long *)HwNANDAddress;
    unsigned char * volatile pucPortB = (unsigned char *)(HwBaseAddress +
                                                          HwPortB);
    long lIdx;

    //

⌨️ 快捷键说明

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