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

📄 nanddrvr.c

📁 ATMEL单片机可用的文件系统源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/***********************************************************************/
/*                                                                     */
/*   Module:  nanddrvr.c                                               */
/*   Release: 2004.5                                                   */
/*   Version: 2003.3                                                   */
/*   Purpose: NAND Flash File System Driver                            */
/*                                                                     */
/***********************************************************************/
#include "../posix.h"
#if INC_NAND_FS
#include "../include/libc/string.h"
#include "../include/targetos.h"
#include "../include/sys.h"
#include "../include/fsprivate.h"

#include "xp860t.h"
#include "mpc860.h"

/***********************************************************************/
/* Symbol Definitions                                                  */
/***********************************************************************/
#define BLOCK_SIZE      (8 * 1024)
#define NUM_BLOCKS      1024
#define PAGE_SIZE       512

/***********************************************************************/
/* Global Variable Definitions                                         */
/***********************************************************************/
static int ExtraBytes;  /* TRUE iff chip is set to access extra bytes */

/***********************************************************************/
/* Function Prototypes                                                 */
/***********************************************************************/
void perror(const char *s);
void SysWait50ms(void);

/***********************************************************************/
/* Local Function Definitions                                          */
/***********************************************************************/

/***********************************************************************/
/* page_erased: Check if page's data bytes and extra bytes are erased  */
/*                                                                     */
/*      Inputs: addr = the page address                                */
/*              vol = driver's volume pointer                          */
/*                                                                     */
/*     Returns: TRUE if erased, FALSE if any bit is not 1              */
/*                                                                     */
/***********************************************************************/
static int page_erased(ui32 addr, void *vol)
{
  int n = PAGE_SIZE + 16;

  /*-------------------------------------------------------------------*/
  /* Clear any pre-existing interrupt and begin access.                */
  /*-------------------------------------------------------------------*/
  MPC860_SIPEND = IRQ3;
  lowerCE();

  /*-------------------------------------------------------------------*/
  /* Send command to start reading at first half of NAND data page.    */
  /*-------------------------------------------------------------------*/
  raiseCLE();
  NandPort = 0x00;  /* read command */
  ExtraBytes = FALSE;
  lowerCLE();

  /*-------------------------------------------------------------------*/
  /* Send address as three separate bytes.                             */
  /*-------------------------------------------------------------------*/
  raiseALE();
  NandPort = 0;
  NandPort = (ui8)(addr >> 9);
  NandPort = (ui8)(addr >> 17);
  lowerALE();

  /*-------------------------------------------------------------------*/
  /* Wait until device is ready.                                       */
  /*-------------------------------------------------------------------*/
  while ((MPC860_SIPEND & IRQ3) == FALSE) ;

  /*-------------------------------------------------------------------*/
  /* Check one byte at a time.                                         */
  /*-------------------------------------------------------------------*/
  do
    if (NandPort != 0xFF)
    {
      raiseCE();
      return FALSE;
    }
  while (--n);

  /*-------------------------------------------------------------------*/
  /* End device access and return success.                             */
  /*-------------------------------------------------------------------*/
  raiseCE();
  return TRUE;
}

/***********************************************************************/
/*  write_page: ECC encode and write one NAND flash page               */
/*                                                                     */
/*      Inputs: buffer = pointer to buffer containing data to write    */
/*              type = page type flag                                  */
/*              addr = the page address                                */
/*              wear = wear count of this page's block                 */
/*              vol = driver's volume pointer                          */
/*                                                                     */
/*     Returns: 0 for success, -1 for chip error, 1 for verify error   */
/*                                                                     */
/***********************************************************************/
static int write_page(void *buffer, ui32 addr, ui32 type, ui32 wear,
                      void *vol)
{
  int n;
  ui8 *dst, ecc[10], status;

  PfAssert(page_erased(addr, vol));

  /*-------------------------------------------------------------------*/
  /* Ensure the NAND address pointer is back to the data page.         */
  /*-------------------------------------------------------------------*/
  if (ExtraBytes)
  {
    /*-----------------------------------------------------------------*/
    /* Clear any pre-existing interrupt and begin access.              */
    /*-----------------------------------------------------------------*/
    MPC860_SIPEND = IRQ3;
    lowerCE();

    /*-----------------------------------------------------------------*/
    /* Send command to start reading at first half of NAND data page.  */
    /*-----------------------------------------------------------------*/
    raiseCLE();
    NandPort = 0x00;  /* read command */
    lowerCLE();

    /*-----------------------------------------------------------------*/
    /* Send address 0 as three separate bytes.                         */
    /*-----------------------------------------------------------------*/
    raiseALE();
    NandPort = 0;
    NandPort = 0;
    NandPort = 0;
    lowerALE();

    /*-----------------------------------------------------------------*/
    /* Wait until device is ready.                                     */
    /*-----------------------------------------------------------------*/
    while ((MPC860_SIPEND & IRQ3) == FALSE) ;

    /*-----------------------------------------------------------------*/
    /* Read one byte and then end the device access.                   */
    /*-----------------------------------------------------------------*/
    NandPort;
    raiseCE();

    /*-----------------------------------------------------------------*/
    /* Clear flag since NAND pointer is reset to start of data page.   */
    /*-----------------------------------------------------------------*/
    ExtraBytes = FALSE;
  }

  /*-------------------------------------------------------------------*/
  /* Compute page's ECC encoding.                                      */
  /*-------------------------------------------------------------------*/
  EncodeEcc(buffer, ecc);

  /*-------------------------------------------------------------------*/
  /* Clear any pre-existing interrupt and begin write access.          */
  /*-------------------------------------------------------------------*/
  MPC860_SIPEND = IRQ3;
  lowerCE();

  /*-------------------------------------------------------------------*/
  /* Send Serial Data Input command.                                   */
  /*-------------------------------------------------------------------*/
  raiseCLE();
  NandPort = 0x80;  /* serial data input command */
  lowerCLE();

  /*-------------------------------------------------------------------*/
  /* Send address as three separate bytes.                             */
  /*-------------------------------------------------------------------*/
  raiseALE();
  NandPort = 0;
  NandPort = (ui8)(addr >> 9);
  NandPort = (ui8)(addr >> 17);
  lowerALE();

  /*-------------------------------------------------------------------*/
  /* Write the data portion.                                           */
  /*-------------------------------------------------------------------*/
  for (dst = buffer, n = 0; n < PAGE_SIZE; ++n)
    NandPort = *dst++;

  /*-------------------------------------------------------------------*/
  /* Write the 10-byte ECC portion.                                    */
  /*-------------------------------------------------------------------*/
  for (n = 0; n < 10; ++n)
    NandPort = ecc[n];

  /*-------------------------------------------------------------------*/
  /* Write the four type bytes.                                        */
  /*-------------------------------------------------------------------*/
  NandPort = (ui8)(type >> 24);
  NandPort = (ui8)(type >> 16);
  NandPort = (ui8)(type >> 8);
  NandPort = (ui8)type;

  /*-------------------------------------------------------------------*/
  /* Send Auto Program command.                                        */
  /*-------------------------------------------------------------------*/
  raiseCLE();
  NandPort = 0x10;  /* auto program command */
  lowerCLE();

  /*-------------------------------------------------------------------*/
  /* Wait until device is ready.                                       */
  /*-------------------------------------------------------------------*/
  while ((MPC860_SIPEND & IRQ3) == FALSE) ;

  /*-------------------------------------------------------------------*/
  /* Send Status Read command.                                         */
  /*-------------------------------------------------------------------*/
  raiseCLE();
  NandPort = 0x70;  /* status read command */
  lowerCLE();

  /*-------------------------------------------------------------------*/
  /* Read device status and end write access.                          */
  /*-------------------------------------------------------------------*/
  status = NandPort;
  raiseCE();

  /*-------------------------------------------------------------------*/
  /* Return -1 if chip reports program error.                          */
  /*-------------------------------------------------------------------*/
  if (status != 0xC0)
    return -1;

  /*-------------------------------------------------------------------*/
  /* Clear any previous interrupt and begin read-verify access.        */
  /*-------------------------------------------------------------------*/
  MPC860_SIPEND = IRQ3;
  lowerCE();

  /*-------------------------------------------------------------------*/
  /* Send command to start reading at first half of NAND data page.    */
  /*-------------------------------------------------------------------*/
  raiseCLE();
  NandPort = 0x00;  /* read command */
  lowerCLE();

  /*-------------------------------------------------------------------*/
  /* Send address as three separate bytes.                             */
  /*-------------------------------------------------------------------*/
  raiseALE();
  NandPort = 0;
  NandPort = (ui8)(addr >> 9);
  NandPort = (ui8)(addr >> 17);
  lowerALE();

  /*-------------------------------------------------------------------*/
  /* Wait until device is ready.                                       */
  /*-------------------------------------------------------------------*/
  while ((MPC860_SIPEND & IRQ3) == FALSE) ;

  /*-------------------------------------------------------------------*/
  /* Read-verify the data portion.                                     */
  /*-------------------------------------------------------------------*/
  for (dst = buffer, n = 0; n < PAGE_SIZE; ++n)
    if (*dst++ != NandPort)
    {
      raiseCE();
      return 1;
    }

  /*-------------------------------------------------------------------*/
  /* Read-verify the 10-byte ECC portion.                              */
  /*-------------------------------------------------------------------*/
  for (n = 0; n < 10; ++n)
    if (NandPort != ecc[n])
    {
      raiseCE();
      return 1;
    }

  /*-------------------------------------------------------------------*/
  /* End device access and return success.                             */
  /*-------------------------------------------------------------------*/
  raiseCE();
  return 0;
}

/***********************************************************************/
/*  write_type: Write page's type value                                */
/*                                                                     */
/*      Inputs: addr = the page address                                */
/*              type = page type (0xFFFF0000)                          */
/*              vol = driver's volume pointer                          */
/*                                                                     */
/*        Note: Updates four-byte type flag written by wr_page()       */
/*                                                                     */
/***********************************************************************/
static int write_type(ui32 addr, ui32 type, void *vol)
{
  ui8 status;

  /*-------------------------------------------------------------------*/
  /* Ensure the NAND address pointer is set to the extra bytes.        */
  /*-------------------------------------------------------------------*/
  if (ExtraBytes == FALSE)
  {
    /*-----------------------------------------------------------------*/
    /* Clear any pre-existing interrupt and begin access.              */
    /*-----------------------------------------------------------------*/
    MPC860_SIPEND = IRQ3;
    lowerCE();

    /*-----------------------------------------------------------------*/
    /* Send command to start reading at the NAND extra bytes.          */
    /*-----------------------------------------------------------------*/
    raiseCLE();
    NandPort = 0x50;  /* read command */
    lowerCLE();

    /*-----------------------------------------------------------------*/
    /* Send address 0 as three separate bytes.                         */
    /*-----------------------------------------------------------------*/
    raiseALE();
    NandPort = 0;
    NandPort = 0;
    NandPort = 0;
    lowerALE();

    /*-----------------------------------------------------------------*/
    /* Wait until device is ready.                                     */

⌨️ 快捷键说明

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