From 273f2be22655f0daeb144f69a6b3b57b4125bcc5 Mon Sep 17 00:00:00 2001 From: wanckl Date: Thu, 28 Nov 2024 11:19:27 +0800 Subject: [PATCH 1/2] fix(driver_spi): fixed slave_hd driver transaction alignment check --- components/esp_driver_spi/src/gpspi/spi_master.c | 4 ++-- components/esp_driver_spi/src/gpspi/spi_slave.c | 4 ++-- components/esp_driver_spi/src/gpspi/spi_slave_hd.c | 4 ++-- .../esp_driver_spi/test_apps/param/main/test_spi_param.c | 6 ++++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/components/esp_driver_spi/src/gpspi/spi_master.c b/components/esp_driver_spi/src/gpspi/spi_master.c index b447b40a5f..d02426f0aa 100644 --- a/components/esp_driver_spi/src/gpspi/spi_master.c +++ b/components/esp_driver_spi/src/gpspi/spi_master.c @@ -1143,7 +1143,7 @@ static SPI_MASTER_ISR_ATTR esp_err_t setup_priv_desc(spi_host_t *host, spi_trans if (send_ptr && bus_attr->dma_enabled) { if ((!esp_ptr_dma_capable(send_ptr) || tx_unaligned)) { - ESP_RETURN_ON_FALSE(!(trans_desc->flags & SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL), ESP_ERR_INVALID_ARG, SPI_TAG, "Set flag SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL but TX buffer addr&len not align to %d, or not dma_capable", alignment); + ESP_RETURN_ON_FALSE(!(trans_desc->flags & SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL), ESP_ERR_INVALID_ARG, SPI_TAG, "Set flag SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL but TX buffer addr&len not align to %d byte, or not dma_capable", alignment); //if txbuf in the desc not DMA-capable, or not bytes aligned to alignment, malloc a new one ESP_EARLY_LOGD(SPI_TAG, "Allocate TX buffer for DMA"); tx_byte_len = (tx_byte_len + alignment - 1) & (~(alignment - 1)); // up align alignment @@ -1163,7 +1163,7 @@ static SPI_MASTER_ISR_ATTR esp_err_t setup_priv_desc(spi_host_t *host, spi_trans if (rcv_ptr && bus_attr->dma_enabled) { if ((!esp_ptr_dma_capable(rcv_ptr) || rx_unaligned)) { - ESP_RETURN_ON_FALSE(!(trans_desc->flags & SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL), ESP_ERR_INVALID_ARG, SPI_TAG, "Set flag SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL but RX buffer addr&len not align to %d, or not dma_capable", alignment); + ESP_RETURN_ON_FALSE(!(trans_desc->flags & SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL), ESP_ERR_INVALID_ARG, SPI_TAG, "Set flag SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL but RX buffer addr&len not align to %d byte, or not dma_capable", alignment); //if rxbuf in the desc not DMA-capable, or not aligned to alignment, malloc a new one ESP_EARLY_LOGD(SPI_TAG, "Allocate RX buffer for DMA"); rx_byte_len = (rx_byte_len + alignment - 1) & (~(alignment - 1)); // up align alignment diff --git a/components/esp_driver_spi/src/gpspi/spi_slave.c b/components/esp_driver_spi/src/gpspi/spi_slave.c index 65b011675d..a2c29fe912 100644 --- a/components/esp_driver_spi/src/gpspi/spi_slave.c +++ b/components/esp_driver_spi/src/gpspi/spi_slave.c @@ -332,7 +332,7 @@ static esp_err_t SPI_SLAVE_ISR_ATTR spi_slave_setup_priv_trans(spi_host_device_t if (spihost[host]->dma_enabled && trans->tx_buffer) { if ((!esp_ptr_dma_capable(trans->tx_buffer) || ((((uint32_t)trans->tx_buffer) | buffer_byte_len) & (alignment - 1)))) { - ESP_RETURN_ON_FALSE_ISR(trans->flags & SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO, ESP_ERR_INVALID_ARG, SPI_TAG, "TX buffer addr&len not align to %d, or not dma_capable", alignment); + ESP_RETURN_ON_FALSE_ISR(trans->flags & SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO, ESP_ERR_INVALID_ARG, SPI_TAG, "TX buffer addr&len not align to %d byte, or not dma_capable", alignment); //if txbuf in the desc not DMA-capable, or not align to "alignment", malloc a new one ESP_EARLY_LOGD(SPI_TAG, "Allocate TX buffer for DMA"); buffer_byte_len = (buffer_byte_len + alignment - 1) & (~(alignment - 1)); // up align to "alignment" @@ -349,7 +349,7 @@ static esp_err_t SPI_SLAVE_ISR_ATTR spi_slave_setup_priv_trans(spi_host_device_t } if (spihost[host]->dma_enabled && trans->rx_buffer) { if ((!esp_ptr_dma_capable(trans->rx_buffer) || ((((uint32_t)trans->rx_buffer) | (trans->length + 7) / 8) & (alignment - 1)))) { - ESP_RETURN_ON_FALSE_ISR(trans->flags & SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO, ESP_ERR_INVALID_ARG, SPI_TAG, "RX buffer addr&len not align to %d, or not dma_capable", alignment); + ESP_RETURN_ON_FALSE_ISR(trans->flags & SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO, ESP_ERR_INVALID_ARG, SPI_TAG, "RX buffer addr&len not align to %d byte, or not dma_capable", alignment); //if rxbuf in the desc not DMA-capable, or not align to "alignment", malloc a new one ESP_EARLY_LOGD(SPI_TAG, "Allocate RX buffer for DMA"); buffer_byte_len = (buffer_byte_len + alignment - 1) & (~(alignment - 1)); // up align to "alignment" diff --git a/components/esp_driver_spi/src/gpspi/spi_slave_hd.c b/components/esp_driver_spi/src/gpspi/spi_slave_hd.c index 8198919513..b93383b527 100644 --- a/components/esp_driver_spi/src/gpspi/spi_slave_hd.c +++ b/components/esp_driver_spi/src/gpspi/spi_slave_hd.c @@ -597,8 +597,8 @@ static esp_err_t s_spi_slave_hd_setup_priv_trans(spi_host_device_t host, spi_sla uint16_t alignment = spihost[host]->internal_mem_align_size; uint32_t byte_len = orig_trans->len; - if (((uint32_t)orig_trans->data) | (byte_len & (alignment - 1))) { - ESP_RETURN_ON_FALSE(orig_trans->flags & SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO, ESP_ERR_INVALID_ARG, TAG, "data buffer addr&len not align to %d, or not dma_capable", alignment); + if (((uint32_t)orig_trans->data | byte_len) & (alignment - 1)) { + ESP_RETURN_ON_FALSE(orig_trans->flags & SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO, ESP_ERR_INVALID_ARG, TAG, "data buffer addr&len not align to %d byte, or not dma_capable", alignment); byte_len = (byte_len + alignment - 1) & (~(alignment - 1)); // up align to alignment ESP_LOGD(TAG, "Re-allocate %s buffer of len %" PRIu32 " for DMA", (chan == SPI_SLAVE_CHAN_TX) ? "TX" : "RX", byte_len); priv_trans->aligned_buffer = heap_caps_aligned_alloc(64, byte_len, MALLOC_CAP_DMA); diff --git a/components/esp_driver_spi/test_apps/param/main/test_spi_param.c b/components/esp_driver_spi/test_apps/param/main/test_spi_param.c index 7f507a549b..56515236b1 100644 --- a/components/esp_driver_spi/test_apps/param/main/test_spi_param.c +++ b/components/esp_driver_spi/test_apps/param/main/test_spi_param.c @@ -1644,6 +1644,7 @@ static void test_master_hd_no_dma(void) uint32_t test_trans_len = SOC_SPI_MAXIMUM_BUFFER_SIZE; unity_wait_for_signal("Slave ready"); TEST_ESP_OK(essl_spi_rddma(dev0, master_receive, test_trans_len, -1, 0)); + unity_wait_for_signal("Slave ready"); TEST_ESP_OK(essl_spi_wrdma(dev0, master_send, test_trans_len, -1, 0)); ESP_LOG_BUFFER_HEX("master tx", master_send, test_trans_len); @@ -1691,11 +1692,12 @@ static void test_slave_hd_no_dma(void) .len = test_trans_len, .flags = SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO, }; - unity_send_signal("Slave ready"); TEST_ESP_OK(spi_slave_hd_queue_trans(TEST_SPI_HOST, SPI_SLAVE_CHAN_TX, &slave_trans, portMAX_DELAY)); + unity_send_signal("Slave ready"); + TEST_ESP_OK(spi_slave_hd_get_trans_res(TEST_SPI_HOST, SPI_SLAVE_CHAN_TX, &ret_trans, portMAX_DELAY)); slave_trans.data = slave_receive; TEST_ESP_OK(spi_slave_hd_queue_trans(TEST_SPI_HOST, SPI_SLAVE_CHAN_RX, &slave_trans, portMAX_DELAY)); - TEST_ESP_OK(spi_slave_hd_get_trans_res(TEST_SPI_HOST, SPI_SLAVE_CHAN_TX, &ret_trans, portMAX_DELAY)); + unity_send_signal("Slave ready"); TEST_ESP_OK(spi_slave_hd_get_trans_res(TEST_SPI_HOST, SPI_SLAVE_CHAN_RX, &ret_trans, portMAX_DELAY)); ESP_LOG_BUFFER_HEX("slave tx", slave_send, test_trans_len); From 86741aebd4a0a8a66837d592ba0971f06613bc37 Mon Sep 17 00:00:00 2001 From: wanckl Date: Thu, 28 Nov 2024 11:21:19 +0800 Subject: [PATCH 2/2] fix(driver_spi): fixed slave example error on esp32p4 --- .../peripherals/spi_slave/receiver/main/app_main.c | 9 ++++----- .../spi_slave_hd/append_mode/master/main/app_main.c | 2 +- .../spi_slave_hd/append_mode/slave/main/app_main.c | 4 ++-- .../segment_mode/seg_slave/main/app_main.c | 12 +++++++----- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/examples/peripherals/spi_slave/receiver/main/app_main.c b/examples/peripherals/spi_slave/receiver/main/app_main.c index 8032f2b830..5d1da4ea64 100644 --- a/examples/peripherals/spi_slave/receiver/main/app_main.c +++ b/examples/peripherals/spi_slave/receiver/main/app_main.c @@ -100,11 +100,10 @@ void app_main(void) ret = spi_slave_initialize(RCV_HOST, &buscfg, &slvcfg, SPI_DMA_CH_AUTO); assert(ret == ESP_OK); - WORD_ALIGNED_ATTR char sendbuf[129] = ""; - WORD_ALIGNED_ATTR char recvbuf[129] = ""; - memset(recvbuf, 0, 33); - spi_slave_transaction_t t; - memset(&t, 0, sizeof(t)); + char *sendbuf = spi_bus_dma_memory_alloc(RCV_HOST, 129, 0); + char *recvbuf = spi_bus_dma_memory_alloc(RCV_HOST, 129, 0); + assert(sendbuf && recvbuf); + spi_slave_transaction_t t = {0}; while (1) { //Clear receive buffer, set send buffer to something sane diff --git a/examples/peripherals/spi_slave_hd/append_mode/master/main/app_main.c b/examples/peripherals/spi_slave_hd/append_mode/master/main/app_main.c index b16711641a..480921c982 100644 --- a/examples/peripherals/spi_slave_hd/append_mode/master/main/app_main.c +++ b/examples/peripherals/spi_slave_hd/append_mode/master/main/app_main.c @@ -24,7 +24,7 @@ #define GPIO_CS 10 #define HOST_ID SPI2_HOST -#define TRANSACTION_LEN 16 +#define TRANSACTION_LEN 64 //The SPI transaction cycles in this example. You may change the cycle. e.g., use the ``sender`` and change it to a infinite loop #define EXAMPLE_CYCLES 10 diff --git a/examples/peripherals/spi_slave_hd/append_mode/slave/main/app_main.c b/examples/peripherals/spi_slave_hd/append_mode/slave/main/app_main.c index 49676693b3..88065a994d 100644 --- a/examples/peripherals/spi_slave_hd/append_mode/slave/main/app_main.c +++ b/examples/peripherals/spi_slave_hd/append_mode/slave/main/app_main.c @@ -25,7 +25,7 @@ #define HOST_ID SPI2_HOST #define QUEUE_SIZE 6 -#define TRANSACTION_LEN 16 +#define TRANSACTION_LEN 64 #define SYNC_REG_FROM_HOST (14 * 4) #define SYNC_REG_TO_HOST (15 * 4) @@ -72,7 +72,7 @@ static esp_err_t create_transaction_pool(uint8_t **data_buf, trans_link_t *trans { for (int i = 0; i < times; i++) { //malloc data buffers for transaction - data_buf[i] = heap_caps_calloc(1, TRANSACTION_LEN, MALLOC_CAP_DMA); + data_buf[i] = spi_bus_dma_memory_alloc(HOST_ID, TRANSACTION_LEN, 0); if (!data_buf[i]) { ESP_LOGI("Create pool:", "No enough memory"); return ESP_ERR_NO_MEM; diff --git a/examples/peripherals/spi_slave_hd/segment_mode/seg_slave/main/app_main.c b/examples/peripherals/spi_slave_hd/segment_mode/seg_slave/main/app_main.c index ad59703d6b..e13c3b1499 100644 --- a/examples/peripherals/spi_slave_hd/segment_mode/seg_slave/main/app_main.c +++ b/examples/peripherals/spi_slave_hd/segment_mode/seg_slave/main/app_main.c @@ -198,7 +198,9 @@ void sender(void *arg) data_ready = get_tx_data(send_buf[descriptor_id], send_buf_size, &ready_data_size); if (data_ready) { slave_trans[descriptor_id].data = send_buf[descriptor_id]; - slave_trans[descriptor_id].len = ready_data_size; + slave_trans[descriptor_id].len = send_buf_size; + //To use dma, data buffer address and trans_len should byte align to hardware requirement, or using following flag for auto deal by driver. + slave_trans[descriptor_id].flags |= SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO; //Due to the `queue_sent_cnt` and `queue_recv_cnt` logic above, we are sure there is space to send data, this will return ESP_OK immediately ESP_ERROR_CHECK(spi_slave_hd_queue_trans(SLAVE_HOST, SPI_SLAVE_CHAN_TX, &slave_trans[descriptor_id], portMAX_DELAY)); descriptor_id = (descriptor_id + 1) % QUEUE_SIZE; //descriptor_id will be: 0, 1, 2, ..., QUEUE_SIZE, 0, 1, .... @@ -234,7 +236,7 @@ void receiver(void *arg) uint8_t *recv_buf[QUEUE_SIZE]; spi_slave_hd_data_t slave_trans[QUEUE_SIZE]; for (int i = 0; i < QUEUE_SIZE; i++) { - recv_buf[i] = heap_caps_calloc(1, recv_buf_size, MALLOC_CAP_DMA); + recv_buf[i] = spi_bus_dma_memory_alloc(SLAVE_HOST, recv_buf_size, MALLOC_CAP_8BIT); if (!recv_buf[i]) { ESP_LOGE(TAG, "No enough memory!"); abort(); @@ -249,6 +251,7 @@ void receiver(void *arg) for (int i = 0; i < QUEUE_SIZE; i++) { slave_trans[descriptor_id].data = recv_buf[descriptor_id]; slave_trans[descriptor_id].len = recv_buf_size; + slave_trans[descriptor_id].flags |= SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO; ESP_ERROR_CHECK(spi_slave_hd_queue_trans(SLAVE_HOST, SPI_SLAVE_CHAN_RX, &slave_trans[descriptor_id], portMAX_DELAY)); descriptor_id = (descriptor_id + 1) % QUEUE_SIZE; //descriptor_id will be: 0, 1, 2, ..., QUEUE_SIZE, 0, 1, .... } @@ -266,7 +269,6 @@ void receiver(void *arg) */ ESP_ERROR_CHECK(spi_slave_hd_get_trans_res(SLAVE_HOST, SPI_SLAVE_CHAN_RX, &ret_trans, portMAX_DELAY)); //Process the received data in your own code. Here we just print it out. - printf("%d bytes are received: \n%s\n", ret_trans->trans_len, ret_trans->data); memset(ret_trans->data, 0x0, recv_buf_size); /** @@ -288,10 +290,10 @@ void app_main(void) uint8_t init_value[SOC_SPI_MAXIMUM_BUFFER_SIZE] = {0x0}; spi_slave_hd_write_buffer(SLAVE_HOST, 0, init_value, SOC_SPI_MAXIMUM_BUFFER_SIZE); - static uint32_t send_buf_size = 5000; + static uint32_t send_buf_size = 4800; spi_slave_hd_write_buffer(SLAVE_HOST, SLAVE_MAX_TX_BUF_LEN_REG, (uint8_t *)&send_buf_size, sizeof(send_buf_size)); - static uint32_t recv_buf_size = 120; + static uint32_t recv_buf_size = 128; spi_slave_hd_write_buffer(SLAVE_HOST, SLAVE_MAX_RX_BUF_LEN_REG, (uint8_t *)&recv_buf_size, sizeof(recv_buf_size)); uint32_t slave_ready_flag = SLAVE_READY_FLAG;