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

📄 smc.c

📁 ATMEL全套MP3设计资料
💻 C
📖 第 1 页 / 共 5 页
字号:
/*C**************************************************************************
* $RCSfile: smc.c,v $
*----------------------------------------------------------------------------
* Copyright (c) 2002 Atmel.
*----------------------------------------------------------------------------
* RELEASE:      $Name: DEMO_FAT_1_9_9 $      
* REVISION:     $Revision: 1.2 $     
* FILE_CVSID:   $Id: smc.c,v 1.2 2002/08/28 09:45:08 njourdan Exp $       
*----------------------------------------------------------------------------
* PURPOSE:
* This file contains the high level SMC 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\smc\smc.h"             /* SMC definition              */
#include "..\src\display\disp.h"              /* Display definition         */
#include "..\..\lib_mem\mmc\mmc.h"            /* MMC definition             */

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


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

xdata Byte smc_send_cmd At(SMC_CMD_LATCH_ENABLE_ADD); /* Command */
xdata Byte smc_send_add At(SMC_ADD_LATCH_ENABLE_ADD); /* Address */
xdata Byte volatile smc_data At(SMC_ADDRESS_CMD_DATA);/* Data    */

/* Card Identification System definition */
code Byte smc_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
  };

/* ECC definition */
code Byte smc_ecc_table[]=
  {
  0x00,0x55,0x56,0x03,0x59,0x0C,0x0F,0x5A,0x5A,0x0F,0x0C,0x59,0x03,0x56,0x55,0x00,
  0x65,0x30,0x33,0x66,0x3C,0x69,0x6A,0x3F,0x3F,0x6A,0x69,0x3C,0x66,0x33,0x30,0x65,
  0x66,0x33,0x30,0x65,0x3F,0x6A,0x69,0x3C,0x3C,0x69,0x6A,0x3F,0x65,0x30,0x33,0x66,
  0x03,0x56,0x55,0x00,0x5A,0x0F,0x0C,0x59,0x59,0x0C,0x0F,0x5A,0x00,0x55,0x56,0x03,
  0x69,0x3C,0x3F,0x6A,0x30,0x65,0x66,0x33,0x33,0x66,0x65,0x30,0x6A,0x3F,0x3C,0x69,
  0x0C,0x59,0x5A,0x0F,0x55,0x00,0x03,0x56,0x56,0x03,0x00,0x55,0x0F,0x5A,0x59,0x0C,
  0x0F,0x5A,0x59,0x0C,0x56,0x03,0x00,0x55,0x55,0x00,0x03,0x56,0x0C,0x59,0x5A,0x0F,
  0x6A,0x3F,0x3C,0x69,0x33,0x66,0x65,0x30,0x30,0x65,0x66,0x33,0x69,0x3C,0x3F,0x6A,
  0x6A,0x3F,0x3C,0x69,0x33,0x66,0x65,0x30,0x30,0x65,0x66,0x33,0x69,0x3C,0x3F,0x6A,
  0x0F,0x5A,0x59,0x0C,0x56,0x03,0x00,0x55,0x55,0x00,0x03,0x56,0x0C,0x59,0x5A,0x0F,
  0x0C,0x59,0x5A,0x0F,0x55,0x00,0x03,0x56,0x56,0x03,0x00,0x55,0x0F,0x5A,0x59,0x0C,
  0x69,0x3C,0x3F,0x6A,0x30,0x65,0x66,0x33,0x33,0x66,0x65,0x30,0x6A,0x3F,0x3C,0x69,
  0x03,0x56,0x55,0x00,0x5A,0x0F,0x0C,0x59,0x59,0x0C,0x0F,0x5A,0x00,0x55,0x56,0x03,
  0x66,0x33,0x30,0x65,0x3F,0x6A,0x69,0x3C,0x3C,0x69,0x6A,0x3F,0x65,0x30,0x33,0x66,
  0x65,0x30,0x33,0x66,0x3C,0x69,0x6A,0x3F,0x3F,0x6A,0x69,0x3C,0x66,0x33,0x30,0x65,
  0x00,0x55,0x56,0x03,0x59,0x0C,0x0F,0x5A,0x5A,0x0F,0x0C,0x59,0x03,0x56,0x55,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[];
extern  bdata   bit     gl_mem_failure;           /* memory hardware failure*/

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 smc_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 smc_busy;                          /* indicate that nand flash is busy           */
bdata bit smc_64;                            /* indicate that memory capacity >= 64Mb      */
bdata bit lut_modified;                     /* indicate that LUT have been modified       */
bdata bit zone_change;                      /* indicate that we have to change zone       */

xdata Uint32 smc_disk_size;                  /* Size of the disk in sector - 1             */ 
xdata Uint16 logical_block;                 /* Current logical block value                */
xdata Uint16 lut_block[SMC_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[SMC_BUFFER_SIZE];          /* Buffer for write operation                 */
xdata Byte smc_old_zone;                     /* for zone change                            */  
xdata Byte smc_zone_max;                     /* max zone number (from 1 to 8)              */
xdata Byte smc_device_type;                  /* Give the size of device in Mbytes          */ 
xdata Byte lut_index[SMC_ZONE_MAX];          /* give the index for updating LUT            */
xdata Byte smc_spare_block_number[SMC_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                 */

/* ECC variable */
xdata Byte ecc1, ecc2, ecc3;
xdata Byte ecc[6];


extern fat_format(bit);

/*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[SMC_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;

  Smc_CS_ON();
  Smc_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 */
  smc_old_zone     = 0xFF;           /* Previous zone number     */
  for (i = 0; i < smc_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 < smc_zone_max; i++)                 /* for each zone */
  {
    smc_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 = SMC_BLOCK_PER_ZONE; j != 0; j--)        /* for each block */ 
    {
      Smc_send_command(SMC_READ_C_AREA_CMD);         /* C Area : redundant data   */
      Smc_send_address(0x00);                        /*                           */
      Smc_send_address ( ((Byte*)&address)[3] );     /* 2nd address cycle         */
      Smc_send_address ( ((Byte*)&address)[2] );     /* 3rd address cycle         */
      if (smc_64)                                    /* Size of card >= 64Mbytes ?*/
        Smc_send_address ( ((Byte*)&address)[1] );   /* 4th address cycle         */

      Smc_wait_busy();
      byte_0 = Smc_rd_byte();   /* Byte 0 : User data byte */
      Smc_rd_byte();            /* Byte 1 : User data byte */
      Smc_rd_byte();            /* Byte 2 : User data byte */
      Smc_rd_byte();            /* Byte 3 :                */
      Smc_rd_byte();            /* Byte 4 :                */
      byte_5 = Smc_rd_byte();   /* Byte 5 : Block status data */
      if ( byte_5 != 0xFF )                         /* block status data : valid/invalid block */
      {
        smc_spare_block_number[i]--;                 /* Defect block */
      }
      else                                          /* Block is valid */
      {
                                                    /* Determine is the block is a specific block */
        byte_6 = Smc_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 */
           )
        { 
          smc_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 < smc_zone_max; i++)
  { /* Determine the index for each correct lut */
    if ((lut_is_present & (0x01 << i)))
    {
      address = (Uint32)(lut_block[i]) << 5;
      do
      {
  
        Smc_send_command(SMC_READ_C_AREA_CMD);        /* Send READ C Area command */
        Smc_send_address( 0x00);
        Smc_send_address ( ((Byte*)&address)[3] );   /* 2nd address cycle          */
        Smc_send_address ( ((Byte*)&address)[2] );   /* 3rd address cycle          */
        if (smc_64)                                  /* Size of card >= 64Mbytes ? */
          Smc_send_address ( ((Byte*)&address)[1] ); /* 4th address cycle          */
        Smc_wait_busy();
        byte_0 = Smc_rd_byte();   /* Byte 0 : User data byte */
        Smc_rd_byte();            /* Byte 1 : User data byte */
        Smc_rd_byte();            /* Byte 2 : User data byte */
        Smc_rd_byte();            /* Byte 3 :                */
        Smc_rd_byte();            /* Byte 4 :                */
        byte_5 = Smc_rd_byte();   /* Byte 5 : Block status data */  
        byte_6 = Smc_rd_byte();
        if (byte_6 == 0xE8)
          lut_index[i]++;
        address+=4;
      }
      while (byte_6 == 0xE8);
      lut_index[i]--;
      address = address - 4;
      Smc_send_command(SMC_READ_C_AREA_CMD);        /* Send READ C Area command */
      Smc_send_address( 0x00);
      Smc_send_address ( ((Byte*)&address)[3] );   /* 2nd address cycle          */
      Smc_send_address ( ((Byte*)&address)[2] );   /* 3rd address cycle          */
      if (smc_64)                                  /* Size of card >= 64Mbytes ? */
        Smc_send_address ( ((Byte*)&address)[1] ); /* 4th address cycle          */
      Smc_wait_busy();
      byte_0 = Smc_rd_byte();   /* Byte 0 : User data byte */
      if (byte_0 != 0xFF)       /* LUT have been modified */
      {
        smc_block_erase(address);
        lut_is_present &= ~((0x01) << i);   /* Reset bi */
        Smc_wait_busy();
        lut_index[i] = 0;
      }

    }
  }
  /*****************************************************************/
  /*          Find free physical block for LUT for each zone       */
  /*****************************************************************/
  for (i = 0; i < smc_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 */
      Smc_wait_busy();
      do
      {
        address = (Uint32)(block) << 5;
  
        Smc_send_command(SMC_READ_C_AREA_CMD);        /* Send READ C Area command */
        Smc_send_address( 0x05 );
        Smc_send_address ( ((Byte*)&address)[3] );   /* 2nd address cycle          */
        Smc_send_address ( ((Byte*)&address)[2] );   /* 3rd address cycle          */
        if (smc_64)                                  /* Size of card >= 64Mbytes ? */
          Smc_send_address ( ((Byte*)&address)[1] ); /* 4th address cycle          */
        Smc_wait_busy();
  
        byte_5 = Smc_rd_byte();
        byte_6 = Smc_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 (smc_zone = 0; smc_zone < smc_zone_max; smc_zone++)   /* for each zone */
  {
    if ( !(lut_is_present & (0x01 << smc_zone)))                  /* If not LUT */

⌨️ 快捷键说明

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