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

📄 nf.c

📁 ATMEL 89c51sndc mp3外接硬盘源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*C**************************************************************************
* NAME:         nf.c
*----------------------------------------------------------------------------
* Copyright (c) 2002 Atmel.
*----------------------------------------------------------------------------
* RELEASE:      snd1c-demo-hdd-0_2_0      
* REVISION:     1.1     
*----------------------------------------------------------------------------
* PURPOSE:
* This file contains the high level NF routines
*****************************************************************************/

/*_____ I N C L U D E S ____________________________________________________*/

#include "config.h"                         /* system configuration         */
#include "lib_demob\board.h"                /* board definition */
#include "lib\usb\usb_drv.h"                /* usb driver definition */
#include "nf.h"                             /* NF definition              */


/*_____ M A C R O S ________________________________________________________*/


/*_____ D E F I N I T I O N ________________________________________________*/

extern  data    Uint32  gl_ptr_mem;         /* memory data pointer */
extern  pdata   Byte gl_buffer[];
extern  bdata bit rx_bank;



xdata Byte nf_send_cmd_odd At(NF_CMD_LATCH_ENABLE_ADD_ODD); /* Command */
xdata Byte nf_send_add_odd At(NF_ADD_LATCH_ENABLE_ADD_ODD); /* Address */
xdata Byte volatile nf_data_odd At(NF_ADDRESS_CMD_DATA_ODD);/* Data    */

xdata Byte nf_send_cmd_even At(NF_CMD_LATCH_ENABLE_ADD_EVEN); /* Command */
xdata Byte nf_send_add_even At(NF_ADD_LATCH_ENABLE_ADD_EVEN); /* Address */
xdata Byte volatile nf_data_even At(NF_ADDRESS_CMD_DATA_EVEN);/* Data    */

/*_____ D E C L A R A T I O N ______________________________________________*/

bdata bit nf_block_used;                              /* Set when a block was used                  */
bdata bit nf_busy;                                    /* indicate that nand flash is busy           */
bdata bit nf_lut_modified;                            /* indicate that LUT have been modified       */
bdata bit nf_zone_change;                             /* indicate that we have to change zone       */
bdata bit nf_parity_bit;


data  Uint16  gl_cpt_page;                          /* internal page counter (byte access)        */
data  Uint32  gl_address;                           /* general address variable                   */
data  Uint32  nf_current_physical_sector_addr_even;    /* give the address of the current sector     */  
data  Uint32  nf_current_physical_sector_addr_odd;     /* give the address of the current sector     */  
data  Byte    nf_gl_buf_idx;

idata Byte    nf_zone;                              /* current zone number                        */
idata Byte    nf_gl_buf_free_idx ;
idata Byte    nf_gl_buf_idx_max;                       /* max index for updating LUT                 */
idata Byte    nf_spare_block;                             /* number of free block                       */
idata Byte    nf_old_zone;                             /* for zone change                            */  
idata Uint16  nf_logical_block;                        /* Current logical block value                */
idata Uint16  nf_look_up_table_block;                  /* look up table address (block)              */
idata Uint16  nf_block_to_be_deleted_even;             /* give the address of the next deleted block */
idata Uint16  nf_block_to_be_deleted_odd;              /* give the address of the next deleted block */
idata Uint16  block_min;                            /* address of the first block in the buffer   */
idata Uint16  block_max;                            /* address of the last block in the buffer    */

xdata t_free_blocks buf_free[24];                   /* contain free physical block address        */
xdata Byte lut_index[NF_ZONE_MAX];                  /* give the index for updating LUT            */
xdata Uint16 lut_block[NF_ZONE_MAX];                /* LUT address (block value)                  */
xdata Byte nf_spare_block_number[NF_ZONE_MAX];      /* Number of free spare block in each zone  */
xdata t_lut   buf[NF_BUFFER_SIZE];                  /* Buffer for write operation                 */

code Uint32 nf_mem_size = NF_DISK_SIZE;


/*F**************************************************************************
* NAME: read_spare_byte
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE:
*   read spare data byte and construct the look up table.
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
void read_spare_byte(void)
{
Byte    byte_5;
Byte    byte_6;
Byte    tmp_spare;
Uint16  j;           /* counter */
Uint16  i;           /* counter */
Uint32  temp_address;              
Uint16  start;       /* start value for the construction of the LUT */
Uint16  end;         /* final value */

xdata Uint16  block;
xdata Uint16  free_bloc_pos_even;
xdata Uint16  last_physical_used_block_even[NF_ZONE_MAX]; /* Last physical block used     */
xdata Uint16  free_bloc_pos_odd;
xdata Uint16  last_physical_used_block_odd[NF_ZONE_MAX]; /* Last physical block used     */
xdata Union16 block2;
bit     block_valid;
xdata Byte    lut_is_present[NF_ZONE_MAX];


  /* Global media initialization */
  nf_old_zone     = 0xFF;
  block_min       = 0xFFFF;         /* Starting buffer value    */
  nf_gl_buf_idx_max  = 0;              /* Max index in the buffer  */
  nf_lut_modified    = FALSE;          /* Buffer change flag       */
  nf_gl_buf_idx      = 0;              /* Main buffer index        */
  nf_gl_buf_free_idx = 0;              /* Free physical buffer idx */
  for (i = 0; i < NF_ZONE_MAX; i++)
  {
    lut_index[i] = 0;               /* LUT index                */
    lut_is_present[i] = FALSE;
  }

  

  /***************************************************/
  /* For each zone, this following lines :           */
  /*   Search bad block                              */
  /*   Determine if a LUT is present                 */
  /*   Determine the last physical block             */ 
  /***************************************************/

  Nf_CS_EVEN();
  Nf_wait_busy_even();
  for (i = 0; i < NF_ZONE_MAX; i++)                   /* for each zone */
  {
    gl_address = i << 5;                                 /* Start from physical sector 0 */
    nf_spare_block_number[i] = 23;                    /* Initialize the spare block table */
    last_physical_used_block_even[i] = (Uint16)(i);   /* Initialize the last used physical block value */

    for (j = NF_BLOCK_PER_ZONE; j != 0; j--)        /* for each block */ 
    {
      Nf_read_open_C_area_even(gl_address, 0x05);
      if ( Nf_rd_byte_even() != 0xFF )                         /* block status data : valid/invalid block */
      {
        nf_spare_block_number[i]--;                 /* Defect block */
      }
      else                                          /* Block is valid */
      {
        byte_6 = Nf_rd_byte_even();                 /* Determine is the block is a specific block */
        if (  (byte_6 == 0x00) ||                                   /* 0x00 = specific block */
              ( (byte_6 != 0xFF) && ( (byte_6 & 0xF8) != 0x10 ) &&  /* Value in redundant spare area not correct */
                (byte_6 != 0xE8) )                                  /* Don't care about LUT block */
           )
        { 
          nf_spare_block_number[i]--;               /* specific or invalid block */
        }
        else
        {
          /* Determine if the block is the look up table */ 
          if (byte_6 == 0xE8)                       /* look up table ? */
          {
            lut_is_present[i] = TRUE;
            lut_block[i] = (gl_address >> 5);
          }
          else
          {
            /* Determine the last physical used block */
            if ( (byte_6 & 0xF8) == 0x10)             /* Used block  */
            {
              last_physical_used_block_even[i] = gl_address >> 5;
            }
          }
        }

      }
      gl_address += (NF_ZONE_MAX << 5);    /* 4*32 */
    }
  }



  Nf_CS_ODD();
  Nf_wait_busy_odd();

  
  for (i = 0; i < NF_ZONE_MAX; i++)                 /* for each zone */
  {
    gl_address = i << 5;                                      /* Start from physical sector 0 */
    tmp_spare = 23;                  /* Initialize the spare block table */
    last_physical_used_block_odd[i] = (Uint16)(i);/* Initialize the last used physical block value */

    for (j = NF_BLOCK_PER_ZONE; j != 0; j--)        /* for each block */ 
    {
      Nf_read_open_C_area_odd(gl_address, 0x05);
      byte_5 = Nf_rd_byte_odd();
      if ( byte_5 != 0xFF )                         /* block status data : valid/invalid block */
      {
        tmp_spare--;                 /* Defect block */
      }
      else                                          /* Block is valid */
      {
                                                    /* Determine is the block is a specific block */
        byte_6 = Nf_rd_byte_odd();
        if (  (byte_6 == 0x00) ||                                   /* 0x00 = specific block */
              ( (byte_6 != 0xFF) && ( (byte_6 & 0xF8) != 0x10 ) &&  /* Value in redundant spare area not correct */
                (byte_6 != 0xE8) )                                  /* Don't care about LUT block */
           )
        { 
          tmp_spare--;               /* specific or invalid block */
        }
        else
        {
          /* Determine if the block is the look up table */ 
          if (byte_6 == 0xE8)                       /* look up table ? */
          {
            Nf_wait_busy_odd();
            Nf_send_command_odd (NF_READ_A_AREA_CMD);
            Nf_send_command_odd (NF_BLOCK_ERASE_CMD);                     /* Auto Block Erase Setup */
            Nf_send_address_odd ( ((Byte*)&gl_address)[3] );                /* 2nd address cycle*/
            Nf_send_address_odd ( ((Byte*)&gl_address)[2] );                /* 3rd address cycle*/
            #if (NF_4_CYCLE_ADDRESS)                                                /* Size of card >= 64Mbytes ?*/
              Nf_send_address_odd ( ((Byte*)&gl_address)[1] );              /* 4th address cycle*/
            #endif
            Nf_send_command_odd(NF_BLOCK_ERASE_CONFIRM_CMD);              /* Erase command */
          }
          else
          {
            /* Determine the last physical used block */
            if ( (byte_6 & 0xF8) == 0x10)             /* Used block  */
            {
              last_physical_used_block_odd[i] = gl_address >> 5;
            }
          }
        }

      }
      gl_address += (NF_ZONE_MAX << 5);
    }

    if (nf_spare_block_number[i] > tmp_spare)
    {
      nf_spare_block_number[i] = tmp_spare;
    }
  }
  
  Nf_CS_EVEN();
  Nf_wait_busy_even();

  for (i = 0; i < NF_ZONE_MAX; i++)
  { /* Determine the index for each correct lut */
    if (lut_is_present[i] == TRUE)
    {
      gl_address = ((Uint32)(lut_block[i]) << 5);
      do
      {
        Nf_read_open_C_area_even(gl_address, 0x06);
        lut_index[i]++;
        gl_address += NB_PAGE_BY_LUT;
        Nf_wait_busy_even();
        byte_6 = Nf_rd_byte_even();
      }
      while ((byte_6 == 0xE8) && ((gl_address & 0x1F) != 0));
      if(((gl_address & 0x1F) == 0) && (byte_6 == 0xE8))
      {
        lut_index[i]-=1;
        gl_address = gl_address - NB_PAGE_BY_LUT;
      }
      else
      {
        lut_index[i]-=2;
        gl_address = gl_address - (2*NB_PAGE_BY_LUT);
      }
      Nf_read_open_C_area_even(gl_address, 0x00);
      if (Nf_rd_byte_even() != 0xFF)       /* LUT have been modified */
      {
        nf_block_erase(gl_address);
        lut_is_present[i] = FALSE;   /* Reset*/
        lut_index[i] = 0;
        Nf_wait_busy_even();
      }
    }
  }
  
  
  /*****************************************************************/
  /*          Find free physical block for LUT for each zone       */
  /*****************************************************************/
  for (i = 0; i < NF_ZONE_MAX; i++)
  {
    if (lut_is_present[i] == FALSE)
    {
      block = last_physical_used_block_even[i];
      start = (Uint16)(i);          /* starting value for each zone */
      if (block == start)                 /* starting block for scan      */
      {
        block = start + ((NF_ZONE_MAX<<10) - NF_ZONE_MAX);
      }
      block_valid = FALSE;                /* init flag block valid */
      do
      {
        gl_address = (Uint32)(block) << 5;
        Nf_read_open_C_area_even(gl_address, 0x05);
        byte_5 = Nf_rd_byte_even();
        byte_6 = Nf_rd_byte_even();
    
        if (gl_address == 0)         /* FIX ME */
          byte_5 = 0x00;
        if ( (byte_5 == 0xFF) && (byte_6 == 0xFF) ) /* not assigned and valid block */
        {
          block_valid = TRUE;                       /* find a correct block         */
        }
        else                                        /* else decrease block number   */
        {
          if (block == start)                       
          {
            block = start + ((NF_ZONE_MAX<<10) - NF_ZONE_MAX);
          }
          else
          {
            block-=NF_ZONE_MAX;
          }
        }
      }
      while ( !block_valid  );
      lut_block[i] = block;                         /* Update look up table address */
    }
  }
      
    
    /**********************************************************/
    /* Create the look-up table                               */
    /* Process is done zone per zone and by step of 256 blocks*/
    /* ********************************************************/

⌨️ 快捷键说明

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