From 096db7521b81b5fe31bc1d823c89ceee1a8291d7 Mon Sep 17 00:00:00 2001 From: Xiao Xufeng Date: Tue, 7 May 2024 02:45:43 +0800 Subject: [PATCH 1/2] feat(sdmmc_io): support sending CMD53 with fixed address --- .../host_sdmmc/main/test_sdio_sdhost.c | 77 +++++++++++++++++-- .../sdio/main/test_sdio_slave.c | 18 +++++ components/sdmmc/include/sdmmc_cmd.h | 18 ++++- components/sdmmc/sdmmc_io.c | 45 +++++++---- 4 files changed, 138 insertions(+), 20 deletions(-) diff --git a/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/host_sdmmc/main/test_sdio_sdhost.c b/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/host_sdmmc/main/test_sdio_sdhost.c index f33985da78..8a63f2b9b6 100644 --- a/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/host_sdmmc/main/test_sdio_sdhost.c +++ b/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/host_sdmmc/main/test_sdio_sdhost.c @@ -14,6 +14,7 @@ #include "freertos/task.h" #include "esp_timer.h" #include "ccomp_timer.h" +#include "string.h" #include "sdmmc_cmd.h" #include "driver/sdmmc_host.h" @@ -43,7 +44,7 @@ typedef struct { ---------------------------------------------------------------*/ static sdmmc_card_t s_card; -static void s_master_init(test_sdio_param_t *host_param, essl_handle_t *out_handle) +static void s_master_init(test_sdio_param_t *host_param, essl_handle_t *out_handle, sdmmc_card_t** out_card) { sdmmc_host_t host_config = (sdmmc_host_t)SDMMC_HOST_DEFAULT(); host_config.flags = host_param->host_flags; @@ -81,6 +82,10 @@ static void s_master_init(test_sdio_param_t *host_param, essl_handle_t *out_hand TEST_ESP_OK(essl_sdio_init_dev(out_handle, &essl_sdio_config)); TEST_ESP_OK(essl_init(*out_handle, TEST_TIMEOUT_MAX)); + + if (out_card) { + *out_card = card; + } } static void s_master_deinit(void) @@ -114,7 +119,7 @@ TEST_CASE("SDIO_SDMMC: test interrupt", "[sdio]") .max_freq_khz = SDMMC_FREQ_HIGHSPEED, }; //essl init and sdmmc init - s_master_init(&test_param, &handle); + s_master_init(&test_param, &handle, NULL); TEST_ESP_OK(essl_set_intr_ena(handle, TEST_INT_MASK_ALL, TEST_TIMEOUT_MAX)); ret = essl_wait_int(handle, 0); @@ -149,7 +154,7 @@ TEST_CASE("SDIO_SDMMC: test register", "[sdio]") .max_freq_khz = SDMMC_FREQ_HIGHSPEED, }; //essl init and sdmmc init - s_master_init(&test_param, &handle); + s_master_init(&test_param, &handle, NULL); uint32_t init_val = 30; srand(850); @@ -183,7 +188,7 @@ TEST_CASE("SDIO_SDMMC: test reset", "[sdio]") .max_freq_khz = SDMMC_FREQ_HIGHSPEED, }; //essl init and sdmmc init - s_master_init(&test_param, &handle); + s_master_init(&test_param, &handle, NULL); //wait for the slave to stop, reset and start again vTaskDelay(10); @@ -215,6 +220,66 @@ TEST_CASE("SDIO_SDMMC: test reset", "[sdio]") s_master_deinit(); } +/*--------------------------------------------------------------- + SDMMC_SDIO: test fixed addr +---------------------------------------------------------------*/ +#include "soc/soc.h" +#define HOST_SLCHOST_CONF_W0_REG (DR_REG_SLCHOST_BASE + 0x6C) + +TEST_CASE("SDIO_SDMMC: test fixed addr", "[sdio]") +{ + essl_handle_t handle = NULL; + sdmmc_card_t* card; + test_sdio_param_t test_param = { + .host_flags = SDMMC_HOST_FLAG_4BIT | SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF, + .max_freq_khz = SDMMC_FREQ_HIGHSPEED, + }; + //essl init and sdmmc init + s_master_init(&test_param, &handle, &card); + + vTaskDelay(10); + + const int test_size = 128; + const int write_addr = 6; + uint8_t buf[test_size] = {}; + srand(850); + for (int i = 0; i < test_size; i++) { + buf[i] = rand(); + } + ESP_LOG_BUFFER_HEX("write_val", buf, test_size); + + TEST_ESP_OK(sdmmc_io_write_bytes(card, 1, ((HOST_SLCHOST_CONF_W0_REG + write_addr) & 0x3FF) | SDMMC_IO_FIXED_ADDR, buf, test_size)); + + const int max_size = 64; + uint8_t read_buf[max_size] = {}; + TEST_ESP_OK(sdmmc_io_read_bytes(card, 1, HOST_SLCHOST_CONF_W0_REG & 0x3FF, read_buf, max_size)); + ESP_LOG_BUFFER_HEX("read_all", read_buf, max_size); + for (int i = 0; i < max_size; i++) { + if (i >= 24 && i < 28) { + continue; + } + if (i >= 32 && i < 48) { + continue; + } + if (i == write_addr) { + TEST_ASSERT_EQUAL_HEX8(buf[test_size - 1], read_buf[i]); + } else { + TEST_ASSERT_EQUAL_HEX8(0xcc, read_buf[i]); + } + } + + const int read_size = (test_size > max_size ? max_size : test_size); + memset(read_buf, 0, read_size); + TEST_ESP_OK(sdmmc_io_read_bytes(card, 1, ((HOST_SLCHOST_CONF_W0_REG + write_addr) & 0x3FF) | SDMMC_IO_FIXED_ADDR, read_buf, read_size)); + ESP_LOG_BUFFER_HEX("read_fixed", read_buf, read_size); + for (int i = 0; i < read_size; i++) { + TEST_ASSERT_EQUAL_HEX8(buf[test_size - 1], read_buf[i]); + } + + s_send_finish_test(handle); + s_master_deinit(); +} + /*--------------------------------------------------------------- Transaction Tests ---------------------------------------------------------------*/ @@ -241,7 +306,7 @@ static void test_from_host(bool check_data) ESP_LOGI(TAG, "host speed: %"PRIu32" kHz", test_param_lists[i].max_freq_khz); essl_handle_t handle = NULL; - s_master_init(&test_param_lists[i], &handle); + s_master_init(&test_param_lists[i], &handle, NULL); // Two counters are used. The `esp_timer_get_time()` is for the typical time, and the // `ccomp_timer` is for performance test to reduce influence caused by cache miss. @@ -298,7 +363,7 @@ static void test_to_host(bool check_data) ESP_LOGI(TAG, "host speed: %"PRIu32" kHz", test_param_lists[i].max_freq_khz); essl_handle_t handle = NULL; - s_master_init(&test_param_lists[i], &handle); + s_master_init(&test_param_lists[i], &handle, NULL); esp_err_t ret; int offset = 0; diff --git a/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/sdio/main/test_sdio_slave.c b/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/sdio/main/test_sdio_slave.c index ca3e6816d2..d91e19dd7c 100644 --- a/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/sdio/main/test_sdio_slave.c +++ b/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/sdio/main/test_sdio_slave.c @@ -155,6 +155,24 @@ TEST_CASE("SDIO_Slave: test reset", "[sdio]") sdio_slave_deinit(); } +/*--------------------------------------------------------------- + SDMMC_SDIO: test fixed addr +---------------------------------------------------------------*/ +TEST_CASE("SDIO_Slave: test fixed addr", "[sdio]") +{ + s_slave_init(SDIO_SLAVE_SEND_PACKET); + TEST_ESP_OK(sdio_slave_start()); + ESP_LOGI(TAG, "slave ready"); + + for (int i = 0; i < 64; i++) { + sdio_slave_write_reg(i, 0xcc); + } + + wait_for_finish(&s_test_slv_ctx); + + sdio_slave_stop(); + sdio_slave_deinit(); +} /*--------------------------------------------------------------- Transaction Tests ---------------------------------------------------------------*/ diff --git a/components/sdmmc/include/sdmmc_cmd.h b/components/sdmmc/include/sdmmc_cmd.h index c4d7194f12..0510defd7b 100644 --- a/components/sdmmc/include/sdmmc_cmd.h +++ b/components/sdmmc/include/sdmmc_cmd.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,6 +14,10 @@ extern "C" { #endif +/** Call `sdmmc_io_read_bytes`, `sdmmc_io_write_bytes`, `sdmmc_io_read_blocks` or `sdmmc_io_write_bocks` APIs with + * address ORed by this flag to send CMD53 with OP Code clear (fixed address) */ +#define SDMMC_IO_FIXED_ADDR BIT(31) + /** * Probe and initialize SD/MMC card using given host * @@ -196,6 +200,9 @@ esp_err_t sdmmc_io_write_byte(sdmmc_card_t* card, uint32_t function, * This function performs read operation using CMD53 in byte mode. * For block mode, see sdmmc_io_read_blocks. * + * By default OP Code is set (incrementing address). To send CMD53 without this bit, OR the argument `addr` with + * `SDMMC_IO_FIXED_ADDR`. + * * @param card pointer to card information structure previously initialized * using sdmmc_card_init * @param function IO function number @@ -218,6 +225,9 @@ esp_err_t sdmmc_io_read_bytes(sdmmc_card_t* card, uint32_t function, * This function performs write operation using CMD53 in byte mode. * For block mode, see sdmmc_io_write_blocks. * + * By default OP Code is set (incrementing address). To send CMD53 without this bit, OR the argument `addr` with + * `SDMMC_IO_FIXED_ADDR`. + * * @param card pointer to card information structure previously initialized * using sdmmc_card_init * @param function IO function number @@ -239,6 +249,9 @@ esp_err_t sdmmc_io_write_bytes(sdmmc_card_t* card, uint32_t function, * This function performs read operation using CMD53 in block mode. * For byte mode, see sdmmc_io_read_bytes. * + * By default OP Code is set (incrementing address). To send CMD53 without this bit, OR the argument `addr` with + * `SDMMC_IO_FIXED_ADDR`. + * * @param card pointer to card information structure previously initialized * using sdmmc_card_init * @param function IO function number @@ -261,6 +274,9 @@ esp_err_t sdmmc_io_read_blocks(sdmmc_card_t* card, uint32_t function, * This function performs write operation using CMD53 in block mode. * For byte mode, see sdmmc_io_write_bytes. * + * By default OP Code is set (incrementing address). To send CMD53 without this bit, OR the argument `addr` with + * `SDMMC_IO_FIXED_ADDR`. + * * @param card pointer to card information structure previously initialized * using sdmmc_card_init * @param function IO function number diff --git a/components/sdmmc/sdmmc_io.c b/components/sdmmc/sdmmc_io.c index 80a3cc26c9..376cebc9e5 100644 --- a/components/sdmmc/sdmmc_io.c +++ b/components/sdmmc/sdmmc_io.c @@ -336,6 +336,13 @@ esp_err_t sdmmc_io_rw_extended(sdmmc_card_t* card, int func, esp_err_t sdmmc_io_read_bytes(sdmmc_card_t* card, uint32_t function, uint32_t addr, void* dst, size_t size) { + uint32_t arg = SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT; + //Extract and unset the bit used to indicate the OP Code (inverted logic) + if (addr & SDMMC_IO_FIXED_ADDR) { + arg &= ~SD_ARG_CMD53_INCREMENT; + addr &= ~SDMMC_IO_FIXED_ADDR; + } + /* host quirk: SDIO transfer with length not divisible by 4 bytes * has to be split into two transfers: one with aligned length, * the other one for the remaining 1-3 bytes. @@ -347,9 +354,7 @@ esp_err_t sdmmc_io_read_bytes(sdmmc_card_t* card, uint32_t function, // Note: sdmmc_io_rw_extended has an internal timeout, // typically SDMMC_DEFAULT_CMD_TIMEOUT_MS - esp_err_t err = sdmmc_io_rw_extended(card, function, addr, - SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT, - pc_dst, will_transfer); + esp_err_t err = sdmmc_io_rw_extended(card, function, addr, arg, pc_dst, will_transfer); if (unlikely(err != ESP_OK)) { return err; } @@ -363,18 +368,22 @@ esp_err_t sdmmc_io_read_bytes(sdmmc_card_t* card, uint32_t function, esp_err_t sdmmc_io_write_bytes(sdmmc_card_t* card, uint32_t function, uint32_t addr, const void* src, size_t size) { + uint32_t arg = SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT; + //Extract and unset the bit used to indicate the OP Code (inverted logic) + if (addr & SDMMC_IO_FIXED_ADDR) { + arg &= ~SD_ARG_CMD53_INCREMENT; + addr &= ~SDMMC_IO_FIXED_ADDR; + } + /* same host quirk as in sdmmc_io_read_bytes */ const uint8_t *pc_src = (const uint8_t*) src; - while (size > 0) { size_t size_aligned = size & (~3); size_t will_transfer = size_aligned > 0 ? size_aligned : size; // Note: sdmmc_io_rw_extended has an internal timeout, // typically SDMMC_DEFAULT_CMD_TIMEOUT_MS - esp_err_t err = sdmmc_io_rw_extended(card, function, addr, - SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT, - (void*) pc_src, will_transfer); + esp_err_t err = sdmmc_io_rw_extended(card, function, addr, arg, (void*) pc_src, will_transfer); if (unlikely(err != ESP_OK)) { return err; } @@ -388,27 +397,37 @@ esp_err_t sdmmc_io_write_bytes(sdmmc_card_t* card, uint32_t function, esp_err_t sdmmc_io_read_blocks(sdmmc_card_t* card, uint32_t function, uint32_t addr, void* dst, size_t size) { + uint32_t arg = SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT | SD_ARG_CMD53_BLOCK_MODE; + //Extract and unset the bit used to indicate the OP Code (inverted logic) + if (addr & SDMMC_IO_FIXED_ADDR) { + arg &= ~SD_ARG_CMD53_INCREMENT; + addr &= ~SDMMC_IO_FIXED_ADDR; + } + esp_dma_mem_info_t dma_mem_info; card->host.get_dma_info(card->host.slot, &dma_mem_info); if (unlikely(!esp_dma_is_buffer_alignment_satisfied(dst, size, dma_mem_info))) { return ESP_ERR_INVALID_ARG; } - return sdmmc_io_rw_extended(card, function, addr, - SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT | SD_ARG_CMD53_BLOCK_MODE, - dst, size); + return sdmmc_io_rw_extended(card, function, addr, arg, dst, size); } esp_err_t sdmmc_io_write_blocks(sdmmc_card_t* card, uint32_t function, uint32_t addr, const void* src, size_t size) { + uint32_t arg = SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT | SD_ARG_CMD53_BLOCK_MODE; + //Extract and unset the bit used to indicate the OP Code (inverted logic) + if (addr & SDMMC_IO_FIXED_ADDR) { + arg &= ~SD_ARG_CMD53_INCREMENT; + addr &= ~SDMMC_IO_FIXED_ADDR; + } + esp_dma_mem_info_t dma_mem_info; card->host.get_dma_info(card->host.slot, &dma_mem_info); if (unlikely(!esp_dma_is_buffer_alignment_satisfied(src, size, dma_mem_info))) { return ESP_ERR_INVALID_ARG; } - return sdmmc_io_rw_extended(card, function, addr, - SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT | SD_ARG_CMD53_BLOCK_MODE, - (void*) src, size); + return sdmmc_io_rw_extended(card, function, addr, arg, (void*) src, size); } esp_err_t sdmmc_io_enable_int(sdmmc_card_t* card) From 4e0d5c923d70d16833b291b4add2e2fb6c22d3e9 Mon Sep 17 00:00:00 2001 From: "Michael (XIAO Xufeng)" Date: Sat, 29 Jun 2024 02:26:14 +0800 Subject: [PATCH 2/2] fix(sdmmc_io): fixed fixed_addr mode will still increase addr when splitting --- components/sdmmc/sdmmc_io.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/components/sdmmc/sdmmc_io.c b/components/sdmmc/sdmmc_io.c index 376cebc9e5..74ab6dd735 100644 --- a/components/sdmmc/sdmmc_io.c +++ b/components/sdmmc/sdmmc_io.c @@ -336,11 +336,15 @@ esp_err_t sdmmc_io_rw_extended(sdmmc_card_t* card, int func, esp_err_t sdmmc_io_read_bytes(sdmmc_card_t* card, uint32_t function, uint32_t addr, void* dst, size_t size) { - uint32_t arg = SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT; - //Extract and unset the bit used to indicate the OP Code (inverted logic) + uint32_t arg = SD_ARG_CMD53_READ; + bool incr_addr = true; + //Extract and unset the bit used to indicate the OP Code if (addr & SDMMC_IO_FIXED_ADDR) { - arg &= ~SD_ARG_CMD53_INCREMENT; addr &= ~SDMMC_IO_FIXED_ADDR; + incr_addr = false; + } + if (incr_addr) { + arg |= SD_ARG_CMD53_INCREMENT; } /* host quirk: SDIO transfer with length not divisible by 4 bytes @@ -360,7 +364,9 @@ esp_err_t sdmmc_io_read_bytes(sdmmc_card_t* card, uint32_t function, } pc_dst += will_transfer; size -= will_transfer; - addr += will_transfer; + if (incr_addr) { + addr += will_transfer; + } } return ESP_OK; } @@ -368,11 +374,15 @@ esp_err_t sdmmc_io_read_bytes(sdmmc_card_t* card, uint32_t function, esp_err_t sdmmc_io_write_bytes(sdmmc_card_t* card, uint32_t function, uint32_t addr, const void* src, size_t size) { - uint32_t arg = SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT; - //Extract and unset the bit used to indicate the OP Code (inverted logic) + uint32_t arg = SD_ARG_CMD53_WRITE; + bool incr_addr = true; + //Extract and unset the bit used to indicate the OP Code if (addr & SDMMC_IO_FIXED_ADDR) { - arg &= ~SD_ARG_CMD53_INCREMENT; addr &= ~SDMMC_IO_FIXED_ADDR; + incr_addr = false; + } + if (incr_addr) { + arg |= SD_ARG_CMD53_INCREMENT; } /* same host quirk as in sdmmc_io_read_bytes */ @@ -389,7 +399,9 @@ esp_err_t sdmmc_io_write_bytes(sdmmc_card_t* card, uint32_t function, } pc_src += will_transfer; size -= will_transfer; - addr += will_transfer; + if (incr_addr) { + addr += will_transfer; + } } return ESP_OK; }