Page 1 of 1

ESP32-S3 - Can't send SPI transaction of more than one DMA max payload size?

Posted: Wed Jan 03, 2024 1:47 pm
by faptastic
I want to be able to send an SPI 8-bit transaction of about 32kBytes (so 4000 bits in parallel), but the ESP32-S3 doesn't ever send more than one DMA linked list's worth of data?

If I create an spi_transaction_t of 32k, I only ever get about one DMA max payload lengths worth of data?

Is there some bug in the IDF?

Code: Untitled.c Select all

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/spi_master.h"
#include "driver/gpio.h"
#include "hal/gpio_types.h"
#include "soc/spi_reg.h"
#include "soc/spi_struct.h"


// SPI2 on ESP32-S3 supports 8-bit Octal SPI mode
#define LCD_HOST SPI2_HOST


void spi_post_transfer_callback(spi_transaction_t *t)
{

}

static void send_lines(spi_device_handle_t spi, int ypos, uint8_t *linedata)
{

esp_err_t ret;
int x;

//Transaction descriptors. Declared static so they're not allocated on the stack; we need this memory even when this
//function is finished because the SPI driver needs access to it even while we're already calculating the next line.
static spi_transaction_t trans_msg;
trans_msg.flags = SPI_TRANS_MODE_OCT;
trans_msg.tx_buffer = linedata; //finally send the line data
trans_msg.length = 31000; //Data length, in bits

// ret = spi_device_queue_trans(spi, &trans_msg, portMAX_DELAY);
// assert(ret == ESP_OK);

ret = spi_device_polling_transmit(spi, &trans_msg); // Transmit!
assert(ret == ESP_OK); // Should have had no issues.

}

void setup() {

// put your setup code here, to run once:
esp_err_t ret;
spi_device_handle_t spi;

spi_bus_config_t buscfg = {
.data0_io_num = 5, // A
.data1_io_num = 4, // B
.sclk_io_num = 42, // C
.data2_io_num = 7, // D
.data3_io_num = 41, // E
.data4_io_num = 1, // oe
.data5_io_num = 6, // lat
.data6_io_num = 2, // clk
.data7_io_num = 48, // sr
.max_transfer_sz = 32768, // ESP32 S3 max size is 64Kbytes
.flags = (SPICOMMON_BUSFLAG_OCTAL | SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_GPIO_PINS), // kinda important
};

//Configure SPI Device
spi_device_interface_config_t devcfg = {
.command_bits = 0,
.address_bits = 0,
.dummy_bits = 0,
.mode = 0, // SPI mode 0
.duty_cycle_pos = 0,
.cs_ena_pretrans = 0,
.cs_ena_posttrans = 0,
.clock_speed_hz = SPI_MASTER_FREQ_8M, // Clock out at 10 MHz
.input_delay_ns = 0,
.spics_io_num = -1, // CS pin

// SPI_DEVICE_NO_RETURN_RESULT = Don't care abut result
//.flags = (SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_NO_RETURN_RESULT),
.flags = (SPI_DEVICE_HALFDUPLEX ),
.queue_size = 10,
.pre_cb = 0, // Not used
.post_cb = spi_post_transfer_callback,

};

//Initialize the SPI bus
ret = spi_bus_initialize(LCD_HOST, &buscfg, SPI_DMA_CH_AUTO);
ESP_ERROR_CHECK(ret);

//Attach the LCD to the SPI bus
ret = spi_bus_add_device(LCD_HOST, &devcfg, &spi);
ESP_ERROR_CHECK(ret);

size_t max_trans_bytes = 0;
ret = spi_bus_get_max_transaction_len(LCD_HOST, &max_trans_bytes);
assert(ret == ESP_OK);
ESP_LOGI("S3", "Max transfer size is %u", (uint32_t)max_trans_bytes);


uint8_t *output_data;
output_data = (uint8_t *) heap_caps_malloc(31000 * sizeof(uint8_t), MALLOC_CAP_DMA);
assert(output_data != NULL);

// Doesn't send data after about the 4096 boundary?
int offset = 4096;
memset(output_data, (uint8_t)0x00, 31000);
memset(output_data+offset, (uint8_t)0xff, 31000-offset); // overwrite from offset with 0xff

while (1)
{
send_lines(spi, 0, output_data);
}


} // setup

void loop() {
// put your main code here, to run repeatedly:

}

Re: ESP32-S3 - Can't send SPI transaction of more than one DMA max payload size?

Posted: Wed Jan 03, 2024 9:32 pm
by MicroController
trans_msg.length = 31000; //Data length, in bits
That'd be 3875 bytes...

Re: ESP32-S3 - Can't send SPI transaction of more than one DMA max payload size?

Posted: Thu Jan 04, 2024 9:52 am
by faptastic
That doesn't make sense when I'm sending in 8-bit parallel.

So I need to multiply by 8 even though it is only 31000 bit LENGTH of the transmission... just there are 8 serial lines in parallel.

On another note, the SPI driver code is a dog's breakfast. Espressif could have coded this better.

Re: ESP32-S3 - Can't send SPI transaction of more than one DMA max payload size?

Posted: Thu Jan 04, 2024 10:33 am
by MicroController
So I need to multiply by 8 even though it is only 31000 bit LENGTH of the transmission... just there are 8 serial lines in parallel.
Depends on what you define as the "bit length" of 8 bits in parallel...
Read it as the length of the message/data in tx_buffer and it makes sense :)