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

📄 smc.c

📁 ATMEL 89c51sndc mp3外接硬盘源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*C**************************************************************************
* NAME:         smc.c
*----------------------------------------------------------------------------
* Copyright (c) 2002 Atmel.
*----------------------------------------------------------------------------
* RELEASE:      snd1c-demo-hdd-0_2_0      
* REVISION:     1.5     
*----------------------------------------------------------------------------
* PURPOSE:
* This file contains the high level SMC 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 "lib_mem\smc\smc.h"                /* SMC 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 smc_current_physical_sector_addr;    /* give the address of the current sector     */  
data  Uint32 gl_address;                          /* general address variable                   */
data  Uint16 smc_look_up_table_block;             /* look up table address (block)              */
data  Byte smc_zone;                              /* current zone number                        */
data  Byte smc_gl_buf_idx;
data  Byte smc_gl_buf_free_idx ;

bdata bit smc_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 smc_lut_modified;                       /* indicate that LUT have been modified       */

xdata Uint32 smc_disk_size;                       /* Size of the disk in sector - 1             */ 
xdata Uint16 smc_logical_block;                   /* Current logical block value                */
xdata Uint16 smc_lut_block[SMC_ZONE_MAX];         /* LUT address (block value)                  */
xdata Uint16 smc_buf_free[24];                    /* contain free physical block address        */
xdata Uint16 smc_spare_block;                     /* number of free block                       */
xdata Uint16 smc_block_to_be_deleted;             /* give the address of the next deleted block */
xdata Uint16 smc_block_min;                       /* address of the first block in the buffer   */
xdata Uint16 smc_block_max;                       /* address of the last block in the buffer    */
xdata Union16 smc_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 smc_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  gl_cpt_page;                        /* internal page counter (byte access)        */
idata Byte smc_gl_buf_idx_max;                    /* max index for updating LUT                 */

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


/*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 Union16 block2;

  Smc_CS_ON();
  Smc_wait_busy();
  /* Global media initialization */
  smc_block_min       = 0xFFFF;         /* Starting buffer value    */
  smc_gl_buf_idx_max  = 0;              /* Max index in the buffer  */
  smc_lut_modified    = FALSE;          /* Buffer change flag       */
  smc_gl_buf_idx      = 0;              /* Main buffer index        */
  smc_gl_buf_free_idx = 0;              /* Free physical buffer idx */
  smc_old_zone     = 0xFF;           /* Previous zone number     */
  for (i = 0; i < smc_zone_max; i++)
  {
    smc_lut_index[i] = 0;               /* LUT index                */
  }

  /***************************************************/
  /* For each zone, this following lines :           */
  /*   Search bad block                              */
  /*   Determine if a LUT is present                 */
  /*   Determine the last physical block             */ 
  /***************************************************/
  gl_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_read_open_C_area(gl_address, 0x00);
      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 ? */
          {
            smc_block_erase(gl_address);
          }
          /* Determine the last physical used block */
          if ( (byte_6 & 0xF8) == 0x10)             /* Used block  */
          {
            last_physical_used_block[i] = gl_address >> 5;
          }
        }

      }
      gl_address += 32;
    }
  }

  /*****************************************************************/
  /*          Find free physical block for LUT for each zone       */
  /*****************************************************************/
  for (i = 0; i < smc_zone_max; 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
    {
      gl_address = (Uint32)(block) << 5;
      Smc_read_open_C_area(gl_address, 0x05);
      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  );

    smc_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 */
  {
    start = 0x00;
    end   = 0x80;     /* 256 bytes for gl_buffer <-> 128 blocks */                            
    free_bloc_pos = (Uint16)(last_physical_used_block[smc_zone]);
    gl_address       = (Uint32)(smc_lut_block[smc_zone]) << 5;        
    do
    {
      smc_init_buffer();                          /* Reinitialize the buffer            */
      temp_address = (Uint32)(smc_zone) << 15;    /* We start at the beginning          */
      block    = (Uint16)(smc_zone) << 10;
      Smc_wait_busy();
      for (j = SMC_BLOCK_PER_ZONE; j != 0 ; j--)  /* for each block                     */
      { 
        Smc_read_open_C_area(temp_address, 0x05);
        byte_5 = Smc_rd_byte();                   /* Block status byte                  */
        if (byte_5 == 0xFF)                       /* If not a bad block                 */
        {
          block2.b[0] = Smc_rd_byte();            /* Read logical block address         */
          block2.b[1] = Smc_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)(smc_zone + 1) << 15) )
                temp_address = (Uint32)(smc_zone) << 15;
            Smc_read_open_C_area(temp_address, 0x05);
            byte_5 = Smc_rd_byte();                          /* Invalid/Valid block */
            byte_6 = Smc_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;
        }
      }
  
      Smc_write_open_A_area(gl_address, 0x00);             /* Write first part of LUT */
      smc_download_buffer();                            /* Write 256 bytes from the buffer */
      Smc_send_command(SMC_PAGE_PROGRAM_CMD);           /* Valid the page programmation */
  
      smc_init_buffer();                                /* reinitialize the global buffer   */
      start    += 0x80;                                 /* process next 128 logical block   */
      end      += 0x80;
      block    = (Uint16)(smc_zone) << 10;
      temp_address = (Uint32)(smc_zone) << 15;           /* restart from the begin of zone   */
      Smc_wait_busy();  
    
      for (j = SMC_BLOCK_PER_ZONE; j != 0 ; j--)         /* for each block             */
      {
        Smc_read_open_C_area(temp_address, 0x05);
        byte_5 = Smc_rd_byte();                           /* Block status byte          */
        if (byte_5 == 0xFF)                               /* If not a bad block         */
        {
          block2.b[0] = Smc_rd_byte();                    /* Read logical block address */
          block2.b[1] = Smc_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++;
      }
  
      temp_address = (Uint32)(free_bloc_pos) << 5;
      for (i = 0; i <= 0xFE; i += 2)
      {
        if (gl_buffer[i] == 0xFF)
        {
          do   
          {
            temp_address += 32;

⌨️ 快捷键说明

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