SPI transaction interval

drozdbartek
Posts: 1
Joined: Sat Jan 05, 2019 6:36 pm

SPI transaction interval

Postby drozdbartek » Sat Jan 05, 2019 6:51 pm

Hi,
I'm making POV display with APA102C leds and ESP32. I have a problem with long interval between next transactions. Even with high clock rate intervals between transactions kills the projet.
MAP001.jpg
MAP001.jpg (49.44 KiB) Viewed 8123 times
My configuration of spi interface:

Code: Select all

// Configuration for the SPI bus
	spi_bus_config_t buscfg = {
		.mosi_io_num = DATA_PIN,
		.miso_io_num = 5,
		.sclk_io_num = CLK_PIN,
		.quadwp_io_num = -1,
		.quadhd_io_num = -1,
		.max_transfer_sz = SPI_MAX_DMA_LEN,
	};

	// Configuration for the SPI master interface
	spi_device_interface_config_t devcfg = {
		.command_bits = 0,
		.address_bits = 0,
		.dummy_bits = 0,
		.duty_cycle_pos = 128,
		.cs_ena_pretrans = 0,
		.cs_ena_posttrans = 0,
		.clock_speed_hz = 26*1000*1000,
		.mode = 0,
		.spics_io_num = 17,
		.queue_size = 1,
		.flags = 0,
		.pre_cb = NULL,
		.post_cb = NULL,
	};
	
	// Initialize and enable SPI
	spi_bus_initialize(VSPI_HOST, &buscfg, 1);
	spi_bus_add_device(VSPI_HOST, &devcfg, &spi_handle);
And sender function

Code: Select all

// Full buffer DMA transfer
int32_t spi_dma_transfer_bytes(uint8_t *data, uint16_t size) {
	esp_err_t trans_result = ESP_OK;
	spi_transaction_t trans_t;

	// Prepare transaction parameters
	trans_t.rx_buffer = NULL;
	trans_t.tx_buffer = data;
	trans_t.rxlength = 0;
	trans_t.length = 8 * size;
	trans_t.flags = 0;
	trans_t.cmd = 0;
	trans_t.addr = 0;
	trans_t.user = NULL;

	// Perform transaction
	trans_result = spi_device_transmit(spi_handle, &trans_t);
	if (ESP_OK != trans_result) {
		return -1;
	}

	return size;
}
Am I doing something wrong or it must take so much time between next transactions?

zotikus
Posts: 3
Joined: Sat Oct 28, 2017 3:41 am

Re: SPI transaction interval

Postby zotikus » Thu Jan 10, 2019 9:10 pm

Hi,

I have struggled with this matter before.
There are a few options to address, and it depends very much on:

What is your data size (Tx) in bytes? (i.g. 3 bytes 0x06 0x00 0x00)
Are they repetitive (same data sent over and over)? (i.g. last 3 bytes to transmit for lets say 3600 times)
Are you expecting any data to be read (Rx)? seems like you don't on your code. If there is, what is the size of it in bytes?

The options to address timings depend very much on previous questions.
The options I may clarify them more if you answer back, and they could be:
-Using no DMA if your tx_data is not long (less than 64bytes)
-Using polling, if you don't mind the CPU being busy while waiting, rather than go do something else.
- Queue transactions if they are the same repeated over and over. This one is tricky, some devices (IC) require status on a pin or channel select between each transaction, but that depends very much on what is the IC you are connecting.

Let me know the answer to my questions in order to help you, I struggled for a specific device and ended up trying (I believe) all possible options.

squonk11
Posts: 69
Joined: Wed Mar 01, 2017 6:53 pm
Location: Germany

Re: SPI transaction interval

Postby squonk11 » Fri Jan 11, 2019 2:35 pm

Hello,

I read that you suggest to read bytes from the slave SPI via polling:

Code: Select all

-Using polling, if you don't mind the CPU being busy while waiting, rather than go do something else.
Do you have sample code for that? AFAIK Espressif is currently only supplying a driver SW which is suffering from a design "peculiarity"; which means that in DMA mode received bytes might become lost.
Polling for me would be not a problem because the ESP32 at that time is only waiting for data. But I don't find any API from Espressif to use the SPI in polling mode. Do you have any hint?
"Whoever believes to be someone has stopped becoming someone"
Sokrates

zotikus
Posts: 3
Joined: Sat Oct 28, 2017 3:41 am

Re: SPI transaction interval

Postby zotikus » Sat Jan 12, 2019 12:15 am

Hi @squonk11,

First time I hear this "peculiarity", do you have a source where to find more about it?
I have seen some posts regarding 4 bytes lost, when using SPI slave mode. I am not currently using the slave mode to verify but that is different from your use case.

You can use polling as

Code: Select all

trans_result=spi_device_polling_transmit(spi_handle, &trans_t);
instead of: spi_device_transmit

You can find the documentation here: https://docs.espressif.com/projects/esp ... aster.html

There you will find what I was describing:
Transaction_times.png
Transaction_times.png (20.96 KiB) Viewed 8044 times


Full example may be found in: https://github.com/espressif/esp-idf/bl ... ple_main.c

Please let us know if you were able to reduce the time with polling and how good was the improving.
I have other options to reduce the timing but it really depends on tx_data size per transmit, if it is constant, and if rx_data is expected.
It really depends on your application as well. In my case I needed the SPI to sample audio from an ADC IC, so no timing between transaction was needed for me. The first, non ideal solution was to consider this "constant" time between transactions as the whole period sample, and increment the clock frequency until finding the desired period equivalent to the sample rate needed. I finally came up with a solution using interruptions, PCNT, and queue transactions, was more complex to develop but achieved what I needed.

squonk11
Posts: 69
Joined: Wed Mar 01, 2017 6:53 pm
Location: Germany

Re: SPI transaction interval

Postby squonk11 » Sat Jan 12, 2019 4:42 pm

Thanx @zotikus,

this design peculiarity is described here: https://docs.espressif.com/projects/esp ... slave.html with the statement:
Also, master should write lengths which are a multiple of 4 bytes. Data longer than that will be discarded.
Unfortunately I have absolutely no influence on the amount of data the master is sending - it is any number of bytes between 4 and 114. Due to this neither the DMA transfer mode nor the mode without DMA (using the internal buffer of the SPI interface) works for me. ESP-IDF currently does not offer any other possibility to read data from SPI in slave mode. Your suggestion (using spi_device_polling_transmit(spi_handle, &trans_t);) does not work work for me because I think this is a functionality for the master mode of the SPI interface.
So I am currently badly searching for a solution for this problem because I urgently need it. Do you have any hint for me? The possibilities I currently see are:
  • polling: waiting and reading the SPI byte by byte, or
  • getting the data byte by byte via interrupt (preferred)
But I do not have any idea how to implement this because the documentation of the SPI in the reference manual does not giving the required information.
"Whoever believes to be someone has stopped becoming someone"
Sokrates

Who is online

Users browsing this forum: Bing [Bot] and 190 guests