📄 mmcsd_protocol.c
字号:
// Parameter entry 0
/* Basic Setup */
hParaMmcrx = CSL_edmaGetParamHandle(hMmcChrx,26,NULL);// Need to put the paramentry number here too.
// Your ACNT will change depending on whether its 8 bit (ACNT=1),16-bit (ACNT=2) or 32 bit (ACNT=4)data, as ACNT is always in # of bytes
paramSetupMmcrx.option = CSL_EDMA_OPT_MAKE(FALSE,FALSE,FALSE,TRUE,26,CSL_EDMA_TCC_NORMAL,CSL_EDMA_FIFOWIDTH_128BIT,FALSE,CSL_EDMA_SYNC_FRAME,CSL_EDMA_ADDRMODE_INCR,CSL_EDMA_ADDRMODE_INCR);
/*MMCSD DRR Register - Source Address */
paramSetupMmcrx.srcAddr = (Uint32)0x01E10028;
//ACNT=4 since DRR is 32 bit wide, BCNT= FifoDepth/ACNT
paramSetupMmcrx.elmArrCnt = CSL_EDMA_CNT_MAKE(4,bcnt);
paramSetupMmcrx.dstAddr = (Uint32)dstBuff;
// Source BIDX stays same, Dst Idx changes by 4 since ACNT =4
paramSetupMmcrx.srcDstBidx = CSL_EDMA_BIDX_MAKE(0,4);
//Link to NULL , BCNTRLD=0.
paramSetupMmcrx.linkBcntrld = CSL_EDMA_LINKBCNTRLD_MAKE(CSL_EDMA_LINK_NULL,0);
//Dst Cidx is (ACNT*BCNT) Src Cidx is 0 .
paramSetupMmcrx.srcDstCidx = CSL_EDMA_CIDX_MAKE(0,(4*bcnt));
paramSetupMmcrx.cCnt = ccnt;
paramSetupMmcrx.triggerWord = CSL_EDMA_TRIGWORD_NONE; //Set this as NONE for EDMA x'fers. Useful in QDMA x'fers
CSL_edmaParamSetup(hParaMmcrx,¶mSetupMmcrx,CSL_EDMA_PARAM_BASIC);
/* Set the blocklength and size of the block in bytes */
status = MMCSD_setDataSize( numBlks, mmcsdCSDRegInfo.readBlkLenBytes);
/* Send the Multi Blk Read Command with a no response check */
status = MMCSD_sendCmd(0x1A080 | MMCSD_READ_MULTIPLE_BLOCK, cardMemAddr, (Bool)0, MMCSD_STAT0_RSPDNE);
/*EDMA Channel Enable */
CSL_edmaHwChannelControl(hMmcChrx,CSL_EDMA_CMD_CHANNEL_ENABLE,NULL);
// Poll for transfer completions, wherein in this case IPR bit 26 (TCC#) will be set
// Important to have TCCINTEN =1 in the OPT field
do
{
CSL_edmaGetHwRegionStatus(shHandle,CSL_EDMA_QUERY_REGION_INTERRUPT_PENDSTATUS,intrQuery);
} while (!(intrQuery[0] & 0x04000000));
#ifdef THROUGHPUT
// CSL_FINST(CSL_TMR_0_REGS->TCR, TMR_TCR_ENAMODE12, DISABLED);
// CSL_FINST(CSL_TMR_0_REGS->TCR, TMR_TCR_ENAMODE34, DISABLED);
// rd_ticksA = (CSL_FEXTR(CSL_TMR_0_REGS->TIM12, 31,16) << 16) | CSL_FEXTR(CSL_TMR_0_REGS->TIM12, 15,0) ;
// rd_ticksB = (CSL_FEXTR(CSL_TMR_0_REGS->TIM34, 31,16) << 16) | CSL_FEXTR(CSL_TMR_0_REGS->TIM34, 15,0) ;
// *RD_TICKS= rd_ticksA;
// CSL_FINST(CSL_TMR_0_REGS->TGCR, TMR_TGCR_TIM12RS, IN_RESET);
// CSL_FINST(CSL_TMR_0_REGS->TGCR, TMR_TGCR_TIM34RS, IN_RESET);
#endif
/*Clear Interrupt Pending Register */
hModule->ICR= 0x04000000;
/*Clear pending events */
hModule->EECR= 0x04000000;
CSL_edmaChannelClose(hMmcChrx);
CSL_edmaRegionClose(shHandle);
CSL_edmaClose(hModule);
if(status == E_PASS)
{
/* Check for MMCSD_DATDNE signal */
status = MMCSD_checkStatus(MMCSD_STAT0_DATDNE, 0, 0); /* TimeOut = 0 */
}
}
else /*CPU used to Read Data */
{
/* Clear all the response registers */
MMCSD_clearResponse();
/* Determine the minimum number of extra bytes */
num_extra_words = datalength % (mmcsdCSDRegInfo.readBlkLenBytes);
/* To find the Number of blocks to be read in terms of 512 Bytes */
numBlks = datalength / (mmcsdCSDRegInfo.readBlkLenBytes);
/*Check whether partial reads are supported */
if(num_extra_words != 0) {
if(mmcsdCSDRegInfo.readBlkPartial != 1) {
return E_INVALID_INPUT;
}
}
/* Set the blocklength and size of the block in bytes */
status = MMCSD_setDataSize( numBlks, mmcsdCSDRegInfo.readBlkLenBytes);
/* reset the FIFO */
MMCSD_FIFOReset();
/* Set the Transfer direction from the FIFO as transmit*/
MMCSD_FIFOReceive();
/* Send the Multi Blk Read Command with a no response check */
status = MMCSD_sendCmd(0x1A080 | MMCSD_READ_MULTIPLE_BLOCK, cardMemAddr, (Bool)0, MMCSD_STAT0_RSPDNE);
if(status == E_PASS)
{ /* Command sent */
/* Read Data, every time Data Rd Reg full, till all words read */
status = MMCSD_readNWords((Uint32*)dest, datalength,cardMemAddr,dmaEnable);
if(status == E_PASS)
{
/* Check for MMCSD_DATDNE signal */
status = MMCSD_checkStatus(MMCSD_STAT0_DATDNE, 0, 0); /* TimeOut = 0 */
}
}
}
return status;
}
/**
\brief Send command to write multiple blocks of data to the MMC/SD card
\param cardAddr Address of the location on the card to be written (should be a multiple of )
\param src Buffer to write data from, into the MMC/SD card
\param numBlks Number of blocks to be written during multiple blk write operation, to MMC/SD
\param blklength Size of the block in bytes, to be written to MMC/SD card
\param dmaEnable 0: Disable DMA, 1: Enable DMA
\param endian Endianness of the data to be written to the MMC/SD card
\return if success, \c E_PASS, else error code
*/
STATUS MMCSD_multipleBlkWrite( Uint32 cardMemAddr, Uint32 *src, Uint32 datalength, Bool dmaEnable, Uint32 endian )
{
STATUS status,i=0;
Uint32 numBlks;
int num_extra_words;
/* Check whether card memory address is valid */
if(cardMemAddr%512){
if(mmcsdCSDRegInfo.writeBlkMisalign != 1)
return E_INVALID_INPUT;
}
/*Clear all Response Registers */
MMCSD_clearResponse();
/*Determine the minimum number of extra bytes */
num_extra_words = datalength % (mmcsdCSDRegInfo.writeBlkLenBytes);
/* To find out number of BLOCKS to be written in terms of 512 bytes */
numBlks = datalength / (mmcsdCSDRegInfo.writeBlkLenBytes);
/*Check whether partial reads are supported */
if(num_extra_words != 0) {
if(mmcsdCSDRegInfo.writeBlkPartial != 1) {
return E_INVALID_INPUT;
}
}
/* Set the blocklength and size of the block in bytes */
status = MMCSD_setDataSize(numBlks, mmcsdCSDRegInfo.readBlkLenBytes);
if(status!=E_PASS)
return E_FAIL;
/* Send the BLOCK LEN command to the card , it is an optional one*/
status = MMCSD_sendCmd(MMCSD_SET_BLOCKLEN, mmcsdCSDRegInfo.writeBlkLenBytes, (Bool)0, MMCSD_STAT0_RSPDNE);
if(status!=E_PASS)
return E_FAIL;
/* Read Data, every time Data Rd Reg full, till all words read */
status = MMCSD_writeNWords((Uint32*)src,datalength,cardMemAddr,dmaEnable);
/*Delay required */
for(i=0;i<100;i++);
if(status == E_PASS)
{
/* Check for MMCSD_DATDNE signal */
if(MMCSD_checkStatus(MMCSD_STAT0_DATDNE, 0, 0)!=E_PASS) /* TimeOut = 0 */
return E_FAIL;
if(MMCSD_sendCmd(0xA180 | MMCSD_STOP_TRANSMISSION, MMCSD_STUFF_BITS, (Bool)0, MMCSD_STAT0_RSPDNE)!=E_PASS)
return E_FAIL;
}
else
{
return E_FAIL;
}
return (status);
}
/**
\brief Card Identification Sequence for MMC and SD
\param mmcsdConfig Structure to configure the MMC/SD card
\param rca Relative Card Address assigned to the card
\param cardStatus Status of the card is received in this parameter
\param opTimeout TimeOut value required for sending Operating Voltage to card
\return if success, \c E_PASS, else error code
*/
STATUS MMCSD_cardIdentification( MMCSD_ConfigData *mmcsdConfig, Uint32 *rca, MMCSD_cardStatusReg *cardStatus, Uint32 opTimeout, MMCSD_CARD_TYPE cardType )
{
STATUS status;
Uint16 cardReg[8];
int count;
Bool mmc = TRUE;
/* Place all cards in idle state */
status = MMCSD_goIdleState();
if( status != E_PASS )
return ( status );
/* Send the operating Voltage Range */
RESEND_CMD41:
//Introduce a delay for slow cards
for(count = 0; count < 1000; ++ count);
if(cardType== MMCSD_SECUREDIGITALCARD)
{
/* Send CMD55 with RCA = 0 */
status = MMCSD_appCmd( 0 );
}
else
{
status = E_FAIL;
}
if( status != E_PASS ){
status = MMC_sendOpCond( MMCSD_VDD_32_34, opTimeout);
} else {
//Experimenting with the whole supported voltage range
status = SD_sendOpCond( 0x00ff8000, opTimeout );
if( status != E_PASS )
goto RESEND_CMD41;
mmc = FALSE;
}
/* Return to the application, of the card is an MMC card or an SD card */
cardStatus->multiMediaCard = (Bool)mmc;
/* Ask all cards to send their CIDs */
status = MMCSD_allSendCID( );
if( status != E_PASS )
return ( status );
MMCSD_getCardCID( &mmcsdResponse, cardReg );
if( mmc == TRUE ){
/* Set Relative Address for the card. As we are using only one card
currently setting the card rca to MMC_CARD_ID = 2
We cannot use 1 because that is the default for all the SanDisk cards
*/
status = MMC_setRCA( *rca, cardStatus );
if( status != E_PASS )
return ( status );
} else {
/* Read Relative Address from the card and store it in variable rca
*/
status = SD_sendRCA( rca );
if( status != E_PASS )
return ( status );
}
/* Send Status may be required at this point */
/* Read the CSD structure for MMC/SD */
status = MMCSD_sendCSD( *rca, cardReg );
if( status != E_PASS )
return ( status );
/* Select the Card which responded */
status = MMCSD_selectCard( *rca );
if( status != E_PASS )
return ( status );
if(*rca >0)
{
status= MMCSD_sendStatus(*rca,cardStatus);
if(status != E_PASS)
return (status);
relCardAdress=*rca;
}
if(mmcsdConfig->busWidth == MMCSD_DATA_BUS_4)
{
status=SD_setBusWidth(*rca, 2,2048);
if(status != E_PASS)
return (status);
}
return ( status );
}
/**
\brief MMCSD CRC set command \n
This turns the CRC check on of off if in the SPI mode
\param enable Whether CRC is to be made on or off 0: OFF 1: ON
\return if successful, \c E_PASS else \c E_DEVICE
\note This command is to be used in the SPI mode only
*/
STATUS MMCSD_setCRC(Bool enable)
{
Uint16 controlReg;
/* Check whether the device is in SPI mode */
controlReg = (Uint16)CSL_MMCSD_0_REGS->MMCCTL;
if((controlReg & 0x0020) == 0) { /* Device in MMC/SD native mode */
return(E_DEVICE);
}
return(E_PASS);
}
/**
\brief MMCSD read OCR \n
This reads the OCR register in the SPI mode
\param cardOCRRegister Buffer to store the OCR register contents
\return if successful, \c E_PASS else \c E_DEVICE
\note This command is to be used ONLY in the SPI mode
*/
STATUS MMCSD_readOCR(Uint32* cardOCRRegister)
{
STATUS status;
Uint32 response;
/* Send the read OCR command */
status = MMCSD_sendCmd(MMCSD_READ_OCR, MMCSD_STUFF_BITS, (Bool)1, MMCSD_STAT0_RSPDNE);
if(status == E_PASS) {
/* Read the OCR contents from the R3 response (SPI) */
response = (CSL_FEXT(CSL_MMCSD_0_REGS->MMCRSP67,MMCSD_MMCRSP67_MMCRSP7) & 0x00ff); /* Extract the MSB of the OCR */
response = (response <<24)|
(CSL_FEXT(CSL_MMCSD_0_REGS->MMCRSP67,MMCSD_MMCRSP67_MMCRSP6) << 8) |
(CSL_FEXT(CSL_MMCSD_0_REGS->MMCRSP67,MMCSD_MMCRSP45_MMCRSP5));
*cardOCRRegister = response;
}
return(status);
}
/* Rev.No. Date/Time ECN No. Modifier */
/* ------- --------- ------- -------- */
/* 1 24 Jun 2004 14:41:05 1864 xjarlika */
/* */
/* Checking in MMCSD drv include and src files */
/********************************************************************/
/* Rev.No. Date/Time ECN No. Modifier */
/* ------- --------- ------- -------- */
/* 2 Jul 15:22:22 8 2049 xjarlika */
/* */
/* FIFOCTL renamed as MMCFIFOCTL */
/* Update due to Register Name Change */
/********************************************************************/
/* Rev.No. Date/Time ECN No. Modifier */
/* ------- --------- ------- -------- */
/* 3 13 Aug 2004 18:21:55 2296 xjarlika */
/* */
/* Updating MMCSD include and src file after inital testing on Hibari*/
/* Updating MMCSD include and src file after inital testing on Hibari*/
/********************************************************************/
/* Rev.No. Date/Time ECN No. Modifier */
/* ------- --------- ------- -------- */
/* 4 20 Aug 2004 11:18:19 2346 xjarlika */
/* */
/* Added EDMA functions to MMCSD library */
/********************************************************************/
/* Rev.No. Date/Time ECN No. Modifier */
/* ------- --------- ------- -------- */
/* 5 24 Aug 2004 14:45:34 2401 xjarlika */
/* */
/* Updating MMCSD drv include and src files after testing on Hibari */
/********************************************************************/
/* Rev.No. Date/Time ECN No. Modifier */
/* ------- --------- ------- -------- */
/* 6 14 Jan 2005 11:28:32 5879 xjarlika */
/* */
/* Updating after testing on DaVinci QT */
/********************************************************************/
/* Rev.No. Date/Time ECN No. Modifier */
/* ------- --------- ------- -------- */
/* 7 Feb 09:55:24 4 6639 xjarlika */
/* */
/* Checking in after firstcut thruput data collection for MMCSD */
/********************************************************************/
/* Rev.No. Date/Time ECN No. Modifier */
/* ------- --------- ------- -------- */
/* 8 17 Feb 2005 09:43:06 7097 xjarlika */
/* */
/* Updating for MMCSD regression tests */
/********************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -