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.

Help with unexpected SSI3/SPI behavior on TM4C1294

Other Parts Discussed in Thread: TM4C1294NCPDT, EK-TM4C1294XL

Hello everyone, I am back with a question regarding SSI3/SPI functionality on TM4C1294NCPDT; I am working on the EK-TM4C1294XL evaluation board.

I have built an add-on card that sits on connectors X6 and X7 of the EK-TM4C1294XL board. On this card, I have attached a connector where I attach an SPI slave device. (The devices I use are proprietary and I cannot give any information about them, except for an important detail that I will discuss below.)

In my firmware, I have inserted several switch()-case()... decision trees to make it work with all kinds of SPI devices that I want to test. What I am presenting below is the function that initializes SSI3 as SPI / Mode 0 (using Port Q and having ~CS on a GPIO line, PQ1):

// InitSPI(uint32_t SCLK)
//
// Configures SSI3 in master Freescale (SPI) mode using polling method.
// Uses PQ1 to drive the ~CS line.
void InitSPI(uint32_t SCLK)
{
    uint8_t pui8DataRx[10]; // local variable for flushing the SSI/SPI RX buffer

    // The SSI3 peripheral must be enabled for use.
    //ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3);

    // For this example SSI3 is used with PortQ[0:3].
    // GPIO port Q needs to be enabled so these pins can be used.
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ);
    ROM_GPIOPinTypeGPIOInput(GPIO_PORTQ_BASE, GPIO_PIN_3);	// MISO - configure it as GPIO input
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTQ_BASE, GPIO_PIN_2);	// MOSI - configure it as GPIO output
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTQ_BASE, GPIO_PIN_0);	// SCLK - configure it as GPIO output
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTQ_BASE, GPIO_PIN_1);	// ~CS - configure it as GPIO output
    CS_High();	// ~CS - set it to logic HIGH

    pinType = GPIODirModeGet(GPIO_PORTQ_BASE, GPIO_PIN_1);	// ~CS
    pinType = GPIODirModeGet(GPIO_PORTQ_BASE, GPIO_PIN_0);	// SCLK
    pinType = GPIODirModeGet(GPIO_PORTQ_BASE, GPIO_PIN_2);	// MOSI
    pinType = GPIODirModeGet(GPIO_PORTQ_BASE, GPIO_PIN_3);	// MISO

    // The SSI3 peripheral must be enabled for use.
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3);

    // Configure the pin muxing for SSI3 functions on port Q0, Q2 and Q3.
    // This step is not necessary if your part does not support pin muxing.
    GPIOPinConfigure(GPIO_PQ0_SSI3CLK);	// SCLK
    GPIOPinConfigure(GPIO_PQ2_SSI3XDAT0);	// MOSI
    GPIOPinConfigure(GPIO_PQ3_SSI3XDAT1);	// MISO

    // Configure the GPIO settings for the SSI pins.  This function also gives
    // control of these pins to the SSI hardware.  Consult the data sheet to
    // see which functions are allocated per pin.
    // The pins are assigned as follows:
    //      PQ3 - SSI0Rx
    //      PQ2 - SSI0Tx
    //      PQ1 - SSI0Fss
    //      PQ0 - SSI0CLK
    ROM_GPIOPinTypeSSI(GPIO_PORTQ_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_0);

    // Configure and enable the SSI port for SPI master mode.  Use SSI3,
    // system clock supply, idle clock level low and active low clock in
    // Freescale SPI mode, master mode, and 8-bit data.
    // For SPI mode, you can set the polarity of the SSI clock when the SSI
    // unit is idle.  You can also configure what clock edge you want to
    // capture data on.  Please reference the datasheet for more information on
    // the different SPI modes.
    ROM_SSIDisable(SSI3_BASE);	// Disable the SSI3 module to configure it
    ROM_SSIConfigSetExpClk(SSI3_BASE,
    			g_ui32SysClock, // this is a global variable to set system clock frequency
    			SSI_FRF_MOTO_MODE_0,
			SSI_MODE_MASTER,
			SCLK,
			8);

    ROM_SSIEnable(SSI3_BASE);	// Enable the SSI3 module.

    // Read any residual data from the SSI port.  This makes sure the receive
    // FIFOs are empty, so we don't read any unwanted junk.  This is done here
    // because the SPI SSI mode is full-duplex, which allows you to send and
    // receive at the same time.  The SSIDataGetNonBlocking function returns
    // "true" when data was returned, and "false" when no data was returned.
    // The "non-blocking" function checks if there is any data in the receive
    // FIFO and does not "hang" if there isn't.
    while(ROM_SSIDataGetNonBlocking(SSI3_BASE, (uint32_t*)&pui8DataRx[0]))
    {
    }

    // Last, initialize number of SPI transfers to zero
    ui32SPITransfers = 0;
}

Below are some information that I can share about the SPI devices that I am trying to test. Both devices have been tested and found to be functional using another, third-party measurement system.

Device #1 has four independent pads for SPI - ~CS, SCLK, MOSI and MISO. This device works fine with the firmware.

Device #2 shares two out of four pads with TWI - namely, SCL/SCLK and SDA/MOSI; moreover, the ~CS pad is internally pulled up and should be driven LOW in order for the device to enter SPI mode. On that device, I keep on having the SDA/MOSI line at logic HIGH, no matter what data I send to the device. This results in getting 0xFF on the MISO line when I try to read data from the device.

I have been searching through this forum all day long and I have found the following post that resembles, to some extent, my case: SSI interface with accelerometer(H3LIS331DL). It states something about locked MCU pins and that was indicated as a solution to this problem. However, by browsing quickly through the MCU datasheet, I could not find anything relevant to that issue.

Does anyone have any idea on how can I get device #2 - that is otherwise functional, I repeat - to work on my test rig? Your answers are most welcome.

  • George Metaxas said:
    devices I use are proprietary and I cannot give any information

    You should know that many "helping here" are off-put by "any" such proclamation.   Our assistance benefits "just one" (happens to be you) and that's rarely - if ever - desirable/good!

    Here my "non-proprietary" (necessarily quick) suggestions:

    • temporarily "break" all common connections between each SPI device.  (but for power)   Repeatedly we've found client devices (claimed to be quiet) to in fact "Violate that quiet/inactive state" thus confound & delay troubleshooting.   (we charge client for that over-sight!)
    • Do you (really) drive ~CS pad low?   Have you confirmed - right @ device pin?   (not @ test-point or header)
    • You report, "keep on having SDA/MOSI line high."   Unclear here is "which device" is being referenced!   (MCU's MOSI or "secret" Slave?)  I'd suspect this is the MCU's MOSI - and if you toggle that line (i.e. perhaps by xmsn. of 0x55 or 0xAA) and the line remains high - should you not (temporarily) break the path between MCU & "secret" device - and confirm that the "secret" device proves the culprit?  (as the MCU proves successful w/other device - this must be the case - don't you agree?
    • Unclear also is, "this 0xFF upon MOSI returning same 0xFF upon MISO."   (again, MCU assumed)  Assuming those 2 SPI data lines are not shorted - why does the one (MOSI) so impact the other?  (MISO)   (I don't believe there's a general "SPI" rule that MISO must "universally" re-broadcast data from MOSI!)

    More "non-proprietary" facts are required - are they not?    As always - as your "proprietary" device is unknown, untested - has not been fully/properly reviewed by peers (its secret) it remains (absolutely) PRIME SUSPECT!   We note that you make (brief, unspecified) mention of a 3rd party test device - and should that be true - your presentation of those successful waveforms - acquired during actual testing - will prove of immense assistance.   Again - if that's the case - I'd bet that you've not fully/properly duplicated connection and/or set-up via this vendor's MCU...

  • Good Heavens, you really have the IC change the I/O lines to IIC when you release CS!?

    Clearly CS must be an acronym for Confuse Sensor. I cannot see this working well on a non-dedicated SPI interface and would question using even a dedicated SPI line.  It's clearly designed for IIC only.

    I agree with cb1's admonitions and besides my incredulity would add that you almost certainly need to impose tri-stateable buffers between this chip and your micro's I/O lines

    Robert

  • Hello again and thank you both for your contributions. I understand that it is not the nicest thing to refer to non-disclosable details, but this is business stuff and I cannot do otherwise. The only thing that I can mention here is the details I have already shared and one more thing:

    In the function that I have quoted above, I try to configure MISO (PQ3) as input and all other three lines (PQ0, PQ1, PQ2) as outputs. Right after that, I have placed four calls to GPIODirModeGet() to check if those settings have been made. A strange thing is that both MOSI and MISO lines seem to have been configured as inputs, since GPIODirModeGet() returns 0. This is true even when I disconnect the SPI device from the MCU's pins. Furthermore, I tried to test the status of the Port Q pins that I am currently using by inserting calls to GPIOPadConfigGet() in the function I have already quoted above. This is what I got:

    Pin Driving strength Pad type
    ~CS GPIO_STRENGTH_2MA GPIO_PIN_TYPE_STD
    SCLK GPIO_STRENGTH_2MA GPIO_PIN_TYPE_STD
    MOSI GPIO_STRENGTH_2MA GPIO_PIN_TYPE_STD
    MISO 0 (?) 0 (?)

    Those zero values returned in the case of MISO are really strange! Any ideas about that?

    In the meanwhile, I am trying to debug things using your suggestions and will come back when I have any news.

    EDIT: I tested and confirmed tested the following things:

    No common connections exist between the two SPI devices; one device at a time is tested.

    ~CS pad is really driven LOW, both with device #2 (or #1) connected to the SPI bus and with no device attached to it:

    MOSI pad stays HIGH when SPI device #2 is connected;

    the same pad shows the data sent to the SPI bus when nothing is connected to it.

    Data read from the device are 0xFF, according to both the debugger and the USB monitor software I am using. MISO and MOSI pads are not shorted.

  • Hello George,

    While I understand you may not be able to disclose the devices being used as slave, it does severely impair the forum investigation into possible root cause. To still be able to perform some analysis, can you describe

    1. What is the connectivity of the TM4C129x pin to each of the devices?
    2. Generally devices have some form of Read Only ID register. Can you check with a Logic probe connected, the CS, MISO, MOSI and SCLK lines when communicating with each of the devices?

    Regards
    Amit
  • Device #2 shares two out of four pads with TWI - namely, SCL/SCLK and SDA/MOSI; moreover, the ~CS pad is internally pulled up and should be driven LOW in order for the device to enter SPI mode. On that device, I keep on having the SDA/MOSI line at logic HIGH, no matter what data I send to the device. This results in getting 0xFF on the MISO line when I try to read data from the device.

    That sounds like a SPI/I2C combi device. I suggest to carefully re-read the datasheet of this (undisclosed) IC. I know of at least one such device (a MEMS sensor) that switches the interface to I2C-mode when /CS is high. Such devices do often not behave well with other devices on one SPI bus.

  • Dear Amit and f.m., thank you for your posts. Unfortunately, today I am at home trying to recover from flu... :(

    About connectivity: To be honest, my setup is not the best; I use about 30 cm of 8-core, shielded cable that runs from the PCB holding the DUT to a perf board with female headers that plug into X6 and X7 male headers of EK-TM4C1294XL. There is a reasonable amount of ringing but this piece of shielded cable is the only solution that enables proper testing of the DUT. I have designed a double-sided PCB with a ground plane that will host the female headers and an 8-pole, shielded Mini-DIN connector that will permit proper connection of the SPI and power lines to the DUT. Anyway, this kind of setup worked OK for device #1 but not for device #2.

    Let me add more on this from yesterday's efforts: I noticed that when I touched the MISO pad/line (bare wire that is soldered on the perf board) the state of the line changed from HIGH to LOW; the data I was reading changed from 0xFF to 0x00. Taking my hand away resulted in the previous situation (MISO to HIGH and data to 0xFF). This shows that somewhere, something is not properly connected - either a ground return or a cold joint on the MISO line or I don;t know what... All this happened just before ending the previous day, so I have not proceeded with any corrective action yet. And the bad news is that, after trying to add some ground wires around and under the SPI lines on the perf board, neither device #2 nor device #1 work; all I get is MISO at HIGH and corresponding data of 0xFF... The first thing to do when I get back is to rebuild the interface in a better way.

    About read-only ID: Actually, what I do in my firmware is to read the default (startup) values of some registers in the DUT. All I get is 0xFF, no matter what I try to read.

    About the I2C/SPI combi: Yes, this is exactly the case for device #2. I checked the firmware that is used on another test rig for the same type of DUT - a different type of MCU is used there - and did not see any special procedure other than taking ~CS LOW to switch the device to SPI mode. Having discussed with some of my colleagues concluded to the same result: just take the ~CS LOW and the DUT switches to SPI mode. And as you can see in my previous post, ~CS does get LOW when it should be. Again, only one device is connected to the SPI bus.

  • And as you can see in my previous post, ~CS does get LOW when it should be. Again, only one device is connected to the SPI bus.

    That would be o.k. The trouble usually start with more than one device on a bus. With /CS=high, this devices tend to interpret SPI communication to another device as I2C communication, sometimes with 'strange' results.

    About connectivity: To be honest, my setup is not the best; I use about 30 cm of 8-core, shielded cable that runs from the PCB holding the DUT to a perf board with female headers that plug into X6 and X7 male headers of EK-TM4C1294XL.

    That might be the source of your problem. The best way is to keep the lines as short as possible, and use termination resistors to pull the lines to the idle-state. A good example for those hardware is a SD-card interface (via SPI) - there are plenty of schematics around. For testing, reducing the SPI clock speed, at least temporary, might help. It will be helpful to check the signals with a scope, but be aware that the probe impedance will affect the signal ...

  • Hi to all, I am back to work and have come to a solution that has to do with wiring!.. I feel really ashamed for not having noticed that earlier, for it would have saved me much time and effort - and I would not have to bother you, too...
    Here is how it goes:
    The cable where I connect the DUT ends to a female connector (2 x 8, 1.27 mm pitch).
    Device #1 sits on a test PCB that has a female connector (2 x 8, 1.27 mm pitch).
    Device #2 sits on the same kind of test PCB that has a MALE connector (2 x 8, 1.27 mm pitch).
    This means that, in order to connect device #1 to my cable connector, I have to reverse the position of the two pin rows by means of a proper custom-made (by myself, of course) male-to-male adapter; to connect device #2, this reversal SHOULD NOT be done!
    That's why I kept having MOSI at HIGH and so on... signals did not even reach the DUT in the first place! :(
    After a lot of head scratching in front of the logic analyzer, I picked up the DMM and soon I came up with the solution.
    Now, I can continue with further firmware- and software development of my measurement system.
    Thanks to everyone that kindly posted here; I hope that next time I post anything it will be about a milestone achieved...
  • We are glad to learn of your success.   That said - many of the tips here were (and are) extremely useful.   You'd do well (as would others) to list & keep these - for on-going development...