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

📄 mmc.c

📁 MP3播放器详细设计方案
💻 C
📖 第 1 页 / 共 3 页
字号:
/*C**************************************************************************
* $RCSfile: mmc.c,v $
*----------------------------------------------------------------------------
* Copyright (c) 2002 Atmel.
*----------------------------------------------------------------------------
* RELEASE:      $Name: DEMO_FAT_1_9_9 $      
* REVISION:     $Revision: 1.14 $     
* FILE_CVSID:   $Id: mmc.c,v 1.14 2002/09/06 13:17:19 njourdan Exp $       
*----------------------------------------------------------------------------
* PURPOSE:
* This file contains the high level MMC routines
*
* NOTES:
* Global Variables:
*   - gl_ptr_mem:   long in data space
*
* - The functions are written to handle a 2-card MMC stack
* - Only MMC cards with block size = 512 bytes are accepted
*****************************************************************************/

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

#include "config.h"                         /* system configuration */
#include "..\..\lib\usb\usb_drv.h"          /* usb driver definition */
#include "mmc.h"                            /* MMC 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  data    Byte    gl_mem_tick;        /* memory tick counter */
extern  bdata   bit     gl_mem_failure;     /* memory hardware failure */

static  Byte    mmc_state;
static  bit     mmc_mem_busy;               /* memory in busy state */
idata   Uint32  mmc_mem_size;               /* memory disk size in pages */


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


/*F**************************************************************************
* NAME: mmc_init
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
*   MMC initialisation
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
void mmc_init (void)
{
  gl_mem_failure = FALSE;
  mmc_state = MMC_FUNCT_START;
  mmc_mem_busy = FALSE;                     /* memory ready */
}


/*F**************************************************************************
* NAME: mmc_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 mmc_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*)&mmc_mem_size)[0] = 0;
  ((Byte*)&mmc_mem_size)[1] = 0;
  ((Byte*)&mmc_mem_size)[2] = Mmc_rd_cmd() & CSD_MSK_CSH;
  ((Byte*)&mmc_mem_size)[3] = Mmc_rd_cmd();
  mmc_mem_size = mmc_mem_size << 2;
  ((Byte*)&mmc_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;
  mmc_mem_size = ((mmc_mem_size + 1) << (tmp + 2));
  mmc_mem_size--;
  Mmc_set_single_block();                   /* single block mode transfer */
  Mmc_enable_flow_ctrl();                   /* start flow control */
  Mmc_reset_cmd_fifos();                    /* reset pointers */
  return OK;
}


/*F**************************************************************************
* NAME: mmc_init_stack
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
*   Initialize MMC controller and reset all cards to idle state
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*   This function is called when initializing stack for first time
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
void mmc_init_stack (void)
{
  gl_mem_failure = FALSE;
  Mmc_set_read();                           /* dir from card to uc */
  Mmc_set_clock(MMC_CLK_INIT);              /* set 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: mmc_init_next
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
*   Initialize MMC controller
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*   This function is called when stack has already been initialized
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
void mmc_init_next (void)
{
  gl_mem_failure = FALSE;
  Mmc_set_read();                           /* dir from card to uc */
  Mmc_set_clock(MMC_CLK_INIT);              /* set MMC clock to 400 KHz */
  Mmc_enable();
  Mmc_reset();
  Mmc_reset_cmd_fifos();
  Mmc_reset_data_fifos();
}


/*F**************************************************************************
* NAME: mmc_single_acq
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*   MMC_OK:     state result OK
*   MMC_ERROR:  state result KO
*   MMC_END:    end of card acquisition
*----------------------------------------------------------------------------
* PURPOSE: 
*   Single 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
*   - It does not take care of the DSR
*   - At the end of this function CSD is in buffer
*
*   STATES: MMC_SINGLE_OP_COND  send operating condition
*           MMC_SINGLE_CID      check busy and send CID or op cond again
*           MMC_SINGLE_SRA      check CID response and set relative address
*           MMC_SINGLE_CSD      send CSD request
*           MMC_SINGLE_END      check CSD reception
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
Byte mmc_single_acq (void)
{
Uint32  response;

  switch (mmc_state)
  {
    case MMC_SINGLE_OP_COND:
    {
      mmc_send_cmd(MMC_SEND_OP_COND, MMC_OCR_INIT, MMC_RESP_R3);
      mmc_state = MMC_SINGLE_CID;
      return (MMC_OK);
    }

    case MMC_SINGLE_CID:
    {
      if (mmc_check_response() == MMC_ERR_RESP)
      {
        mmc_state = MMC_FUNCT_START;
        return (MMC_ERROR);                 /* no response */
      }
      else
      {
        response = mmc_read_response();
        if ((((Byte*)&response)[0] & MMC_BUSY_OCR) != MMC_BUSY_OCR)
        {   /* at least one card is busy */
          mmc_send_cmd(MMC_SEND_OP_COND, MMC_OCR_INIT, MMC_RESP_R3);
        }
        else
        {
          mmc_send_scmd(MMC_ALL_SEND_CID, MMC_RESP_R2);
          mmc_state = MMC_SINGLE_SRA;
        }
        return (MMC_OK);
      }
    }

    case MMC_SINGLE_SRA:
    {
      if (mmc_check_response() == MMC_ERR_RESP)
      {
        mmc_state = MMC_FUNCT_START;
        return (MMC_ERROR);                 /* no response */
      }
      else
      {
        mmc_send_cmd(MMC_SET_RELATIVE_ADDRESS, MMC_RCA_1, MMC_RESP_R1);
        mmc_state = MMC_SINGLE_CSD;
        return (MMC_OK);
      }
    }

    case MMC_SINGLE_CSD:
    {
      if (mmc_check_response() == MMC_ERR_RESP)
      {
        mmc_state = MMC_FUNCT_START;
        return (MMC_ERROR);                 /* no response */
      }
      else
      {
        mmc_send_cmd(MMC_SEND_CSD, MMC_RCA_1, MMC_RESP_R2);
        mmc_state = MMC_SINGLE_END;
        return (MMC_OK);
      }
    }

    case MMC_SINGLE_END:
    {
      if (mmc_check_response() == MMC_ERR_RESP)
      {
        mmc_state = MMC_FUNCT_START;
        return (MMC_ERROR);                 /* no response */
      }
      else
      {
        Mmc_set_clock(MMC_CLK_TRANS);       /* set MMC clock to transfer */
        mmc_state = MMC_FUNCT_START;
        Mmc_set_single_block();             /* single block transfer */
        return (MMC_END);
      }
    }
  }
}


/*F**************************************************************************
* NAME: mmc_update_acq
*----------------------------------------------------------------------------
* PARAMS:   
*
* return:
*   MMC_OK:     state result OK
*   MMC_ERROR:  state result KO
*   MMC_END:    end of new card acquisition
*----------------------------------------------------------------------------
* PURPOSE: 
*   New card acquisition
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*   - This function must be called 5 or 6 times for completion
*     depending on busy card
*   - Each call must be delayed enough to leave time for command
*     transmission and response reception
*   - It does not take care of the DSR
*
*   STATES: MMC_STACK_OP_COND   send operating condition
*           MMC_STACK_CID       check busy and send CID or op cond again
*           MMC_STACK_SRA       check CID response and set relative address
*           MMC_STACK_CSD       send CSD request
*           MMC_STACK_END       check CSD reception
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
Byte mmc_update_acq (void)
{
Uint32  response;

  switch (mmc_state)
  {
    case MMC_STACK_OP_COND:
    {
      mmc_send_cmd(MMC_SEND_OP_COND, MMC_OCR_INIT, MMC_RESP_R3);
      mmc_state = MMC_STACK_CID;
      return (MMC_OK);
    }

    case MMC_STACK_CID:
    {
      if (mmc_check_response() == MMC_ERR_RESP)
      {
        mmc_send_scmd(MMC_ALL_SEND_CID, MMC_RESP_R2);
        mmc_state = MMC_STACK_SRA;          /* card already in stack ? */
      }
      else
      {
        response = mmc_read_response();
        if ((((Byte*)&response)[0] & MMC_BUSY_OCR) != MMC_BUSY_OCR)
        {   /* at least one card is busy */
          mmc_send_cmd(MMC_SEND_OP_COND, MMC_OCR_INIT, MMC_RESP_R3);
        }
        else
        {
          mmc_send_scmd(MMC_ALL_SEND_CID, MMC_RESP_R2);
          mmc_state = MMC_STACK_SRA;
        }
      }
      return (MMC_OK);
    }

    case MMC_STACK_SRA:
    {
      if (mmc_check_response() == MMC_ERR_RESP)
      {
        mmc_state = MMC_FUNCT_START;
        return (MMC_ERROR);                 /* no response: no new card */
      }
      else
      {
        mmc_send_cmd(MMC_SET_RELATIVE_ADDRESS, MMC_RCA_2, MMC_RESP_R1);
        mmc_state = MMC_STACK_CSD;
        return (MMC_OK);
      }
    }

    case MMC_STACK_CSD:
    {
      if (mmc_check_response() == MMC_ERR_RESP)
      {
        mmc_state = MMC_FUNCT_START;
        return (MMC_ERROR);                 /* no response */
      }
      else
      {
        mmc_send_cmd(MMC_SEND_CSD, MMC_RCA_2, MMC_RESP_R2);
        mmc_state = MMC_STACK_END;
        return (MMC_OK);
      }
    }

    case MMC_STACK_END:
    {
      if (mmc_check_response() == MMC_ERR_RESP)
      {
        mmc_state = MMC_FUNCT_START;
        return (MMC_ERROR);                 /* no response */
      }
      else
      {

⌨️ 快捷键说明

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