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

📄 nandfs.c

📁 基于EP7312的MP3播放器源代码,包括MCU和PC端代码.
💻 C
📖 第 1 页 / 共 3 页
字号:
//****************************************************************************//// NANDFS.C - File system driver for the on-board NAND FLASH.//// Copyright (c) 1999,2000,2001 Cirrus Logic, Inc.////****************************************************************************#include "globals.h"#include "../hwport.h"#include "../hwdefs.h"//****************************************************************************//// The persistent state of the NAND file system.////****************************************************************************static struct{    //    // A list of the bad blocks in the on-board NAND FLASH, in numerical order.    //    unsigned short usBadBlocks[64];    //    // The number of bad blocks in the on-board NAND FLASH.    //    unsigned short usNumBadBlocks;    //    // The number of blocks in the on-board NAND FLASH.    //    unsigned short usNumBlocks;    //    // The number of pages per block of the on-board NAND FLASH.    //    unsigned char ucPagesPerBlock;    //    // Unused bytes to pad the next member to a word boundary.    //    unsigned char ucUnused1, ucUnused2, ucUnused3;    //    // The length of the one file in the on-board NAND FLASH.    //    unsigned long ulFileLength;    //    // A pointer to the function used to read a page from the on-board NAND    // FLASH.    //    void (*pfnRead)(unsigned long ulNANDAddress, unsigned long ulPage,                    unsigned char *pucData, unsigned char *pucRedundant);    //    // A pointer to the function used to write a page to the on-board NAND    // FLASH.    //    void (*pfnWrite)(unsigned long ulNANDAddress, unsigned long ulPage,                     unsigned char *pucData, unsigned char *pucRedundant);    //    // A pointer to the function used to erase a block of the on-board NAND    // FLASH.    //    void (*pfnErase)(unsigned long ulNANDAddress, unsigned long ulBlock);} sNAND;//****************************************************************************//// The following structure contains the parameters of an opened file.////****************************************************************************typedef struct{    //    // The next page of the file to be read.    //    unsigned long ulPage;    //    // The current byte offset into the file.    //    unsigned long ulFilePos;} tNANDFile;//****************************************************************************//// The following structure contains the parameters of an opened directory.////****************************************************************************typedef struct{    //    // An indicator that is true when there have been no IOCTL_FS_READDIR    // Ioctls after an IOCTL_FS_OPENDIR Ioctl.    //    unsigned long bIsFirstDirEntry;} tNANDDir;//****************************************************************************//// NextPage increments to the next valid page of the NAND FLASH.  The next// valid page is "*pulPage++", unless this falls on an invalid block.  The// current value of the page variable is returned, so that this function can// be used as a post-increment reference (i.e. NextPage(&x) is roughly// equivalent to x++).////****************************************************************************static unsigned longNextPage(unsigned long *pulPage){    unsigned long ulRet;    int iIdx;    //    // Save the current page number.    //    ulRet = *pulPage;    //    // Increment the page number.    //    (*pulPage)++;    //    // If this is not the first page of a block, then it is not part of an    // invalid block.    //    if((*pulPage & (sNAND.ucPagesPerBlock - 1)) != 0)    {        //        // Return the previous page number.        //        return(ulRet);    }    //    // Increment the page number until we reach a page in a valid block.    //    while(1)    {        //        // See if this page lies in one of our invalid blocks.        //        for(iIdx = 0; iIdx < sNAND.usNumBadBlocks; iIdx++)        {            if((*pulPage / sNAND.ucPagesPerBlock) == sNAND.usBadBlocks[iIdx])            {                break;            }        }        //        // If this page does not lie in one of the invalid blocks, then stop        // incrementing the page number.        //        if(iIdx == sNAND.usNumBadBlocks)        {            break;        }        //        // Skip to the first page of the next block.        //        *pulPage += sNAND.ucPagesPerBlock;    }    //    // Return the previous page number.    //    return(ulRet);}//****************************************************************************//// CheckNAND determines if the NAND FLASH on the board has been "formatted"// and reads the bad block table if it has been formatted.////****************************************************************************static intCheckNAND(unsigned char *pucBuffer, unsigned char *pucWriteBuffer){    int iLoop;    //    // Read the first page of the NAND FLASH.    //    (sNAND.pfnRead)(HwNANDAddress, 0, pucBuffer, pucWriteBuffer);    //    // See if the NAND FLASH has been formatted by looking for the signature    // at the beginning of the first page.    //    if((pucBuffer[0] != 'B') || (pucBuffer[1] != 'K') ||       (pucBuffer[2] != 'O') || (pucBuffer[3] != 'K'))    {        //        // The signature does not exist, so the NAND FLASH has not been        // formatted yet.        //        return(0);    }    //    // Get the number of bad blocks.    //    sNAND.usNumBadBlocks = pucBuffer[4] | (pucBuffer[5] << 8);    //    // Make sure that the number of bad blocks is valid.    //    if(sNAND.usNumBadBlocks > 64)    {        sNAND.usNumBadBlocks = 0;        return(0);    }    //    // Read the bad block table.    //    for(iLoop = 0; iLoop < sNAND.usNumBadBlocks; iLoop++)    {        sNAND.usBadBlocks[iLoop] = pucBuffer[6 + (iLoop << 1)] |                                   (pucBuffer[7 + (iLoop << 1)] << 8);    }    //    // The media has been formatted.    //    return(1);}//****************************************************************************//// FormatNAND prepares the NAND FLASH for use to record/download file data.// It checks the NAND FLASH for bad blocks and builds a bad block table.////****************************************************************************static voidFormatNAND(unsigned char *pucBuffer, unsigned char *pucWriteBuffer){    unsigned long ulValue;    int iBlock, iPage, iIdx;    //    // We only need to check for bad blocks if the NAND FLASH has not already    // been formatted.    //    if(!CheckNAND(pucBuffer, pucWriteBuffer))    {        //        // Initially, there are no bad blocks in the NAND FLASH (until we find        // bad blocks).        //        sNAND.usNumBadBlocks = 0;        //        // Loop through all the blocks in the on-board NAND FLASH.        //        for(iBlock = 1; iBlock < sNAND.usNumBlocks; iBlock++)        {            //            // Read the first two pages of each block.  The page will be all            // 0xff if it is good, and will contain zeros if it is bad.            //            for(iPage = 0; iPage < 2; iPage++)            {                //                // Read the page from NAND FLASH.                //                (sNAND.pfnRead)(HwNANDAddress,                                (iBlock * sNAND.ucPagesPerBlock) + iPage,                                pucBuffer, pucWriteBuffer);                //                // Verify that the page contains all 0xff.                //                for(iIdx = 0; iIdx < 512; iIdx++)                {                    if(pucBuffer[iIdx] != 0xff)                    {                        break;                    }                }                //                // If this page did not contain all 0xff, then break out of the                // loop.                //                if(iIdx != 512)                {                    break;                }                //                // Verify that the spare area contains all 0xff.                //                for(iIdx = 0; iIdx < 16; iIdx++)                {                    if(pucWriteBuffer[iIdx] != 0xff)                    {                        break;                    }                }                //                // If the spare area did not contain all 0xff, then break out                // of the loop.                //                if(iIdx != 16)                {                    break;                }            }            //            // If both pages did not contain all 0xff, then this block is bad.            //            if(iPage != 2)            {                //                // Save this block in the bad block table.                //                sNAND.usBadBlocks[sNAND.usNumBadBlocks++] = iBlock;                //                // Quit scanning if we've found too many bad blocks.  This                // ignores any following bad blocks, but what can you do (this                // isn't exactly a "filesystem" and is certainly not product                // worthy)?                //                if(sNAND.usNumBadBlocks == 64)                {                    break;                }            }        }        //        // Build the signature and bad block table for the first page of the        // NAND FLASH.        //        pucBuffer[0] = 'B';        pucBuffer[1] = 'K';        pucBuffer[2] = 'O';        pucBuffer[3] = 'K';        //        // Fill in the bad block table.        //        pucBuffer[4] = sNAND.usNumBadBlocks & 0xFF;        pucBuffer[5] = (sNAND.usNumBadBlocks >> 8) & 0xFF;        for(iIdx = 0; iIdx < sNAND.usNumBadBlocks; iIdx++)        {            pucBuffer[6 + (iIdx << 1)] = sNAND.usBadBlocks[iIdx] & 0xFF;            pucBuffer[7 + (iIdx << 1)] = (sNAND.usBadBlocks[iIdx] >> 8) & 0xFF;        }        //        // Write the bad block table to the beginning of the NAND FLASH.        //        (sNAND.pfnErase)(HwNANDAddress, 0);        NANDWaitTilNotBusy(HwNANDAddress);        (sNAND.pfnWrite)(HwNANDAddress, 0, pucBuffer, pucWriteBuffer);        NANDWaitTilNotBusy(HwNANDAddress);    }    //    // Set the file size to zero, so that we do not try to play the empty    // contents of the NAND FLASH.    //    pucBuffer[0] = 0;    pucBuffer[1] = 0;    pucBuffer[2] = 0;    pucBuffer[3] = 0;    ulValue = sNAND.ucPagesPerBlock - 1;    NextPage(&ulValue);    (sNAND.pfnErase)(HwNANDAddress, ulValue / sNAND.ucPagesPerBlock);    NANDWaitTilNotBusy(HwNANDAddress);    (sNAND.pfnWrite)(HwNANDAddress, ulValue, pucBuffer, pucWriteBuffer);    NANDWaitTilNotBusy(HwNANDAddress);}//****************************************************************************//// The file system entry point for the on-board NAND FLASH.////****************************************************************************unsigned longNANDIoctl(unsigned char *pucScratch, unsigned char *pucWriteBuffer,          unsigned long ulIoctl, unsigned long ulInstance,          unsigned long ulParam1, unsigned long ulParam2){    volatile unsigned long *pulGPIO = (unsigned long *)HwBaseAddress;    //    // If we are being initialized, then we need to setup our global variables.    //    if(ulIoctl == IOCTL_FS_INIT)    {        unsigned long ulDeviceID;        //        // Select the on-board NAND.        //        pulGPIO[HwPortABCD >> 2] &= ~HwPortABCD_NAND1_CS;        //        // Get the ID of the on-board NAND FLASH.        //        ulDeviceID = NANDGetID(HwNANDAddress);        //        // Determine the size and geometry of the on-board NAND FLASH.        //        switch(ulDeviceID)        {            //            // The device capacity is 4MB.            //            case 0x6B:            case 0xE3:            case 0xE5:            {                //                // There are 512 blocks in this device.                //                sNAND.usNumBlocks = 512;                //                // There are 16 pages per block in this device.                //                sNAND.ucPagesPerBlock = 16;                //                // Fill in the function pointers for accessing this FLASH                // device.                //                sNAND.pfnRead = NANDRead_512_3;                sNAND.pfnWrite = NANDWrite_512_3;                sNAND.pfnErase = NANDErase_16;                //                // We've interpreted the device ID.                //                break;            }            //            // The device capacity is 8MB.            //            case 0xE6:            {                //                // There are 1024 blocks in this device.                //                sNAND.usNumBlocks = 1024;                //                // There are 16 pages per block in this device.                //                sNAND.ucPagesPerBlock = 16;                //                // Fill in the function pointers for accessing this FLASH                // device.                //                sNAND.pfnRead = NANDRead_512_3;                sNAND.pfnWrite = NANDWrite_512_3;                sNAND.pfnErase = NANDErase_16;                //                // We've interpreted the device ID.                //                break;            }            //            // The device capacity is 16MB.            //            case 0x73:

⌨️ 快捷键说明

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