mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
feat(sdmmc_io): support sending CMD53 with fixed address
This commit is contained in:
parent
b102277a12
commit
52baadf0db
@ -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;
|
||||
|
@ -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
|
||||
---------------------------------------------------------------*/
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user