📄 mmcsd_protocol.c
字号:
/*
DaVinci ARM Evaluation Software
(c)Texas Instruments 2004
*/
/**
\file mmcsd_protocol.c
\brief Contains APIs common to MMC and SD, which are protocol specific
*/
#include <cslr_mmcsd.h>
#include <memcd_rettypes.h>
#include <mmcsd_protocol.h>
#include <mmc_protocol.h>
#include <mmcsd_evm.h>
#include <csl_edma.h>
//#include <davinci64plus.h>
#define CSL_EDMA_0 0
extern MMCSD_ResponseData mmcsdResponse;
extern MMCSD_csdRegInfo mmcsdCSDRegInfo;
Uint32 relCardAdress;
/**
\brief Send command to set all the MMC/SD cards to Idle State
\return if success, \c E_PASS, else error code
*/
STATUS MMCSD_goIdleState()
{
STATUS status;
status = MMCSD_sendCmd( (0x4000 | MMCSD_GO_IDLE_STATE), MMCSD_STUFF_BITS, (Bool)0, MMCSD_STAT0_RSPDNE);
return ( status );
}
/**
\brief Send command to read the contents of the Card Identification (CID) register, on the MMC/SD
\return if success, \c E_PASS, else error code
*/
STATUS MMCSD_allSendCID( void )
{
volatile Uint16 stat;
STATUS status;
status = MMCSD_sendCmd( MMCSD_ALL_SEND_CID, MMCSD_STUFF_BITS, (Bool)1, MMCSD_STAT0_RSPDNE);
return ( status );
}
/**
\brief Send command to set the Driver Stage Register (DSR) on the MMC/SD
\param dsr The DSR value to be programmed into the card (default value of DSR = 0x04040000, where last 6bits are stuff bits)
\return if success, \c E_PASS, else error code
*/
STATUS MMCSD_setDSR( Uint32 dsr )
{
STATUS status;
if( mmcsdCSDRegInfo.dsrImp != 1 )
return E_DEVICE;
status = MMCSD_sendCmd( MMCSD_SET_DSR, dsr, (Bool)1, MMCSD_STAT0_RSPDNE);
return ( status );
}
/**
\brief Send command to read the status of the MMC/SD
\param rca Relative Card Address assigned to the card
\param cardStatus Status of the card is received in this structure
\return if success, \c E_PASS, else error code
*/
STATUS MMCSD_sendStatus( Uint32 rca, MMCSD_cardStatusReg *cardStatus )
{
STATUS status;
/* the rca value is sent as the upper 16 bits of the command argument */
status = MMCSD_sendCmd( MMCSD_SEND_STATUS, rca<<16, (Bool)1, MMCSD_STAT0_RSPDNE);
if( status == E_PASS ) {
/* Response expected: R1 in native mode and R2 in SPI mode*/
MMCSD_getCardStatus( &mmcsdResponse, cardStatus );
return ( E_PASS );
}
return ( status );
}
/**
\brief Send command to select a particular MMC/SD, using it's assigned RCA
\param rca Relative Card Address assigned to the card
\return if success, \c E_PASS, else error code
*/
STATUS MMCSD_selectCard( Uint32 rca )
{
STATUS status;
MMCSD_cardStatusReg cardStatus;
/* the rca value is sent as the upper 16 bits of the command argument */
status = MMCSD_sendCmd( MMCSD_SELECT_CARD, rca<<16, (Bool)1, MMCSD_STAT0_RSPDNE );
if( status == E_PASS ) {
/* no timeout */
if ( rca > 0 ) {
if( (MMCSD_sendStatus( rca, &cardStatus ) == E_PASS) ) {
if( (cardStatus.currentState == MMCSD_STATE_TRAN) || (cardStatus.currentState == MMCSD_STATE_PRG ) ) {
return ( E_PASS );
}
}
}
}
return ( status );
}
/**
\brief Send command to deselect all MMCs / SDs (rca=0) or only the currently selected MMC/SD (rca != current MMCs/SDs rca)
\param newRCA a new RCA value, used for deselecting only the currently selected MMC/SD
\param oldRCA the currently selected MMCs/SDs RCA value, used for checking if that MMC/SD is deselected
\return if success, \c E_PASS, else error code
*/
STATUS MMCSD_deSelectCard( Uint16 newRCA, Uint16 oldRCA )
{
STATUS status;
MMCSD_cardStatusReg cardStatus;
int i=0;
/* Deselect the card then check status to see if
we are in the proper state. Because we are
using rca = 0 to deselect there will not be
the typical R1 response. : This is true if u want to deselect
all cards with 1 cmd - Rati
*/
if( newRCA == oldRCA ){
status = MMCSD_sendCmd( MMCSD_DESELECT_CARD, 0, (Bool)0, MMCSD_STAT0_RSPDNE );
} else {
status = MMCSD_sendCmd( MMCSD_DESELECT_CARD, newRCA, (Bool)0, MMCSD_STAT0_RSPDNE );
}
/* delay reqd. */
for( i=0; i<1000; i++ );
/* Check if card is de-selected */
if( status == E_PASS ) {
status = MMCSD_sendStatus( oldRCA, &cardStatus );
if( status == E_PASS )
if( (cardStatus.currentState == MMCSD_STATE_STBY) || (cardStatus.currentState == MMCSD_STATE_DIS ) ) {
return ( E_PASS );
}
}
return ( E_DEVICE );
}
/**
\brief Send command to read the contents of the Card Specific Data (CSD) register, on the MMC/SD
\param rca Relative Card Address assigned to the card
\param cardCSD CSD of the card is received in this structure
\return if success, \c E_PASS, else error code
*/
STATUS MMCSD_sendCSD( Uint32 rca, Uint16 *cardCSD )
{
STATUS status;
/* the rca value is sent as the upper 16 bits of the command argument */
status = MMCSD_sendCmd( MMCSD_SEND_CSD, rca<<16, (Bool)1, MMCSD_STAT0_RSPDNE);
if( status == E_PASS ) {
MMCSD_getCardCSD( &mmcsdResponse, cardCSD, &mmcsdCSDRegInfo );
return ( E_PASS );
}
return ( status );
}
/**
\brief Send command to read the contents of the Card Identification (CID) register, on the MMC/SD
\param rca Relative Card Address assigned to the card
\param cardCID CID of the card is received in this structure
\return if success, \c E_PASS, else error code
*/
STATUS MMCSD_sendCID( Uint32 rca, Uint16 *cardCID )
{
STATUS status;
/* the rca value is sent as the upper 16 bits of the command argument */
status = MMCSD_sendCmd( MMCSD_SEND_CID, rca<<16, (Bool)1, MMCSD_STAT0_RSPDNE);
if( status == E_PASS ) {
MMCSD_getCardCID( &mmcsdResponse, cardCID );
return ( E_PASS );
}
return ( status );
}
/**
\brief Send command to send the specified MMC/SD (selected using RCA) into Inactive State
\param rca Relative Card Address assigned to the card
\return if success, \c E_PASS, else error code
*/
STATUS MMCSD_goInactiveState( Uint32 rca )
{
STATUS status;
/* the rca value is sent as the upper 16 bits of the command argument */
status = MMCSD_sendCmd( MMCSD_GO_INACTIVE_STATE, rca<<16, (Bool)1, MMCSD_STAT0_RSPDNE);
return ( status );
}
/**
\brief Send command to set the block length of data to be transferred to/from the MMC/SD
\param blkLength Block length, in bytes, of data to be transferred to/from MMC/SD
\param write 0: read data from MMC/SD, 1: write data to MMC/SD
\return if success, \c E_PASS, else error code
*/
STATUS MMCSD_setBlkLen( Uint32 blkLength, Bool write )
{
STATUS status;
if( blkLength%512 )
if( write == 1 ){
if( mmcsdCSDRegInfo.writeBlkPartial != 1 ){
return E_FAIL; /* Command not supported */
}
}else {
if( mmcsdCSDRegInfo.readBlkPartial != 1 ){
return E_FAIL; /* Command not supported */
}
}
status = MMCSD_sendCmd( MMCSD_SET_BLOCKLEN, blkLength, (Bool)1, MMCSD_STAT0_RSPDNE);
return ( status );
}
/**
\brief Send command to program the programmable fields of the CSD register of MMC/SD
\param rca Relative Card Address assigned to the card
\param numBlks
\return if success, \c E_PASS, else error code
*/
STATUS MMCSD_programCSD( Uint32 rca, MMCSD_cardStatusReg *cardStatus, DM_BOOL writeProtect,Uint32 cardMemAddr )
{
STATUS status;
Uint16 cardCSD[8];
Uint32 numWords;
status = MMCSD_sendCSD( rca, cardCSD ) ;
if( status != E_PASS ) {
return E_DEVICE;
}
// Set the temporary write protection
if(writeProtect) {
cardCSD[7] = cardCSD[7]|0x10;
} else {
cardCSD[7] = cardCSD[7]&0xEF;
}
numWords = 2;
status = MMCSD_writeNWords( (Uint32 *)cardCSD , numWords,cardMemAddr,FALSE );
if( status == E_PASS ) {
status = MMCSD_checkStatus( (MMCSD_STAT0_DATDNE|MMCSD_STAT0_BSYDNE), 0, 0 ); //> TimeOut = 0
}
status = MMCSD_sendCmd( MMCSD_PROGRAM_CSD, MMCSD_STUFF_BITS, (Bool)1, MMCSD_STAT0_RSPDNE);
if( status == E_PASS ) {
/* Response expected: R1 */
MMCSD_getCardStatus( &mmcsdResponse, cardStatus );
return ( E_PASS );
}
numWords = 6;
status = MMCSD_writeNWords( (Uint32 *)cardCSD+2 , numWords,cardMemAddr,FALSE );
if( status == E_PASS ) {
status = MMCSD_checkStatus( (MMCSD_STAT0_DATDNE|MMCSD_STAT0_BSYDNE), 0, 0 ); //> TimeOut = 0
}
return ( status );
}
/**
\brief Send command to set Write Protection features of the addressed group on the MMC/SD
\param addr Address of the WP Group to be write protected
\return if success, \c E_PASS, else error code
\note The user application should check the Write Protect Grp Size, for determining how many sectors get write protected.
\note This value is present in the CSD structure of the MMC/SD cards.
*/
STATUS MMCSD_setWriteProtect( Uint32 addr )
{
STATUS status;
if( mmcsdCSDRegInfo.wpGrpEnable != 1 )
return E_FAIL; /* Command Not supported */
status = MMCSD_sendCmd( MMCSD_SET_WRITE_PROT, addr, (Bool)1, MMCSD_STAT0_RSPDNE );
if( status == E_PASS )
status = MMCSD_checkStatus( MMCSD_STAT0_BSYDNE, 0, 0 ); /* TimeOut = 0 */
return ( status );
}
/**
\brief Send command to clear the Write Protection feature set for the addressed group on the MMC/SD
\param addr Address of the WP Group from which to remove write protection
\return if success, \c E_PASS, else error code
\note The user application should check the Write Protect Grp Size, for determining how many sectors get write protected.
\note This value is present in the CSD structure of the MMC/SD cards.
*/
STATUS MMCSD_clearWriteProtect( Uint32 addr )
{
STATUS status;
if( mmcsdCSDRegInfo.wpGrpEnable != 1 )
return E_FAIL; /* Command Not supported */
status = MMCSD_sendCmd( MMCSD_CLR_WRITE_PROT, addr, (Bool)1, MMCSD_STAT0_RSPDNE );
if( status == E_PASS )
status = MMCSD_checkStatus( MMCSD_STAT0_BSYDNE, 0, 0 ); /* TimeOut = 0 */
return ( status );
}
/**
\brief Send command to check the status of the write protection bits of MMC/SD
\param addr Address of the WP Group for which write protection property is checked
\param writeProtBits write protect bits, representing 32 write protect groups, starting from 'addr'
\return if success, \c E_PASS, else error code
\note The user application should check the Write Protect Grp Size, for determining how many sectors get write protected.
\note This value is present in the CSD structure of the MMC/SD cards.
*/
STATUS MMCSD_sendWriteProtect( Uint32 addr, Uint16 *writeProtBits,Uint32 cardMemAddr )
{
STATUS status;
if( mmcsdCSDRegInfo.wpGrpEnable != 1 )
return E_FAIL; /* Command Not supported */
status = MMCSD_sendCmd( MMCSD_SET_BLOCKLEN, 4, (Bool)1, MMCSD_STAT0_RSPDNE);
if( status != E_PASS )
return E_FAIL;
status = MMCSD_setDataSize( 1, 4 ); /* num_blks = 1, num_of_bytes = blklength */
if( status == E_PASS ){
status = MMCSD_sendCmd( (0xA080 | MMCSD_SEND_WRITE_PROT), addr, (Bool)1, MMCSD_STAT0_RSPDNE);
if( status == E_PASS ) {
status = MMCSD_readNWords( (Uint32 *)writeProtBits, 2,cardMemAddr,FALSE );
/* Check for MMCSD_DATDNE signal */
if( status == E_PASS )
status = MMCSD_checkStatus( MMCSD_STAT0_DATDNE, 0, 0 ); //> TimeOut = 0
}
}
return ( status );
}
/**
\brief Send command to indicate that the next command is an application specific command
\param rca Relative Card Address assigned to the card
\return if success, \c E_PASS, else error code
*/
STATUS MMCSD_appCmd( Uint32 rca )
{
STATUS status;
/* the rca value is sent as the upper 16 bits of the command argument */
status = MMCSD_sendCmd( MMCSD_APP_CMD, rca<<16, (Bool)1, MMCSD_STAT0_RSPDNE);
return ( status );
}
/**
\brief Send command to read a single block of data from the MMC/SD card
\param cardAddr Address of the location on the card to be read (should be a multiple of )
\param dest Buffer to read data into, from MMC/SD card
\param blklength Size of the block in bytes, to be read from MMC/SD card
\param dmaEnable 0: Disable DMA, 1: Enable DMA
\param endian Endianness of the data to be read from the MMC/SD card
\return if success, \c E_PASS, else error code
*/
STATUS MMCSD_singleBlkRead( Uint32 cardMemAddr, Uint32 *dest, Uint32 blklength, Bool dmaEnable, Uint32 endian,MMCSD_FIFOTHR_LEVEL fifoLevel )
{
STATUS status=0,i=0 ;
Uint16 fifoDxrRdCnt=0;
Uint32 fifoReadItrCount=0; /* Word counter */
Uint16 fifoThrlevel =0;
/*Memory location for storing START & STOP count from Timer 1*/
Uint32 * rd_tickstart =(Uint32 *)0x80400008;
Uint32 * rd_tickstop =(Uint32 *)0x8040000c;
/*EDMA Objects */
CSL_EdmaHandle hModule;
CSL_EdmaParamHandle hParaMmcrx;
CSL_EdmaChanObj ChObjMmcrx;
CSL_EdmaChanHandle hMmcChrx;
CSL_EdmaParamSetup paramSetupMmcrx;
CSL_EdmaContext edmaContext;
CSL_EdmaChannelParam chParamMmcrx;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -