Skip to content

Commit

Permalink
fix(esp_driver_spi): Make spi_bus_free() exit early on issues
Browse files Browse the repository at this point in the history
If for example there are still devices configured on the bus
spi_bus_free() will report that with ESP_ERR_INVALID_STATE, but not
before it frees all other things like IO and DMA. This means that
after the function exits any other task that is still running and
using those devices will all of a sudden stop working (and probably
crash the device).

This commit prevents that situation by making the function return
early so it can be called again safely later when all devices have
been removed.

Closes #13856
  • Loading branch information
MathyV authored and wanckl committed May 28, 2024
1 parent 43af0fb commit d35239d
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 0 deletions.
3 changes: 3 additions & 0 deletions components/esp_driver_spi/src/gpspi/spi_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,9 @@ esp_err_t spi_bus_free(spi_host_device_t host_id)

if (ctx->destroy_func) {
err = ctx->destroy_func(ctx->destroy_arg);
if (err != ESP_OK) {
return err;
}
}
spicommon_bus_free_io_cfg(&bus_attr->bus_cfg);

Expand Down
27 changes: 27 additions & 0 deletions components/esp_driver_spi/test_apps/master/main/test_spi_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -1757,3 +1757,30 @@ static void test_iram_slave_normal(void)

TEST_CASE_MULTIPLE_DEVICES("SPI_Master:IRAM_safe", "[spi_ms]", test_master_iram, test_iram_slave_normal);
#endif

TEST_CASE("test_bus_free_safty_to_remain_devices", "[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_handle_t dev0, dev1;
spi_device_interface_config_t devcfg = SPI_DEVICE_TEST_DEFAULT_CONFIG();
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &dev0));
devcfg.spics_io_num = PIN_NUM_MISO;
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &dev1));

int master_send;
spi_transaction_t trans_cfg = {
.tx_buffer = &master_send,
.length = sizeof(uint32_t) * 8,
};

TEST_ESP_OK(spi_bus_remove_device(dev0));
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, spi_bus_free(TEST_SPI_HOST));

//transaction should OK after a failed call to bus_free
TEST_ESP_OK(spi_device_transmit(dev1, (spi_transaction_t *)&trans_cfg));

TEST_ESP_OK(spi_bus_remove_device(dev1));
TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST));
}

0 comments on commit d35239d

Please sign in to comment.