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

📄 nf.c

📁 MP3播放器详细设计方案
💻 C
📖 第 1 页 / 共 4 页
字号:
/*C**************************************************************************
* $RCSfile: nf.c,v $
*----------------------------------------------------------------------------
* Copyright (c) 2002 Atmel.
*----------------------------------------------------------------------------
* RELEASE:      $Name: DEMO_FAT_1_9_9 $      
* REVISION:     $Revision: 1.11 $     
* FILE_CVSID:   $Id: nf.c,v 1.11 2002/09/06 13:17:19 njourdan Exp $       
*----------------------------------------------------------------------------
* PURPOSE:
* This file contains the high level NF routines
*****************************************************************************/
 
/*_____ I N C L U D E S ____________________________________________________*/

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

extern void fat_format (bit );

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


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

xdata Byte nf_send_cmd At(NF_CMD_LATCH_ENABLE_ADD); /* Command */
xdata Byte nf_send_add At(NF_ADD_LATCH_ENABLE_ADD); /* Address */
xdata Byte volatile nf_data At(NF_ADDRESS_CMD_DATA);/* Data    */

/* Card Identification System definition */
code Byte nf_cis_table[]=
  {
  0x01, 0x03, 0xD9, 0x01, 0xFF, 0x18, 0x02, 0xDF, 0x01, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x21,
  0x02, 0x04, 0x01, 0x22, 0x02, 0x01, 0x01, 0x22, 0x03, 0x02, 0x04, 0x07, 0x1A, 0x05, 0x01, 0x03,
  0x00, 0x02, 0x0F, 0x1B, 0x08, 0xC0, 0xC0, 0xA1, 0x01, 0x55, 0x08, 0x00, 0x20, 0x1B, 0x0A, 0xC1,
  0x41, 0x99, 0x01, 0x55, 0x64, 0xF0, 0xFF, 0xFF, 0x20, 0x1B, 0x0C, 0x82, 0x41, 0x18, 0xEA, 0x61,
  0xF0, 0x01, 0x07, 0xF6, 0x03, 0x01, 0xEE, 0x1B, 0x0C, 0x83, 0x41, 0x18, 0xEA, 0x61, 0x70, 0x01,
  0x07, 0x76, 0x03, 0x01, 0xEE, 0x15, 0x14, 0x05, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
  0x00, 0x20, 0x20, 0x20, 0x20, 0x00, 0x30, 0x2E, 0x30, 0x00, 0xFF, 0x14, 0x00, 0xFF, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  };


/*_____ D E C L A R A T I O N ______________________________________________*/
extern  data    Uint32  gl_ptr_mem;         /* memory data pointer */
extern  pdata   Byte gl_buffer[];

data  Uint32 current_physical_sector_addr;  /* give the address of the current sector     */  
data  Uint32 address;                       /* general address variable                   */
data  Uint16 look_up_table_block;           /* look up table address (block)              */
data  Byte nf_zone;                         /* current zone number                        */
data  Byte gl_buf_idx;
data  Byte gl_buf_free_idx ;

bdata bit block_used;                       /* Set when a block was used                  */
bdata bit nf_busy;                          /* indicate that nand flash is busy           */
bdata bit lut_modified;                     /* indicate that LUT have been modified       */
bdata bit zone_change;                      /* indicate that we have to change zone       */

xdata Uint16 logical_block;                 /* Current logical block value                */
xdata Uint16 lut_block[NF_ZONE_MAX];        /* LUT address (block value)                  */
xdata Uint16 buf_free[24];                  /* contain free physical block address        */
xdata Uint16 spare_block;                   /* number of free block                       */
xdata Uint16 block_to_be_deleted;           /* give the address of the next deleted block */
xdata Uint16 block_min;                     /* address of the first block in the buffer   */
xdata Uint16 block_max;                     /* address of the last block in the buffer    */
xdata Union16 buf[NF_BUFFER_SIZE];          /* Buffer for write operation                 */
xdata Byte nf_old_zone;                     /* for zone change                            */  
xdata Byte lut_index[NF_ZONE_MAX];          /* give the index for updating LUT            */
xdata Byte nf_spare_block_number[NF_ZONE_MAX];/* Number of free spare block in each zone  */


idata Uint16 redundant_logical_block_value; /* Logical block value in the redundant area  */
idata Uint16  gl_cpt_page;                  /* internal page counter (byte access)        */
idata Byte gl_buf_idx_max;                  /* max index for updating LUT                 */


/*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)
{
data  Uint16 block;
data  Uint16 j;           /* counter */
data  Uint16 i;           /* counter */
bit   block_valid;
xdata Uint32 temp_address;              
xdata Byte byte_0, byte_5, byte_6;
xdata Uint16 free_bloc_pos;
xdata Uint16 last_physical_used_block[NF_ZONE_MAX]; /* Last physical block used     */
xdata Uint16 start;       /* start value for the construction of the LUT */
xdata Uint16 end;         /* final value */
xdata Byte lut_is_present;
xdata Union16 block2;


  Nf_CS_ON();
  Nf_wait_busy();
  /* Global media initialization */
  block_min       = 0xFFFF;         /* Starting buffer value    */
  gl_buf_idx_max  = 0;              /* Max index in the buffer  */
  lut_modified    = FALSE;          /* Buffer change flag       */
  gl_buf_idx      = 0;              /* Main buffer index        */
  gl_buf_free_idx = 0;              /* Free physical buffer idx */
  nf_old_zone     = 0xFF;           /* Previous zone number     */
  for (i = 0; i < NF_ZONE_MAX; i++)
  {
    lut_index[i] = 0;               /* LUT index                */
  }
  lut_is_present = 0x00;

  /***************************************************/
  /* For each zone, this following lines :           */
  /*   Search bad block                              */
  /*   Determine if a LUT is present                 */
  /*   Determine the last physical block             */ 
  /***************************************************/
  address = 0;                                      /* Start from physical sector 0 */
  for (i = 0; i < NF_ZONE_MAX; i++)                 /* for each zone */
  {
    nf_spare_block_number[i] = 23;                  /* Initialize the spare block table */
    last_physical_used_block[i] = (Uint16)(i) << 10;/* Initialize the last used physical block value */

    for (j = NF_BLOCK_PER_ZONE; j != 0; j--)        /* for each block */ 
    {
      Nf_send_command(NF_READ_C_AREA_CMD);         /* C Area : redundant data   */
      Nf_send_address(0x00);                        /*                           */
      Nf_send_address ( ((Byte*)&address)[3] );     /* 2nd address cycle         */
      Nf_send_address ( ((Byte*)&address)[2] );     /* 3rd address cycle         */
      if (NF_4_CYCLE_ADDRESS)                                    /* Size of card >= 64Mbytes ?*/
        Nf_send_address ( ((Byte*)&address)[1] );   /* 4th address cycle         */

      Nf_wait_busy();
      byte_0 = Nf_rd_byte();   /* Byte 0 : User data byte */
      Nf_rd_byte();            /* Byte 1 : User data byte */
      Nf_rd_byte();            /* Byte 2 : User data byte */
      Nf_rd_byte();            /* Byte 3 :                */
      Nf_rd_byte();            /* Byte 4 :                */
      byte_5 = Nf_rd_byte();   /* Byte 5 : Block status data */
      if ( byte_5 != 0xFF )                         /* block status data : valid/invalid block */
      {
        nf_spare_block_number[i]--;                 /* Defect block */
      }
      else                                          /* Block is valid */
      {
                                                    /* Determine is the block is a specific block */
        byte_6 = Nf_rd_byte();
        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 |= (0x01) << i;
              lut_block[i] = address >> 5;
 
          }
          /* Determine the last physical used block */
          if ( (byte_6 & 0xF8) == 0x10)             /* Used block  */
          {
            last_physical_used_block[i] = address >> 5;
          }
        }

      }
      address += 32;
    }
  }

  for (i = 0; i < NF_ZONE_MAX; i++)
  { /* Determine the index for each correct lut */
    if ((lut_is_present & (0x01 << i)))
    {
      address = (Uint32)(lut_block[i]) << 5;
      do
      {
  
        Nf_send_command(NF_READ_C_AREA_CMD);        /* Send READ C Area command */
        Nf_send_address( 0x00);
        Nf_send_address ( ((Byte*)&address)[3] );   /* 2nd address cycle          */
        Nf_send_address ( ((Byte*)&address)[2] );   /* 3rd address cycle          */
        if (NF_4_CYCLE_ADDRESS)                                  /* Size of card >= 64Mbytes ? */
          Nf_send_address ( ((Byte*)&address)[1] ); /* 4th address cycle          */
        Nf_wait_busy();
        byte_0 = Nf_rd_byte();   /* Byte 0 : User data byte */
        Nf_rd_byte();            /* Byte 1 : User data byte */
        Nf_rd_byte();            /* Byte 2 : User data byte */
        Nf_rd_byte();            /* Byte 3 :                */
        Nf_rd_byte();            /* Byte 4 :                */
        byte_5 = Nf_rd_byte();   /* Byte 5 : Block status data */  
        byte_6 = Nf_rd_byte();
        if (byte_6 == 0xE8)
          lut_index[i]++;
        address+=4;
      }
      while (byte_6 == 0xE8);
      lut_index[i]--;
      address = address - 4;
      Nf_send_command(NF_READ_C_AREA_CMD);        /* Send READ C Area command */
      Nf_send_address( 0x00);
      Nf_send_address ( ((Byte*)&address)[3] );   /* 2nd address cycle          */
      Nf_send_address ( ((Byte*)&address)[2] );   /* 3rd address cycle          */
      if (NF_4_CYCLE_ADDRESS)                                  /* Size of card >= 64Mbytes ? */
        Nf_send_address ( ((Byte*)&address)[1] ); /* 4th address cycle          */
      Nf_wait_busy();
      byte_0 = Nf_rd_byte();   /* Byte 0 : User data byte */
      if (byte_0 != 0xFF)       /* LUT have been modified */
      {
        nf_block_erase(address);
        lut_is_present &= ~((0x01) << i);   /* Reset bi */
        Nf_wait_busy();
        lut_index[i] = 0;
      }

    }
  }
  /*****************************************************************/
  /*          Find free physical block for LUT for each zone       */
  /*****************************************************************/
  for (i = 0; i < NF_ZONE_MAX; i++)
  {
    if (!(lut_is_present && (0x01 << i)))
    {
      block = last_physical_used_block[i];
      start = (Uint16)(i) << 10;          /* starting value for each zone */
      if (block == start)                 /* starting block for scan      */
      {
        block = start + 1023;
      }
      block_valid = FALSE;                /* init flag block valid */
      Nf_wait_busy();
      do
      {
        address = (Uint32)(block) << 5;
  
        Nf_send_command(NF_READ_C_AREA_CMD);        /* Send READ C Area command */
        Nf_send_address( 0x05 );
        Nf_send_address ( ((Byte*)&address)[3] );   /* 2nd address cycle          */
        Nf_send_address ( ((Byte*)&address)[2] );   /* 3rd address cycle          */
        if (NF_4_CYCLE_ADDRESS)                                  /* Size of card >= 64Mbytes ? */
          Nf_send_address ( ((Byte*)&address)[1] ); /* 4th address cycle          */
        Nf_wait_busy();
  
        byte_5 = Nf_rd_byte();
        byte_6 = Nf_rd_byte();
  
        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 + 1023;
          }
          else
          {
            block--;
          }
        }
      }
      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*/
  /* ********************************************************/
  for (nf_zone = 0; nf_zone < NF_ZONE_MAX; nf_zone++)   /* for each zone */
  {
    if ( !(lut_is_present & (0x01 << nf_zone)))                  /* If not LUT */
    {
      start = 0x00;
      end   = 0x80;     /* 256 bytes for gl_buffer <-> 128 blocks */                            
      free_bloc_pos = (Uint16)(last_physical_used_block[nf_zone]);
      address       = (Uint32)(lut_block[nf_zone]) << 5;        
      do
      {
        nf_init_buffer();                         /* Reinitialize the buffer            */
        temp_address = (Uint32)(nf_zone) << 15;   /* We start at the beginning          */
        block    = (Uint16)(nf_zone) << 10;
        Nf_wait_busy();
        for (j = NF_BLOCK_PER_ZONE; j != 0 ; j--) /* for each block                     */
        { 
          Nf_send_command (NF_READ_C_AREA_CMD);   /* Read Spare data value              */
          Nf_send_address ( 0x05 );
          Nf_send_address ( ((Byte*)&temp_address)[3] );  /* 2nd address cycle          */
          Nf_send_address ( ((Byte*)&temp_address)[2] );  /* 3rd address cycle          */
          if (NF_4_CYCLE_ADDRESS)                                      /* Size of card >= 64Mbytes ? */
            Nf_send_address ( ((Byte*)&temp_address)[1] );/* 4th address cycle          */
    
          Nf_wait_busy();
          byte_5 = Nf_rd_byte();                  /* Block status byte                  */
          if (byte_5 == 0xFF)                     /* If not a bad block                 */
          {
            block2.b[0] = Nf_rd_byte();           /* Read logical block address         */
            block2.b[1] = Nf_rd_byte();
            if ( (block2.b[0] & 0xF8) == 0x10)
            {
              
              block2.w = (block2.w & 0x0FFF) >> 1;          
              if ( (block2.w < end) && (block2.w >= start)) 
              { /* Save logical block value in the buffer */
                gl_buffer[2 * block2.b[1]] = block >> 8;
                gl_buffer[2 * block2.b[1] + 1] = block;
              }
            }
          }
          temp_address += 32; 
          block++;
        }
          
        /* affect to the free physical block a fictive logical block */
        /* free physical block => gl_buffer[x] = 0xFF */
        temp_address = (Uint32)(free_bloc_pos) << 5;
        for (i = 0; i <= 0xFE; i+=2)
        {
          if (gl_buffer[i] == 0xFF)
          {
            do                                                /* Search free physical block */
            {
              temp_address += 32;
              if (temp_address >= ((Uint32)(nf_zone + 1) << 15) )
                  temp_address = (Uint32)(nf_zone) << 15;
    
              Nf_send_command(NF_READ_C_AREA_CMD);
              Nf_send_address(0x05);
              Nf_send_address ( ((Byte*)&temp_address)[3] );  /* 2nd address cycle         */
              Nf_send_address ( ((Byte*)&temp_address)[2] );  /* 3rd address cycle         */
              if (NF_4_CYCLE_ADDRESS)                                      /* Size of card >= 64Mbytes ?*/
                Nf_send_address ( ((Byte*)&temp_address)[1] );/* 4th address cycle         */
              Nf_wait_busy();
              
              byte_5 = Nf_rd_byte();                          /* Invalid/Valid block */
              byte_6 = Nf_rd_byte();                          /* Used/Unused block */
            }
            while ( ( (byte_6 != 0xFF) && (byte_6 != 0xE8) ) || (byte_5 != 0xFF) );
  
            free_bloc_pos = temp_address >> 5;
            gl_buffer[i] = (free_bloc_pos >> 8) + 0x80;
            gl_buffer[i + 1] = free_bloc_pos;
          }
        }
    

⌨️ 快捷键说明

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