ESP32C6 - spi_device_queue_trans hangs
Posted: Fri Nov 14, 2025 3:21 am
Hello,
I am trying to perform a simple SPI transaction of 3 bytes, and the ESP32C6 hangs when doing
Here is what I am doing:
I am setting up the bus like so:
Here is what I get for my logs:
I have tried with as well, but it does the same thing...
I am trying to perform a simple SPI transaction of 3 bytes, and the ESP32C6 hangs when doing
Code: Select all
spi_device_queue_transCode: Select all
int writetospi(uint16_t headerLength,
const uint8_t *headerBuffer,
uint32_t bodyLength,
const uint8_t *bodyBuffer)
{
ESP_LOGI(TAG, "writetospi: Entering, headerLen=%d, bodyLen=%d", headerLength, bodyLength);
if (!spi_initialized || spi_device == NULL) {
ESP_LOGE(TAG, "writetospi: SPI not initialized");
return -1;
}
ESP_LOGI(TAG, "writetospi: SPI initialized, about to acquire mutex");
decaIrqStatus_t stat = decamutexon();
ESP_LOGI(TAG, "writetospi: Mutex acquired");
/* Prepare transaction */
ESP_LOGI(TAG, "writetospi: Preparing transaction structure");
spi_transaction_t trans = {};
uint8_t *tx_buffer = NULL;
uint8_t *rx_buffer = NULL; /* Dummy RX buffer - ESP-IDF may require this even for write-only */
uint32_t total_length = headerLength + bodyLength;
ESP_LOGI(TAG, "writetospi: Total length=%d bytes", total_length);
/* Allocate buffer for combined header and body */
if (total_length > 0) {
ESP_LOGI(TAG, "writetospi: Allocating TX buffer of %d bytes", total_length);
tx_buffer = (uint8_t *)malloc(total_length);
if (tx_buffer == NULL) {
ESP_LOGE(TAG, "writetospi: Failed to allocate TX buffer");
if (rx_buffer != NULL) free(rx_buffer);
decamutexoff(stat);
return -1;
}
ESP_LOGI(TAG, "writetospi: TX buffer allocated successfully");
/* Allocate dummy RX buffer - ESP-IDF may need this even for write-only transactions */
rx_buffer = (uint8_t *)malloc(total_length);
if (rx_buffer == NULL) {
ESP_LOGE(TAG, "writetospi: Failed to allocate RX buffer");
free(tx_buffer);
decamutexoff(stat);
return -1;
}
ESP_LOGI(TAG, "writetospi: RX buffer allocated successfully");
/* Copy header */
if (headerLength > 0 && headerBuffer != NULL) {
ESP_LOGI(TAG, "writetospi: Copying header, length=%d, header[0]=0x%02X", headerLength, headerBuffer[0]);
memcpy(tx_buffer, headerBuffer, headerLength);
ESP_LOGI(TAG, "writetospi: Header copied");
}
/* Copy body */
if (bodyLength > 0 && bodyBuffer != NULL) {
ESP_LOGI(TAG, "writetospi: Copying body, length=%d", bodyLength);
memcpy(tx_buffer + headerLength, bodyBuffer, bodyLength);
ESP_LOGI(TAG, "writetospi: Body copied");
}
trans.length = total_length * 8; /* Length in bits */
trans.tx_buffer = tx_buffer;
trans.rx_buffer = rx_buffer; /* Provide dummy RX buffer - ESP-IDF may require this */
trans.rxlength = total_length * 8; /* Set rxlength to match length - ESP-IDF may require this */
/* With spics_io_num = -1 (manual CS), we don't use SPI_TRANS_CS_KEEP_ACTIVE
* The driver knows CS is manual and won't try to control it */
trans.flags = 0;
ESP_LOGI(TAG, "writetospi: Transaction prepared, length=%d bits, rxlength=%d bits, flags=0", trans.length, trans.rxlength);
}
/* Acquire SPI bus - required when using manual CS control */
ESP_LOGI(TAG, "writetospi: Acquiring SPI bus");
esp_err_t ret = spi_device_acquire_bus(spi_device, portMAX_DELAY);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "writetospi: Failed to acquire SPI bus: %s (0x%x)", esp_err_to_name(ret), ret);
if (tx_buffer != NULL) free(tx_buffer);
if (rx_buffer != NULL) free(rx_buffer);
decamutexoff(stat);
return -1;
}
ESP_LOGI(TAG, "writetospi: SPI bus acquired");
/* Manual CS control - pull CS low BEFORE transaction */
ESP_LOGI(TAG, "writetospi: Setting CS low before transaction");
port_SPIx_clear_chip_select();
ESP_LOGI(TAG, "writetospi: CS set low");
/* Small delay to ensure CS is stable before starting transaction */
// usleep(10); /* 10 microseconds */
/* Perform transaction using spi_device_transmit (queue-based, blocking)
* With spics_io_num = -1, the driver knows CS is manual and won't try to control it */
ESP_LOGI(TAG, "writetospi: Starting SPI transaction with spi_device_transmit()");
ret = spi_device_queue_trans(spi_device, &trans, 200);
ESP_LOGI(TAG, "writetospi: spi_device_polling_transmit() returned: %s (0x%x)", esp_err_to_name(ret), ret);
/* Manual CS control - pull CS high AFTER transaction */
ESP_LOGI(TAG, "writetospi: Setting CS high after transaction");
port_SPIx_set_chip_select();
ESP_LOGI(TAG, "writetospi: CS set high");
/* Release SPI bus */
spi_device_release_bus(spi_device);
ESP_LOGI(TAG, "writetospi: SPI bus released");
if (ret != ESP_OK) {
ESP_LOGE(TAG, "writetospi: SPI transmit failed: %s", esp_err_to_name(ret));
}
#ifdef ESP_PLATFORM
/* Yield to scheduler to prevent interrupt watchdog timeout */
taskYIELD();
#endif
/* Free buffers */
if (tx_buffer != NULL) {
free(tx_buffer);
}
if (rx_buffer != NULL) {
free(rx_buffer);
}
decamutexoff(stat);
return (ret == ESP_OK) ? 0 : -1;
} // end writetospi()
Code: Select all
/* Configure SPI bus */
spi_bus_config_t buscfg = {};
buscfg.mosi_io_num = config->mosi_pin;
buscfg.miso_io_num = config->miso_pin;
buscfg.sclk_io_num = config->sclk_pin;
buscfg.quadwp_io_num = -1;
buscfg.quadhd_io_num = -1;
buscfg.max_transfer_sz = 4096;
/* Initialize the SPI bus */
esp_err_t ret = spi_bus_initialize(config->spi_host, &buscfg, SPI_DMA_DISABLED);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "openspi: Failed to initialize SPI bus: %s", esp_err_to_name(ret));
return -1;
}
/* Configure SPI device */
spi_device_interface_config_t devcfg = {};
devcfg.clock_speed_hz = SPI_SLOW_CLOCK_HZ; /* Start with slow clock (2 MHz) */
devcfg.mode = 0; /* SPI mode 0 (CPOL=0, CPHA=0) - clock idle low, data sampled on rising edge */
devcfg.spics_io_num = -1; /* CS handled manually */
devcfg.queue_size = 1;
devcfg.flags = 0; /* MSB first (default), no special flags */
devcfg.input_delay_ns = 0; /* No input delay */
devcfg.pre_cb = NULL; /* No pre-callback */
devcfg.post_cb = NULL; /* No post-callback */
devcfg.cs_ena_pretrans = 0; /* No CS pre-transmission delay (manual CS) */
devcfg.cs_ena_posttrans = 0; /* No CS post-transmission delay (manual CS) */
/* Add device to SPI bus */
ret = spi_bus_add_device(config->spi_host, &devcfg, &spi_device);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "openspi: Failed to add SPI device: %s", esp_err_to_name(ret));
spi_bus_free(config->spi_host);
return -1;
}
As you can see from the attached image, the write happens just fine, but it just hangs after "Starting SPI transaction..."I (356) dwt_init: dwt_initialise: About to call dwt_write16bitoffsetreg(SYS_CFG_ID=4, 0, 0x0400)
I (356) dwt_init: dwt_write16bitoffsetreg: Entering, regFileID=0x04, regOffset=0, regval=0x0400
I (366) dwt_init: dwt_write16bitoffsetreg: Buffer prepared [0x00, 0x04], about to call dwt_writetodevice()
I (376) dwt_init: dwt_writetodevice: Entering, recordNumber=0x04, index=0, length=2
I (376) dwt_init: dwt_writetodevice: Header prepared, cnt=1, header[0]=0x84, about to call writetospi()
I (386) deca_spi: writetospi: Entering, headerLen=1, bodyLen=2
I (396) deca_spi: writetospi: SPI initialized, about to acquire mutex
I (396) deca_mutex: decamutexon: About to take mutex
I (406) deca_mutex: decamutexon: Mutex taken successfully
I (406) deca_spi: writetospi: Mutex acquired
I (416) deca_spi: writetospi: Preparing transaction structure
I (416) deca_spi: writetospi: Total length=3 bytes
I (426) deca_spi: writetospi: Allocating TX buffer of 3 bytes
I (426) deca_spi: writetospi: TX buffer allocated successfully
I (436) deca_spi: writetospi: RX buffer allocated successfully
I (436) deca_spi: writetospi: Copying header, length=1, header[0]=0x84
I (446) deca_spi: writetospi: Header copied
I (446) deca_spi: writetospi: Copying body, length=2
I (456) deca_spi: writetospi: Body copied
I (456) deca_spi: writetospi: Transaction prepared, length=24 bits, rxlength=24 bits, flags=0
I (466) deca_spi: writetospi: Acquiring SPI bus
I (476) deca_spi: writetospi: SPI bus acquired
I (476) deca_spi: writetospi: Setting CS low before transaction
I (486) deca_spi: writetospi: CS set low
I (486) deca_spi: writetospi: Starting SPI transaction with spi_device_transmit()
I have tried with
Code: Select all
spi_device_polling_transmit