Spi_ReadWrite - problems

Hi,
I try to read data from a slave System using SPI.
I monitor SCLK and MISO with my scope and see 0xC0 as the first transmitted Byte. This is exactly what I expected.
Testing the first byte in the buffer I received isn’t 0xC0 !!! I get 0x7A.

I tried all the SPI-modes, never get the expected data back.

Any special things to do using this function?

With best regards

Gerhard

Dear @Gerhard
Could you please paste the full code so we can reproduce the error?
Regards, Andy

Hi Andy,

not so easy, cause the data transfer is only one part of many to get something meaningful.

What I have for now:

The slave system generates dummy data, so it is clear which data we expected.
I monitor the SPI-SCLK (from iMX7, which is the master) and the MISO with my scope. The data here is exactly what I expect to get.
I placed a printf in the ISR where the SPI data were read out by the master. This corrupts the system timing, but the rest of the system is safe, so no problem. I do this only once.

I didn’t get out the expected data. It seems, that 2 Bytes were missing.

Scope:
[upload|8uuhnsZHpZoLfx4C9bDpCeXArIM=]
DL-SCLK is the shift clock of the SPI1 interface of my iMX7D.
I didnt plot the data signal, but my scope can decode the data, you see the result at ‘MISO’.

ISR:
[upload|CiR87qKoZdUEIjLRHFOVzB9wYvs=]

You see the call of Spi_ReadWrite (actually I only need to read data, but Spi_Read doesn’t work out, see other post).
You also see my printf and down you see the result.

SPI-Modes:
I played around, one of my guess was, that the two systems using different SPI-modes, but … if the selected mode on one of the systems is wrong/incompatible, there can only be a shift of one BIT, or random data if the data is changed during the sampling phase of the receiver, but I get stable data.

The first two bytes were lost.

My slave is able to work with clock frequencies of SysClock/6, this means 100Mhz/6 = 16.67Mhz, I currently use ~8Mhz. It is fast enough (cause the Interrupt latency of the iMX7 is very short and stable) to be sure there is no problem on the transmitter side.

The software on my slave transmitted some 10th GB using another SoM without data loss, so I think, this part is quite good tested.

If you want to reproduce something, please use two different systems (and so for two different time domains). A simple loopback test maybe misslead in some special cases.

With best regards

Gerhard
(Keep on tesing)

Hi Andy,

here the usage of Spi_Read:
~CS1 stays low after transfer and the line printing the report isn’t executed ==> Spi_Read hangs internally.
I have to reboot the system to get it running again.

Scope:
[upload|MNm2+mThYUPu7VDIitoz9AxUTPI=]

[upload|aA5+87RfEMMfOK9Gt/76ywKWTgE=]

I also miss the ‘Job done’ message, as the software hangs cause the Spi_Read function hangs.

I only get the promt cause the Job runs async.

With best regards

Gerhard

Hi Andy,
sorry, I forgot to update the .dll. Now I work with the newest official version.
Finally it turned out, that the first two bytes were lost.

Scope:
[upload|f7vUX1OZ9oR8upEW5Tkj3QBSBJw=]
You can see, the transfer starts with 0x00, cause the flipping ~CS1 fools the slave system.

Report:
[upload|EL/zJvxAYFLjBe0+DhsAHLQGEYA=]
You can see, that the guess that we lost two bytes can be right, this can explain the position of the 0x01.

The transfer contains 30 packets a 21 bytes, each starting with 0xC0. If I am right, the byte with index 19 is the first byte of the second frame, cause the very first frame counts only 19 bytes.

[upload|0qs9YAT6xUh2xlmyJeBA54sVANs=]

qed.

At this point I have to stop the development until Toradex fixed this. No (easy) chance to get it going now.
But the critical timing works much better than expected, there is really hope to use iMX7D in the future.

With best regards

Gerhard

Dear @Gerhard,

Thank you for the reply. I tried to reproduce the issue with our default Spi_demo but unfortunately couldn’t able to reproduce issue similar to your waveform.

Could you please share the following things, it will help us to reproduce the issue on our side and solve it.

  1. Complete VS project it can build and run without modification.
  2. The same project already built as an .exe file which you run and seeing the issue - This will exclude any influence from the build system.

Hi,
I can share the project, but …
I have two systems working together. You start a measurement cycle on the system running on the iMX7D, this system communicates with the second system, which controls special hardware and starts collecting data. This data is sent to the first system for mass storage via SPI.
I guess, without the hardware it will be hard to reproduce the problems.

I pack the project and will send it, but have no hope.

With best regards

Gerhard

… I use a virtual Computer for this development, maybe I can send you the Image, but we Need some place I can put it (ftp …)

With best regards

Gerhard

Dear @Gerhard,

Thank you for the reply. Please share the iMX7 visual studio application project as of now, let me explore the code and get back to you if I find something or have some questions to you. You can use attachment feature or https://share.toradex.com/ to share the project with us.

Hi Raja,

ok.
For the version you get now, I use a different data layout. As I wrote earlier, I found out, that the SPI Driver only works for messages with data length Modulo 4. I sent 630 Byte, now I sent 672 Byte which fixes the problem.
But, this is only possible, as I am the writer of the software on both sides.

If someone want to use a SPI chip (which always has a fixed structure/Firmware), there is no chance, as almost all chips needed byte transfers, or multiple of byte.

With best regards

Gerhard

Ok, Uploaded

Hi Raja,
I do some ‘measurements’ with my system now, but transmitted a test pattern over the SPI interface. As far as I can see now, no errors.

==> Hardware is ok, initialization of the hardware is ok, but the number of transmitted bytes within a call to Spi_ReadWrite(…) has to be mod 4, otherwise data is lost.

This isn’t an issue of the slave system (not Toradex), cause I do transfers of 630 byte packets for a year or so, several GB in total without data loss.

The specification ‘buffer has to be alligned DWORD…’ didnt iclude this ‘data lenghth modulo 4’ issue, you can allign a single byte on a DWORD boundary.

So, please patch the SPI driver, so one can transmit a single byte or multiple of single byte, to be conform to SPI standards.

There were chips with SPI interface (EEPROMs for instance) around which needed single byte transfers, the write protect command for instance.

With best regards

Gerhard

Hi Raja,
I do some investigations. I download this manual.
Than I start reading the section about ECSPI, and yes byte wide transfers were possible:

So, ‘all’ we need is this kind of transfer and copying the pointer to the data buffer and the value of the length parameter to the counter register. Using the DMA feature will be a fine thing.

Multi byte transfers can be done by configuring the ECSPI to hold ~CS low until the counter reaches zero, I am sure, this is also possible.

With this settings, the SPI interface of the Colibri iMX7 can be used universally.

With best regards

Gerhard

Hi Raja,

oh, the SPI controller of the iMX7 is really tricky, now I understand whats going on internally …

Check out this:

“Since the shift register always loads 32-bit
data from transmit FIFO, only the n least-significant (n = BURST LENGTH + 1) will be shifted out. The remaining BITS will be ignored.”

Ok, the data buffer size must be greater than the actual data, if the lenght isn’t mod 4. The FIFO needs this and the OS may be angry if we don’t respect that.

The table above is counting BITS. There is the possibility to transfer only 1 BIT, which is totally unusual (for me).
If I read this table correct, this means:

BURST_LENGHT = 0x7 … 1 byte transfer
BURST_LENGHT = 0x0f … 2 byte transfer
BURST_LENGHT = 0x17 … 3 byte transfer
BURST_LENGHT = 0x1f … 4 byte Transfer
BURST_LENGHT = 0x27 … 5 Byte transfer, LSB of first word and all 4 bytes of second word, wow.
BURST_LENGHT = 0x2f … 6 byte transfer

Proof: BURST_LENGTH = 0x2f ==> 47 ==> n = 47 + 1 ==> 48 / 8 = 6 (bytes) qed.

WOW, really ‘cool’ method to calculate the burst length for a byte-oriented interface.

However:

A quick and dirty idea how I will solve that:
I get a pointer to a buffer (bytes) and a length.

The longest burst possible is 2^7 words, if the buffer we got is longer than 2^7 * 4 Bytes we have to split the transfer. This means not to bring ~CS high, this only means that we have to use DMA to prepare the next chunk of data in time.

I do not know, if this machine is big endian or little endian. So dependent of that fact, we have to adust the buffer to be able to do transfers with length mod 4 != 0.
Maybe using a own buffer and copying the data there is a safe method to do that. The user didn#t have to check for buffer length mod 4.
Calculate the BURST_LENGTH field according to the upper formular.

if transfer_length > 512, write 0xfff to the BURST_LENGTH field.
Adjust pointer, adjust counter of bytes left.
Write bytes_to_send * 8 -1 to the BURST_LENGHT field and we were done.

For my application for instance:

630 > 512, yes, write 0xfff to the BURST_LENGHT field, 630 - 512 = 118 bytes left.
118 > 512, no, 118 * 8 - 1 = 943, write 0x3AF to BURST_LENGHT.

I am save for now, only using transfers of length mod 4, but for the future, 1 Byte transfers or multiple of one byte should be possible as this is SPI interface standard.

Sorry.

With best regards

Gerhard

Dear @Gerhard,

If you upload the project at https://share.toradex.com/, you need to share the link. I couldn’t able to download the file without the link. Please upload once again there and share the link with us or use attachment feature in the community.

… yes, but than everybody can get the Project …

… ok, link ready, how can I send you the link without public Access?

Dear @Gerhard,

If you want to share private, please write to support@toradex.com and mention Raja Sivasankaran then it will be assigned to me. Also, mention this community link.
Thank you