Ошибка функции 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. |