mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
feat(sdio): add sdio over sdmmc support for esp32p4
This commit is contained in:
parent
6f053704dc
commit
216284b767
@ -57,6 +57,13 @@ extern "C" {
|
||||
// Forces data to be placed to DMA-capable places
|
||||
#define DMA_ATTR WORD_ALIGNED_ATTR DRAM_ATTR
|
||||
|
||||
//Force data to be placed in DRAM and aligned according to DMA and cache's requirement
|
||||
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
#define DRAM_DMA_ALIGNED_ATTR __attribute__((aligned(CONFIG_CACHE_L1_CACHE_LINE_SIZE))) DRAM_ATTR
|
||||
#else
|
||||
#define DRAM_DMA_ALIGNED_ATTR WORD_ALIGNED_ATTR DRAM_ATTR
|
||||
#endif
|
||||
|
||||
// Forces the data to be tightly packed with minimum required padding and no extra bytes are added for alignment
|
||||
#define PACKED_ATTR __attribute__((packed))
|
||||
|
||||
|
@ -47,9 +47,9 @@ static void s_master_init(test_sdio_param_t *host_param, essl_handle_t *out_hand
|
||||
{
|
||||
sdmmc_host_t host_config = (sdmmc_host_t)SDMMC_HOST_DEFAULT();
|
||||
host_config.flags = host_param->host_flags;
|
||||
if (host_config.flags == SDMMC_HOST_FLAG_4BIT) {
|
||||
if (host_config.flags & SDMMC_HOST_FLAG_4BIT) {
|
||||
ESP_LOGI(TAG, "Probe using SD 4-bit...");
|
||||
} else if (host_config.flags == SDMMC_HOST_FLAG_1BIT) {
|
||||
} else if (host_config.flags & SDMMC_HOST_FLAG_1BIT) {
|
||||
ESP_LOGI(TAG, "Probe using SD 1-bit...");
|
||||
}
|
||||
host_config.max_freq_khz = host_param->max_freq_khz;
|
||||
@ -83,6 +83,14 @@ static void s_master_init(test_sdio_param_t *host_param, essl_handle_t *out_hand
|
||||
TEST_ESP_OK(essl_init(*out_handle, TEST_TIMEOUT_MAX));
|
||||
}
|
||||
|
||||
static void s_master_deinit(void)
|
||||
{
|
||||
free(s_card.host.dma_aligned_buffer);
|
||||
s_card.host.dma_aligned_buffer = 0;
|
||||
|
||||
sdmmc_host_deinit();
|
||||
}
|
||||
|
||||
//trigger event 7 to indicate Slave to stop the test
|
||||
static void s_send_finish_test(essl_handle_t handle)
|
||||
{
|
||||
@ -102,7 +110,7 @@ TEST_CASE("SDIO_SDMMC: test interrupt", "[sdio]")
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
essl_handle_t handle = NULL;
|
||||
test_sdio_param_t test_param = {
|
||||
.host_flags = SDMMC_HOST_FLAG_4BIT,
|
||||
.host_flags = SDMMC_HOST_FLAG_4BIT | SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF,
|
||||
.max_freq_khz = SDMMC_FREQ_HIGHSPEED,
|
||||
};
|
||||
//essl init and sdmmc init
|
||||
@ -127,7 +135,7 @@ TEST_CASE("SDIO_SDMMC: test interrupt", "[sdio]")
|
||||
TEST_ESP_OK(essl_clear_intr(handle, int_st, TEST_TIMEOUT_MAX));
|
||||
}
|
||||
|
||||
sdmmc_host_deinit();
|
||||
s_master_deinit();
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
@ -137,7 +145,7 @@ TEST_CASE("SDIO_SDMMC: test register", "[sdio]")
|
||||
{
|
||||
essl_handle_t handle = NULL;
|
||||
test_sdio_param_t test_param = {
|
||||
.host_flags = SDMMC_HOST_FLAG_4BIT,
|
||||
.host_flags = SDMMC_HOST_FLAG_4BIT | SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF,
|
||||
.max_freq_khz = SDMMC_FREQ_HIGHSPEED,
|
||||
};
|
||||
//essl init and sdmmc init
|
||||
@ -161,7 +169,7 @@ TEST_CASE("SDIO_SDMMC: test register", "[sdio]")
|
||||
}
|
||||
|
||||
s_send_finish_test(handle);
|
||||
sdmmc_host_deinit();
|
||||
s_master_deinit();
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
@ -171,7 +179,7 @@ TEST_CASE("SDIO_SDMMC: test reset", "[sdio]")
|
||||
{
|
||||
essl_handle_t handle = NULL;
|
||||
test_sdio_param_t test_param = {
|
||||
.host_flags = SDMMC_HOST_FLAG_4BIT,
|
||||
.host_flags = SDMMC_HOST_FLAG_4BIT | SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF,
|
||||
.max_freq_khz = SDMMC_FREQ_HIGHSPEED,
|
||||
};
|
||||
//essl init and sdmmc init
|
||||
@ -204,7 +212,7 @@ TEST_CASE("SDIO_SDMMC: test reset", "[sdio]")
|
||||
}
|
||||
|
||||
s_send_finish_test(handle);
|
||||
sdmmc_host_deinit();
|
||||
s_master_deinit();
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
@ -212,11 +220,11 @@ TEST_CASE("SDIO_SDMMC: test reset", "[sdio]")
|
||||
---------------------------------------------------------------*/
|
||||
test_sdio_param_t test_param_lists[TEST_TARNS_PARAM_NUMS] = {
|
||||
{
|
||||
.host_flags = SDMMC_HOST_FLAG_4BIT,
|
||||
.host_flags = SDMMC_HOST_FLAG_4BIT | SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF,
|
||||
.max_freq_khz = SDMMC_FREQ_HIGHSPEED,
|
||||
},
|
||||
{
|
||||
.host_flags = SDMMC_HOST_FLAG_1BIT,
|
||||
.host_flags = SDMMC_HOST_FLAG_1BIT | SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF,
|
||||
.max_freq_khz = SDMMC_FREQ_HIGHSPEED,
|
||||
},
|
||||
};
|
||||
@ -229,7 +237,7 @@ static void test_from_host(bool check_data)
|
||||
test_prepare_buffer_pool(TEST_RX_BUFFER_SIZE * 4, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA);
|
||||
|
||||
for (int i = 0; i < TEST_TARNS_PARAM_NUMS; i++) {
|
||||
ESP_LOGI(TAG, "host mode: %s", (test_param_lists[i].host_flags == SDMMC_HOST_FLAG_4BIT) ? "4BIT Mode" : "1BIT Mode");
|
||||
ESP_LOGI(TAG, "host mode: %s", (test_param_lists[i].host_flags & SDMMC_HOST_FLAG_4BIT) ? "4BIT Mode" : "1BIT Mode");
|
||||
ESP_LOGI(TAG, "host speed: %"PRIu32" kHz", test_param_lists[i].max_freq_khz);
|
||||
|
||||
essl_handle_t handle = NULL;
|
||||
@ -262,7 +270,7 @@ static void test_from_host(bool check_data)
|
||||
|
||||
esp_rom_delay_us(50 * 1000);
|
||||
s_send_finish_test(handle);
|
||||
sdmmc_host_deinit();
|
||||
s_master_deinit();
|
||||
}
|
||||
|
||||
test_destroy_buffer_pool();
|
||||
@ -286,7 +294,7 @@ static void test_to_host(bool check_data)
|
||||
uint8_t *host_rx_buffer = (uint8_t *)heap_caps_calloc(1, recv_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA);
|
||||
|
||||
for (int i = 0; i < TEST_TARNS_PARAM_NUMS; i++) {
|
||||
ESP_LOGI(TAG, "host mode: %s", (test_param_lists[i].host_flags == SDMMC_HOST_FLAG_4BIT) ? "4BIT Mode" : "1BIT Mode");
|
||||
ESP_LOGI(TAG, "host mode: %s", (test_param_lists[i].host_flags & SDMMC_HOST_FLAG_4BIT) ? "4BIT Mode" : "1BIT Mode");
|
||||
ESP_LOGI(TAG, "host speed: %"PRIu32" kHz", test_param_lists[i].max_freq_khz);
|
||||
|
||||
essl_handle_t handle = NULL;
|
||||
@ -333,7 +341,7 @@ static void test_to_host(bool check_data)
|
||||
|
||||
esp_rom_delay_us(50 * 1000);
|
||||
s_send_finish_test(handle);
|
||||
sdmmc_host_deinit();
|
||||
s_master_deinit();
|
||||
}
|
||||
|
||||
free(host_rx_buffer);
|
||||
|
@ -165,7 +165,8 @@ esp_err_t sdmmc_host_set_cclk_always_on(int slot, bool cclk_always_on);
|
||||
* can call sdmmc_host_do_transaction as long as other sdmmc_host_*
|
||||
* functions are not called.
|
||||
*
|
||||
* @attention Data buffer passed in cmdinfo->data must be in DMA capable memory
|
||||
* @attention Data buffer passed in cmdinfo->data must be in DMA capable memory and aligned to 4 byte boundary. If it's
|
||||
* behind the cache, both cmdinfo->data and cmdinfo->buflen need to be aligned to cache line boundary.
|
||||
*
|
||||
* @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1)
|
||||
* @param cmdinfo pointer to structure describing command and data to transfer
|
||||
|
@ -29,12 +29,6 @@
|
||||
*/
|
||||
#define SDMMC_DMA_DESC_CNT 4
|
||||
|
||||
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
#define SDMMC_ALIGN_ATTR __attribute__((aligned(CONFIG_CACHE_L1_CACHE_LINE_SIZE)))
|
||||
#else
|
||||
#define SDMMC_ALIGN_ATTR
|
||||
#endif
|
||||
|
||||
#define ALIGN_UP_BY(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
|
||||
static const char* TAG = "sdmmc_req";
|
||||
@ -67,7 +61,7 @@ const uint32_t SDMMC_CMD_ERR_MASK =
|
||||
SDMMC_INTMASK_RCRC |
|
||||
SDMMC_INTMASK_RESP_ERR;
|
||||
|
||||
SDMMC_ALIGN_ATTR static sdmmc_desc_t s_dma_desc[SDMMC_DMA_DESC_CNT];
|
||||
DRAM_DMA_ALIGNED_ATTR static sdmmc_desc_t s_dma_desc[SDMMC_DMA_DESC_CNT];
|
||||
static sdmmc_transfer_state_t s_cur_transfer = { 0 };
|
||||
static QueueHandle_t s_request_mutex;
|
||||
static bool s_is_app_cmd; // This flag is set if the next command is an APP command
|
||||
|
@ -176,6 +176,11 @@ typedef struct {
|
||||
#define SDMMC_HOST_FLAG_SPI BIT(3) /*!< host supports SPI protocol */
|
||||
#define SDMMC_HOST_FLAG_DDR BIT(4) /*!< host supports DDR mode for SD/MMC */
|
||||
#define SDMMC_HOST_FLAG_DEINIT_ARG BIT(5) /*!< host `deinit` function called with the slot argument */
|
||||
#define SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF \
|
||||
BIT(6) /*!< Allocate internal buffer of 512 bytes that meets DMA's requirements.
|
||||
Currently this is only used by the SDIO driver. Set this flag when
|
||||
using SDIO CMD53 byte mode, with user buffer that is behind the cache
|
||||
or not aligned to 4 byte boundary. */
|
||||
int slot; /*!< slot number, to be passed to host functions */
|
||||
int max_freq_khz; /*!< max frequency supported by the host */
|
||||
#define SDMMC_FREQ_DEFAULT 20000 /*!< SD/MMC Default speed (limited by clock divider) */
|
||||
@ -201,6 +206,7 @@ typedef struct {
|
||||
esp_err_t (*get_real_freq)(int slot, int* real_freq); /*!< Host function to provide real working freq, based on SDMMC controller setup */
|
||||
sdmmc_delay_phase_t input_delay_phase; /*!< input delay phase, this will only take into effect when the host works in SDMMC_FREQ_HIGHSPEED or SDMMC_FREQ_52M. Driver will print out how long the delay is*/
|
||||
esp_err_t (*set_input_delay)(int slot, sdmmc_delay_phase_t delay_phase); /*!< set input delay phase */
|
||||
void* dma_aligned_buffer; /*!< Leave it NULL. Reserved for cache aligned buffers for SDIO mode */
|
||||
} sdmmc_host_t;
|
||||
|
||||
/**
|
||||
|
@ -200,8 +200,10 @@ esp_err_t sdmmc_io_write_byte(sdmmc_card_t* card, uint32_t function,
|
||||
* using sdmmc_card_init
|
||||
* @param function IO function number
|
||||
* @param addr byte address within IO function where reading starts
|
||||
* @param dst buffer which receives the data read from card
|
||||
* @param size number of bytes to read
|
||||
* @param dst buffer which receives the data read from card. Aligned to 4 byte boundary unless
|
||||
* `SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF` flag is set when calling `sdmmc_card_init`. The flag is mandatory
|
||||
* when the buffer is behind the cache.
|
||||
* @param size number of bytes to read, 1 to 512.
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_SIZE if size exceeds 512 bytes
|
||||
@ -220,8 +222,9 @@ esp_err_t sdmmc_io_read_bytes(sdmmc_card_t* card, uint32_t function,
|
||||
* using sdmmc_card_init
|
||||
* @param function IO function number
|
||||
* @param addr byte address within IO function where writing starts
|
||||
* @param src data to be written
|
||||
* @param size number of bytes to write
|
||||
* @param src data to be written. Aligned to 4 byte boundary unless `SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF` flag is set
|
||||
* when calling `sdmmc_card_init`. The flag is mandatory when the buffer is behind the cache.
|
||||
* @param size number of bytes to write, 1 to 512.
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_SIZE if size exceeds 512 bytes
|
||||
@ -240,7 +243,8 @@ esp_err_t sdmmc_io_write_bytes(sdmmc_card_t* card, uint32_t function,
|
||||
* using sdmmc_card_init
|
||||
* @param function IO function number
|
||||
* @param addr byte address within IO function where writing starts
|
||||
* @param dst buffer which receives the data read from card
|
||||
* @param dst buffer which receives the data read from card. Aligned to 4 byte boundary, and also cache line size if
|
||||
* the buffer is behind the cache.
|
||||
* @param size number of bytes to read, must be divisible by the card block
|
||||
* size.
|
||||
* @return
|
||||
@ -261,7 +265,8 @@ esp_err_t sdmmc_io_read_blocks(sdmmc_card_t* card, uint32_t function,
|
||||
* using sdmmc_card_init
|
||||
* @param function IO function number
|
||||
* @param addr byte address within IO function where writing starts
|
||||
* @param src data to be written
|
||||
* @param src data to be written. Aligned to 4 byte boundary, and also cache line size if the buffer is behind the
|
||||
* cache.
|
||||
* @param size number of bytes to read, must be divisible by the card block
|
||||
* size.
|
||||
* @return
|
||||
|
@ -325,6 +325,21 @@ esp_err_t sdmmc_fix_host_flags(sdmmc_card_t* card)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t sdmmc_allocate_aligned_buf(sdmmc_card_t* card)
|
||||
{
|
||||
if (card->host.flags & SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF) {
|
||||
void* buf = NULL;
|
||||
size_t actual_size = 0;
|
||||
esp_err_t ret = esp_dma_malloc(SDMMC_IO_BLOCK_SIZE, 0, &buf, &actual_size);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
assert(actual_size == SDMMC_IO_BLOCK_SIZE);
|
||||
card->host.dma_aligned_buffer = buf;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
uint32_t sdmmc_get_erase_timeout_ms(const sdmmc_card_t* card, int arg, size_t erase_size_kb)
|
||||
{
|
||||
if (card->is_mmc) {
|
||||
|
@ -99,11 +99,12 @@ uint32_t sdmmc_sd_get_erase_timeout_ms(const sdmmc_card_t* card, int arg, size_t
|
||||
esp_err_t sdmmc_io_reset(sdmmc_card_t* card);
|
||||
esp_err_t sdmmc_io_enable_hs_mode(sdmmc_card_t* card);
|
||||
esp_err_t sdmmc_io_send_op_cond(sdmmc_card_t* card, uint32_t ocr, uint32_t *ocrp);
|
||||
esp_err_t sdmmc_io_rw_direct(sdmmc_card_t* card, int function,
|
||||
uint32_t reg, uint32_t arg, uint8_t *byte);
|
||||
esp_err_t sdmmc_io_rw_extended(sdmmc_card_t* card, int function,
|
||||
uint32_t reg, int arg, void *data, size_t size);
|
||||
|
||||
esp_err_t sdmmc_io_rw_direct(sdmmc_card_t* card, int function, uint32_t reg, uint32_t arg, uint8_t *byte);
|
||||
// Requirement to `data` and `size` when using SDMMC host:
|
||||
// Buffer pointer (`data`) needs to be aligned to 4 byte boundary, and also cache line size if the buffer is behind the
|
||||
// cache, unless `SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF` flag is set when calling `sdmmc_card_init`. This flag is mandory
|
||||
// when the buffer is behind the cache in byte mode.
|
||||
esp_err_t sdmmc_io_rw_extended(sdmmc_card_t* card, int function, uint32_t reg, int arg, void *data, size_t size);
|
||||
|
||||
/* MMC specific */
|
||||
esp_err_t sdmmc_mmc_send_ext_csd_data(sdmmc_card_t* card, void *out_data, size_t datalen, size_t buffer_len);
|
||||
@ -154,3 +155,7 @@ static inline uint32_t get_host_ocr(float voltage)
|
||||
void sdmmc_flip_byte_order(uint32_t* response, size_t size);
|
||||
|
||||
esp_err_t sdmmc_fix_host_flags(sdmmc_card_t* card);
|
||||
|
||||
//Currently only SDIO support using this buffer. And only 512 block size is supported.
|
||||
#define SDMMC_IO_BLOCK_SIZE 512
|
||||
esp_err_t sdmmc_allocate_aligned_buf(sdmmc_card_t* card);
|
||||
|
@ -35,10 +35,14 @@ esp_err_t sdmmc_card_init(const sdmmc_host_t* config, sdmmc_card_t* card)
|
||||
{
|
||||
memset(card, 0, sizeof(*card));
|
||||
memcpy(&card->host, config, sizeof(*config));
|
||||
|
||||
const bool is_spi = host_is_spi(card);
|
||||
const bool always = true;
|
||||
const bool io_supported = true;
|
||||
|
||||
/* Allocate cache-aligned buffer for SDIO over SDMMC.*/
|
||||
SDMMC_INIT_STEP(!is_spi, sdmmc_allocate_aligned_buf);
|
||||
|
||||
/* Check if host flags are compatible with slot configuration. */
|
||||
SDMMC_INIT_STEP(!is_spi, sdmmc_fix_host_flags);
|
||||
|
||||
|
@ -266,16 +266,28 @@ esp_err_t sdmmc_io_rw_extended(sdmmc_card_t* card, int func,
|
||||
uint32_t reg, int arg, void *datap, size_t datalen)
|
||||
{
|
||||
esp_err_t err;
|
||||
const size_t max_byte_transfer_size = 512;
|
||||
const int buflen = (datalen + 3) & (~3); //round up to 4
|
||||
sdmmc_command_t cmd = {
|
||||
.flags = SCF_CMD_AC | SCF_RSP_R5,
|
||||
.arg = 0,
|
||||
.opcode = SD_IO_RW_EXTENDED,
|
||||
.data = datap,
|
||||
.datalen = datalen,
|
||||
.blklen = max_byte_transfer_size /* TODO: read max block size from CIS */
|
||||
.buflen = buflen,
|
||||
.blklen = SDMMC_IO_BLOCK_SIZE /* TODO: read max block size from CIS */
|
||||
};
|
||||
|
||||
if (unlikely(datalen > 0 && !esp_dma_is_buffer_aligned(datap, buflen, ESP_DMA_BUF_LOCATION_AUTO))) {
|
||||
if (datalen > SDMMC_IO_BLOCK_SIZE || card->host.dma_aligned_buffer == NULL) {
|
||||
// User gives unaligned buffer while `SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF` not set.
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
memset(card->host.dma_aligned_buffer, 0xcc, SDMMC_IO_BLOCK_SIZE);
|
||||
memcpy(card->host.dma_aligned_buffer, datap, datalen);
|
||||
cmd.data = card->host.dma_aligned_buffer;
|
||||
cmd.buflen = SDMMC_IO_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
uint32_t count; /* number of bytes or blocks, depending on transfer mode */
|
||||
if (arg & SD_ARG_CMD53_BLOCK_MODE) {
|
||||
if (cmd.datalen % cmd.blklen != 0) {
|
||||
@ -283,11 +295,11 @@ esp_err_t sdmmc_io_rw_extended(sdmmc_card_t* card, int func,
|
||||
}
|
||||
count = cmd.datalen / cmd.blklen;
|
||||
} else {
|
||||
if (datalen > max_byte_transfer_size) {
|
||||
if (datalen > SDMMC_IO_BLOCK_SIZE) {
|
||||
/* TODO: split into multiple operations? */
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
}
|
||||
if (datalen == max_byte_transfer_size) {
|
||||
if (datalen == SDMMC_IO_BLOCK_SIZE) {
|
||||
count = 0; // See 5.3.1 SDIO simplifed spec
|
||||
} else {
|
||||
count = datalen;
|
||||
@ -305,6 +317,12 @@ esp_err_t sdmmc_io_rw_extended(sdmmc_card_t* card, int func,
|
||||
}
|
||||
|
||||
err = sdmmc_send_cmd(card, &cmd);
|
||||
|
||||
if (datalen > 0 && cmd.data == card->host.dma_aligned_buffer) {
|
||||
assert(datalen <= SDMMC_IO_BLOCK_SIZE);
|
||||
memcpy(datap, card->host.dma_aligned_buffer, datalen);
|
||||
}
|
||||
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: sdmmc_send_cmd returned 0x%x", __func__, err);
|
||||
return err;
|
||||
@ -368,8 +386,8 @@ 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)
|
||||
{
|
||||
if (unlikely(size % 4 != 0)) {
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
if (unlikely(!esp_dma_is_buffer_aligned(dst, size, ESP_DMA_BUF_LOCATION_INTERNAL))) {
|
||||
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,
|
||||
@ -379,8 +397,8 @@ esp_err_t sdmmc_io_read_blocks(sdmmc_card_t* card, uint32_t function,
|
||||
esp_err_t sdmmc_io_write_blocks(sdmmc_card_t* card, uint32_t function,
|
||||
uint32_t addr, const void* src, size_t size)
|
||||
{
|
||||
if (unlikely(size % 4 != 0)) {
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
if (unlikely(!esp_dma_is_buffer_aligned(src, size, ESP_DMA_BUF_LOCATION_INTERNAL))) {
|
||||
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,
|
||||
|
@ -197,6 +197,10 @@ esp_err_t slave_init(essl_handle_t* handle)
|
||||
config.max_freq_khz = SDMMC_FREQ_DEFAULT;
|
||||
#endif
|
||||
|
||||
// Set this flag to allocate aligned buffer of 512 bytes to meet DMA's requirements for CMD53 byte mode. Mandatory
|
||||
// when any buffer is behind the cache, or not aligned to 4 byte boundary.
|
||||
config.flags |= SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF;
|
||||
|
||||
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
|
||||
/* Note: For small devkits there may be no pullups on the board.
|
||||
This enables the internal pullups to help evaluate the driver quickly.
|
||||
@ -424,17 +428,13 @@ void job_write_reg(essl_handle_t handle, int value)
|
||||
//so first 5 packets (use 1+1+8+4+1=15 buffers) are sent, the others (513, 517) failed (timeout)
|
||||
int packet_len[] = {6, 12, 1024, 512, 3, 513, 517};
|
||||
//the sending buffer should be word aligned
|
||||
DMA_ATTR uint8_t send_buffer[READ_BUFFER_LEN];
|
||||
DRAM_DMA_ALIGNED_ATTR uint8_t send_buffer[READ_BUFFER_LEN];
|
||||
|
||||
//send packets to the slave (they will return and be handled by the interrupt handler)
|
||||
void job_fifo(essl_handle_t handle)
|
||||
{
|
||||
for (int i = 0; i < READ_BUFFER_LEN; i++) {
|
||||
send_buffer[i] = 0x46 + i * 5;
|
||||
}
|
||||
|
||||
esp_err_t ret;
|
||||
int pointer = 0;
|
||||
int data_index = 0;
|
||||
|
||||
ESP_LOGI(TAG, "========JOB: send fifos========");
|
||||
/* CAUTION: This example shows that we can send random length of packet to the slave.
|
||||
@ -443,16 +443,21 @@ void job_fifo(essl_handle_t handle)
|
||||
* Try to avoid unaligned packets if possible to get higher effeciency.
|
||||
*/
|
||||
for (int i = 0; i < sizeof(packet_len) / sizeof(int); i++) {
|
||||
const int wait_ms = 50;
|
||||
//Prepare data to send. The length can be random, but data should start at the 32-bit boundary.
|
||||
int length = packet_len[i];
|
||||
ret = essl_send_packet(handle, send_buffer + pointer, length, wait_ms);
|
||||
for (int i = 0; i < length; i ++) {
|
||||
send_buffer[i] = 0x46 + (data_index + i) * 5;
|
||||
}
|
||||
data_index += (length + 3) & (~3); //get different data next time
|
||||
|
||||
const int wait_ms = 50;
|
||||
ret = essl_send_packet(handle, send_buffer, length, wait_ms);
|
||||
if (ret == ESP_ERR_TIMEOUT || ret == ESP_ERR_NOT_FOUND) {
|
||||
ESP_LOGD(TAG, "slave not ready to receive packet %d", i); // And there are several packets expected to timeout.
|
||||
} else {
|
||||
ESP_ERROR_CHECK(ret);
|
||||
ESP_LOGI(TAG, "send packet length: %d", length);
|
||||
}
|
||||
pointer += (length + 3) & (~3); //the length can be random, but data should start at the 32-bit boundary.
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user