📄 mmc.c
字号:
/*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 + -