This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM3359: SPI Chip select to SPI clock start mismatch

Part Number: AM3359

We have an AM3359 custom board running with Linux SDK v 6.1.

There is a device connected on SPI CS0, the data transfer is successful.

When the signals are probed it is observed that the duration between CS and SCLK signals are about 83us i.e., after asserting chip select the processor is taking 83us to initiate the s-clock for data transfer.

The Linux application is made to work with the device file /dev/spidev.0, by calling open, IOCTL (fd, SPI_LOC_MESSAGE(1), &tr).

The delay parameter of struct spi_ioc_transfer is assigned with value zero.

Please help on how to rectify this.

  • Hello,

    What timing are you expecting to see?

    In your Linux SDK, under Documentation/spi/spi-summary, delay_usecs is documented as defining a short delay after transfers. So I would not expect it to impact relative timing between CS and SCLK.

    Regards,

    Nick

  • Hi nick,

    Thanks for the doc link. I have through this, the delay_usecs is the delay considered after data transmission is done. My doubt is about the start of data transaction time.

    I have attached the snapshot of the output. The cursors marked are the CS and start of SCLK, the difference is 49.93uS.

    The user application created to work with the device file "/dev/spidev0.1", 

    mode =0;

    bits = 8;

    fd = open(device, O_RDWR);
    if (fd < 0)
    R4_RCU_GPMC_FPGA_SPI_pabort("can't open device");
    /*
    * spi mode
    */
    ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
    if (ret == -1)
    R4_RCU_GPMC_FPGA_SPI_pabort("can't set spi mode");

    ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
    if (ret == -1)
    R4_RCU_GPMC_FPGA_SPI_pabort("can't get spi mode");

    /*
    * bits per word
    */
    ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
    if (ret == -1)
    R4_RCU_GPMC_FPGA_SPI_pabort("can't set bits per word");

    ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
    if (ret == -1)
    R4_RCU_GPMC_FPGA_SPI_pabort("can't get bits per word");

    struct spi_ioc_transfer tr = {
    .tx_buf = (ULONG)tx,
    .rx_buf = (ULONG)rx,
    .len = 5,
    .delay_usecs = 0,
    .speed_hz = speed,
    .bits_per_word = bits,
    };

    ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
    if (ret < 1)
    R4_RCU_GPMC_FPGA_SPI_pabort("can't send spi message");

  • Hi nick,

    Thanks for the doc link. I have through this, the delay_usecs is the delay considered after data transmission is done. My doubt is about the start of data transaction time.

    I have attached the snapshot of the output. The cursors marked are the CS and start of SCLK, the difference is 49.93uS.

    The user application created to work with the device file "/dev/spidev0.1", 

    mode =0;

    bits = 8;

    fd = open(device, O_RDWR);
    if (fd < 0)
    R4_RCU_GPMC_FPGA_SPI_pabort("can't open device");
    /*
    * spi mode
    */
    ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
    if (ret == -1)
    R4_RCU_GPMC_FPGA_SPI_pabort("can't set spi mode");

    ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
    if (ret == -1)
    R4_RCU_GPMC_FPGA_SPI_pabort("can't get spi mode");

    /*
    * bits per word
    */
    ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
    if (ret == -1)
    R4_RCU_GPMC_FPGA_SPI_pabort("can't set bits per word");

    ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
    if (ret == -1)
    R4_RCU_GPMC_FPGA_SPI_pabort("can't get bits per word");

    struct spi_ioc_transfer tr = {
    .tx_buf = (ULONG)tx,
    .rx_buf = (ULONG)rx,
    .len = 5,
    .delay_usecs = 0,
    .speed_hz = speed,
    .bits_per_word = bits,
    };

    ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
    if (ret < 1)
    R4_RCU_GPMC_FPGA_SPI_pabort("can't send spi message");

  • CS is manually controlled by the mcspi kernel driver, so what you're seeing is the driver somehow being incredibly inefficient (which is unfortunately not that uncommon with linux).  One would need to dig into the code to see if there's some sort of explanation for how it manages to spend nearly 50 μs between asserting CS and starting the transfer.  This is way worse than what I've ever observed with a scope, but I haven't inspected the SPI bus in quite a while so maybe the kernel driver somehow managed to become more inefficient since then?  The transfer itself looks terrible too, huge spacing between the bytes.  I'm confused about one thing though: your code says the length is 5 bytes, but your scope capture is clearly showing at least 11 bytes, does this scope capture not correspond to the code you showed?

  • Hmm, I dug up some of my old scope captures of the SPI bus and it shows only 0.65 μs between CS asserted and start of first byte, and no significant inter-byte gap:

    So there's definitely something weird going on in your case.

  • Matthijs van duin,

    Glad to see the spi capture with 0.65us. Many thanks for digging the captures.

    The code which I sent is of 5 bytes transmission and the scope is captured with more bytes transfer. Sorry for the confusion, as I was experimenting more on this, the code bytes got changed.

    I'm using the SDK 6.1 and Linux sources from TI, expecting this will be addressed soon. Being a beginner on this platform, highly looking forward for an expert's help.

    Thanks

  • Hello,

    Let me check if the developer has any thoughts.

    Is there anything else about your system we should know? For example, you are using regular Linux, not RT Linux? Is the ARM juggling a bunch of other tasks? Etc.

    Regards,

    Nick

  • Nick,

    Our system runs with regular Linux. There is only one back ground application task which listens on Ethernet socket.

    Is there any other spi driver available to use SPI apart from spidev driver? because we have an onboard SPI flash it's working properly from AM3359.

    Thanks

  • Hello,

    TI provides the low-level AM335x SPI driver, and then a separate higher-level SPI driver builds on top of that low-level driver (e.g., spidev).

    What are you trying to communicate with over SPI? There might be a higher level driver already written that could be used instead of spidev. Note that if a driver is written by someone other than TI, I will be limited in any support I can offer.

    The SPI driver developer is on vacation the rest of this week, so I will not be able to get his thoughts for a couple more business days.

    Regards,

    Nick

  • I just noticed you're using per-spi_ioc_transfer overrides o spi configuration (specifically .speed_hz and .bits_per_word). This means that when the driver processes that spi_ioc_transfer, before it can start the data transfer it first has to reconfigure the spi controller to these overrides, and during this time the chip select will indeed already be asserted.

    Try configuring your settings with ioctls only (SPI_IOC_WR_MAX_SPEED_HZ for the clock speed) while leaving those settings zero in the spi_ioc_transfer.

  • Hi Matthijs van Duin,

    Thanks for the information.

    I have modified the application in the sequence you mentioned,the output observed as before.

    I tried one more way, configuring speed through ioctl and performing SPI Write function (in place of SPI IOC MESSAGE), then the output observed is 15.95us.

    Please help if any other methods to crack this.

    Regards

  • Hi Nick,

    Im trying to communicate with a custom FPGA logic over SPI (it's a simple logic of data reception). This is a generic one so we went with spidev. Please suggest if we can use any other driver for this operation.

    Thanks

  • Hi Matthijs van Duin,

    Any inputs on this?

  • Hi Matthijs van Duin and Nick,

    Based on my study of SPIDEV Driver and experiments, the driver itself generating about ~16us to ~26us delay between SPI CS and SPI CLK.

    I could see there are other driver entries which are very straight forward for data communication like spi-gpio or spi-bitbang. Can you help how can I use these with SPI controller 0, Chip select 1?

    Very much awaited to make this interface work. Please provide your valuable inputs.