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.

Unable to send more then 8 bits on SSI

I have been fighting this issue for 2 days and hoping someone can help.

I am using the Tiva TM4C1294 Launchpad and need to communicate with a touch screen.

I am using CCS on a Windows machine.

I need to send a 16 bit word over an SSI port but every method I have tried will only send 8 bits and stop.

Here are the versions of code I have tried:

Try 1. Manual chip select sending two 8 bit words. I have used this successfully on the Stellaris MCU.

// Enable and configure SSI0
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); //
SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);

GPIOPinConfigure(GPIO_PA2_SSI0CLK); 
GPIOPinConfigure(GPIO_PA4_SSI0XDAT0);
GPIOPinConfigure(GPIO_PA5_SSI0XDAT1);
// Setup SSI Port for Touch Screen
GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_2);

SSIConfigSetExpClk(SSI0_BASE, g_ui32SysClock, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 4000000, 8);
SSIAdvModeSet(SSI0_BASE, SSI_ADV_MODE_LEGACY);
SSIEnable(SSI0_BASE);

// Setup Touch screen chip select
GPIODirModeSet(GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_DIR_MODE_OUT); //  /TCS
GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3);
GPIOPadConfigSet( GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_STD );

SET_TCS; // this is same as SSIOFSS

// interrupt pin
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP);
SysCtlDelay(20000);
GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_0); // P0
GPIOIntTypeSet(GPIO_PORTP_BASE, GPIO_PIN_0, GPIO_FALLING_EDGE); // was FALLING_EDGE

CLR_TCS;

SSIDataPut(SSI0_BASE, 0x02);
while ( SSIBusy(SSI0_BASE)) {
}

SSIDataPut(SSI0_BASE, 0xF0);

while ( SSIBusy(SSI0_BASE)) {
}

SET_TCS;

Try 2. Manual chip select send one 16 bit word

// Enable and configure SSI0
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); //
SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);

GPIOPinConfigure(GPIO_PA2_SSI0CLK); // defined in pin_map.h
GPIOPinConfigure(GPIO_PA4_SSI0XDAT0);
GPIOPinConfigure(GPIO_PA5_SSI0XDAT1);
// Setup SSI Port for Touch Screen
GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_2);

SSIConfigSetExpClk(SSI0_BASE, g_ui32SysClock, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 4000000, 16);
SSIAdvModeSet(SSI0_BASE, SSI_ADV_MODE_LEGACY);
SSIEnable(SSI0_BASE);

// Setup Touch screen chip select
GPIODirModeSet(GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_DIR_MODE_OUT); // SSI0Fss PA3 /TCS
GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3);
GPIOPadConfigSet( GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_STD );

SET_TCS;

// interrupt pin
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP);
SysCtlDelay(20000);
GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_0); // P0
GPIOIntTypeSet(GPIO_PORTP_BASE, GPIO_PIN_0, GPIO_FALLING_EDGE); // was FALLING_EDGE

CLR_TCS;

SSIDataPut(SSI0_BASE, 0x02F0);
while ( SSIBusy(SSI0_BASE)) {
}

SET_TCS;

Tries 3 and 4 are same as above except I set pin A3 as the SSIOFSS chip select and removed the CLR_TCS and SET_TCS macros

I have also tried to do a direct hardware write to the FIFO as here:

CLR_TCS;

// Wait until there is space.

//
while(!(HWREG(SSI0_BASE + SSI_O_SR) & SSI_SR_TNF))
{
}

//
// Write the data to the SSI.
//
// HWREG(SSI0_BASE + SSI_O_DR) = 0x02F0;

SET_TCS;

I have tried with and without SSIAdvModeSet(...)

Looking at the serial data analyzer I see the CS line go low, all 16 clock pulses sent but only the first byte of data sent.

The second byte does not get sent.

I am at a loss. 

I can send screenshot if you like.

Thanks in advance.

Sam

  • Clarification: When setting pin A3 as the SSIOFSS chip select instead of a manual chip select, I could only do a 16 bit send as two 8 bit sends would have toggled the CS line. However, it would still only send the first byte (left 8 bits) of the 16 bit word.
  • This is a complaint that's always puzzled me when it's made. It's simple enough just to send multiple bytes. I could understand the dilemma more easily if you needed to send, say, 14 bits and you couldn't mock it up with 16 and just throw away the leading bits. OTOH, I don't know of any SPI peripheral that works in that fashion.

    In more direct answer to your question, why assume that the micro's SPI peripheral has to toggle the chip select?

    Robert
  • The device I am communicating with requires a 16 bit word with CS held low.  I don't care if I send one 16 bit or two 8 bit words.

    I just need to hold CS low the whole time.

    Oddly, if I don't set the CS line low and sent the bytes, they both are sent.  It is as if the CS line is somehow tied to the SSI function.

    I may have to use a different line for CS.

    Thanks

  • One question that may help you. What happens to the input data?

    Robert
  • I stay clear of the auto cs for that reason if i can. Some implementations have been known to be buggy. Don't know about TI's though.

    Robert
  • Not using input data, just sending.
    I have used SPI on many processors (Atmel, PIC, Silabs, TI and Rabbit and have never run into this problem.
    Setting the SSI for 8 bits and allowing it to control the PA3 line it does send both bytes, however I have to use a different line for chip select and just ignore the PA3 line.
    It's not perfect, but it works.
    Thanks for your input.
    Sam
  • I know, but the SSI FIFO does fill up and may perhaps block.

        GPIO_PORTF_DATA_R &= ~(0x4u);		/* Select chip		*/
        for( index=0u;index<2u; index++) {
             SSIDataPut(SSI0_BASE, ~out_data[index]);
             }
    ....
    
        SSIDataPut(SSI0_BASE, ~out_control);
    
    	      	/* Wait until SSI done */
        while(SSIBusy(SSI0_BASE)) {
            }
    
        GPIO_PORTF_DATA_R |= 0x4u;			/* De-select chip	*/
    
        for( index=0u; index<3u; index++) {
             SSIDataGet(SSI0_BASE, &data_in[index]);
             }
    

    Above is extracts from my SPI write, data_in is a dummy just to flush the buffer. At the very least I need to also perform reads from other devices so I must clear the buffer.  Even if I didn't now it would be a could code hygiene practice.

    Checking my init, I see I do assign FSS even though I don't use it.

        		/* Configure SPI pin muxing */
             GPIOPinConfigure(GPIO_PA2_SSI0CLK);	
             GPIOPinConfigure(GPIO_PA3_SSI0FSS);	
             GPIOPinConfigure(GPIO_PA4_SSI0RX);	
             GPIOPinConfigure(GPIO_PA5_SSI0TX);	
        		/* Configure SSI to use pins */
             GPIOPinTypeSSI( GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 |
        		GPIO_PIN_2);

    The FSS really shouldn't come into play if it's not used. Maybe Amit or Sai can comment on the TI implementation?

    Robert

  • Here is an example of my output using 16 bit.   /CS is PA3

    The code:

    // Enable and configure SSI0
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);

    MAP_GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    MAP_GPIOPinConfigure(GPIO_PA4_SSI0XDAT0);
    MAP_GPIOPinConfigure(GPIO_PA3_SSI0FSS);
    MAP_GPIOPinConfigure(GPIO_PA5_SSI0XDAT1);
    // Setup SSI Port for Touch Screen
    MAP_GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 | GPIO_PIN_2);

    MAP_SSIConfigSetExpClk(SSI0_BASE, g_ui32SysClock, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 4000000, 16);
    MAP_SSIEnable(SSI0_BASE);

    MAP_SSIDataPut(SSI0_BASE, 0x02F0);

    while ( MAP_SSIBusy(SSI0_BASE)) {
    }

    The output:

  • That image lacks a time scale, that's a pretty elementary feature to be missing from a logic analyzer display.

    However it does suggest you're sampling at 12 MHz and your code suggests a 4 MHz clock. If true that's not entirely adequate sampling. My first sanity check would be to either increase the sampling rate and/ or lower the clock speed and remeasure. My second sanity check would be to measure the width of the select since it appears you can do that.

    Robert
  • The clock was measured at 4 MHz. One test I did was to drop it to 400 kHz but had same result.
    The /CS period measured at 5.33 uS
    For a $150 logic analyzer it does the job.
  • Ok, my fault. I didn't count the clocks. I had assumed from the discussion that there were only 8. Still, you are working in an area where there will be sampling issues.

    5.3 uS gives a little over 21 clock periods so it all seems to line up correctly. I'm not sure what you're complaint about the output could be.

    Robert
  • Okay.    Got it!

    See if you can tell by looking at this screen shot why it worked.

  • My complaint was that I was sending 0x02F0 and only the 02 got sent. After finding the problem it now send both the 02 and the F0.
  • Well if you haven't guessed by looking at the screenshot, the MISO line is low. Due to a wiring error the line was being held high and the MCU was waiting for a response which is why the second byte never got set. After fixing the error all is right with the world.
    Thanks for you help. Once again, never assume anything.
  • Sam Virgillo97352 said:
    Well if you haven't guessed by looking at the screenshot, the MISO line is low. Due to a wiring error the line was being held high and the MCU was waiting for a response which is why the second byte never got set

    Um, that makes no sense to me the SPI peripheral shouldn't care about the state of the MISO line. Pretty much by definition.  After all how would you distinguish between a returned value being all high and the line being stuck?

    The miss-wiring maybe affected something else?

    Robert

  • From the SPI Wiki:

    During each SPI clock cycle, a full duplex data transmission occurs. The master sends a bit on the MOSI line and the slave reads it, while the slave sends a bit on the MISO line and the master reads it. This sequence is maintained even when only one-directional data transfer is intended.
  • Exactly, the state of the line (high or low) determines the value read in, it does not halt the process.

    Robert
  • May I (Like) & "second,"  poster Robert's statement.

    We've past used Display Controllers - which had (both) SPI TX & SPI RX capability - and "TX only" operation succeeded!

    I2C - w/the dreaded ACK/NAK - indeed requires a (proper) bit return/presentation - but "not so" under SPI...

  • So it should have just read in 0xFF. Hmmmm. Mystery.
  • Yep, I've had cases of shorts or miss-wiring (wire-wrap is prone to miss- wiring), it can cause debug confusion but not a stop.

    One of the reasons I prefer SPI over IIC is that it doesn't hang when a device is miss-configured or improperly addressed.

    Robert
  • My "bet" - while you surely altered that cabling - the "return" of any data bit did NOT (then) enable a (desired) 16 bit transmission.

    During development - it's "usual" for code changes to occur. Either that - or another impact of your hook-up efforts - may prove a better explanation of your "mystery"...

    Wise man once said, "We truly understand something when we can "Break - and then FIX" it - not when it runs by itself - minus our understanding..."

    Your reestablishment of the original (errant) connection would prove of interest!   (assumes that you (really) want to know/master...)

  • My theory is that because the MISO line NEVER went low even after the 8 clock cycle period the MCU got hung up.
    When I forced that line low even before fixing the wiring error, it worked correctly.
  • Sam Virgillo97352 said:
    When I forced that line low even before fixing the wiring error, it worked correctly.

    May I dispute that statement as, "causal nexus?"

    Firm/I have long employed SPI-based, flash memories for data, font & graphic image storage.   And often - "ALL NON-ZERO bytes and/or 16 bit words" are returned.   And the SPI memory works - and we log 0xFFFF.

    Have you a 2nd board to test/verify?   I'm (almost) sensing that you've a "bad pin" or "external device/signal" on "MISO" - yet that (fails terribly) to explain how your first 8 bits pass untarnished...

    Seems most fitting to carefully "monitor" MISO - it may be rising in voltage beyond its spec - and the "grounding exercise" restores it to acceptable levels.   (for a brief period - that's why this "fix" may NOT be what it seems...

  • Yeah, I don't believe that's a reasonable explanation either. I would suspect an unrecognized SW change but possibly an odd HW effect like your overvoltage or a reset.

    Robert
  • I will accept success... even if it's random.

    I can move on and finish this project.

    Thanks to all.
  • Such success may prove to be quicksand. It looks more stable than it is.

    Robert