sd_result_t SD_DMA_SingleBlockRead(SD_Card *card, sd_block_t addr, SD_Data_Block *data) {
    uint8_t result;
    uint8_t args[4];
    uint16_t i=0;

    if (card->State != SD_IDLE) {
        DBG_ERR_printf("SBR failed: Card not in idle state, state is 0x%02x", card->State);
        return SD_FAILED;
    }

    if (!card->SDHC) {
        addr = addr * card->BlockSize;
    }

    args[0] = (uint8_t)((addr >> 24) & 0xff);
    args[1] = (uint8_t)((addr >> 16) & 0xff);
    args[2] = (uint8_t)((addr >> 8) & 0xff);
    args[3] = (uint8_t)((addr >> 0) & 0xff);

    SD_SPI_Open(card);
    result = SD_SendCommand(card, SD_CMD_READ_SINGLE_BLOCK, args, 0x00);
    if (result != 0x00) {
        DBG_ERR_printf("SBR failed: Bad response to READ_SINGLE_BLOCK - got 0x%02x", result);

        SD_SPI_Terminate(card);
        SD_SPI_Close(card);

        return SD_PHY_ERR;
    }

    // wait for the start block token
    result = 0xff;
    while (result != SD_TOKEN_START_BLOCK && i < SD_BLOCK_TIMEOUT) {
        result = SD_SPI_Transfer(card, SD_DUMMY_BYTE);
        i++;
    }
    if (result != SD_TOKEN_START_BLOCK) {
        DBG_ERR_printf("SBR failed: Card did not send block, got 0x%02x", result);

        SD_SPI_Terminate(card);
        SD_SPI_Close(card);

        return SD_PHY_ERR;
    }

    data->StartOffset = 2;
    data->BlockLen = 514;
    SD_DMA_ReceiveBlock(card, data);

    SD_DMA_OnBlockRead();

    card->State = SD_DMA_SBR;
    card->SubState = 0;

    return SD_BUSY;
}
Beispiel #2
0
/**
 * Sends a command to the SD Card. This function blocks until the transmission is complete.
 * The R1 Response byte is returned. The calling function should check to make sure it is valid.
 * The calling function can continue requesting bytes from the SD card for some operations.
 *
 * @bug There is currently no timeout, so this function might enter an infinite loop.
 *
 * @param command Command to send, bits [45:40].
 * @param arg1 First byte of the arguments, bits [39:32].
 * @param arg2 Second byte of the arguments, bits [31:24].
 * @param arg3 Third byte of the arguments, bits [16:23].
 * @param arg4 Fourth byte of the arguments, bits [8:15].
 * @param crc The 7-bit CRC to be transmitted, shifted one bit to the left, bits [7:1].
 *
 * @return The first byte of the response, which should be the R1 response
 */
inline uint8_t SD_SPI_SendCommand(uint8_t command,
		uint8_t arg1, uint8_t arg2, uint8_t arg3, uint8_t arg4, uint8_t crc) {
	uint8_t response = 0xFF;
	uint16_t i = 0;

	SD_SPI_Transfer(0b01000000 | command);
	SD_SPI_Transfer(arg1);
	SD_SPI_Transfer(arg2);
	SD_SPI_Transfer(arg3);
	SD_SPI_Transfer(arg4);
	SD_SPI_Transfer(crc | 0b00000001);

	// NON-STANDARD: Empirically determined SanDisk SD Cards output 0b10111111 before command response for some reason
	while (response & 0x80 && i < SD_SPI_MAX_CMD_WAIT) {
		response = SD_SPI_Transfer(SD_SPI_DUMMY_BYTE);
		i++;
	}
	return response;
}
Beispiel #3
0
/**
 * Sends the required blocks before terminating a command
 */
inline void SD_SPI_Terminate() {
	SD_SPI_Transfer(SD_SPI_DUMMY_BYTE);
	SD_SPI_Transfer(SD_SPI_DUMMY_BYTE);
}