I’m playing around with the SPI on my iMX7D module.
For that I changed the device tree as mentioned in this guide. I’m able to configure the interface with calls of ioctl() and and can send data out with write().
But I’m not happy with the transfer rate und I have two questions for that:
The datasheet says that a frequency of 52 MHz is possible. I add the following line to the device in the device tree:
But the max achivable frequency that I can measure is 30 MHz. How can the frequency be raised?
And second: Between every transmitted FIFO-frame (32 bit x 64) I have a pause of 39 us. Therefore my transmission is slowed down significantly. How can I enable DMA support for the spidev? For me, it seems that it isn’t enabled by default in the device tree that is provided by Toradex for this module.
Thank you for the link. The explanation for the behavior sound plausibel.
I already set the spi frame size to 32 bit. When I send 512 bytes of data I get a gap between the two FIFO blocks of around 35…40 µs.
In the link you posted it is mentioned that “request a multiple of 32 FIFO words for DMA to be used, other lengths will be worked on in interrupt mode”.
Now when I reduce my data by one word (4 Bytes) and therefore not send a multiple of 32 FIFO words I expected that the gap will be longer because the interrupt mode should be used. But it remains the same.
Do I don’t understand correctly the quoted sentence? How can I check for sure whether DMA is used or not?
Thank you for your patience. I have tested with 4.14.117 kernel with 3.0B2 image, there are quite some improvements in SPI driver and it is really using SPI DMA.
512 bytes with 32 bits per word mode has been transferred by 4 packets of the transaction, each 128 bytes packet. There is a 6.9us pause between the packet transactions. This is better than 40us pause between transaction with 2.8B6 image kernel.
Could you test the same with the 3.0B2 image and let us know is that meeting your requirement.
If you are not happy with 7us pause then try this suggestion, it does the continuous transfer without any pause. However, you need to live with the ERR009165 silicon issue.
Thank you very for your answer and that you could find a solution.
Here is a short test program:
#include <unistd.h> // write
#include <fcntl.h> // open
#include <sys/ioctl.h> // ioctl
#include <linux/spi/spidev.h>
#include <cstdio>
#define SPI_DEVADDR "/dev/spidev2.0"
int main(int argc, char *argv[])
{
int spidev_fd;
unsigned char spi_mode = SPI_MODE_0; // Mode
unsigned char spi_bpw = 32; // Bits per Word
unsigned long spi_speed = 52 * 1000 * 1000; // Speed [Hz]
if ((spidev_fd = open(SPI_DEVADDR, O_RDWR)) >= 0)
{
// 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
else
{
unsigned char buf[16 * 256];
if (write(spidev_fd, buf, sizeof(buf)) < 0)
perror("SPI write");
}
close(spidev_fd);
}
else perror("SPI open");
}
I tried to run it with the 3.0B2 image but I got the following errors:
[ 2014.161978] imx-sdma 30bd0000.sdma: sdma firmware not ready!
[ 2014.167668] spidev spi2.0: SPI transfer failed: -22
[ 2014.172657] spi_master spi2: failed to transfer one message from queue
SPI write: Invalid argument
For the SPI max frequency:
I already changed the device tree by setting the max frequency to 52 MHz and I’m sending data only by using the write() command. But I still don’t get above 30 MHz.
Did you use 3.0B2 image or did you build 4.14.117 kernel and updated on the module?
Did you update kernel, modules and device tree on the module?
Could you share a complete dmesg log file with us?
In the official 3.0B2 image the spidev is not present in ‘/dev’.
Therefore I bitbake the ‘console-tdx-image’ of the BSP3.0b2 with the following addings in the device tree file ‘imx7d-colibri-emmc-eval-v3.dts’ to enable the spidev:
&ecspi3 {
status = "okay";
mcp2515: can@0 {
status = "disabled";
};
spidev0: spidev@0 {
spi-max-frequency = <52000000>;
status = "okay";
};
};
We are not seeing this error with our 3.0B2 image. Maybe you need to clean build and probably SDMA is changed to as module driver. Maybe the modules section not updated correctly.
Are you sure, that you get the exact same image and devicetree as Bsp 3.0b2 when you do a clean OE Build?
Additionally is your compiled custom devicetree is the same when you do a clean build?
How did you introduce your changes to the OE Build.