📄 mmcsd_protocol.c
字号:
CSL_EdmaRegionObj edmaShObj;
CSL_EdmaRegionParam regionParam;
CSL_EdmaHwChannelSetup chSetupMmcrx;
CSL_EdmaRegionHandle shHandle;
CSL_EdmaCmdDmaRegion draeAttr;
CSL_Status chStatus;
Uint32 revision;
Uint32 intrQuery[2];/*EDMA object declaration ends */
/*Required for EDMA setup */
Uint32 *dstBuff= NULL;
Uint32 bcnt=0x0;
Uint32 ccnt=0x0; /*EDMA Objects */
#ifdef THROUGHPUT
/*Initialize the Memorylocations storing the START & STOP count from TIMER1 for READ operation */
*rd_tickstart=0x0;
*rd_tickstop=0x0;
#endif
if(mmcsdCSDRegInfo.readBlkLenBytes != blklength){
if(mmcsdCSDRegInfo.readBlkPartial != 1)
return E_INVALID_INPUT;
}
if(cardMemAddr%512){
if(mmcsdCSDRegInfo.readBlkMisalign != 1) {
return E_INVALID_INPUT;
}
}
fifoThrlevel= fifoLevel;
/*Required for EDMA setup */
if(fifoThrlevel)
{
MMCSD_FIFOThreshold(MMCSD_FIFOLEVEL_32BYTES);
fifoReadItrCount=blklength/32;
fifoDxrRdCnt=8;
}
else
{
fifoReadItrCount=blklength/16;
fifoDxrRdCnt=4;
}
if (dmaEnable)
{
/* reset the FIFO */
MMCSD_FIFOReset();
/* Set the Transfer direction from the FIFO as receive*/
MMCSD_FIFOReceive();
dstBuff= (Uint32 *)dest;
bcnt = fifoDxrRdCnt;
ccnt = fifoReadItrCount;
// Module Initialization
CSL_edmaInit(&edmaContext);
// Module Level Open
hModule = CSL_edmaOpen(NULL,CSL_EDMA_0,NULL,NULL);
// Query Module revision
CSL_edmaGetHwStatus(hModule,CSL_EDMA_QUERY_REVISION,&revision);
// Setup the DRAE Masks
// Region 0 for ARM based peripherals.
draeAttr.region = CSL_EDMA_REGION_0;
draeAttr.drae = 0xFFFFFFFF;
draeAttr.draeh = 0x1FFFFFFF;
CSL_edmaHwControl(hModule,CSL_EDMA_CMD_DMAREGION_ENABLE,&draeAttr);
// Shadow Region 0 Open: ARM Shadow Region
regionParam.regionNum = CSL_EDMA_REGION_0;
shHandle = CSL_edmaRegionOpen(&edmaShObj,CSL_EDMA_0,®ionParam,NULL);
// Channel Open
chParamMmcrx.regionNum = CSL_EDMA_REGION_0;
chParamMmcrx.chaNum = CSL_EDMA_MMCRXEVT; //MMCSDREVT sync event
hMmcChrx = CSL_edmaChannelOpen(&ChObjMmcrx,
CSL_EDMA_0,
&chParamMmcrx,
&chStatus);
// Channel Setup
chSetupMmcrx.paramEntry = 26; // This number corresponds to channel/event number=paramentry associated w/ a periph. Refer Table 5-9 (chap5)
chSetupMmcrx.que = CSL_EDMA_EVT_QUE1;// Use Q1 as default, might change when building Chains.
CSL_edmaHwChannelSetup(hMmcChrx,&chSetupMmcrx);
// Acquire parameters and set them up
// Acquire basic param and set it up
// 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);
status = MMCSD_sendCmd(MMCSD_SET_BLOCKLEN, blklength, (Bool)0, MMCSD_STAT0_RSPDNE);
if(status != E_PASS)
return E_FAIL;
MMCSD_clearResponse();
status = MMCSD_setDataSize(1, blklength); /* num_blks = 1, num_of_bytes = blklength */
if(status != E_PASS)
return E_FAIL;
/*EDMA Channel Enable */
CSL_edmaHwChannelControl(hMmcChrx,CSL_EDMA_CMD_CHANNEL_ENABLE,NULL);
#ifdef THROUGHPUT
/*Obtain the Read Start Count from Timer 1 */
*rd_tickstart = (CSL_FEXTR(CSL_TMR_1_REGS->TIM12, 31,16) << 16) | CSL_FEXTR(CSL_TMR_1_REGS->TIM12, 15,0) ;
#endif
/*Send read single Block Command */
status = MMCSD_sendCmd(0x12000 | MMCSD_READ_SINGLE_BLOCK, cardMemAddr, (Bool)0, MMCSD_STAT0_RSPDNE);
if(status != E_PASS)
return E_FAIL;
// 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
/*Obtain the Start Count from Timer 1 */
*rd_tickstop = (CSL_FEXTR(CSL_TMR_1_REGS->TIM12, 31,16) << 16) | CSL_FEXTR(CSL_TMR_1_REGS->TIM12, 15,0) ;
#endif
/*Clear Interrupt Pending Register */
hModule->ICR= 0x04000000;
/*Clear pending events */
hModule->EECR= 0x04000000;
CSL_edmaChannelClose(hMmcChrx);
CSL_edmaRegionClose(shHandle);
CSL_edmaClose(hModule);
for(i=0;i<100;i++);
if(status == E_PASS)
{
if(MMCSD_checkStatus(MMCSD_STAT0_DATDNE,0,0)==E_PASS)
return E_PASS;
else
return E_FAIL;
}
}
else /* CPU used for transfer */
{
status = MMCSD_sendCmd(MMCSD_SET_BLOCKLEN, blklength, (Bool)0, MMCSD_STAT0_RSPDNE);
if(status != E_PASS)
return E_FAIL;
MMCSD_clearResponse();
status = MMCSD_setDataSize(1, blklength); /* num_blks = 1, num_of_bytes = blklength */
if(status != E_PASS)
return E_FAIL;
/* reset the FIFO */
MMCSD_FIFOReset();
/* Set the Transfer direction from the FIFO as receive*/
MMCSD_FIFOReceive();
#ifdef THROUGHPUT
/*Obtain the Read Start Count from Timer 1 */
*rd_tickstart = (CSL_FEXTR(CSL_TMR_1_REGS->TIM12, 31,16) << 16) | CSL_FEXTR(CSL_TMR_1_REGS->TIM12, 15,0) ;
#endif
/*Send read single Block Command */
status = MMCSD_sendCmd(0x12000 | MMCSD_READ_SINGLE_BLOCK, cardMemAddr, (Bool)0, MMCSD_STAT0_RSPDNE);
if(status != E_PASS)
return E_FAIL;
status=MMCSD_readNWords((Uint32*)dest, blklength,cardMemAddr,dmaEnable);
if(status !=E_PASS)
return E_FAIL;
for(i=0;i<100;i++);
if(status == E_PASS)
{
if(MMCSD_checkStatus(MMCSD_STAT0_DATDNE,0,0)==E_PASS)
return E_PASS;
else
return E_FAIL;
}
#ifdef THROUGHPUT
/*Obtain the Start Count from Timer 1 */
*rd_tickstop = (CSL_FEXTR(CSL_TMR_1_REGS->TIM12, 31,16) << 16) | CSL_FEXTR(CSL_TMR_1_REGS->TIM12, 15,0) ;
#endif
}
return E_PASS;
}
/**
\brief Send command to write a single block 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 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_singleBlkWrite( Uint32 cardMemAddr, Uint32 *src, Uint32 blklength, Bool dmaEnable, Uint32 endian,MMCSD_FIFOTHR_LEVEL fifolevel)
{
STATUS status = E_PASS,i=0;
/* Check for the Valid block length of the Card */
if(mmcsdCSDRegInfo.writeBlkLenBytes != blklength)
status=E_INVALID_INPUT;
if(mmcsdCSDRegInfo.writeBlkLenBytes != blklength)
{
if(mmcsdCSDRegInfo.writeBlkPartial != 1)
return E_INVALID_INPUT;
}
if(cardMemAddr%512)
{
if(mmcsdCSDRegInfo.writeBlkMisalign != 1)
return E_INVALID_INPUT;
}
status = MMCSD_setDataSize( 1, blklength ); /* num_blks = 1, num_of_bytes = blklength */
status = MMCSD_sendCmd(MMCSD_SET_BLOCKLEN, blklength, (Bool)0, MMCSD_STAT0_RSPDNE);
if(status == E_PASS)
{
/* Write Data, every time MMCDXR Reg full */
status = MMCSD_writeNWords((Uint32*)src, blklength,cardMemAddr,dmaEnable);
/*Delay Required*/
for(i=0;i<100;i++);
if(status == E_PASS)
{
/* command been sent */
if(MMCSD_checkStatus(MMCSD_STAT0_DATDNE,0,0)!=E_PASS)
return E_FAIL;
}
else
return E_FAIL;
}
return E_PASS;
}
/**
\brief Send command to read multiple blocks 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 numBlks Number of blocks to be read during multiple blk read operation, from MMC/SD
\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_multipleBlkRead( Uint32 cardMemAddr, Uint32 *dest, Uint32 datalength, Bool dmaEnable, Uint32 endian )
{
STATUS status;
Uint32 numBlks;
int num_extra_words;
Uint16 fifoDxrRdCnt=0,fifoThrlevel=0;
Uint32 fifoReadItrCount=0;
/*EDMA Objects */
CSL_EdmaHandle hModule;
CSL_EdmaParamHandle hParaMmcrx;
CSL_EdmaChanObj ChObjMmcrx;
CSL_EdmaChanHandle hMmcChrx;
CSL_EdmaParamSetup paramSetupMmcrx;
CSL_EdmaContext edmaContext;
CSL_EdmaChannelParam chParamMmcrx;
CSL_EdmaRegionObj edmaShObj;
CSL_EdmaRegionParam regionParam;
CSL_EdmaHwChannelSetup chSetupMmcrx;
CSL_EdmaRegionHandle shHandle;
CSL_EdmaCmdDmaRegion draeAttr;
CSL_Status chStatus;
Uint32 revision;
Uint32 intrQuery[2];/*EDMA object declaration ends */
/*Required for EDMA setup */
Uint32 *dstBuff= NULL;
Uint32 bcnt=0x0;
Uint32 ccnt=0x0; /*EDMA Objects */
//Check whether address is valid
if(cardMemAddr%512){
if(mmcsdCSDRegInfo.readBlkMisalign != 1)
return E_INVALID_INPUT;
}
/*Required for EDMA setup */
fifoThrlevel= CSL_FEXT(CSL_MMCSD_0_REGS->MMCFIFOCTL,MMCSD_MMCFIFOCTL_FIFOLEV);
if(fifoThrlevel)
{
MMCSD_FIFOThreshold(MMCSD_FIFOLEVEL_32BYTES);
fifoReadItrCount=datalength/32;
fifoDxrRdCnt=8;
}
else
{
fifoReadItrCount=datalength/16;
fifoDxrRdCnt=4;
}
if(dmaEnable)
{
/* reset the FIFO */
MMCSD_FIFOReset();
/* Set the Transfer direction from the FIFO as transmit*/
MMCSD_FIFOReceive();
/* 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;
}
}
dstBuff= (Uint32 *)dest;
bcnt = fifoDxrRdCnt;
ccnt = fifoReadItrCount;
// Module Initialization
CSL_edmaInit(&edmaContext);
// Module Level Open
hModule = CSL_edmaOpen(NULL,CSL_EDMA_0,NULL,NULL);
// Query Module revision
CSL_edmaGetHwStatus(hModule,CSL_EDMA_QUERY_REVISION,&revision);
// Setup the DRAE Masks
// Region 0 for ARM based peripherals.
draeAttr.region = CSL_EDMA_REGION_0;
draeAttr.drae = 0xFFFFFFFF;
draeAttr.draeh = 0x1FFFFFFF;
CSL_edmaHwControl(hModule,CSL_EDMA_CMD_DMAREGION_ENABLE,&draeAttr);
// Shadow Region 0 Open: ARM Shadow Region
regionParam.regionNum = CSL_EDMA_REGION_0;
shHandle = CSL_edmaRegionOpen(&edmaShObj,CSL_EDMA_0,®ionParam,NULL);
// Channel Open
chParamMmcrx.regionNum = CSL_EDMA_REGION_0;
chParamMmcrx.chaNum = CSL_EDMA_MMCRXEVT; //MMCSDREVT sync event
hMmcChrx = CSL_edmaChannelOpen(&ChObjMmcrx,
CSL_EDMA_0,
&chParamMmcrx,
&chStatus);
// Channel Setup
chSetupMmcrx.paramEntry = 26; // This number corresponds to channel/event number=paramentry associated w/ a periph. Refer Table 5-9 (chap5)
chSetupMmcrx.que = CSL_EDMA_EVT_QUE1;// Use Q1 as default, might change when building Chains.
CSL_edmaHwChannelSetup(hMmcChrx,&chSetupMmcrx);
// Acquire parameters and set them up
// Acquire basic param and set it up
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -