I have created a 'simple' example of using ESP32S3's Segmented Transfer mode for SPI in order to create a continuous loop.
However, I can NEVER get it to trigger a SPI_DMA_SEG_TRANS_DONE_INT interrupt never seems to trigger, no matter what I do.
https://github.com/mrcodetastic/esp32s3 ... x_seg_loop
I have this function that ends the transfer by setting the linked list to end, but even that won't cause an interrupt to be generated!
Code: Select all
// Doesn't quite clean up cleanly.
esp_err_t spi_transfer_loop_stop(void) {
const spi_bus_attr_t* bus_attr = spi_bus_get_attr(SPI2_HOST);
// Disconnect the looping DMA transfer to cause the transfer to finish
ESP_LOGD(TAG, "Calling spi_transfer_loop_stop()");
dma_data_lldesc[dma_lldesc_required-1].eof = 1;
dma_data_lldesc[dma_lldesc_required-1].qe.stqe_next = NULL;
return ESP_OK;
}
Code: Select all
esp_err_t spi_transfer_loop_start()
{
// Setup interrupt
static intr_handle_t intr;
esp_intr_alloc (ETS_SPI2_DMA_INTR_SOURCE, ESP_INTR_FLAG_SHARED, dma_isr3, NULL, &intr);
esp_intr_alloc (ETS_SPI2_INTR_SOURCE, ESP_INTR_FLAG_SHARED, dma_isr3, NULL, &intr);
esp_intr_enable (intr);
dma_isr3(0); // increase count to 1
esp_err_t err;
// Dispatch transaction; link_trans will finish it off
ESP_LOGD(TAG, "Initial Transfer");
static spi_transaction_t trans;
trans.flags = SPI_TRANS_MODE_OCT;
// What do we do here? TO DO, send null packet just to kick off transfer?
// https://www.esp32.com/viewtopic.php?p=123221#p123211
trans.tx_buffer = spi_tx_payload_testchunk2;
trans.length = (sizeof(spi_tx_payload_testchunk2)) * 8;
trans.rx_buffer = NULL;
trans.rxlength = 0;
CHECK_CALLE(spi_device_polling_start(spi_device, &trans, portMAX_DELAY), "Could not start SPI transfer");
//esp_register_shutdown_handler(vga_deinit);
ESP_LOGD(TAG, "spi_transfer_loop_start() complete");
return ESP_OK;
}
esp_err_t spi_transfer_loop_start_2()
{
// Need to do first start first to set registers.
ESP_LOGD(TAG, "Part 2");
// TODO; Figure out a way to get interrupts working, and when the GCLK segement has completed and about to restert - then allow a DCLK / Greyscale transfer
// AT THE SAME TIME
// esp_intr_alloc_intrstatus(ETS_SPI2_INTR_SOURCE, ESP_INTR_FLAG_SHARED, (uint32_t)&GPSPI2.dma_int_st.val, SPI_DMA_SEG_TRANS_DONE_INT_ENA_M, dma_isr2, NULL, &intr);
GPSPI2.slave.dma_seg_magic_value = 0xA;
const spi_bus_attr_t* bus_attr = spi_bus_get_attr(SPI2_HOST);
// hal->dmadesc_tx = &dma_data_lldesc[0]; // START OFF A DESCRIPTOR 0
spi_dma_ll_tx_reset(&GDMA, bus_attr->tx_dma_chan);
spi_ll_dma_tx_fifo_reset(&GPSPI2);
spi_ll_outfifo_empty_clr(&GPSPI2);
spi_ll_dma_tx_enable(&GPSPI2, 1);
spi_dma_ll_tx_start(&GDMA, bus_attr->tx_dma_chan, &dma_data_lldesc[0]);
GPSPI2.slave.usr_conf = 1; // Enable user conf for segmented transfers
GPSPI2.user.usr_conf_nxt = 1;
GPSPI2.misc.cs0_dis = 1; // turn off client select pin
// 13. Set SPI_DMA_SEG_TRANS_DONE_INT_ENA to enable the SPI_DMA_SEG_TRANS_DONE_INT interrupt.
// Configure other interrupts if needed according to Section 30.10.
//esp_intr_free(spi_device->host->intr);
spi_ll_clear_intr(&GPSPI2, SPI_LL_INTR_TRANS_DONE); // need this for the transacion to start
spi_ll_clear_intr(&GPSPI2, SPI_LL_INTR_SEG_DONE); // need this for the transacion to start
GPSPI2.dma_int_ena.dma_seg_trans_done = 1; // Doesn't work, so can't use it. :-(
GPSPI2.dma_int_ena.trans_done = 1; // Doesn't work, so can't use it. :-(
GPSPI2.cmd.conf_bitlen = 0;
// Configure interrupt
// TODO; Figure out a way to get interrupts working, and when the GCLK segement has completed and about to restert - then allow a DCLK / Greyscale transfer
// AT THE SAME TIME
// esp_intr_alloc_intrstatus(ETS_SPI2_INTR_SOURCE, ESP_INTR_FLAG_SHARED, (uint32_t)&GPSPI2.dma_int_st.val, SPI_DMA_SEG_TRANS_DONE_INT_ENA_M, dma_isr2, NULL, &intr);
//esp_intr_free(spi_device->host->intr);
//spi_ll_clear_int_stat (spi_device->host->hal.hw);
GPSPI2.cmd.update = 1;
while (GPSPI2.cmd.update); //waiting config applied
// start trans
GPSPI2.cmd.usr = 1;
//esp_register_shutdown_handler(vga_deinit);
ESP_LOGD(TAG, "spi_transfer_loop_start_2() complete");
return ESP_OK;
}