fix(esp_hw_support): fixed spi buslock multi dev acq/release logic issue

This commit is contained in:
wanckl
2026-04-20 18:31:20 +08:00
committed by Wan Lei
parent c88902ae28
commit 8ee2dce0d6
6 changed files with 186 additions and 33 deletions

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2010-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2010-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -162,8 +162,8 @@ esp_err_t spi_slave_hd_init(spi_host_device_t host_id, const spi_bus_config_t *b
.dma_enabled = host->dma_enabled,
.append_mode = append_mode,
.mode = config->mode,
.tx_lsbfirst = (config->flags & SPI_SLAVE_HD_RXBIT_LSBFIRST),
.rx_lsbfirst = (config->flags & SPI_SLAVE_HD_TXBIT_LSBFIRST),
.tx_lsbfirst = (config->flags & SPI_SLAVE_HD_TXBIT_LSBFIRST),
.rx_lsbfirst = (config->flags & SPI_SLAVE_HD_RXBIT_LSBFIRST),
};
//Init the hal according to the hal_config set above

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -44,7 +44,7 @@
#if !CONFIG_FREERTOS_SMP // IDF-5223
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING 15
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING_NO_DMA 15
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING 33
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING 35
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING_NO_DMA 30
#else
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING 17
@@ -55,8 +55,8 @@
#elif CONFIG_IDF_TARGET_ESP32C6
#define IDF_PERFORMANCE_MAX_SPI_CLK_FREQ 26*1000*1000
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING 35 //TODO: IDF-9551, check perform
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING 17
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING 37 //TODO: IDF-9551, check perform
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING 19
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING_NO_DMA 32
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING_NO_DMA 15

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -347,3 +347,61 @@ TEST_CASE("spi master can be used on SPI1", "[spi]")
//TODO: add a case when a non-polling transaction happened in the bus-acquiring time and then release the bus then queue a new trans
#endif //!(CONFIG_SPIRAM && CONFIG_IDF_TARGET_ESP32)
#define TEST_LARGE_TRANS_LEN 2048
static void dev2_polling_task(void *arg)
{
task_context_t *ctx = (task_context_t *)arg;
spi_transaction_t t = {
.flags = SPI_TRANS_USE_TXDATA,
.length = 32,
};
while (!ctx->finished) {
TEST_ESP_OK(spi_device_polling_transmit(ctx->handle, &t));
vTaskDelay(pdMS_TO_TICKS(1));
}
vTaskDelete(NULL);
}
TEST_CASE("release_bus during flying is safe to other device acquiring", "[spi]")
{
spi_bus_config_t buscfg = SPI_BUS_TEST_DEFAULT_CONFIG();
TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
spi_device_interface_config_t devcfg_p = SPI_DEVICE_TEST_DEFAULT_CONFIG();
spi_device_interface_config_t devcfg_q = SPI_DEVICE_TEST_DEFAULT_CONFIG();
devcfg_q.spics_io_num = -1;
devcfg_q.queue_size = 3;
devcfg_q.clock_speed_hz = 500 * 1000;
spi_device_handle_t dev_q;
task_context_t ctx = {};
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg_p, &ctx.handle));
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg_q, &dev_q));
// polling task with higher priority than the interrupt task
xTaskCreate(dev2_polling_task, "spi17860_p", 4096, &ctx, 6, NULL);
uint8_t *q_txb = heap_caps_malloc(TEST_LARGE_TRANS_LEN, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
spi_transaction_t *ret_trans, trans = {
.length = TEST_LARGE_TRANS_LEN * 8,
.tx_buffer = q_txb,
};
for (int i = 0; i < 30; i++) {
TEST_ESP_OK(spi_device_acquire_bus(dev_q, portMAX_DELAY));
TEST_ESP_OK(spi_device_queue_trans(dev_q, &trans, portMAX_DELAY));
esp_rom_printf("queue trans %d\n", i);
spi_device_release_bus(dev_q);
}
ctx.finished = true;
vTaskDelay(pdMS_TO_TICKS(100)); // wait for all trans finished
for (int i = 0; i < devcfg_q.queue_size; i++) {
spi_device_get_trans_result(dev_q, &ret_trans, 0);
}
free(q_txb);
TEST_ESP_OK(spi_bus_remove_device(ctx.handle));
TEST_ESP_OK(spi_bus_remove_device(dev_q));
TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST));
}