📄 mmc.c
字号:
{
pMMC->argh = 0;
pMMC->argl = block_len;
pMMC->cmd = SET_BLOCKLEN;
if( wait_for( RSPDNE ) == 0 )
{
CurrentBlen = block_len;
return(0);
}
return( -1 );
}
// Tested, tnyc, just one block
int MMC_ReadBlock(unsigned long lba, unsigned short *pBuf, int swapbytes)
{
unsigned short count = CurrentBlen/2;
register volatile unsigned short stat;
int error;
int ddr;
// The nblk and blen parameters can be a little confusing.
// blen can be less then the CSD blen which is usually 512.
// Thus I can simply read 10 bytes.
pMMC->nblk = 1;
pMMC->blen = CurrentBlen;
pMMC->argl = (unsigned short)((lba << 9) & 0xffff);
pMMC->argh = (unsigned short)((lba >> 7) & 0xffff);
pMMC->cmd = READ_SINGLE_BLOCK | DATA | DCLR;
// May want to check for a response. But for now
// we just check for data.
if( count < 1 )
return( -1 );
do
{
do
{
stat = pMMC->st0;
ddr = ((stat & DRRDY) != 0);
error = ((stat & ( CRCRD | TOUTRD)) != 0 );
// Checking for early DATDNE
Done |= (stat & 1);
}while( !error && !ddr );
if(ddr)
*pBuf++ = (swapbytes) ? ((pMMC->ddr & 0xff00) >> 8) + ((pMMC->ddr & 0x00ff) << 8) : pMMC->ddr;
}while( !error && --count );
// Test to make sure that we see a DATDNE signal
if( (error == 0) && (Done == 0) )
{
if( (error = wait_for( DATDNE )) == 0 )
Done = 1;
}
// Check for errors.
return( error == 0 ? 0 : -1 );
}
// Tested, tnyc, just one block
static int read_single_block( unsigned long address )
{
unsigned short count = CurrentBlen/2;
unsigned short * pBuf = ReadBlock;
register volatile unsigned short stat;
int error;
int ddr;
// The nblk and blen parameters can be a little confusing.
// blen can be less then the CSD blen which is usually 512.
// Thus I can simply read 10 bytes.
pMMC->nblk = 1;
pMMC->blen = CurrentBlen;
pMMC->argl = (unsigned short)address;
pMMC->argh = (unsigned short)(address>>16);
pMMC->cmd = READ_SINGLE_BLOCK | DATA | DCLR;
// May want to check for a response. But for now
// we just check for data.
if( count < 1 )
return( -1 );
do
{
do
{
stat = pMMC->st0;
ddr = ((stat & DRRDY) != 0);
error = ((stat & ( CRCRD | TOUTRD)) != 0 );
// Checking for early DATDNE
Done |= (stat & 1);
}while( !error && !ddr );
if(ddr)
*pBuf++ = pMMC->ddr;
}while( !error && --count );
// Test to make sure that we see a DATDNE signal
if( (error == 0) && (Done == 0) )
{
if( (error = wait_for( DATDNE )) == 0 )
Done = 1;
}
// Check for errors.
return( error == 0 ? 0 : -1 );
}
// Tested, tnyc. Just one block
int write_single_block( unsigned long address )
{
unsigned short count = CurrentBlen/2;
unsigned short * pBuf = ReadBlock;
register volatile unsigned short stat;
int error;
int dxr;
// The nblk and blen parameters can be a little confusing.
// blen can be less then the CSD blen which is usually 512.
// Thus I can simply read 10 bytes.
pMMC->nblk = 1;
pMMC->blen = CurrentBlen;
pMMC->argl = (unsigned short)address;
pMMC->argh = (unsigned short)(address>>16);
pMMC->cmd = WRITE_BLOCK | DATA | WRITE| DCLR;
SWDelayUsec(1);
// May want to check for a response. But for now
// we just check for data.
if( count < 1 )
return( -1 );
do
{
do
{
stat = pMMC->st0;
dxr = ((stat & DXRDY) != 0 );
error = ((stat & ( CRCWR ))!= 0 );
// Checking for early DATDNE
Done |= ( stat & 1 );
}while( !error && !dxr );
if(dxr)
pMMC->dxr = *pBuf++;
}while( !error && --count );
// Test to make sure that we see a DATDNE signal
if( (error == 0) && (Done == 0) )
{
if( (error = wait_for( DATDNE )) == 0 )
Done = 1;
}
// Check for errors.
return( error == 0 ? 0 : -1 );
}
int MMC_InitClock()
{
// Reset the command/data
pMMC->ctl= CMDRST | DATRST;
// controls the MMC clock-- should be 20 Mhz for MMC mode and 5 Mhz for SPI mode
// MMC clock = function clock / (MMCCLK_RATE + 1)
//
pMMC->clk &= ~CLKEN; // Turn off the clock before switching to new rate
// This has no effect on the FPGA implementation. The functional clock
// equal to the C55xx clockout.
pMMC->fckctl = dspclk.pllmult - 1;
pMMC->clk = 0x000e; // Clock divide by 8 ~400KHz = 9
pMMC->im = 0; /*all interrupts are masked */
pMMC->tor = 16; /*response time out */
pMMC->tod = 0; /*no data read time out */
/*need to set the length of a block in bytes-- must be same as in CSD register*/
pMMC->blen = BLEN;
pMMC->ctl = 0; /*enable dat and cmd lines*/
/* enable the clock ???? where to put it ????? */
/*maybe put it before go idle state????*/
pMMC->clk |= CLKEN;
// Wait long enough MMC module to reset.
SWDelayUsec(10);
}
int MMC_Init(void)
{
PC55XX_EXTBUS pExtBus = (PC55XX_EXTBUS)C55XX_EXTBUS_ADDR;
volatile long delay = 1000;
int error = 0;
// Configure serial port 2 for MMC mode
WriteField(pExtBus -> exbussel, EXBUSSEL_SPMODE_MMC, EXBUSSEL_SP2MODE);
// Set all the arguments to the default state
memset( &csd, 0, sizeof(CSD_STRUCT));
memset( &cid, 0, sizeof(CID_STRUCT));
memset( &status, 0, sizeof(STATUS_STRUCT));
memset( &Mmc, 0, sizeof(C55XX_MMC));
memset( &CardStatus,0, sizeof(CARD_STATUS));
memset( &CardCid, 0, sizeof(CARD_CID));
memset( &CardCsd, 0, sizeof(CARD_CSD));
SaveStat0 = 0;
SaveStat1 = 0;
OpLoop = 0;
TestFail = 0;
Debug = 1; // Enable debug stuff
CurrentBlen = 512;
MmcAddr = 2; // Non-default address
// Emif_Init();
// InterruptInit();
MMC_InitClock();
if( go_idle_state() != 0 )
{
error = ERROR_IDLE;
goto MMC_INIT_FAIL;
}
if( send_op_cond() != 0 )
{
error = ERROR_OP;
goto MMC_INIT_FAIL;
}
// For simulation test there is only one card so skip
// multiple card stuff
if( all_send_cid() != 0 )
{
error = ERROR_ALL_CID;
goto MMC_INIT_FAIL;
}
// Set the RCA to something other then the
// default of 0x0001
if( set_relative_addr( MmcAddr ) != 0 )
{
error = ERROR_ADDR;
goto MMC_INIT_FAIL;
}
// Make sure the card is in Standby at this point
if( send_status( MmcAddr ) != 0 )
{
error = ERROR_STATUS;
goto MMC_INIT_FAIL;
}
if( CardStatus.state != stby )
{
error = ERROR_STATUS;
goto MMC_INIT_FAIL;
}
// Read the CID via the CID command. Check for the Sandisk ID.
// Need to know the Siemens ID.
if( send_cid( MmcAddr ) != 0 )
{
error = ERROR_CID;
goto MMC_INIT_FAIL;
}
if( CardCid.mfg_id != MFG_ID_SANDISK )
{
error = ERROR_MFG_ID;
goto MMC_INIT_FAIL;
}
// Read the CSD and verify that structure is for MMC protocol version 1.4
if( send_csd( MmcAddr ) != 0 )
{
error = ERROR_CSD;
goto MMC_INIT_FAIL;
}
if( CardCsd.csd_struct != 1 )
{
error = ERROR_CSD_VER;
goto MMC_INIT_FAIL;
}
if( select_card( MmcAddr ))
{
error = -1;
goto MMC_INIT_FAIL;
}
return( 0 );
MMC_INIT_FAIL:
return( error );
}
int
MMC_Test( int TestLoop )
{
int TestFail;
int i,j;
int ErrorCount;
unsigned long BlockAddr = 0;
ErrorCount = 0;
if( TestFail = MMC_Init())
return( -1 );
for( i=0; i<TestLoop; i++ )
{
BlockAddr = 0;
for( j=0; j<4; j++ )
{
for( OpLoop=0; OpLoop<256; OpLoop++)
ReadBlock[OpLoop] = (OpLoop+j+i) + OpLoop;
OpLoop = 0;
// Set done to 0. If we get a DATADNE then this will be
// set to 1 if DATDNE is working.
Done = 0;
if( TestFail = write_single_block( BlockAddr ))
return(-1);
do
{
if( TestFail = send_status( MmcAddr ))
return(-1 );
}while( CardStatus.state == prg );
BlockAddr += 512;
}
BlockAddr = 0;
for( j=0; j<4; j++ )
{
// Set done to 0. If we get a DATADNE then this will be
// set to 1 if DATDNE is working.
Done = 0;
MMC_ReadBlock(BlockAddr, ReadBlock, 0);
// if( TestFail = read_single_block( BlockAddr ))
// return(-1);
for( OpLoop=0; OpLoop<256; OpLoop++)
if( ReadBlock[OpLoop] != OpLoop+j+i)
ErrorCount++;
// if( ErrorCount )
// return( -1 );
BlockAddr += 512;
}
// if( TestFail = deselect_card( MmcAddr ))
// return(-1);
}
return( 0 );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -