#include "sd_mmc_spi.h" #include "assert.h" static sd_mmc_spi_errno_t sd_mmc_spi_err; static uint8_t spi_m_sync_crc7(uint8_t * buf, uint8_t size) { uint8_t crc, value, i; crc = 0; while (size--) { value = *buf++; for (i = 0; i < 8; i++) { crc <<= 1; if ((value & 0x80) ^ (crc & 0x80)) { crc ^= 0x09; } value <<= 1; } } crc = (crc << 1) | 1; return crc; } bool spi_m_sync_send_cmd(struct spi_m_sync_descriptor* spi, uint32_t cmd, uint32_t arg) { return spi_m_sync_adtc_start(spi, cmd, arg, 0, 0, false); } bool spi_m_sync_adtc_start(struct spi_m_sync_descriptor* spi, uint32_t cmd, uint32_t arg, uint16_t block_size, uint16_t nb_block, bool access_block) { uint8_t dummy = 0xFF; uint8_t cmd_token[6]; uint8_t ncr_timeout; uint8_t r1; uint16_t dummy2 = 0xFF; (void)access_block; assert(cmd & SDMMC_RESP_PRESENT); sd_mmc_spi_err = SD_MMC_SPI_NO_ERR; cmd_token[0] = SPI_CMD_ENCODE(SDMMC_CMD_GET_INDEX(cmd)); cmd_token[1] = arg >> 24; cmd_token[2] = arg >> 16; cmd_token[3] = arg >> 8; cmd_token[4] = arg; cmd_token[5] = spi_m_sync_crc7(cmd_token, 5); // 8 cycles to respect Ncs timing spi_m_sync_io_write(spi, &dummy, 1); // send command spi_m_sync_io_write(spi, cmd_token, sizeof(cmd_token)); // Wait for response // Two retries will be done to manage the Ncr timing between command and response // Ncr: Min. 1x8 clock cycle, Max 8x8 clock cycles // WORKAROUND for no compliance (Atmel Internal ref. SD13) r1 = 0xFF; // Ignore first byte because Ncr min. = 8 clock cycles spi_m_sync_io_write(spi, &dummy, 1); spi_m_sync_io_read(spi, &r1, 1); ncr_timeout = 7; while(1) { spi_m_sync_io_write(spi, &dummy, 1); spi_m_sync_io_read(spi, &r1, 1); if((r1 & R1_SPI_ERROR) == 0) { // Valid response break; } if(--ncr_timeout == 0) { } } return true; } bool spi_m_sync_start_read_blocks(struct spi_m_sync_descriptor* spi, void *dst, uint16_t nb_block) { return true; } bool spi_m_sync_start_write_blocks(struct spi_m_sync_descriptor* spi, const void *src, uint16_t nb_block) { return true; } bool spi_m_sync_wait_end_of_write_blocks(struct spi_m_sync_descriptor* spi) { return true; } bool spi_m_sync_wait_end_of_read_blocks(struct spi_m_sync_descriptor* spi) { return true; } bool spi_m_sync_write_word(struct spi_m_sync_descriptor* spi, uint32_t value) { return true; } bool spi_m_sync_read_word(struct spi_m_sync_descriptor* spi, uint32_t* value) { return true; } uint32_t spi_m_sync_get_response(struct spi_m_sync_descriptor* spi) { return 0; } void spi_m_sync_send_clock(struct spi_m_sync_descriptor* spi) {} int32_t spi_m_sync_select_device(struct spi_m_sync_descriptor* spi, uint8_t slot, uint32_t clock, uint8_t bus_width, bool high_speed) { return 0; } int32_t spi_m_sync_deselect_device(struct spi_m_sync_descriptor* spi, uint8_t slot) { return 0; }