Spi_Read crash?

Hi,
I try to read data periodically, it works two times, than the function call fails, blocking further execution.

My code:

void DL_ManagerProc(GPIO_IRQ_t* irq)
{
	volatile bool	lastXfer		= false;
	token_t			aToken;

	while (g_bThreadRun)
	{
		if (WAIT_OBJECT_0 == WaitForSingleObject(irq->hEvent, INFINITE) && g_bThreadRun)
		{
			SetDebugSignalA(1);				  // Signals that the transfer is started.
			Spi_Read(hSPI, (LPBYTE)&dataLinkBuffer[0][0], TRANSFER_LENGTH);
			Int_InterruptDone(hIntr, irq->dwSysIntrNumber);	// Tell the system, that the ISR has completed.
			SetDebugSignalA(0);					// Signals that the transfer is done.	
		}
		else
		{
			// Cleanup code goes here
			break;
		}
	}
	ExitThread(0);
}

The fact, that the SPI Transfer started tells me, that the configuration is ok.

How does it work:
One System generates a signal, ~BRDY, the falling edge of this signal fires the event. The task unblocks, set the GPIO signal GH_DBG0, starts the SPI transfer (DL_SLK) and clears the GPIO.
Two times ok, but the third time the call blocks and never returns.

When I exit the program, the task blocks the exit procedure.

And yes, the buffer is correct, size is ok.

Any ideas?
Maybe an alignment problem?

With best regards

Gerhard

Hi,
new facts. using Spi_ReadWrite( .. ), works better.

Maybe this helps finding the problems with Spi_Read( .. ).

With best regards

Gerhard

Dear @Gerhard
That sounds like a bug which we had in old versions of the Toradex CE libraries. Please make sure you are using the latest library release (at least V2.3), or keep using Spi_ReadWrite() only.
Regards, Andy

Dear @Gerhard,

Thank you for your reply. If you share the reproducible project that will help us to figure out the issue and solve it. Already I request the same here. Also your comment “it will be better, not flipping the ~CS1 signal this way” Do you mean there is a short period of high in ~CS1 line? Is it causing any problem?
Most probably, we are guessing if you share a reproducible project that will help a lot to look the issue.

… and as you can see, ~CS stays low long after the transmission is done. You cant see it on the scope, but only a reset and a new transfer can generate a short pulse.

Hi Raja,
ok, I started again at zero and used the SPI_Demo program.
I tested it as it comes, works. I dont use a loopback wire, data doesnt matter for now.
I changed one line of code and tried the Spi_Read function. It works also, the ~CS signal is 1 after each transfer, sometimes it needs a very long time, but ok for now.

I discovered, that you have the buffers loke:
DWORD …

This is very unusual, as SPI is a byte interface, some devices allow 16 bit transfers …
To proof this, I reduced the transmitted/received data from 20 to 1, thats easyer for counting.

And yes, 32 bit go over the line. Sorry, but I don’t know a device (EEPROM, ADC, …) which can accept that.

So I change the buffers to BYTE …

And now I get the error. The ~CS signal stays low for ever.

And we have 32 clock cycles instead of 8. This corrupts memory.

My slave system is running on an ATMEL SAM4N chip, one serial port is used in SPI mode, and can manage byte transfers only.

With best regards

Gerhard

Hi Raja,
here a sample.
I just searched for an EEPROM with SPI Interface (on Mouser.at home page) and took the very first one. M95128-DRE

There is a diagram showing how a value is written in the status Register, a very basic operation:

The first 8 clock cycles were for the instruction flowing from the processor to the memory and the next 8 clock cycles were from the answer flowing from the memory to the processor.

With your implementation of the SPI interface it will be not possible to use this chip (and many more).

To use the SPI Interface universally, we need byte transfers, some Chips allow 16 bit Transfers after issuing a special command to speed things up, but this is some kind of luxury.

With best regards

Gerhard

Dear @Gerhard,

Thank you for the reply.

Issue #1: CS-signal active low
I am able to reproduce this issue

Issue #2:~CS signal stays low forever
Trying to reproduce this issue.

Issue #3: 8 - bit and 16 - bit transfer consecutively
The SPI signals are identical, this can be possible by below options

  1. Transfers 1x8bit + 1x16bit - This is not possible with the libraries. If you use another GPIO as CS signal and leaving(open-ended) default CS signal and then change dynamically 8-bit and 16-bit transfer in the library APIs and do the SPI transfer.

  2. Transfers 3x8bit - This is possible and recommended. Please refer PackedMode , BitsPerWord in Toradex_CE_Libraries.chm documentation for more information.

  3. Transfers 1x24bit - It will work for some Socs(not all socs support 24bit SPI-words)

Could you please wait for a couple of days and let me try to reproduce the issue and get back you.

Please let us know if you have any other questions.

Hi Raja,
Issue #1: Ok, fine, so you can work on that.
Issue #2: It is simple to reproduce, use Spi_Read( hSPI, (BYTE*)buffer, 1); This generates 32 clock cycles and ~CS stays low after that.

Issue #3: The granularity of the SPI interface in general is 8 bit, or one byte. Most hardware I know have a config bit, that tells the master, to release the ~CS after each transmitted byte or not. There is some hardware which can transmit 16 bit words instead of 8 bit, but this is a special mode, not used that often.

With a standard SPI interface you only have to set the tx/rx pointer registers to buffers (maybe the OS needs some alignment here) and the rx/tx counter register. There is a good chance to have a DMA module which can manage that for you.
If you have done it, the hardware starts transmitting decrementing the counter and fires an interrupt when the counter reaches zero, if this is configured. You also can poll for that condition.
This way you can transmit x bytes, x = 1 … n.
On my Atmel SAM4N I have 32 bit wide memory pointers to buffers and a 32 bit wide counter holding the transfer length (master mode).

It is very easy to have transmissions of one byte and the next transmission with 2 bytes, just set the Counter first to 1 and than to 2.

If you can send me a link to the data sheet of the iMX7D chip used on the Colibri modules I can check out the specs of the SPI interface, no problem.

With best regards

Gerhard

Hi Andy,
sorry, forgot to update the dll, but now I use the dll you told me.
Yes there is a difference, but …


… it will be better, not flipping the ~CS1 signal this way. The slave system struggles and as you can see, the first byte is 0x00 instead 0xC0.
The ~CS1 signal stays low and the function call Spi_Read hangs.

With best regards

Gerhard

Hi Raja,
the CS-signal is an active low signal, which means it has to be high normally and only gos low, if the corresponding chip is used.
As you see on the scope, the ~CS line is low, but the chip isn’t in use, than it is set to 1 and set to low again, now the communication starts. This fools the transmitter.

The ~CS line should be 1, than the communication starts with ~CS going low, clock starts and data is shifted, after the message is sent/received, the ~CS line should go high and stay high until the next transmission starts.

What happens on the slave side here: I prepare some pointer and set up the DMA controller, actions I only should do when ~CS is high and so the transmitter is disabled. I know, there is no communication on the way. Than I generate a falling edge on one of the GPIO signals, ~BRDY, telling the master that data is ready. Now the master should set ~CS low and start clock, Together with the settings of the DMA controller at the slave side, correct data is transmitted.
If ~CS is accidently low during DMA Setup … nobody knows.

With best regards

Gerhard

Dear @Gerhard,

I tried to reproduce “Issue #2:~CS signal stays low forever”, with your suggestion “Spi_Read( hSPI, (BYTE*)buffer, 1);” but couldn’t able to do it. Could you please share the demo code for the issue. I have attached my demo code for your reference.

Thank you for your patience and effort.

Hi Raja,
will try.
Have written a simple SPI_Tester, and … works. Can’t reproduce the Problem, but I use the V2.3 libs now.

With best regards

Gerhard