Программирование ARM: решение проблем, FAQ Ошибка функции spi_bus_remove_device: Have unfinished transactions Sat, December 21 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.


Ошибка функции spi_bus_remove_device: Have unfinished transactions Печать
Добавил(а) microsin   

Ошибка функции spi_bus_remove_device: Have unfinished transactions

При попытке освободить аппаратуру SPI2 на микроконтроллере ESP32-C3 наткнулся на ошибку "Have unfinished transactions" при вызове функции spi_bus_remove_device:

void spi2_deinit(void)
{
  spi_transaction_t *rtrans;
  ESP_ERROR_CHECK(spi_device_get_trans_result(spi, &rtrans, portMAX_DELAY));
  ESP_ERROR_CHECK(spi_bus_remove_device(spi));  // Ошибка: Have unfinished transactions
  ESP_ERROR_CHECK(spi_bus_free(SPI2_HOST));
}

SPI2 использовался на передачу в режиме interrupt-транзакций [1] для управления RGB-светодиодами [2]. Проблема была в том, что несмотря на то, что даже если SPI2 работает только на передачу, в очереди приема все равно накапливаются сообщения. В функции spi_bus_remove_device производится проверка, что все очереди пустые, и приема, и передачи, и если это не так, то выводится ошибка "Have unfinished transactions":

SPI_CHECK(uxQueueMessagesWaiting(handle->ret_queue)==0, "Have unfinished transactions", ESP_ERR_INVALID_STATE);

Если не нужно освобождать шину SPI (вызывать spi_bus_remove_device, spi_bus_free), то на заполнение очереди приема можно не обращать внимания. Даже если она переполнится, передача все равно будет нормально работать (в драйвере spi_master.c не делается проверка на переполнении очереди при её заполнении). Однако если необходимо вызвать spi_bus_remove_device, то очереди приема и передачи нужно освободить. Иначе возникнет вышеупомянутая ошибка "spi_bus_remove_device: Have unfinished transactions".

Как в этом случае можно решить проблему:

1. Перед вызовом spi_bus_remove_device запустить цикл вызовов spi_device_queue_trans, который освободит очередь приема:

void spi2_deinit(void)
{
  spi_transaction_t *rtrans;
  // Цикл для очистки очереди приема:
  do {} while(ESP_OK == spi_device_get_trans_result(spi, &rtrans, 1));
  ESP_ERROR_CHECK(spi_bus_remove_device(spi));
  ESP_ERROR_CHECK(spi_bus_free(SPI2_HOST);
}

2. После каждого запуска транзакции вызывать функцию spi_device_get_trans_result:

  ESP_ERROR_CHECK(spi_device_queue_trans(spi, &t, portMAX_DELAY));
  spi_transaction_t *rtrans;
  ESP_ERROR_CHECK(spi_device_get_trans_result(spi, &rtrans, portMAX_DELAY));

3. Воспользоваться вызовом xQueueReset для очистки очереди приема:

xQueueReset(ret_queue);

Последний вариант требует модификации драйвера spi_master.c - надо сохранить дескриптор очереди приема при инициализации драйвера.

[Ссылки]

1. ESP32-C3: драйвер SPI Master.
2. WS2811: микросхема для управления трехцветным RGB-светодиодом.

 

Добавить комментарий


Защитный код
Обновить

Top of Page