ESP32C6 - spi_device_queue_trans hangs

NicolasMontoya
Posts: 2
Joined: Fri Nov 14, 2025 3:12 am

ESP32C6 - spi_device_queue_trans hangs

Postby NicolasMontoya » 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

Code: Select all

spi_device_queue_trans
Here is what I am doing:

Code: 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()
I am setting up the bus like so:

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;
    }
Here is what I get for my logs:
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()
As you can see from the attached image, the write happens just fine, but it just hangs after "Starting SPI transaction..."

I have tried with

Code: Select all

spi_device_polling_transmit
as well, but it does the same thing...
Attachments
Screenshot 2025-11-13 211956.png
Screenshot 2025-11-13 211956.png (60.57 KiB) Viewed 2204 times

nopnop2002
Posts: 347
Joined: Thu Oct 03, 2019 10:52 pm
Contact:

Re: ESP32C6 - spi_device_queue_trans hangs

Postby nopnop2002 » Sat Nov 15, 2025 3:54 am

I don't know why, but there is no MISO signal.

NicolasMontoya
Posts: 2
Joined: Fri Nov 14, 2025 3:12 am

Re: ESP32C6 - spi_device_queue_trans hangs

Postby NicolasMontoya » Mon Nov 17, 2025 2:48 pm

Yes its becaues the CS stays high the entire time.. For some reason the SPI driver cannot take control of the CS line..

nopnop2002
Posts: 347
Joined: Thu Oct 03, 2019 10:52 pm
Contact:

Re: ESP32C6 - spi_device_queue_trans hangs

Postby nopnop2002 » Tue Nov 18, 2025 5:18 am

For some reason the SPI driver cannot take control of the CS line..

This is why the SPI driver is not controlling the CS line.

Code: Select all

devcfg.spics_io_num = -1;                   /* CS handled manually */

Who is online

Users browsing this forum: Google [Bot] and 2 guests