/**
* @brief Send 6 bytes command to the SD card.
* @param Cmd: The command send to SD card.
* @param argument: The command argument.
* @param response_type: the SPI command response type.
* @param *response: the SPI response returned.
* @retval The SD Response.
*/
uint8_t ARC_sd_send_command(uint8_t cmd, uint32_t argument,
SD_Response response_type, uint8_t *response)
{
int32_t i = 0;
uint8_t crc = 0x01;
int8_t response_length = 0;
uint8_t tmp;
uint8_t Frame[6];
if (cmd & 0x80) /* Send a CMD55 prior to ACMD<n> */
{
cmd &= 0x7F;
ARC_sd_send_command(SD_CMD_APP_CMD, 0, R1, response);
if (response[0] > 0x1)
{
ARC_SD_CS_HIGH();
ARC_SPI_SendByte(SPI1, SD_DUMMY_BYTE);
return response[0];
}
}
ARC_SD_CS_LOW();
if(cmd == SD_CMD_GO_IDLE_STATE)
crc = 0x95;
if(cmd == SD_CMD_SEND_IF_COND)
crc = 0x87;
/* All data is sent MSB first, and MSb first */
/* cmd Format:
cmd[7:6] : 01
cmd[5:0] : command */
Frame[0] = ((cmd & 0x3F) | 0x40); /*!< Construct byte 1 */
Frame[1] = (uint8_t)(argument >> 24); /*!< Construct byte 2 */
Frame[2] = (uint8_t)(argument >> 16); /*!< Construct byte 3 */
Frame[3] = (uint8_t)(argument >> 8); /*!< Construct byte 4 */
Frame[4] = (uint8_t)(argument); /*!< Construct byte 5 */
Frame[5] = (uint8_t)(crc); /*!< Construct CRC: byte 6 */
for (i = 0; i < 6; i++)
{
ARC_SPI_SendByte(SPI1, Frame[i]); /*!< Send the Cmd bytes */
}
switch (response_type)
{
case R1:
case R1B:
response_length = 1;
break;
case R2:
response_length = 2;
break;
case R3:
case R7:
response_length = 5;
break;
default:
break;
}
/* Wait for a response. A response can be recognized by the start bit (a zero) */
i = 0xFF;
do
{
tmp = ARC_SPI_SendByte(SPI1, SD_DUMMY_BYTE);
}while ((tmp & 0x80) && --i);
response[0] = tmp;
/* Just bail if we never got a response */
if (i == 0)
{
ARC_SD_CS_HIGH();
ARC_SPI_SendByte(SPI1, SD_DUMMY_BYTE);
return response[0];
}
if((response[0] & SD_ILLEGAL_COMMAND) == SD_ILLEGAL_COMMAND)
{
ARC_SD_CS_HIGH();
ARC_SPI_SendByte(SPI1, SD_DUMMY_BYTE);
return response[0];
}
i = 1;
while(i < response_length)
{
tmp = ARC_SPI_SendByte(SPI1, SD_DUMMY_BYTE);
response[i] = tmp;
i++;
}
/* If the response is a "busy" type (R1B), then there's some
* special handling that needs to be done. The card will
* output a continuous stream of zeros, so the end of the BUSY
* state is signaled by any nonzero response. The bus idles
* high.
*/
if (response_type == R1B)
{
do
{
tmp = ARC_SPI_SendByte(SPI1, SD_DUMMY_BYTE);;
}while (tmp != 0xFF);
ARC_SPI_SendByte(SPI1, SD_DUMMY_BYTE);
}