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

faptastic
Posts: 15
Joined: Mon Nov 14, 2022 10:38 pm

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

Postby faptastic » Wed Jan 03, 2024 1:47 pm

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?
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <inttypes.h>
  5. #include "freertos/FreeRTOS.h"
  6. #include "freertos/task.h"
  7. #include "esp_system.h"
  8. #include "driver/spi_master.h"
  9. #include "driver/gpio.h"
  10. #include "hal/gpio_types.h"
  11. #include "soc/spi_reg.h"
  12. #include "soc/spi_struct.h"
  13.  
  14.  
  15. // SPI2 on ESP32-S3 supports 8-bit Octal SPI mode
  16. #define LCD_HOST    SPI2_HOST
  17.  
  18.  
  19. void spi_post_transfer_callback(spi_transaction_t *t)
  20. {
  21.  
  22. }
  23.  
  24. static void send_lines(spi_device_handle_t spi, int ypos, uint8_t *linedata)
  25. {
  26.  
  27.     esp_err_t ret;
  28.     int x;
  29.  
  30.     //Transaction descriptors. Declared static so they're not allocated on the stack; we need this memory even when this
  31.     //function is finished because the SPI driver needs access to it even while we're already calculating the next line.
  32.     static spi_transaction_t trans_msg;
  33.     trans_msg.flags     = SPI_TRANS_MODE_OCT;
  34.     trans_msg.tx_buffer = linedata;      //finally send the line data
  35.     trans_msg.length    = 31000;  //Data length, in bits
  36.  
  37. //  ret = spi_device_queue_trans(spi, &trans_msg, portMAX_DELAY);
  38. //  assert(ret == ESP_OK);
  39.  
  40.     ret = spi_device_polling_transmit(spi, &trans_msg); // Transmit!
  41.     assert(ret == ESP_OK);                              // Should have had no issues.
  42.  
  43. }
  44.  
  45. void setup() {
  46.  
  47.   // put your setup code here, to run once:
  48.     esp_err_t ret;
  49.     spi_device_handle_t spi;
  50.    
  51.     spi_bus_config_t buscfg = {
  52.         .data0_io_num = 5, // A
  53.         .data1_io_num = 4, // B
  54.         .sclk_io_num =  42, // C
  55.         .data2_io_num = 7, // D
  56.         .data3_io_num = 41, // E
  57.         .data4_io_num = 1, // oe
  58.         .data5_io_num = 6, // lat
  59.         .data6_io_num = 2, // clk
  60.         .data7_io_num = 48, // sr
  61.         .max_transfer_sz = 32768, // ESP32 S3 max size is 64Kbytes
  62.         .flags        = (SPICOMMON_BUSFLAG_OCTAL | SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_GPIO_PINS), // kinda important      
  63.     };
  64.  
  65.     //Configure SPI Device
  66.     spi_device_interface_config_t devcfg = {
  67.         .command_bits = 0,
  68.         .address_bits = 0,
  69.         .dummy_bits = 0,      
  70.         .mode = 0,                                  // SPI mode 0
  71.         .duty_cycle_pos = 0,
  72.         .cs_ena_pretrans = 0,
  73.         .cs_ena_posttrans = 0,
  74.         .clock_speed_hz = SPI_MASTER_FREQ_8M,       // Clock out at 10 MHz
  75.         .input_delay_ns = 0,
  76.         .spics_io_num = -1,                         // CS pin
  77.  
  78.         // SPI_DEVICE_NO_RETURN_RESULT = Don't care abut result
  79.         //.flags = (SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_NO_RETURN_RESULT),
  80.         .flags = (SPI_DEVICE_HALFDUPLEX ),
  81.         .queue_size = 10,                    
  82.         .pre_cb = 0, // Not used
  83.         .post_cb = spi_post_transfer_callback,
  84.  
  85.     };
  86.  
  87.     //Initialize the SPI bus
  88.     ret = spi_bus_initialize(LCD_HOST, &buscfg, SPI_DMA_CH_AUTO);
  89.     ESP_ERROR_CHECK(ret);
  90.  
  91.     //Attach the LCD to the SPI bus
  92.     ret = spi_bus_add_device(LCD_HOST, &devcfg, &spi);
  93.     ESP_ERROR_CHECK(ret);
  94.  
  95.     size_t max_trans_bytes = 0;
  96.     ret = spi_bus_get_max_transaction_len(LCD_HOST, &max_trans_bytes);
  97.     assert(ret == ESP_OK);    
  98.     ESP_LOGI("S3", "Max transfer size is %u", (uint32_t)max_trans_bytes);        
  99.    
  100.  
  101.     uint8_t *output_data;
  102.     output_data = (uint8_t *) heap_caps_malloc(31000 * sizeof(uint8_t), MALLOC_CAP_DMA);
  103.     assert(output_data != NULL);
  104.  
  105.     // Doesn't send data after about the 4096 boundary?
  106.     int offset = 4096;
  107.     memset(output_data, (uint8_t)0x00, 31000);
  108.     memset(output_data+offset, (uint8_t)0xff, 31000-offset); // overwrite from offset with 0xff  
  109.    
  110.     while (1)
  111.     {
  112.         send_lines(spi, 0, output_data);
  113.     }
  114.  
  115.  
  116. } // setup
  117.  
  118. void loop() {
  119.   // put your main code here, to run repeatedly:
  120.  
  121. }

MicroController
Posts: 1734
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

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

Postby MicroController » Wed Jan 03, 2024 9:32 pm

trans_msg.length = 31000; //Data length, in bits
That'd be 3875 bytes...

faptastic
Posts: 15
Joined: Mon Nov 14, 2022 10:38 pm

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

Postby faptastic » Thu Jan 04, 2024 9:52 am

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.

MicroController
Posts: 1734
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

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

Postby MicroController » Thu Jan 04, 2024 10:33 am

faptastic wrote:
Thu Jan 04, 2024 9:52 am
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 :)

Who is online

Users browsing this forum: atx823, Majestic-12 [Bot] and 230 guests