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.

Missing CLK signal in SPI communication

Other Parts Discussed in Thread: SYSBIOS

Hi!

I've tried the example code "psi_master.c" in both LM4F232 and the LaunchPad (LM4F120) with the same issue. I can't get the signal clock during a "read" instruction (e.g. SSIDataGetNonBlocking). I can see the CLK signal if I write  (e.g. SSIDataPutNonBlocking) but not if I just read. Since in my system I don't need to send any information, what I ended up doing is a dummy write call and then immediately a read call. In that way I can use the clock generated for the write instruction to read data. I'm pretty sure that is not the way it suppose to work. Any Idea of why the stellaris doesn't generate the CLK signal for a reading call? The initialization code is the same as "psi_master.c". Thank you!

Regards,

Max

  • Hi Max,

    This is not an error, it is part of how the SPI protocol works. To get a clock signal you have to do a write.

    In brief, the SPI protocol is a Master-Slave protocol that has 4 data transmission lines: serial clock (SCLK), master output slave input (MOSI), master input slave output (MISO), and slave select (SS). The Master controls the clock and only turns it on when there is something to be written to the slave, or when the slave it writing to the master. That is to say the clock is not always on, so to get the clock signal you must perform a write.

    Here is a reference to an excellent Wikipedia article on it.

    http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus

    I hope that answered your question, please let me know if there is anything further you need help with, and if you would please click the coveted "Verified Answer" button if my answer was helpful.

    -Austin

  • Hi Austin,

    I understand your answer, however, If a write is necessary to read, wouldn't this should be automatically created by the read call? The "psi_master.c" example shows that the read instruction alone is enough for reading (as common sense will dictate).

    You see, if I have the instruction

    SSIDataGetNonBlocking(SSI0_BASE, &ulDataRx);

    I get no clock signal so I don't get any data from the slave. If instead i do

    SSIDataPutNonBlocking(SSI0_BASE, 0x00);            // Dummy write
    SSIDataGetNonBlocking(SSI0_BASE, &ulDataRx);

    Then a clock signal is generated and then I get the data in ulDataRx. However, I don't think this is the way it should be done, at least this is not how is shown in the "psi_master.c" example. I mean the program is working with this code. It just feels wrong and unnecessary to have that write instruction there, and if this is the case, then there is no way the "psi_master.c" example would work. I hope you got what I mean.

    Regards,

    Max

  • Answered in another thread, but you are tripping yourself up by using the non-blocking versions of the functions.

    I don't unterstand why so many people want to call the non-blocking versions of the functions but don't check the return results.   The non-blocking functions are only appropriate if you can take some other action if the function call fails, like do a task switch while you are waiting, or check for timeout or some other error condition.

    In many cases I see people wait for data to be ready by checking the FIFO status bits, then call tne non-blocking function.  This is better, and you can get away without checking the return value because you know the call will succeed.  However, this is duplicating the effort that is taken just by calling the standard blocking version of the function, taking extra time and code space in the application unnecessarily.

  • Blocking functions are in many cases the better choice ...

    This is particularly true if you are using an OS like FreeRTOS or SysBIOS -- (even the new TI version of same) where you establish a thread -- perhaps with a watchdog timer even... or some form of built-in "dead thread-watch"

    Somebody pointed out to me a few years ago that MS programmers developed the "Blocking Functions are Evil " meme -- because they had a non-threaded OS and needed some way to counter Unix/Linux "propaganda". Maybe the story is even true...

    It takes some experience to evaluate which is more appropriate -- I make no claim that I always get it right... maybe in another 40 years of this stuff I will risk the claim..

  • Hi slandrum,

    Thanks, and as I said on the other thread, the issue is independently of the blocking or non-blocking functions. Non of them is generating a clock signal. I actually do the dummy write with the non-blocking one, and the read with the blocking one. As I said, it is working, it's just feels weird to do that dummy write.

    Hi David,

    Thanks, I get your point, and I personally think that the use of these functions depends on your communication protocol and what is more convenient in your case. Rather than diverge the topic to the use of the blocking or non-blocking functions  I would like to focus on the issue (maybe not, and that's how it has to be) of doing a dummy write to get a useful clock signal for your readings.

    Regards,

    Max

  • Max,

    I understand your frustration. The reason that the Read function is written this way is because it was written to spec, not to convenience. That is to say the functions were written to comply with the SPI standard, which it does. I am sorry for the confusion and I am forwarding your suggestion to our development team as a suggestion for integration in future examples, or at the very least extending another interface that would do the dummy write automatically.

    I am glad to hear that it is working for your now, sorry for the inconvenience,

    -Austin

  • Hi Austin,

    I understand, and it sounds like a good idea to include it in the documentation. I mean, if this is the way it works, then it would be nice to point out somewhere that the get function can never be used alone without calling a "put" first. Thanks!

  • You could write your own convenience functions (these are sketches, details like type declarations are left out):

    SPIMasterSend(base, data)

    {

    SSIDataPut(base, data);

    SSIDataGet(base, &dummy);

    }

    SPIMasterReceive(base, *data)

    {

    SSIDataPut(base, DUMMYVAL);

    SSIDataGet(base, data);

    }

    DUMMYVAL could be required to be 0x00 or 0xff for some devices, most devices probably don't care

    Then in your code, you can make calls that look more like what you'd expect.

  • @ slandrum:

    Masterful!  (especially your caring advisory re: "dummyval.")   Thanks...

    @ Austin:

    Suspect that camouflaged - somewhere - there must be an earlier "Put" which enabled Max's "Get" to appear to work stand-alone...