📄 sdmmc.c
字号:
// Simply turn off the card
//
void ShutdownMedia(void)
{
// close the spi bus
CloseSPI();
// deselect the device
CS_HIGH;
// Turn off the card
//MMC_OFF;
}
/******************************************************************************
* Function: void SendMMCCmd(BYTE cmd, DWORD address)
*
*
* Input: None
*
* Output: response - Response from the card
* - 0x00 or 0x01 Command received
* successfully, else, command failed
* -Bit 0 - In idle state if 1
* -Bit 1 - Erase Reset if 1
* -Bit 2 - Illgal Command if 1
* -Bit 3 - Com CRC Error if 1
* -Bit 4 - Erase Sequence Error if 1
* -Bit 5 - Address Error if 1
* -Bit 6 - Parameter Error if 1
* -Bit 7 - Not used, always '0'
*
* Side Effects: None
*
* Overview: SendMMCCmd prepares the command packet and sends it out
* over the SPI interface. Response data of type 'R1' (see
* SD or MMC product manuals) is returned.
*
* Note: MMC_CS is not set at the end of this function.
* if the command has no data stage, call macro
* mSendMediaCmd_NoData(), it reasserts MMC_CS to 1.
* If the command has a data stage, MMC_CS must be
* reasserted after the data transfer stage is complete.
* See SECTORread and SECTORwrite for examples.
*****************************************************************************/
MMC_RESPONSE SendMMCCmd(BYTE cmd, DWORD address)
{
int timeout = 8;
char index;
MMC_RESPONSE response;
CMD_PACKET CmdPacket;
// memset(&response,0,sizeof(SD_RESPONSE));
CS_LOW; //Card Select
WriteSPI(0xFF); // delay 8 spi clock
// Copy over data
CmdPacket.cmd = sdmmc_cmdtable[cmd].CmdCode;
CmdPacket.address = address;
CmdPacket.crc = sdmmc_cmdtable[cmd].CRC; // Calc CRC here
CmdPacket.TRANSMIT_BIT = 1; //Set Tranmission bit
WriteSPI(0x40|CmdPacket.cmd); //Send Command
WriteSPI(CmdPacket.addr3); //Most Significant Byte
WriteSPI(CmdPacket.addr2);
WriteSPI(CmdPacket.addr1);
WriteSPI(CmdPacket.addr0); //Least Significant Byte
WriteSPI(CmdPacket.crc); //Send CRC
// see if we are going to get a response
if(sdmmc_cmdtable[cmd].responsetype == R1 || sdmmc_cmdtable[cmd].responsetype == R1b)
{
do
{
response.r1._byte = SPI_RecByte();
timeout--;
}while(((response.r1._byte & 0x80)!= 0x00) &&( timeout != 0));
}
else if(sdmmc_cmdtable[cmd].responsetype == R2)
{
SPI_RecByte();
response.r2._byte1 = SPI_RecByte();
response.r2._byte0 = SPI_RecByte();
}
if(sdmmc_cmdtable[cmd].responsetype == R1b)
{
response.r1._byte = 0x00;
for(index =0; index < 0xFF && response.r1._byte == 0x00; index++)
{
timeout = 0xFFFF;
do
{
response.r1._byte = SPI_RecByte();
timeout--;
}while(response.r1._byte == 0x00 && timeout != 0);
}
}
WriteSPI(0xff); //Required clocking (see spec)
// see if we are expecting data or not
if(!(sdmmc_cmdtable[cmd].moredataexpected))
{
CS_HIGH;
}
return(response);
}
/******************************************************************************
* Function: BYTE SECTORread(DWORD sector_addr, BYTE *buffer)
*
* PreCondition: None
*
* Input: sector_addr - Sector address, each sector contains 512-byte
* buffer - Buffer where data will be stored, see
* 'ram_acs.h' for 'block' definition.
* 'Block' is dependent on whether internal or
* external memory is used
*
* Output: See MMC_Error.
*
* Side Effects: None
*
* Overview: SECTORread reads 512 bytes of data from the card starting
* at the sector address specified by sector_addr and stores
* them in the location pointed to by 'buffer'.
*
* Note: The card expects the address field in the command packet
* to be byte address. Therefore the sector_addr must first
* be converted to byte address. This is accomplished by
* shifting the address left 9 times.
*****************************************************************************/
BYTE SECTORread(DWORD sector_addr, BYTE* buffer)
{
WORD index;
MMC_RESPONSE response;
BYTE data_token;
BYTE status = TRUE;
DWORD new_addr;
#ifdef STATUSLED
STTRIS = OUTPUT;
STLED = 1;
#endif
// send the cmd
new_addr = sector_addr << SECTOR_SHIFT_BITS;
response = SendMMCCmd(READ_SINGLE_BLOCK,new_addr);
// Make sure the command was accepted
if(response.r1._byte != 0x00)
{
response = SendMMCCmd(READ_SINGLE_BLOCK,new_addr);
if(response.r1._byte != 0x00)
status = FALSE;
}
else
{
index = 0x2FF;
//Now, must wait for the start token of data block
do
{
data_token = ReadMedia();
index--;
}while((data_token == MMC_FLOATING_BUS) && (index != 0));
// Hopefully that zero is the datatoken
if((index == 0) || (data_token != DATA_START_TOKEN))
{
//status = FALSE;
new_addr = sector_addr <<SECTOR_SHIFT_BITS;
response = SendMMCCmd(READ_SINGLE_BLOCK,new_addr);
index = 0x2FF;
//Now, must wait for the start token of data block
do
{
data_token = ReadMedia();
index--;
}while((data_token == MMC_FLOATING_BUS) && (index != 0));
if((index == 0) || (data_token != DATA_START_TOKEN))
{
status = FALSE;
}
else
{
goto here;
}
}
else
{
here:
for(index = 0; index < MEDIA_SECTOR_SIZE; index++) //Reads in 512-byte of data
{
buffer[index] = ReadMedia();
#ifdef DEBUG_SDMMC
U8toHexString(buffer[index],string);
if((index % 0x10) == 0x00)
DEBUG_PRINT("\n\r");
DEBUG_PRINT_RAM((char*)string);
DEBUG_PRINT(" ");
#endif
}
// Now ensure CRC
mReadCRC(); //Read 2 bytes of CRC
//status = mmcCardCRCError;
}
mSend8ClkCycles(); //Required clocking (see spec)
}
CS_HIGH;
#ifdef STATUSLED
STLED = 0;
#endif
return(status);
}//end SECTORread
/******************************************************************************
* Function: BYTE SECTORwrite(DWORD sector_addr, BYTE *buffer)
*
* PreCondition: None
*
* Input: sector_addr - Sector address, each sector contains 512-byte
* buffer - Buffer where data will be read, see
* 'ram_acs.h' for 'block' definition.
* 'Block' is dependent on whether internal or
* external memory is used
*
* Output: See MMC_Error.
*
* Side Effects: None
*
* Overview: SECTORwrite sends 512 bytes of data from the location
* pointed to by 'buffer' to the card starting
* at the sector address specified by sector_addr.
*
* Note: The card expects the address field in the command packet
* to be byte address. Therefore the sector_addr must first
* be converted to byte address. This is accomplished by
* shifting the address left 9 times.
*****************************************************************************/
BYTE SECTORwrite(DWORD sector_addr, BYTE* buffer)
{
WORD index;
BYTE data_response;
MMC_RESPONSE response;
BYTE status = TRUE;
#ifdef STATUSLED
STTRIS = OUTPUT;
STLED = 1;
#endif
if (sector_addr == 0)
status = FALSE;
else
{
// send the cmd
response = SendMMCCmd(WRITE_SINGLE_BLOCK,(sector_addr << SECTOR_SHIFT_BITS));
// see if it was accepted
if(response.r1._byte != 0x00)
status = FALSE;
else
{
//Send data start token
WriteSPI(DATA_START_TOKEN);
for(index = 0; index < 512; index++) //Send 512 bytes of dat
WriteSPI(buffer[index]);
// calc crc
mSendCRC(); //Send 2 bytes of CRC
data_response = ReadMedia(); //Read response
if((data_response & 0x0F) != DATA_ACCEPTED)
{
status = FALSE;
}
else
{
index = 0; //using i as a timeout counter
do //Wait for write completion
{
data_response = ReadMedia();
index++;
}while((data_response == 0x00) && (index != 0));
if(index == 0) //if timeout first
status = FALSE;
}
mSend8ClkCycles();
}
CS_HIGH;
#ifdef STATUSLED
STLED = 0;
#endif
} // Not writing to 0 sector
return(status);
} //end SECTORwrite
/*****************************************************************
Return the state of the WP Pin
*****************************************************************/
BYTE WriteProtectState(void)
{
// return(SD_WE);
return 0;
}
void Delayms(BYTE milliseconds)
{
BYTE ms;
DWORD count;
ms = milliseconds;
while (ms--)
{
count = ((SYSTEM_CLOCK / 28) / 1000) - 5;
while (count--)
{
;
}
}
return;
}
/******************************************************************************
* Function: BYTE ReadMedia(void)
*
* PreCondition: None
*
* Input: None
*
* Output: BYTE - One byte of data read in from SPI port
*
* Side Effects: None
*
* Overview: ReadMedia reads in one byte of data while sending out 0xFF
*
* Note: Could not use ReadSPI because it initializes SSPBUF to
* 0x00. The card expects 0xFF (see spec).
*****************************************************************************/
BYTE ReadMedia(void)
{
SPI1BUF = 0xFF; //Data Out - Logic ones
while(!SPI1STATbits.SPIRBF); //Wait until cycle complete
return(SPI1BUF); //Return with byte read
}//end ReadMedia
/******************************************************************************
* Function: BYTE StartupCard(DISK *dsk, CARDSTATUS *CardStatus)
*
* PreCondition: SocketInitialize called
*
* Input: dsk - Disk to be mounted
*
* Output: CE_GOOD - Disk set up successfully
* CE_NOT_PRESENT - Card not inserted
*
* Side Effects: None
*
* Overview: Startup the SDMMC Card
*
* Note: None
*****************************************************************************/
BYTE StartupCard(DISK *dsk, CARDSTATUS *CardStatus)
{
CETYPE error;
MMCSTATE Flag;
BYTE * buffer = gblSDMMCBuf;
CardStatus->_word = 0x00;
CardStatus->CS_Reset = TRUE;
if((error = DISKmount( dsk, buffer, &Flag)) == CE_GOOD)
{
CardStatus->CS_Inserted = TRUE;
//set the type and write protect stuff
CardStatus->CS_SDMMC = ((Flag.isSDMMC) ? TRUE : FALSE);
CardStatus->CS_WP = ((Flag.isWP) ? TRUE : FALSE);
}
else
{
// there was an issue so turn off the card
StopCard(dsk, CardStatus);
CardStatus->CS_Failure = TRUE;
}
return(error);
}
/******************************************************************************
* Function: BYTE DISKmount ( DISK *dsk, BYTE* b, MMCSTATE *Flag)
*
* PreCondition: SocketInitialize function has been executed.
*
* Input: dsk - The disk to be mounted
* b - The buffer of to be assigned to the disk
* Flag - Flag structure of card conditions
*
* Output: CE_GOOD - Disk mounted
* CE_INIT_ERROR - Initialization error has occured
*
* Side Effects: None
*
* Overview: Will mount only the first partition on the disk/card
*
* Note: None
*****************************************************************************/
BYTE DISKmount( DISK *dsk, BYTE* b, MMCSTATE *Flag)
{
BYTE error = CE_GOOD;
dsk->mount = FALSE; // default invalid
dsk->buffer = b; // assign buffer
// Initialize the sdmmc card
if(MediaInitialize() != TRUE)
{
error = CE_INIT_ERROR;
}
else
{
// Load the Master Boot Record (partition)
error = LoadMBR(dsk);
if((error) == CE_GOOD)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -