📄 mmc.c
字号:
{
// SS = LOW (on)
CS_LOW();
// send write command
mmcSendCmd( 24 , address , 0xFF );
// check if the MMC acknowledged the write block command
// it will do this by sending an affirmative response
// in the R1 format (0x00 is no errors)
// UART_PutString(UART0,"set write block length\n");//add by chang
if ( mmcGetXXResponse( MMC_R1_RESPONSE ) == MMC_R1_RESPONSE )
{
// UART_PutString(UART0,"write signal block\n");//add by chang
spiSendByte( 0xff );
// send the data token to signify the start of the data
spiSendByte( 0xfe );
// clock the actual data transfer and transmitt the bytes
for ( i = 0; i < 512; i++ )
spiSendByte( mmc_buffer[i] ); // mmc_buffer[i]; Test: i & 0xff
// put CRC bytes (not really needed by us, but required by MMC)
spiSendByte( 0xff );
spiSendByte( 0xff );
// read the data response xxx0<status>1 : status 010: Data accected, status 101: Data
// rejected due to a crc error, status 110: Data rejected due to a Write error.
mmcCheckBusy();
}
else
{
// the MMC never acknowledge the write command
rvalue = MMC_RESPONSE_ERROR; // 2
}
rvalue = MMC_SUCCESS;
}
else
{
rvalue = MMC_BLOCK_SET_ERROR; // 1
}
//give the MMC the required clocks to finish up what ever it needs to do
//for (i = 0; i < 9; ++i)
//spiSendByte(0xff);
CS_HIGH();
// Uart_Printf("rvalue=%d\n",rvalue);
// Send 8 Clock pulses of delay.
spiSendByte( 0xff );
return rvalue;
}// mmc_write_block
//---------------------------------------------------------------------
void mmcSendCmd( const char cmd , unsigned long data , const char crc )
{
char frame[6];
char temp;
int i;
frame[0] = ( cmd | 0x40 );
for ( i = 3; i >= 0; i-- )
{
temp = ( char ) ( data >> ( 8 * i ) );
frame[4 - i] = ( temp );
}
frame[5] = ( crc );
for ( i = 0; i < 6; i++ )
spiSendByte( frame[i] );
}
//--------------- set blocklength 2^n ------------------------------------------------------
// Ti Modification: long int-> long
char mmcSetBlockLength( const unsigned long blocklength )
{
//char rValue = MMC_TIMEOUT_ERROR;
//char i = 0;
// SS = LOW (on)
CS_LOW();
// Set the block length to read
//MMC_SET_BLOCKLEN =CMD16
mmcSendCmd( 16 , blocklength , 0xFF );
// get response from MMC - make sure that its 0x00 (R1 ok response format)
if ( mmcGetResponse() != 0x00 )
{
//UART_PutString(UART0,"not set \n");
return 0xff;
}
CS_HIGH();
// Send 8 Clock pulses of delay.
spiSendByte( 0xff );
spiSendByte( 0xff );
return MMC_SUCCESS;
}
unsigned char spiSendByte( const unsigned char data )
{
/*
unsigned char spib;
//while(SSIOST_bit.BUSY != 0); // Wait until the character can be sent
SSIOINT_bit.TXCMP = 1; //clear interrupt register
SSIOBUF = data; // Send the data
while((SSIOINT & 0x02) != 0x02); // Wait for the transfer to complete
spib = SSIOBUF; // Get the data received
SSIOINT_bit.RXCMP = 1; //clear interrupt register
return spib; //return transmited character
*/
//NOTE!!! This function send character to SPI bus when mode is MASTER
//NOTE!!! This function receive character from SPI when mode is SLAVE
unsigned int spib;
//while(SSPSR_bit.BSY); // Wait until the character can be sent
while ( SSPSR_bit.TNF == 0 );
SSPDR = data; // Send the data
//while(!SPSR0_bit.SPIF); // Wait for the transfer to complete
while ( SSPSR_bit.RNE == 0 ); // Wait until the character can be sent
spib = SSPDR; // Get the data received
return spib;
//return 0;
}
void spiWriteByte( const unsigned char data )
{
//while(SSIOST_bit.BUSY != 0); // Wait until the character can be sent
//SSIOINT_bit.TXCMP = 1; // clear interrupt register
//SSIOBUF = data;
}
unsigned char spiReadByte()
{
//unsigned char spib;
//while(SSIOINT_bit.RXCMP == 0);
//spib = SSIOBUF; // Get the data received
//SSIOINT_bit.RXCMP = 1; //clear interrupt register
//return spib;
return 0;
}
// Reading the contents of the CSD and CID registers in SPI mode is a simple
// read-block transaction.
char mmcReadRegister( const char cmd_register , const unsigned char length )
{
char uc = 0;
char rvalue = MMC_TIMEOUT_ERROR;
// char i = 0;
if ( mmcSetBlockLength( length ) == MMC_SUCCESS )
{
CS_LOW();
// CRC not used: 0xff as last byte
mmcSendCmd( cmd_register , 0x000000 , 0xff );
// wait for response
// in the R1 format (0x00 is no errors)
if ( mmcGetResponse() == 0x00 )
{
//UART_PutString(UART0,"set MMC BlockLength ok\n");
if ( mmcGetXXResponse( 0xfe ) == 0xfe )
{
//UART_PutString( UART0 , "\nread register\n" );//add by chang
for ( uc = 0; uc < length; uc++ )
mmc_buffer[uc] = spiSendByte( 0xff );
}
// get CRC bytes (not really needed by us, but required by MMC)
//add chang guo feng
rvalue = 0x00;
spiSendByte( 0xff );
spiSendByte( 0xff );
}
else
rvalue = MMC_RESPONSE_ERROR;
// CS = HIGH (off)
// CS_HIGH ();
// Send 8 Clock pulses of delay.
spiSendByte( 0xff );
// CS_HIGH ();
}
CS_HIGH();
return rvalue;
}// mmc_read_register
/************************************************************************************
**Function:MMC_Test
**autor:chang guofeng
*************************************************************************************/
void MMC_Test( void )
{
int err;
int i;//,j;
int block_len, block_num, tmp;
unsigned char ret;//,csdbuf[16];
PINSEL0 = PINSEL0 & (~(0x3<<8)) ; //P0.4,GPIO(sck0)
IO0DIR = IO0DIR | 0x1<<4 ; //output
err = initMMC();
if ( err == 0 )
UART_PutStringByPolling( UART0 , "\nInit MMC OK\n" );
else
UART_PutStringByPolling( UART0 , "\nInit MMC error\n" );
// Uart_Printf("MMC Test\n");
ret = mmcReadRegister( MMC_READ_CSD , 16 );
if ( ret != 0 )
{
UART_PutStringByPolling( UART0 , "Get Card info error\n" );
return;
}
IO0CLR = IO0CLR | 0x1 << 4; //Clear P0.4,0
///* 计算块的最大长度 */ /* calculate the size of a sector */
block_len = 1 << ( mmc_buffer[READ_BL_LEN_POS] & READ_BL_LEN_MSK ); ///* (2 ^ READ_BL_LEN) */
///* 计算卡中块的个数 */ /* calculate the sector numbers of the SD Card */
block_num = ( ( mmc_buffer[C_SIZE_POS1] & C_SIZE_MSK1 ) << 10 ) +
( mmc_buffer[C_SIZE_POS2] << 2 ) +
( ( mmc_buffer[C_SIZE_POS3] & C_SIZE_MSK3 ) >> 6 ) +
1; /* (C_SIZE + 1)*/
tmp = ( ( mmc_buffer[C_SIZE_MULT_POS1] & C_SIZE_MULT_MSK1 ) << 1 ) +
( ( mmc_buffer[C_SIZE_MULT_POS2] & C_SIZE_MULT_MSK2 ) >> 7 ) +
2; /* (C_SIZE_MULT + 2) */
/* 获得卡中块的数量 */ /* get the block numbers in card */
block_num = block_num * ( 1 << tmp ); /* (C_SIZE + 1) * 2 ^ (C_SIZE_MULT + 2) */
/* 计算擦除的单位(单位: 块) */
tmp = ( ( mmc_buffer[ERASE_GRP_SIZE_POS] & ERASE_GRP_SIZE_MSK ) >> 2 ) + 1; /* (ERASE_GRP_SIZE + 1) */
/* (ERASE_GRP_SIZE + 1) * (ERASE_GRP_MULTI + 1) */
tmp *= ( ( mmc_buffer[ERASE_GRP_MULTI_POS1] & ERASE_GRP_MULTI_MSK1 ) << 3 ) +
( ( mmc_buffer[ERASE_GRP_MULTI_POS2] & ERASE_GRP_MULTI_MSK2 ) >> 5 ) +
1;
/* MMC: SECTOR_SIZE */
UART_PutStringByPolling( UART0 , "MMC Card Info:\n" );
Uart_Printf( UART0, " Max Bock Length : %dbyte\n" , block_len );
Uart_Printf( UART0, " Bock Number : %d\n" , block_num );
Uart_Printf( UART0, " Size : %dM\n" , tmp );
for ( i = 0; i < 512; i++ )
mmc_buffer[i] = 5;
// for(i=0;i<=4;i++)
//{
// for(j=0;j<16;j++)
// Uart_Printf(" %02u ",mmc_buffer[i*16+j]);
// Uart_Printf("\n");
// }
UART_PutStringByPolling( UART0 , "\nWrite a block\n" );
if ( mmcWriteBlock( 0x0 ) != 0 )
{
UART_PutStringByPolling( UART0 , " Write error\n" );
return;
}
UART_PutStringByPolling( UART0 , " Write OK\n" );
for ( i = 0; i < 512; i++ )
mmc_buffer[i] = 0; //clear mmc_buffer
UART_PutStringByPolling( UART0 , "\nRead a Block\n" );
if ( mmcReadBlock( 0x0 , 512 ) != 0 )
{
UART_PutStringByPolling( UART0 , " Read error\n" );
return;
}
UART_PutStringByPolling( UART0 , " Read OK\n" );
for ( i = 0; i < 512; i++ )
{
if ( mmc_buffer[i] != 5 )
{
UART_PutStringByPolling( UART0 , "\n Data compare is error\n" );
return ;
}
//else
//UART_PutStringByPolling( UART0 , "\n Data compare is OK\n" );
}
UART_PutStringByPolling( UART0 , "\nRead and write is OK\n" );
}
//---------------------------------------------------------------------
#endif /* _MMCLIB_C */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -