Data Missing in SPI Slave Mode - Colibri iMX6ULL

Hi Toradex Team,

We are testing SPI slave mode comunication on Colibri iMX6ULL using the Colibri Evaluation Board. This query is to seek help on an observation that some bytes – supposed to be sent by the slave device – are missing and not seen on the MISO line.

Introduction


Platform info (from tdx-info)
Software (custom Yocto-based image):

- Bootloader     : U-Boot
- Kernel version : 6.1.55-00020-g9dccaf40e612 #1 SMP Sat Sep 23 09:11:13 UTC 2023
- Distro version : VERSION_ID=6.4.0-devel-20240403095552-build.0

Hardware (Colibri iMX6ULL on Colibri Evaluation Board):

- Toradex version : 0044 V1.1A
- Serial number   : 14985046
- Processor arch  : armv7l

Setup

  1. An ESP8266 is configured as the SPI master, with a clock frequency of 125kHz. The master simply sends a set number of bytes over SPI.
  2. The Colibri device contains an image that has a custom device driver which configures the SPI registers (slave mode), and just sends response to the master with some valid data (loop-back or pre-defined values). The TX FIFO is filled with 32 words of data initially.
  3. The SPI bus only contains one slave. CS pin on the Colibri is connected to GND so that the device is always active.

SPI Configuration on Colibri iMX6ULL
ECSPI1 is used as the slave device.

Pins:

CS   : SODIMM 86
CLK  : SODIMM 88
MISO : SODIMM 90
MOSI : SODIMM 92

Registers:

/* Control Register */
(0x1f << 20)    // Burst Length
(0x00 << 18)    // Channel Select
(0x00 << 16)    // DRCTL
(0x00 << 12)    // Pre Divider
(0x00 << 8)     // Post Divider
(0x00 << 4)     // CH Mode
(0x00 << 3)     // SMC
(0x00 << 2)     // XCH
(0x00 << 1)     // HT
(0x01 << 0)     // Enable

/* Configuration Register */
(0x00 << 20)    // Reserved
(0x00 << 24)    // HT Length
(0x00 << 20)    // SCLK CTL
(0x00 << 16)    // Data CRL
(0x01 << 12)    // SS POL
(0x00 << 8)     // SS CTL
(0x00 << 4)     // SCLK_POL
(0x00 << 0)     // SCLK_PHA

/* Interrupt Control Register */
(0x00 << 8)     // Reserved
(0x00 << 7)     // Transfer Completed
(0x01 << 6)     // RX Overflow
(0x00 << 5)     // RX FIFO Full
(0x01 << 4)     // RX Data Threshold
(0x00 << 3)     // RX Ready
(0x00 << 2)     // TX FIFO Full
(0x00 << 1)     // TX Data Threshold
(0x00 << 0)     // TX Empty

/* DMA Control Register */
(0x00 << 31)     // RXTDEN Disable
(0x00 << 30)     // Reserved
(0x00 << 24)     // RX DMA Len
(0x00 << 23)     // RX DMA Disable
(0x00 << 22)     // Reserved
(0x10 << 16)     // RX Threshold
(0x00 << 8)      // Reserved
(0x00 << 7)      // TEDEN
(0x00 << 6)      // Reserved
(0x10 << 0)      // TX Threshold

Issue


Statement
The slave device receives all the bytes sent by the master. However, in the response data sent by the slave device, some words are missing and those words are received as all-zeros instead of the actual data.

To be specific, there is a pattern. After a reset, the very first two words sent from the slave device are missed, and zeros are received instead. And after that, every next 256th word is missing and zero is received. This pattern continues.

The observation is represented in the following table.

Word Sent by Master Word Received from Slave Note
0 0x00000000 Valid data expected
1 0x00000000 Valid data expected
2 Valid data
3 Valid data
… Valid data …
255 Valid data
256 Valid data
257 0x00000000 Valid data expected
258 Valid data
259 Valid data
… Valid data …
513 0x00000000 Valid data expected
… Valid data …
769 0x00000000 Valid data expected
Pattern continued

Methods of Observation

  1. Primarily, the data received on the master device is used to find the observation.
  2. To confirm the observation, a logic analyser was used and the signals showed the same behavior.

Debugging Steps Performed
With an aim to see if there will be a change in the observation (such as a deviation in the figure 256 which seems like a sort of cycle), we had tried out a few things.

  1. Changing the SPI clock frequency (no difference).
  2. Tweaking some of the SPI register values (no difference).
  3. Running the experiment at varied CPU loads, including 100% load (no difference).

Please provide a solution for this issue if it is a straight one, or share your suggestions to go forward. Also, please let me know if you need more details to work on this.

Expecting a fast response.

Thanks and regards,
Ajith

Hi, I’m the Toradex AI Assistant. I’m in early beta, and I would appreciate your feedback.
The Toradex Support team will follow up with you shortly!

Did you like my answer?

:+1: :-1:


Hi Ajith,

Thank you for providing detailed information about your setup and the issue you’re facing with SPI slave mode communication on the Colibri iMX6ULL.

Based on the description, it seems like the issue might be related to the SPI FIFO handling or timing issues in the SPI slave mode. Here are a few suggestions to help you debug and potentially resolve the issue:

  1. Check the SPI FIFO Configuration:

    • Ensure that the TX FIFO is being refilled promptly. Since the first two words and every 256th word are missing, it might indicate that the FIFO is not being refilled in time.
    • Verify that the TX FIFO threshold is set correctly. You might want to experiment with different threshold values to see if it affects the behavior.
  2. Interrupt Handling:

    • Ensure that the SPI interrupt handling is correctly implemented. Missing words could be due to missed interrupts or delays in handling them.
    • Check if the SPI interrupt priorities are set appropriately, especially if there are other high-priority interrupts in the system.
  3. DMA Configuration:

    • If you are using DMA for SPI transfers, ensure that the DMA configuration is correct and that the DMA buffers are being managed properly.
    • Verify that the DMA transfer length and thresholds are set correctly.
  4. Timing Analysis:

    • Use a logic analyzer to capture the SPI signals and analyze the timing of the CS, CLK, MISO, and MOSI lines. Look for any anomalies or timing issues that might explain the missing words.
    • Ensure that the SPI clock polarity and phase settings match between the master and slave devices.
  5. Driver Code Review:

    • Review the custom SPI driver code to ensure that there are no logical errors or race conditions that might cause the TX FIFO to be improperly managed.
    • Check for any potential issues in the initialization and configuration of the SPI registers.
  6. Test with Different Data Patterns:

    • Try sending different data patterns to see if the issue persists. This might help identify if the problem is data-dependent.

If the above suggestions do not resolve the issue, please provide more details about the custom SPI driver implementation and any additional observations you might have. This will help in providing more specific guidance.

Best regards,
[Your Name]

Hi,

I had tried out the suggested things, but there is no difference in the observation yet.

The driver is a very basic one that configures the SPI registers for slave-mode operation and fills the TX FIFO partially (32 words). The application logic is to just send back each word it receives from master.

I would like Toradex technical members to provide immediate help on this issue.

Thanks and regards,
Ajith

Hi @ajith ,
You have configured Colibri iMX6ULL as spi slave and ESP8266 as SPI master, right?
I am not sure if this is related to your issue but there is an issue on how you send/receive data in slave mode.
SPI slave mode on i.MX6UL is affected by errata ERR009535, the burst completion by SS signal in slave mode is not functional. In practice this means that the slave must know in advance how large the transfer will be. For further information on this errata read NXP Chip Errata for the i.MX 6UltraLite.

Hi @sahil.tx,

Thank you for the response.

It’s correct that we are using Colibri i.MX6ULL as SPI slave, and ESP8266 as the SPI master.

I have gone through the errata you had shared. In our case, we are not de-asserting the SS line at any time. The slave is always kept active. Burst length is set to 32 bits, and the master transmits data continuously. The slave just loops back the data it receives.

For a better understanding, please have a look at the observation we have, in the table below.

Data Put into Slave (i.MX6ULL) TX FIFO (hex) Data Received by Master (ESP8266) (hex)
aa bb cc 01 00 00 00 00
aa bb cc 02 00 00 00 00
aa bb cc 03 aa bb cc 03
aa bb cc 04 aa bb cc 04

Please do help as soon as possible as our deadline is near.

Thanks and regards,
Ajith

Hi @ajith,
Does the slave know in advance how much data it is going to receive?
You must first run the spidev application on the slave so that it pre-fills the FIFO with the message having the same no of bytes which is expected to receive.
eg.
On the slave,
spidev_test -D /dev/spidev0.0 -p "SLAVE_HELLO_TO_MASTER" -v

On master
spidev_test -D /dev/spidev0.0 -p "MASTER_HELLO_TO_SLAVE" -v

Hello @sahil.tx

We have been doing many tests and here is a summary.

Setup: Colibri i.MX6ULL (SPI SLAVE) <—> Node MCU (SPI MASTER)

  1. The Chip Select is permanently grounded on the SOM side, since there is only device.
  2. Effectively we have a point to point link and we need to achieve continuous data exchange, like streaming. So we are NOT using the Linux SPI driver, instead we have developed a custom driver that does the following:
    a. Configure the SPI Controller as Slave
    b. Fill the TXFIFO with the pattern 0xAABBCC40, 0xAABBCC41 etc. up to 48 words. The pattern is given so that when we probe the data is more identifiable. The buffers are filled initially to ensure that when the slave receives clock, there is some known data to be returned to the master.
    c. RX Interrupt threshold configured as 16 Words. When Interrupt is received, we read 16 words from the RXFIFO and fill 16 words into the TXFIFO with the incremental pattern.
  3. We are never keeping the TXFIFO empty, as you can see from 2.b and 2.c above.

Under this configuration the test results are as follows:

Premise: SPI Master Sends 32 Bytes(8 Words) in each transfer. Chip Select is grounded. Driver is configured for a burst value of 0xFFF (2^7 Words).
Result: First 16 words from SOM are Zeroes. From 17th word one word in each block of 16 words is zero. From 128th word, one word in every 256 words is zero

To check the effect of Chip Select we also tried the follwoing:

  1. Test Case 1
    Premise: SPI Master Sends 4 Bytes(1 Word) in each transfer. Chip Select is toggled every word. Driver is configured for a burst size of 1 word.
    Result: First 16 words from SOM are Zeroes. 17th word is the first data filled from the ISR. From then, no missing data. However, the initial 48 words data filled into the TXFIFO is not sent out at all.

  2. Test Case 2
    Premise: SPI Master Sends 32 Bytes(8 Words) in each transfer. Chip Select is toggled every word. Driver is configured for a burst value of 0xFFF (2^7 Words).
    Result: First 16 words from SOM are Zeroes. The first 48 Words added to FIFO is missing. 17th word is the first data filled from the ISR. From then, all data received.

  3. Test Case 3
    Premise: SPI Master Sends 512 Bytes(128 Words) in each transfer. Chip Select is toggled every 512 Bytes. Driver is configured for a burst value of 4 bytes (1 word)
    Result: First 56 words from SOM are Zeroes. From 57th word all data is good.

So from all these tests we have the following questions:

  1. Is Chip Select toggling REQUIRED for the i.MX6ULL to work properly? Or can we keep it grounded all the time. THIS IS THE MOST IMPORTANT QUESTION THAT WE WOULD LIKE A CONFIRMATION QUICKLY.
  2. All the workaround for erratas have been applied or not relevant under our use case. The most important ones as we saw are:
    a. The transfer size is determined by burst size and not cs. This is fine, since we are not using the CS.
    b. The TX FIFO should not be empty. This is also taken care.
    Still we are getting misbehaviors. Could you let us know what could be wrong?
  3. Our expectation is to get a streaming data transfer without any limit on the data size and no break in data and NO Chip Select Toggles in between. Is this possible with i.MX6ULL as SPI Slave?