diff --git a/components/esp_common/include/esp_attr.h b/components/esp_common/include/esp_attr.h index 2ce549b6fe..4bd9ef1c02 100644 --- a/components/esp_common/include/esp_attr.h +++ b/components/esp_common/include/esp_attr.h @@ -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)) 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 23ef53a52c..f33985da78 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 @@ -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); diff --git a/components/esp_driver_sdmmc/include/driver/sdmmc_host.h b/components/esp_driver_sdmmc/include/driver/sdmmc_host.h index 3a4de21bca..94080760b2 100644 --- a/components/esp_driver_sdmmc/include/driver/sdmmc_host.h +++ b/components/esp_driver_sdmmc/include/driver/sdmmc_host.h @@ -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 diff --git a/components/esp_driver_sdmmc/src/sdmmc_transaction.c b/components/esp_driver_sdmmc/src/sdmmc_transaction.c index 0ab9510617..ca471ec384 100644 --- a/components/esp_driver_sdmmc/src/sdmmc_transaction.c +++ b/components/esp_driver_sdmmc/src/sdmmc_transaction.c @@ -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 diff --git a/components/sdmmc/include/sd_protocol_types.h b/components/sdmmc/include/sd_protocol_types.h index 61af3f8037..ec834807bd 100644 --- a/components/sdmmc/include/sd_protocol_types.h +++ b/components/sdmmc/include/sd_protocol_types.h @@ -175,7 +175,12 @@ typedef struct { #define SDMMC_HOST_FLAG_8BIT BIT(2) /*!< host supports 8-line MMC protocol */ #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_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; /** diff --git a/components/sdmmc/include/sdmmc_cmd.h b/components/sdmmc/include/sdmmc_cmd.h index 96889fbf99..c4d7194f12 100644 --- a/components/sdmmc/include/sdmmc_cmd.h +++ b/components/sdmmc/include/sdmmc_cmd.h @@ -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 diff --git a/components/sdmmc/sdmmc_common.c b/components/sdmmc/sdmmc_common.c index b57e67ef1a..b7e32b6a07 100644 --- a/components/sdmmc/sdmmc_common.c +++ b/components/sdmmc/sdmmc_common.c @@ -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) { diff --git a/components/sdmmc/sdmmc_common.h b/components/sdmmc/sdmmc_common.h index f48f2cf0cc..cd271e8a7c 100644 --- a/components/sdmmc/sdmmc_common.h +++ b/components/sdmmc/sdmmc_common.h @@ -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); diff --git a/components/sdmmc/sdmmc_init.c b/components/sdmmc/sdmmc_init.c index 997dd8ef71..9a713b9d3b 100644 --- a/components/sdmmc/sdmmc_init.c +++ b/components/sdmmc/sdmmc_init.c @@ -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); diff --git a/components/sdmmc/sdmmc_io.c b/components/sdmmc/sdmmc_io.c index 90051111ee..5b7ef581db 100644 --- a/components/sdmmc/sdmmc_io.c +++ b/components/sdmmc/sdmmc_io.c @@ -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, diff --git a/examples/peripherals/sdio/host/main/app_main.c b/examples/peripherals/sdio/host/main/app_main.c index f9542ac01e..fba7d30412 100644 --- a/examples/peripherals/sdio/host/main/app_main.c +++ b/examples/peripherals/sdio/host/main/app_main.c @@ -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. } }