📄 mmc_x_hw.c
字号:
*
* Description:
* FS low level function. Be sure that your card slot si within the given
* voltage range. Return 1 if your slot can support the required voltage,
* and if not, return 0;
*
* Parameters:
* Unit - Device Index
* MaxFreq - SPI clock frequency in kHz
*
* Return value:
* 1 - the card slot supports the voltage range
* ==0 - the card slot does not support the voltage range
*/
char FS_MMC_HW_X_SetVoltage(FS_u8 Unit, FS_u16 Vmin, FS_u16 Vmax) {
/* voltage range check */
char r;
if((Vmin <= MMC_DEFAULTSUPPLYVOLTAGE) && (Vmax >= MMC_DEFAULTSUPPLYVOLTAGE)) {
r = 1;
} else {
r = 0;
}
return r;
}
/*********************************************************************
*
* FS_MMC_HW_X_IsPresent
*
* Description:
* Returns the state of the media. If you do not know the state, return
* FS_MEDIA_STATEUNKNOWN and the higher layer will try to figure out if
* a media is present.
*
* Parameters:
* Unit - Device Index
*
* Return value:
* FS_MEDIA_STATEUNKNOWN - the state of the media is unkown
* FS_MEDIA_ISNOTPRESENT - no card is present
* FS_MEDIA_ISPRESENT - a card is present
*/
char FS_MMC_HW_X_IsPresent(FS_u8 Unit) {
return FS_MEDIA_ISPRESENT ;
}
/*********************************************************************
*
* FS_MMC_HW_X_Read
*
* Description:
* FS low level function. Reads a specified number of bytes from MMC
* card to buffer.
*
* Parameters:
* Unit - Device Index
* pData - Pointer to a data buffer
* NumBytes - Number of bytes
*
* Return value:
* void
*/
void FS_MMC_HW_X_Read (FS_u8 Unit, FS_u8 * pData, int NumBytes) {
FS_u8 bpos;
FS_u8 c;
SPI_SET_DATAOUT();
do {
c = 0;
bpos = 8; /* get 8 bits */
do {
SPI_CLR_CLK();
SPI_DELAY();
c <<= 1;
if (SPI_DATAIN()) {
c |= 1;
}
SPI_SET_CLK();
SPI_DELAY();
} while (--bpos);
*pData++ = c;
} while (--NumBytes);
}
/*********************************************************************
*
* FS_MMC_HW_X_Write
*
* Description:
* FS low level function. Writes a specified number of bytes from
* data buffer to the MMC/SD card.
*
* Parameters:
* Unit - Device Index
* pData - Pointer to a data buffer
* NumBytes - Number of bytes
*
* Return value:
* void
*/
void FS_MMC_HW_X_Write(FS_u8 Unit, const FS_u8 * pData, int NumBytes) {
int i;
FS_u8 mask;
FS_u8 data;
for (i = 0; i < NumBytes; i++) {
data = pData[i];
mask = 0x80;
while (mask) {
if (data & mask) {
SPI_SET_DATAOUT();
} else {
SPI_CLR_DATAOUT();
}
SPI_CLR_CLK();
SPI_DELAY();
SPI_SET_CLK();
SPI_DELAY();
mask >>= 1;
}
}
SPI_SET_DATAOUT(); /* default state of data line is high */
}
/*********************************************************************
*
* FS_MMC_HW_X_Command(FS_u8 Unit,FS_u8 cmd,FS_u32 arg)
*/
FS_u8 FS_MMC_HW_X_Command(FS_u8 Unit,FS_u8 cmd,FS_u32 arg)
{
FS_u8 response=0;
FS_u8 temp[5];
FS_u8 i;
temp[0]=0x40 | cmd;
temp[1]=(arg >> 24) & 0xff;
temp[2]=(arg >> 16) & 0xff;
temp[3]=(arg >> 8 ) & 0xff;
temp[4]=(arg >> 0 ) & 0xff;
/* wait some clock cycles */
FS_MMC_HW_X_Read(Unit,&response,1);
/* send command via SPI */
FS_MMC_HW_X_Write(Unit,temp,5);
switch(cmd)
{
case CMD_GO_IDLE_STATE:
temp[0]=0x95;
FS_MMC_HW_X_Write(Unit,temp,1);
break;
case CMD_SEND_IF_COND:
temp[0]=0x87;
FS_MMC_HW_X_Write(Unit,temp,1);
break;
default:
temp[0]=0xff;
FS_MMC_HW_X_Write(Unit,temp,1);
break;
}
/*receive response */
for(i = 0; i < 10; ++i)
{
FS_MMC_HW_X_Read(Unit,&response,1);
if(response != 0xff) break;
}
return response;
}
/*********************************************************************
*
* FS_u8 FS_MMC_Init(FS_u8 Unit)
*/
FS_u8 FS_MMC_Init(FS_u8 Unit)
{
FS_u16 i;
FS_u8 response;
FS_u8 arg;
SPI_SET_CLK();
SPI_SET_DATAOUT();
FS_MMC_HW_X_DisableCS(Unit);
SPI_Delay_Count=400;
/* initialization procedure */
sd_raw_card_type = 0;
if(!FS_MMC_HW_X_IsPresent(Unit)) return 0;
/* card needs 74 cycles minimum to start up */
for(i = 0; i < 10; ++i)
{
/* wait 8 clock cycles */
FS_MMC_HW_X_Read(Unit,&response,1);
}
/* address card */
FS_MMC_HW_X_EnableCS(Unit);
/* reset card */
for(i = 0; ; ++i)
{
response =FS_MMC_HW_X_Command(Unit,CMD_GO_IDLE_STATE,0);
if(response == (1 << R1_IDLE_STATE)) break;
if(i == 0x1ff)
{
FS_MMC_HW_X_DisableCS(Unit);
return 0;
}
}
/* determine SD/MMC card type */
FS_MMC_HW_X_Command(Unit,CMD_APP, 0);
response = FS_MMC_HW_X_Command(Unit,CMD_SD_SEND_OP_COND, 0);
if((response & (1 << R1_ILL_COMMAND)) == 0)
{
/* card conforms to SD 1 card specification */
sd_raw_card_type |= (1 << SD_RAW_SPEC_1);
}
else{/* MMC card */}
/* wait for card to get ready */
for(i = 0; ; ++i)
{
if(sd_raw_card_type & ((1 << SD_RAW_SPEC_1) | (1 << SD_RAW_SPEC_2)))
{
arg = 0;
FS_MMC_HW_X_Command(Unit,CMD_APP, 0);
response = FS_MMC_HW_X_Command(Unit,CMD_SD_SEND_OP_COND, arg);
}
else
{
response = FS_MMC_HW_X_Command(Unit,CMD_SEND_OP_COND, 0);
}
if((response & (1 << R1_IDLE_STATE)) == 0)
break;
if(i == 0x7fff)
{
FS_MMC_HW_X_DisableCS(Unit);
return 0;
}
}
/* set block size to 512 bytes */
if(FS_MMC_HW_X_Command(Unit,CMD_SET_BLOCKLEN, 512))
{
FS_MMC_HW_X_DisableCS(Unit);
return 0;
}
/* deaddress card */
FS_MMC_HW_X_DisableCS(Unit);
SPI_Delay_Count=10;
return 1;
}
/*********************************************************************
*
* FS_u8 FS_MMC_Read(FS_u8 Unit,FS_u32 Sector, void *pBuffer)
*/
FS_u8 FS_MMC_Read(FS_u8 Unit,FS_u32 Sector, void *pBuffer)
{
FS_u8 response;
/* address card */
FS_MMC_HW_X_EnableCS(Unit);
/* send single block request */
if(FS_MMC_HW_X_Command(Unit,CMD_READ_SINGLE_BLOCK, Sector*512))
{
FS_MMC_HW_X_DisableCS(Unit);
return 0;
}
/* wait for data block (start byte 0xfe) */
while(response != 0xfe) FS_MMC_HW_X_Read(Unit,&response,1);
/* read byte block */
FS_MMC_HW_X_Read(Unit,pBuffer,512);
/* read crc16 */
FS_MMC_HW_X_Read(Unit,&response,1);
FS_MMC_HW_X_Read(Unit,&response,1);
/* deaddress card */
FS_MMC_HW_X_DisableCS(Unit);
/* let card some time to finish */
FS_MMC_HW_X_Read(Unit,&response,1);
return 1;
}
/*********************************************************************
*
* FS_u8 FS_MMC_Write(FS_u8 Unit,FS_u32 Sector, void *pBuffer)
*/
FS_u8 FS_MMC_Write(FS_u8 Unit,FS_u32 Sector, void *pBuffer)
{
FS_u8 temp;
FS_u8 response=0;
/* address card */
FS_MMC_HW_X_EnableCS(Unit);
/* send single block request */
if(FS_MMC_HW_X_Command(Unit,CMD_WRITE_SINGLE_BLOCK,Sector*512))
{
FS_MMC_HW_X_DisableCS(Unit);
return 0;
}
/* send start byte */
temp=0xfe;
FS_MMC_HW_X_Write(Unit,&temp,1);
/* write byte block */
FS_MMC_HW_X_Write(Unit,pBuffer,512);
/* write dummy crc16 */
temp=0xff;
FS_MMC_HW_X_Write(Unit,&temp,1);
FS_MMC_HW_X_Write(Unit,&temp,1);
/* wait while card is busy */
while(response != 0xff) FS_MMC_HW_X_Read(Unit,&response,1);
FS_MMC_HW_X_Read(Unit,&response,1);
/* deaddress card */
FS_MMC_HW_X_DisableCS(Unit);
return 1;
}
#endif /* FS_USE_MMC_DRIVER */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -