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

📄 sd.c

📁 MP3设计源代码 使用atmel的单片机
💻 C
📖 第 1 页 / 共 3 页
字号:
/*C**************************************************************************
* NAME:         sd.c
*----------------------------------------------------------------------------
* Copyright (c) 2002 Atmel.
*----------------------------------------------------------------------------
* RELEASE:      snd1c-demo-df-sd-3_0_0      
* REVISION:     1.2     
*----------------------------------------------------------------------------
* PURPOSE:
* This file contains the high level SD routines
*
* NOTES:
* Global Variables:
*   - gl_ptr_mem:   long in data space
*
* - Only SD or MMC card with block size = 512 bytes are accepted
*****************************************************************************/

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

#include "config.h"                 /* system configuration */
#include "lib_mcu\usb\usb_drv.h"    /* usb driver definition */
#include "sd.h"                             /* SD definition */

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


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

extern  pdata   Byte    gl_buffer[];
extern  data    Uint32  gl_ptr_mem;         /* memory data pointer */
extern  data    Byte    gl_mem_tick;        /* memory tick counter */
extern  bdata   bit     gl_mem_failure;     /* memory hardware failure */

static  bdata   bit     sd_flag;            /* memory flag (sd or mmc?) */
static  idata   Uint32  sd_rca;                     /* memory card relative address*/
static  Byte    sd_state;
static  bit     sd_mem_busy;                /* memory in busy state */
idata   Uint32  sd_mem_size;                /* memory disk size in pages */



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


/*F**************************************************************************
* NAME: sd_init
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
*   SD/MMC initialisation
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
bit sd_init (void)
{
  gl_mem_failure = FALSE;
  sd_state = SD_INIT;
  sd_mem_busy = FALSE;                      /* memory ready */
  sd_flag = SD;                             /* Hyp: card is SD */
  return OK;
}


/*F**************************************************************************
* NAME: sd_install
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
*   SD/MMC installation routine
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
Byte sd_install (void)
{
Byte    func_state;

  switch (sd_state & MMC_MSK_STATE)
  {
    case SD_INIT:
    {
      /* reset card stack */
      sd_init_card();
      sd_state = SD_ACQ;
      gl_mem_tick = SD_FUNCT_TIME;         /* init delay timer */
      break;
    }

    case SD_ACQ:
    {
      if (gl_mem_tick >= SD_DELAY_TIME)
      {
        /* send operating conditions */
        func_state = sd_acq_card();
        if (func_state == SD_ERROR)
        {
          sd_state = SD_INIT;
          return SD_ERROR;
        }
        else
        {
          if (func_state == SD_END)        /* end of execution */
          { /* MMC1/2 or SD CSD is available now */
            if (!sd_init_csd())            /* init & check card validity */
            {
              sd_state = SD_INIT;
              return SD_ERROR;
            }
            else
            {
              sd_state = SD_SETUP;
            }
          }
          gl_mem_tick = SD_FUNCT_TIME;     /* init delay timer */
        }
      }
      break;
    }

    case SD_SETUP: 
    {
      if (gl_mem_tick >= SD_DELAY_TIME)
      { /* go to transfer state */
        func_state = sd_setup_card();
        if (func_state == SD_ERROR)
        {
          sd_state = SD_INIT;
          return SD_ERROR;
        }
        else
        {
          if (func_state == SD_END)        /* end of execution */
          {
            gl_mem_failure = FALSE;
            sd_mem_busy = FALSE;           /* memory ready */
            sd_state = SD_INIT;
            return SD_END;                  /* install done */
          }
          gl_mem_tick = SD_FUNCT_TIME;     /* init delay timer */
        }
      }
      break;
    }

    default:
    {
      sd_state = SD_INIT;
      return SD_ERROR;
    }
  }
  return SD_BUSY;
}



/*F**************************************************************************
* NAME: sd_init_csd
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*   check status  - OK: card supported by software
*                 - KO: card not supported by software
*----------------------------------------------------------------------------
* PURPOSE: 
*   Card validity checking, memory variable initialisation and
*   controller data transfer mode initialisation
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*   Card with block size != 512 are rejected
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
bit sd_init_csd (void)
{
Byte  tmp;

  ACC = Mmc_rd_cmd();                       /* dummy read of header */
  ACC = Mmc_rd_cmd();                       /* dummy read of CSD[0] */
  ACC = Mmc_rd_cmd();                       /* dummy read */
  ACC = Mmc_rd_cmd();                       /* dummy read */
  ACC = Mmc_rd_cmd();                       /* dummy read */
  ACC = Mmc_rd_cmd();                       /* dummy read */

  if ((Mmc_rd_cmd() & CSD_MSK_RBL) != CSD_BLEN_512) /* check block length */
  { /* block size != 512 bytes not supported by firmware */
    Mmc_reset_cmd_fifos();                  /* reset pointers */
    return KO;
  }
  else
  {
    Mmc_set_block_size(CSD_BLEN_512);       /* init controller */
  }
  /* compute card size in number of block (block size = 512) */
  /* read C_SIZE */
  ((Byte*)&sd_mem_size)[0] = 0;
  ((Byte*)&sd_mem_size)[1] = 0;
  ((Byte*)&sd_mem_size)[2] = Mmc_rd_cmd() & CSD_MSK_CSH;
  ((Byte*)&sd_mem_size)[3] = Mmc_rd_cmd();
  sd_mem_size = sd_mem_size << 2;
  ((Byte*)&sd_mem_size)[3] |= ((Mmc_rd_cmd() & CSD_MSK_CSL) >> 6);
  /* read C_SIZE_MULT */
  tmp = Mmc_rd_cmd() << 1;
  tmp = (tmp | (Mmc_rd_cmd() >> 7)) & CSD_MSK_CSM;

  sd_mem_size = ((sd_mem_size + 1) << (tmp + 2));
  sd_mem_size--;
  Mmc_set_multi_block();                    /* multi block mode transfer */
  Mmc_enable_flow_ctrl();                   /* start flow control */
  Mmc_reset_cmd_fifos();                    /* reset pointers */

  return OK;
}


/*F**************************************************************************
* NAME: sd_init_card
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
*   Initialize MMC controller and reset card to idle state
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*   This function is called when initializing stack for first time
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
void sd_init_card (void)
{
  gl_mem_failure = FALSE;
  Mmc_set_read();                           /* dir from card to uc */
  Mmc_set_clock(SD_CLK_INIT);               /* set SD/MMC clock to 400 KHz */
  Mmc_enable();
  Mmc_reset();
  Mmc_reset_cmd_fifos();
  Mmc_reset_data_fifos();
  mmc_send_scmd(MMC_GO_IDLE_STATE, MMC_NO_RESP);
}

/*F**************************************************************************
* NAME: sd_acq_card 
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*   SD_BUSY:   busy state
*   SD_ERROR:  state result KO
*   SD_END:    end of card acquisition
*----------------------------------------------------------------------------
* PURPOSE: 
*   Card acquisition
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*   - This function must be called 5 or 6 times for completion depending on
*     the busy card
*   - Each call must be delayed enough to leave time for command
*     transmission and response reception
*   - By default, the memory card is a sd card. It checks the response to the
*     CMD55 in idle state to determine wich card it is.
*   - It does not take care of the DSR
*   - At the end of this function CSD is in buffer
*
*   STATES: SD_SINGLE_OP_COND    send CMD55 for sd card by default
*           SD_SIGNLE_OP_COND_2  send operating condition for sd or mmc
*           SD_SINGLE_CID        check busy and send CID or op cond again
*           SD_SINGLE_SRA        check CID response and set or send
*                                relative adress (mmc or sd)
*           SD_SINGLE_CSD        send CSD request
*           SD_SINGLE_END        check CSD reception
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
Byte sd_acq_card (void)
{
Uint32  response;
  switch (sd_state)
  {
    case SD_SINGLE_OP_COND:                 /* Card is SD Card by default */
    {
      mmc_send_cmd(MMC_APP_CMD, SD_RCA_DEFAULT, MMC_RESP_R1);
      sd_state = SD_SINGLE_OP_COND_2;
      return (SD_BUSY);
    }

    case SD_SINGLE_OP_COND_2:               /* check if the card is SD */
    {
      if (mmc_check_response() == MMC_ERR_RESP)  /* the card may be MMC */
      {                                     /* sending MMC operation condition */
        mmc_send_cmd(MMC_SEND_OP_COND, MMC_OCR_INIT, MMC_RESP_R3);  
        sd_state = SD_SINGLE_CID;
        sd_flag = MMC;
        return (SD_BUSY);                 
      }
      else
      {
        response = mmc_read_response();     /* the card is SD, next step for
                                            sending SD operation condition */
        mmc_send_cmd(SD_APP_OP_COND, MMC_OCR_INIT, MMC_RESP_R3);
        sd_state = SD_SINGLE_CID;
        sd_flag = SD;
        return (SD_BUSY);
      } 
    }

    case SD_SINGLE_CID:
    {
      if (mmc_check_response() == MMC_ERR_RESP)
      {
        return (SD_ERROR);                  /* no response */
      }
      else
      {
        response = mmc_read_response();
        if ((((Byte*)&response)[0] & MMC_BUSY_OCR) != MMC_BUSY_OCR)
        {                                   /* at least one card is busy */
          if (sd_flag == SD)                /* connected card is sd */    
          {
            mmc_send_cmd(MMC_APP_CMD, SD_RCA_DEFAULT, MMC_RESP_R1);
            sd_state = SD_SINGLE_OP_COND_2;
          }
          else
          {                                 /* connected card is mmc */
            mmc_send_cmd(MMC_SEND_OP_COND, MMC_OCR_INIT, MMC_RESP_R3);
          }
        }
        else
        {
          mmc_send_scmd(MMC_ALL_SEND_CID, MMC_RESP_R2);
          sd_state = SD_SINGLE_SRA;
        }
        return (SD_BUSY);
      }
    }

    case SD_SINGLE_SRA:
    {
      if (mmc_check_response() == MMC_ERR_RESP)
      {
        return (SD_ERROR);                  /* no response */
      }
      else
      {
        if (sd_flag == SD)                  /* connected card is sd */    
        {
          mmc_send_scmd(SD_SEND_RELATIVE_ADDRESS, SD_RESP_R6);
        }
        else                                /* connected card is mmc */
        {
          mmc_send_cmd(MMC_SET_RELATIVE_ADDRESS, MMC_RCA, MMC_RESP_R1);
        }
        sd_state = SD_SINGLE_CSD;
        return (SD_BUSY);
      }
    }

    case SD_SINGLE_CSD:
    {
      if (mmc_check_response() == MMC_ERR_RESP)
      {
        return (SD_ERROR);                  /* no response */
      }
      else
      {
        if (sd_flag == SD)                  /* connected card is sd */    
        {
          response = mmc_read_response();
          sd_rca = response >> 16;
          sd_rca = sd_rca << 16;  
          sd_rca = sd_rca | 0x0000FFFF;
          mmc_send_cmd(MMC_SEND_CSD, sd_rca, MMC_RESP_R2);
        }
        else                                /* connected card is mmc */
        {
          mmc_send_cmd(MMC_SEND_CSD, MMC_RCA, MMC_RESP_R2);
        }
        sd_state = SD_SINGLE_END;
        return (SD_BUSY);
      }
    }

    case SD_SINGLE_END:
    {
      if (mmc_check_response() == MMC_ERR_RESP)
      {
        return (SD_ERROR);                  /* no response */
      }
      else
      {

        Mmc_set_clock(SD_CLK_TRANS);        /* set SD clock to transfer */
        Mmc_set_multi_block();              /* multi block transfer */
        return (SD_END);
      }
    }
  }
}


/*F**************************************************************************
* NAME: sd_setup_card
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*   SD_BUSY:   busy state
*   SD_ERROR:  state result KO
*   SD_END:    end of setup execution
*----------------------------------------------------------------------------
* PURPOSE: 
*   Select the corresponding card
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*   - This function must be called at least 2 times for completion
*   - Each call must be delayed enough to leave time for command
*     transmission and response reception
*   - Contrary to what is written in MMC spec, the request CSD can
*     not be done in transfer state
*
*   STATES: SD_SETUP_SELECT   select card

⌨️ 快捷键说明

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