Page 1 of 1

How fast can I transmit another SPI frame calling spi_device_polling_transmit() again?

Posted: Mon Aug 07, 2023 8:53 am
by mad_b747
I have been experimenting with SPI;
Set and init for VSPI ok, then considering the code below:
(Ignoring that it will trigger watchdog in some seconds and etc.)
-Or working dedicated without interrupts enabled.
  1. // SPI configuration
  2. #define PIN_NUM_MISO GPIO_NUM_19
  3. #define PIN_NUM_MOSI GPIO_NUM_23
  4. #define PIN_NUM_CLK  GPIO_NUM_18
  5. #define PIN_NUM_CS   GPIO_NUM_5
  6.  
  7.     spi_bus_config_t bus_config;
  8.     bus_config.miso_io_num = PIN_NUM_MISO;
  9.     bus_config.mosi_io_num = PIN_NUM_MOSI;
  10.     bus_config.sclk_io_num = PIN_NUM_CLK;
  11.     bus_config.quadwp_io_num = -1;
  12.     bus_config.quadhd_io_num = -1;
  13.     bus_config.max_transfer_sz = 0;
  14.  
  15.     spi_device_interface_config_t dev_config;
  16.     dev_config.clock_speed_hz = 1000000;  // Clock speed (1 MHz)
  17.     dev_config.spics_io_num = PIN_NUM_CS;
  18.     dev_config.queue_size = 1;
  19.     dev_config.mode = 0;  // SPI mode 0
  20.  
  21.     spi_device_handle_t spi_handle;
  22.  
  23.     // Initialize the SPI bus
  24.     esp_err_t ret;
  25.     ret = spi_bus_initialize(VSPI_HOST, &bus_config, SPI_DMA_DISABLED);
  26.     assert(ret == ESP_OK);
  27.  
  28.     // Attach the device to the SPI bus
  29.     ret = spi_bus_add_device(VSPI_HOST, &dev_config, &spi_handle);
  30.     assert(ret == ESP_OK);
  31.  
  32.     // Data to send
  33.     spi_transaction_t trans;
  34.     trans.flags = 0;
  35.     trans.length = 64;  // Data length in bits
  36.     trans.tx_buffer = data_to_send0;
  37.  
  38.     uint8_t data_to_send0[8] = { 0xFA, 0x5E, 0x01, 0xD0, 0xDA, 0xD0, 0xCA, 0xB0 };
  39.     uint8_t data_to_send1[8] = { 0xFA, 0x5E, 0x02, 0xD0, 0xDA, 0xD0, 0xCA, 0xB1 };
  40.  
  41.     while (1)
  42.     {
  43.       trans.tx_buffer = data_to_send0;
  44.       ret = spi_device_polling_transmit(spi_handle, &trans);
  45.       //trans.tx_buffer = data_to_send1;
  46.       //ret = spi_device_polling_transmit(spi_handle, &trans);
  47.     }
  48.  
I have a couple of questions on this PoC/test code.
(This is not checking status of return, it previously was and it calls and works ok)

1-Even as it is above, with no scheduler interrupts, I checked in the logic analyzer to have a ~14 us delay between the data_to_send0 frames of data. I expect/need no delay in between calls, is something behind scenes that consumes the time after a transmit ends?

2-If I uncomment the second transmit, code breaks. Always. Immediately. So I cannot have double buffering for this? I tried also to let same references and refil a single data_to_send buffer, or have it source of data updated; is there some data lock or similar behind this, causing an access violation or whatever?

I do not want to reinvent the SPI and make a bit banging procedure for it to attend my need, what else could I do, in case someone have seen similar issues?
I need to feed a device near 1MHz limit of SPI functioning, few KB of data for a couple of seconds each time or so.

Thanks :)
PS. This runs in the second core, a single task, no interrupts. Disabled task watchdog.
PS2. Tried both using
trans.tx_buffer = data_to_send0;
and
trans.tx_buffer = &data_to_send0;
No change in results fir both working and not working cases.

Re: How fast can I transmit another SPI frame calling spi_device_polling_transmit() again?

Posted: Mon Aug 07, 2023 12:44 pm
by ESP_Sprite
First of all, please don't initialize your structs like that; make sure they're zeroed, e.g.

Code: Select all

    spi_device_interface_config_t dev_config={0};

Re: How fast can I transmit another SPI frame calling spi_device_polling_transmit() again?

Posted: Mon Aug 07, 2023 1:21 pm
by mad_b747
[Edit] Thanks, this seems to have solved the issue.

I presume that, for the compiler, when the next example statement is made, the non mentioned fields are by default initialized to zero

Code: Select all

spi_bus_config_t buscfg={
        .miso_io_num = -1,
        .mosi_io_num = MOSI_PIN,
        .sclk_io_num = CLK_PIN,
        .quadwp_io_num = -1,
        .quadhd_io_num = -1,
        .max_transfer_sz = 32,
    };

Re: How fast can I transmit another SPI frame calling spi_device_polling_transmit() again?

Posted: Tue Aug 08, 2023 1:47 am
by ESP_Sprite
Yes, if you initialize it using that method, you'll zero-initialize unmentioned members.