Spidev: DMA burst length


I’m successfully using the spidev on a iMX8MM board with the BSPv5.6 to transfer data with a width of 32 bit:

The data is loaded into the TX-FIFO of the spi by the dma. But what bothers me is that only 32 of the 64 FIFO registers that the ECSPI has are used:

I can remember that with BSPv5.0 there wasn’t this behavior and a burst was 2048 bits (64 x 32 bits) long.

Best regards,

I compared the spi transfer for different BSPs and figured out that with BSPv5.2 the DMA behavior changed. See the pictures below. The red signal is the clock, the white the data.



With BSPv5.1 the burst is continuous with a total length of 2048 bits (64 x 32 bits). This corresponds to the size that the send buffer of the SPI has.

With BSPv5.2, however, the burst is split into 16 x 32 bit sections so that a total of only 1024 bits (32 x 32 bits), half of the possible transmit buffer, is transmitted. My logic analyzer overlooks 2 clock pulses, so there are only 1022 rising edges in the evaluation display. Between the 32 bit sections there is a gap of about 110 ns.

I would be interested if someone knows why the behavior of the DMA was changed and only half of the transmit buffer is used.

At the same time, the time between two bursts has also been drastically reduced from about 25 us to only about 7.5 us. So it could also simply be a compromise to shorten the total time of a transfer.

Best regards,

Hi @Mowlwurf !

Sorry for the answer delay.

Could you please specify which version of Verdin iMX8M Mini are you using and which carrier board?

From this article Verdin Product Family Specification Update | Toradex Developer Center, you can see that there was an update on the Verdin Family specification from BSP 5.1 to 5.2. I am not sure if this would cause the different behavior that you are facing, but knowing your hardware version is certainly important.

Also, how/which SPI are you using? Is this the spidev that you are triggering from userspace or some driver for some device?

Best regards,


I’m using the spiedev from the userspace on a Verdin iMX8M Mini V1.1B with its default pins (196, 198, 200, 202).
On a Colibri iMX7D V1.1A there is the same behavior. The pictures in my second posts were made with that module. With a Verdin iMX8M Mini it looks the same.

Best regards,

Hi @Mowlwurf !

Could you please share the script/application/source code that you are using to send the data through SPI?

Best regards,

There you go:

#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#include <fstream>

//#define SPI_DEVADDR			"/dev/spidev2.0"	//iMX7D
#define SPI_DEVADDR			"/dev/spidev1.0"	//iMX8MM

int main(int argc, char *argv[])

	int spidev_fd;
	uint8_t spi_mode = SPI_MODE_0;	// Mode
//	uint8_t spi_bpw = 8;			// Bits per Word
//	uint8_t spi_bpw = 16;			// Bits per Word
	uint8_t spi_bpw = 32;			// Bits per Word
	uint32_t spi_speed = 60000000;
//	uint32_t spi_speed = 58181818;	// Speed [Hz]
//	uint32_t spi_speed = 50000000;
//	uint32_t spi_speed = 40000000;	// Speed [Hz]
//	uint32_t spi_speed = 30000000;	// Speed [Hz]
//	uint32_t spi_speed = 20000000;
//	uint32_t spi_speed = 10000000;
//	uint32_t spi_speed =  5000000;
//	uint32_t spi_speed =  2000000;
//	uint32_t spi_speed =  1000000;

	if ((spidev_fd = open(SPI_DEVADDR, O_RDWR)) < 0)
		perror("SPI open");
		// set mode
		if (ioctl(spidev_fd, SPI_IOC_WR_MODE, &spi_mode) < 0)
			perror("SPI set mode");
		// set number of bits per word
		else if (ioctl(spidev_fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bpw) < 0)
			perror("SPI set bits per word");
		// set max speed (in Hz)
		else if (ioctl(spidev_fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed) < 0)
			perror("SPI set speed");
		// send data
			//uint8_t buf[(16 * 256)];
			uint8_t buf[2192012];
			//uint8_t buf[2*4096];
			uint32_t u32bufsize = sizeof(buf)/sizeof(*buf);

			// get buffer size of SPI
			uint32_t spi_bufsiz = 0;
			std::ifstream ifspi_bufsiz("/sys/module/spidev/parameters/bufsiz");
			if (ifspi_bufsiz.good() == true)
				ifspi_bufsiz >> std::dec >> spi_bufsiz;

				uint32_t ulOffset = 0;
					uint32_t u32BytesToWrite = std::min(spi_bufsiz, u32bufsize - ulOffset);
					ssize_t BytesWritten = 0;

					if ((BytesWritten = write(spidev_fd, buf + ulOffset, u32BytesToWrite)) < 0)
						perror("SPI write");

					ulOffset += BytesWritten;
				} while (ulOffset < u32bufsize);
			else perror("SPI buffer size unknown");



Dear @Mowlwurf,

Sorry for the delay in reaching back to you. We made a few changes to your code in order to test somethings. Our setup was the following:

  • Verdin iMX8MM Q 2GB WB IT V1.1B
  • Dahlia Carrier Board V1.1A
NAME="TDX Wayland with XWayland"
VERSION="5.7.0-devel-20220719174547+build.0 (dunfell)"
PRETTY_NAME="TDX Wayland with XWayland 5.7.0-devel-20220719174547+build.0 (dunfell)"

And here are the changes that we’ve made to the sample code:

                        uint8_t buf[2192012];
+                        int k = 0;
+                       for (int i = 0; i < sizeof(buf); i++){
+                                buf[i] = i%256;
+                              if (buf[i] == 0){
+                                 buf[i] = k++;
+                                        if (k == 256){
+                                          k = 0;
+                                        }
+                                }
+                        }
                        //uint8_t buf[2*4096];
                        uint32_t u32bufsize = sizeof(buf)/sizeof(*buf);

Our goal with these changes was to help us count how many bits that were sent.

However, our results seem to be a bit different from what we describe and we’d like to confirm this with you.

After 16 sets of 256 bits have been sent, we saw a 0.77ms pause, i.e., the pause appeared only after 4096 bits.

Between every 32 bits, we had a 4us pause. Is this similar to what you’re experiencing? We had to change the main frequency of the buffer due to limitations of the logic analyser we were using.

Have you tested this with the BSP 5.7?
Also, which carrier board are you using and which device tree is loaded to the module?

Hi @Mowlwurf !

Were you able to check the questions from @gclaudino.tx?

Best regards?

Sorry for my late reply. Currently I’m busy with other more important topics.
But this is still on my todo list and I will come back when I know more.

Best regards,