diff --git a/components/driver/sdio_slave/include/driver/sdio_slave.h b/components/driver/sdio_slave/include/driver/sdio_slave.h index 6d05406bb76..17b20fafe09 100644 --- a/components/driver/sdio_slave/include/driver/sdio_slave.h +++ b/components/driver/sdio_slave/include/driver/sdio_slave.h @@ -25,11 +25,13 @@ typedef struct { sdio_slave_sending_mode_t sending_mode; ///< mode of sdio_slave. `SDIO_SLAVE_MODE_STREAM` if the data needs to be sent as much as possible; `SDIO_SLAVE_MODE_PACKET` if the data should be sent in packets. int send_queue_size; ///< max buffers that can be queued before sending. size_t recv_buffer_size; - ///< If buffer_size is too small, it costs more CPU time to handle larger number of buffers. - ///< If buffer_size is too large, the space larger than the transaction length is left blank but still counts a buffer, and the buffers are easily run out. - ///< Should be set according to length of data really transferred. - ///< All data that do not fully fill a buffer is still counted as one buffer. E.g. 10 bytes data costs 2 buffers if the size is 8 bytes per buffer. - ///< Buffer size of the slave pre-defined between host and slave before communication. All receive buffer given to the driver should be larger than this. + ///< If buffer_size is too small, it costs more CPU time to handle larger number of buffers. + ///< If buffer_size is too large, the space larger than the transaction length is left blank but still counts a buffer, and the buffers are easily run out. + ///< Should be set according to length of data really transferred. + ///< All data that do not fully fill a buffer is still counted as one buffer. E.g. 10 bytes data costs 2 buffers if the size is 8 bytes per buffer. + ///< Buffer size of the slave pre-defined between host and slave before communication. It must not exceed the + ///< maximum size supported by a single SDIO slave DMA descriptor on the current chip, + ///< and all receive buffer given to the driver should be larger than this. sdio_event_cb_t event_cb; ///< when the host interrupts slave, this callback will be called with interrupt number (0-7). uint32_t flags; ///< Features to be enabled for the slave, combinations of ``SDIO_SLAVE_FLAG_*``. #define SDIO_SLAVE_FLAG_DAT2_DISABLED BIT(0) /**< It is required by the SD specification that all 4 data @@ -186,7 +188,7 @@ uint8_t* sdio_slave_recv_get_buf(sdio_slave_buf_handle_t handle, size_t *len_o); * ``sdio_slave_send_get_finished`` after the transaction is finished. * * @param addr Address for data to be sent. The buffer should be DMA capable and 32-bit aligned. - * @param len Length of the data, should not be longer than 4092 bytes (may support longer in the future). + * @param len Length of the data, should not exceed the maximum size supported by a single SDIO slave DMA descriptor on the current chip. * @param arg Argument to returned in ``sdio_slave_send_get_finished``. The argument can be used to indicate which transaction is done, * or as a parameter for a callback. Set to NULL if not needed. * @param wait Time to wait if the buffer is full. diff --git a/components/driver/sdio_slave/sdio_slave.c b/components/driver/sdio_slave/sdio_slave.c index c959e85c27d..e41b032c32c 100644 --- a/components/driver/sdio_slave/sdio_slave.c +++ b/components/driver/sdio_slave/sdio_slave.c @@ -92,6 +92,7 @@ The driver of FIFOs works as below: #include "hal/sdio_slave_hal.h" #include "hal/gpio_hal.h" +#define SDIO_SLAVE_DMA_DESC_MAX_BUF_SIZE_ALIGNED_DOWN (SDIO_SLAVE_LL_DMA_DESC_MAX_BUF_SIZE & ~0x3U) #define SDIO_SLAVE_CHECK(res, str, ret_val) do { if(!(res)){\ SDIO_SLAVE_LOGE("%s", str);\ @@ -583,7 +584,8 @@ static void sdio_intr_send(void *arg) esp_err_t sdio_slave_send_queue(uint8_t *addr, size_t len, void *arg, TickType_t wait) { - SDIO_SLAVE_CHECK(len > 0 && len <= 4092, "length out of range: (0, 4092]", ESP_ERR_INVALID_ARG); + SDIO_SLAVE_CHECK(len > 0 && len <= SDIO_SLAVE_DMA_DESC_MAX_BUF_SIZE_ALIGNED_DOWN, + "length out of range for a single DMA descriptor", ESP_ERR_INVALID_ARG); SDIO_SLAVE_CHECK(esp_ptr_dma_capable(addr) && (uint32_t)addr % 4 == 0, "buffer to send should be DMA capable and 32-bit aligned", ESP_ERR_INVALID_ARG); diff --git a/components/hal/esp32/include/hal/sdio_slave_ll.h b/components/hal/esp32/include/hal/sdio_slave_ll.h index 695c647941f..d252b48e1c2 100644 --- a/components/hal/esp32/include/hal/sdio_slave_ll.h +++ b/components/hal/esp32/include/hal/sdio_slave_ll.h @@ -63,6 +63,9 @@ typedef struct sdio_slave_ll_desc_s { }; } sdio_slave_ll_desc_t; +/* Maximum buffer size that a single SDIO slave DMA descriptor can point to. */ +#define SDIO_SLAVE_LL_DMA_DESC_MAX_BUF_SIZE ((1 << 12) - 1) + /// Mask of general purpose interrupts sending from the host. typedef enum { SDIO_SLAVE_LL_SLVINT_0 = BIT(0), ///< General purpose interrupt bit 0. diff --git a/components/hal/esp32c6/include/hal/sdio_slave_ll.h b/components/hal/esp32c6/include/hal/sdio_slave_ll.h index 7319cbe20a0..ae0b4e65403 100644 --- a/components/hal/esp32c6/include/hal/sdio_slave_ll.h +++ b/components/hal/esp32c6/include/hal/sdio_slave_ll.h @@ -63,6 +63,9 @@ typedef struct sdio_slave_ll_desc_s { }; } sdio_slave_ll_desc_t; +/* Maximum buffer size that a single SDIO slave DMA descriptor can point to. */ +#define SDIO_SLAVE_LL_DMA_DESC_MAX_BUF_SIZE ((1 << 14) - 1) + /// Mask of general purpose interrupts sending from the host. typedef enum { SDIO_SLAVE_LL_SLVINT_0 = BIT(0), ///< General purpose interrupt bit 0. diff --git a/docs/en/api-reference/peripherals/sdio_slave.rst b/docs/en/api-reference/peripherals/sdio_slave.rst index e1162543957..60f6b072e07 100644 --- a/docs/en/api-reference/peripherals/sdio_slave.rst +++ b/docs/en/api-reference/peripherals/sdio_slave.rst @@ -223,7 +223,7 @@ Each time the slave has data to send, it raises an interrupt, and the host reque To avoid overhead from copying data, the driver itself does not have any buffer inside. Namely, the DMA takes data directly from the buffer provided by the application. The application should not touch the buffer until the sending is finished, so as to ensure that the data is transferred correctly. -The sending mode can be set in the ``sending_mode`` member of ``sdio_slave_config_t``, and the buffer numbers can be set in the ``send_queue_size``. All the buffers are restricted to be no larger than 4092 bytes. Though in the stream mode, several buffers can be sent in one transfer, each buffer is still counted as one in the queue. +The sending mode can be set in the ``sending_mode`` member of ``sdio_slave_config_t``, and the buffer numbers can be set in the ``send_queue_size``. Each buffer is restricted by the maximum size supported by a single SDIO slave DMA descriptor, which is chip-dependent. Though in the stream mode, several buffers can be sent in one transfer, each buffer is still counted as one in the queue. The application can call ``sdio_slave_transmit`` to send packets. In this case, the function returns when the transfer is successfully done, so the queue is not fully used. When higher efficiency is required, the application can use the following functions instead: diff --git a/docs/zh_CN/api-reference/peripherals/sdio_slave.rst b/docs/zh_CN/api-reference/peripherals/sdio_slave.rst index 708e608bf3e..08bbed9f6e1 100644 --- a/docs/zh_CN/api-reference/peripherals/sdio_slave.rst +++ b/docs/zh_CN/api-reference/peripherals/sdio_slave.rst @@ -223,7 +223,7 @@ SDIO 从机驱动程序的相关术语如下: 为减少复制数据的开销,驱动程序本身没有内部缓冲区,DMA 直接从应用程序提供的缓冲区中获取数据。发送完成前,应用程序不应该访问缓冲区,以确保数据传输的正确性。 -结构体 ``sdio_slave_config_t`` 中的 ``sending_mode`` 可以设置发送模式,``send_queue_size`` 可以设置缓冲区数量。缓冲区大小均限制在 4092 字节内。尽管在流模式下,一次传输可以发送多个缓冲区,但每个缓冲区在队列中仍然计为一个。 +结构体 ``sdio_slave_config_t`` 中的 ``sending_mode`` 可以设置发送模式,``send_queue_size`` 可以设置缓冲区数量。每个缓冲区的大小都受单个 SDIO slave DMA 描述符可支持的最大长度限制,且该限制因芯片而异。尽管在流模式下,一次传输可以发送多个缓冲区,但每个缓冲区在队列中仍然计为一个。 应用程序可以调用 ``sdio_slave_transmit`` 函数发送数据包。此时,函数在传输完成后返回,因此队列并未完全占用。若需要更高效率,应用程序可以改用以下函数: