sdmmc: don’t flip word order in MMC_RSP_BITS

MMC_RSP_BITS helper function had a hack that it flipped word order in
the response, assuming that response size is 4 words. This hack does not
work for responses which are not 4 words long (such as the SWITCH_FUNC
response, which is 64 words long).

This change removes the hack and the matching word order reversal code
in sdmmc driver.
This commit is contained in:
Ivan Grokhotkov 2017-07-12 19:44:17 +08:00
parent 159a2d01d1
commit e6258ac6cb
4 changed files with 54 additions and 16 deletions

View file

@ -304,13 +304,38 @@
#define SD_ACCESS_MODE_SDR104 3
#define SD_ACCESS_MODE_DDR50 4
/**
* @brief Extract up to 32 sequential bits from an array of 32-bit words
*
* Bits within the word are numbered in the increasing order from LSB to MSB.
*
* As an example, consider 2 32-bit words:
*
* 0x01234567 0x89abcdef
*
* On a little-endian system, the bytes are stored in memory as follows:
*
* 67 45 23 01 ef cd ab 89
*
* MMC_RSP_BITS will extact bits as follows:
*
* start=0 len=4 -> result=0x00000007
* start=0 len=12 -> result=0x00000567
* start=28 len=8 -> result=0x000000f0
* start=59 len=5 -> result=0x00000011
*
* @param src array of words to extract bits from
* @param start index of the first bit to extract
* @param len number of bits to extract, 1 to 32
* @return 32-bit word where requested bits start from LSB
*/
static inline uint32_t MMC_RSP_BITS(uint32_t *src, int start, int len)
{
uint32_t mask = (len % 32 == 0) ? UINT_MAX : UINT_MAX >> (32 - (len % 32));
size_t word = 3 - start / 32;
size_t word = start / 32;
size_t shift = start % 32;
uint32_t right = src[word] >> shift;
uint32_t left = (len + shift <= 32) ? 0 : src[word - 1] << ((32 - shift) % 32);
uint32_t left = (len + shift <= 32) ? 0 : src[word + 1] << ((32 - shift) % 32);
return (left | right) & mask;
}

View file

@ -261,11 +261,8 @@ static void process_command_response(uint32_t status, sdmmc_command_t* cmd)
{
if (cmd->flags & SCF_RSP_PRESENT) {
if (cmd->flags & SCF_RSP_136) {
cmd->response[3] = SDMMC.resp[0];
cmd->response[2] = SDMMC.resp[1];
cmd->response[1] = SDMMC.resp[2];
cmd->response[0] = SDMMC.resp[3];
/* Destination is 4-byte aligned, can memcopy from peripheral registers */
memcpy(cmd->response, (uint32_t*) SDMMC.resp, 4 * sizeof(uint32_t));
} else {
cmd->response[0] = SDMMC.resp[0];
cmd->response[1] = 0;

View file

@ -51,7 +51,7 @@ static esp_err_t sdmmc_send_cmd_stop_transmission(sdmmc_card_t* card, uint32_t*
static esp_err_t sdmmc_send_cmd_send_status(sdmmc_card_t* card, uint32_t* out_status);
static esp_err_t sdmmc_send_cmd_crc_on_off(sdmmc_card_t* card, bool crc_enable);
static uint32_t get_host_ocr(float voltage);
static void response_ntoh(sdmmc_response_t response);
static void flip_byte_order(uint32_t* response, size_t size);
static esp_err_t sdmmc_write_sectors_dma(sdmmc_card_t* card, const void* src,
size_t start_block, size_t block_count);
static esp_err_t sdmmc_read_sectors_dma(sdmmc_card_t* card, void* dst,
@ -419,7 +419,7 @@ static esp_err_t sdmmc_send_cmd_send_cid(sdmmc_card_t *card, sdmmc_cid_t *out_ci
if (err != ESP_OK) {
return err;
}
response_ntoh(buf);
flip_byte_order(buf, sizeof(buf));
return sdmmc_decode_cid(buf, out_cid);
}
@ -501,10 +501,12 @@ static esp_err_t sdmmc_send_cmd_send_csd(sdmmc_card_t* card, sdmmc_csd_t* out_cs
if (err != ESP_OK) {
return err;
}
uint32_t* ptr = cmd.response;
if (is_spi) {
response_ntoh(spi_buf);
flip_byte_order(spi_buf, sizeof(spi_buf));
ptr = spi_buf;
}
return sdmmc_decode_csd(is_spi ? spi_buf : cmd.response, out_csd);
return sdmmc_decode_csd(ptr, out_csd);
}
static esp_err_t sdmmc_send_cmd_select_card(sdmmc_card_t* card)
@ -520,8 +522,8 @@ static esp_err_t sdmmc_send_cmd_select_card(sdmmc_card_t* card)
static esp_err_t sdmmc_decode_scr(uint32_t *raw_scr, sdmmc_scr_t* out_scr)
{
sdmmc_response_t resp = {0xabababab, 0xabababab, 0x12345678, 0x09abcdef};
resp[2] = __builtin_bswap32(raw_scr[0]);
resp[3] = __builtin_bswap32(raw_scr[1]);
resp[1] = __builtin_bswap32(raw_scr[0]);
resp[0] = __builtin_bswap32(raw_scr[1]);
int ver = SCR_STRUCTURE(resp);
if (ver != 0) {
return ESP_ERR_NOT_SUPPORTED;
@ -597,10 +599,15 @@ static uint32_t get_host_ocr(float voltage)
return SD_OCR_VOL_MASK;
}
static void response_ntoh(sdmmc_response_t response)
static void flip_byte_order(uint32_t* response, size_t size)
{
for (int i = 0; i < 4; ++i) {
response[i] = __builtin_bswap32(response[i]);
assert(size % (2 * sizeof(uint32_t)) == 0);
const size_t n_words = size / sizeof(uint32_t);
for (int i = 0; i < n_words / 2; ++i) {
uint32_t left = __builtin_bswap32(response[i]);
uint32_t right = __builtin_bswap32(response[n_words - i - 1]);
response[i] = right;
response[n_words - i - 1] = left;
}
}

View file

@ -26,6 +26,15 @@
#include <time.h>
#include <sys/time.h>
TEST_CASE("MMC_RSP_BITS", "[sd]")
{
uint32_t data[2] = { 0x01234567, 0x89abcdef };
TEST_ASSERT_EQUAL_HEX32(0x7, MMC_RSP_BITS(data, 0, 4));
TEST_ASSERT_EQUAL_HEX32(0x567, MMC_RSP_BITS(data, 0, 12));
TEST_ASSERT_EQUAL_HEX32(0xf0, MMC_RSP_BITS(data, 28, 8));
TEST_ASSERT_EQUAL_HEX32(0x3, MMC_RSP_BITS(data, 1, 3));
TEST_ASSERT_EQUAL_HEX32(0x11, MMC_RSP_BITS(data, 59, 5));
}
TEST_CASE("can probe SD", "[sd][ignore]")
{