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.

SPI Chip Selection signal using GPIOPinWrite problem

Other Parts Discussed in Thread: EK-TM4C123GXL

Hi all,

I'm moving from atmel uControllers, into ARM uControlers, so I'm relatively new with this architecture and way of code. I acquired a stellaris launchpad and started with some SPI experiments. So, my question is related with the following code: 

1. GPIOPinWrite(GPIO_PORTB_BASE,GPIO_PIN_6,0x00);

2. SSIDataPut(SSI0_BASE, 0x00);

3. SSIDataGetNonBlocking(SSI0_BASE, &ulData1);

4. //ROM_SysCtlDelay(DELAY1);

5. GPIOPinWrite(GPIO_PORTB_BASE,GPIO_PIN_6,0x40);

The Pin 6 of the PORTB  is used as a Chip Select pin, I don't want to use the chip selection of the SPI interface, I want to use the pin 6 signal. I put the pin at logic level 1 in the beginning of the code, and in the above line 1, I put it at 0 level. After that I acquire the SPI data, and put it back to 0. However, analyzing the signals in the oscilloscope  it seems that the processor evaluates the lines 1. and 5. first and after that it sends the SPI data, as shown in the picture below. The yellow wave is the GPIO_PIN_6 and the blue line is the SPI clock.I want the yellow signal to go to one only after the SPI clock ends. I'm missing something about the uController behavior, I don't know what, but this look like pretty strange to me, can anyone please help with this.  

I figure out a way to solve this, if I add the line 4. in the code with a proper delay, I can extend the GPIO_PIN_6 duration, but I still want to understand why the uController does not hold the Pin at 0 level during the SPI functions.

Thanks in advance

Cheers

  • Your post is silent with regard to chosen MCU.  There are different classes w/in Stellaris MCUs - and not all Stellaris functions are available across all classes.

    In addition - we're not shown which pins you've chosen - and configured - as SPI.  It is possible that PB6 (your claimed SPI_CS) either defaults into SPI mode - or has been configured as such by your code.  The fact that you can GPIOPinWrite() PB_6 argues against this - but imperfectly config'ed pins may behave in a strange manner.  (not confined just to this ARM vendor)  Thus - we need to see your set-up and config code for all relevant ports, pins, and peripherals - none appear currently.

    If indeed - SPI default is confounding PB_6 - simply choose an unrelated (to SPI) port & pin - and bit-bang it for total SPI_CS control - no worry about SPI "encroachment" via this method.  In addition - this method allows multiple SPI Slaves to be "worked" - by employing multiple such "foreign" GPIO as SPI_CS of choice...

  • Hi Jorge, a couple things I might suggest,

    First, please add PA5(SSI0Tx) and PA4(SSI0Rx) to the scope so we can see if you are actually writing / reading anything. Also please verify that you do in fact have channel 2 hooked up to PA2(SSI0CLK)

    Next, why are you using PB6 as the chip select and not PA3, which is SSI0Fss (chip select).

    Finally, please make sure that your pinmuxing is set up correctly. (done by default through the API's, but you will want to check that your PB6 isnt being used by something else) This utility is a great way for people new to the launchpad to get their pinmuxing done, it takes alot of the headache out of it (http://www.ti.com/tool/lm4f_pinmux)

    If you would like further help please provide a screen shot with the pins hooked up as listed above, Also your source code would be useful so i can try to reproduce / debug your issue.

    Regards,

    -Austin

  • Hello,

    I have tried to reproduce the error today, and it seems that the problem disappeared (I really don't understand why it disappeared) . Despite this factor, below you have my code (which is now working) and a representation of the waveform requested by Austin. Once I have not connect SSI TX to anything, because I only want to read values from the other device, I substituted the 0x00 in SSIDataPut with 0x4444, just to see the signal in the scope. Thanks Austin, for the tip about the lm4f_pinmux utility.

    Code:

    #include "inc/hw_memmap.h"
    #include "inc/hw_ssi.h"
    #include "inc/hw_types.h"
    #include "driverlib/ssi.h"
    #include "driverlib/gpio.h"
    #include "driverlib/sysctl.h"
    #include "utils/uartstdio.h"
    #include "driverlib/uart.h"
    #include "driverlib/rom.h"

    #define DELAY1 260
    #define DELAY2 2000000

    //UART0 initialization
    void
    InitUART0(void)
    {
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);

    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    UARTStdioInit(0);
    }


    //SSI0 initialization
    void
    InitSSI0(void)
    {

    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);

    GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    GPIOPinConfigure(GPIO_PA3_SSI0FSS);
    GPIOPinConfigure(GPIO_PA4_SSI0RX);
    GPIOPinConfigure(GPIO_PA5_SSI0TX);

    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 | GPIO_PIN_2);

    SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_1,SSI_MODE_MASTER, 1000000, 16);

    SSIEnable(SSI0_BASE);
    }


    int main(void){

    unsigned long ulData1;

    SysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

    GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE,GPIO_PIN_6);

    //Chip Select Pin PORTB_PIN_6 change to '1'
    GPIOPinWrite(GPIO_PORTB_BASE,GPIO_PIN_6,0x40);


    InitUART0();
    InitSSI0();

    UARTprintf("Started\n");

    while(1){

    UARTprintf("Clear");
    while(SSIDataGetNonBlocking(SSI0_BASE, &ulData1))
    {
    }


    UARTprintf("Get Data:\n");
    //Chip Select Pin PORTB_PIN_6 change to '0'
    GPIOPinWrite(GPIO_PORTB_BASE,GPIO_PIN_6,0x00);
    //Send dummy
    SSIDataPut(SSI0_BASE, 0x4444);
    //Read SSI data
    SSIDataGet(SSI0_BASE, &ulData1);
    //Chip Select Pin PORTB_PIN_6 change to '1'
    GPIOPinWrite(GPIO_PORTB_BASE,GPIO_PIN_6,0x40);
    //Send read value via UART
    UARTprintf("B: %d",ulData1);
    UARTprintf("\n");

    SysCtlDelay(DELAY2);
    }
    }

    SCOPE:

    Yellow: GPIO_PORTB_PIN_6

    Blue: GPIO_PORTA_PIN_2 (SSI0CLK)

    Rose: GPIO_PORTA_PIN_4 (SSI0RX)

    Green: GPIO_PORTA_PIN_5 (SSI0TX)

    Thanks for your help.

  • Jorge,

    Glad to hear it's working. Sometimes there's just a ghost in the machine and it all clears up. Do you still have a question or are you good to go?

    -Austin

  • For now, I'm good. If I get something more I will post it. 

    Thanks very much for your quick replies.

    Regards 

  • I beleive that real cause here is the line 3. There "Non Blocking" operation is used.

    To fix it you should use "while" statement with "SSIBusy(SSI0_BASE)" check after line 3 or place line into while statement in place of SSIBusy

  • Jorge Carola said:
    I have not connect SSI TX to anything, because I only want to read values from the other device,

    If indeed that is the case - you will never (acquire or read) any "meaningful" data.  As fellow poster slandrum has told us (maybe once/twice!) SPI reads (Get) occur in concert w/ SPI writes (Put) - and w/out that SSI TX signal reaching the slave - slave's output is likely to be meaningless!

    Alexey's observation also deserves analysis - further consideration.  (machine resident ghosts - not so much...)

  • Hy All!
    I have some problem with SSI module. I tuse EK-TM4C123gxl launch pad with an FT800 EVE graph proc, I want to communicate via SSI, but If I try to change the logic level on FSS (Pin PA3) nothing happens... It stays in inactive logic level ( 3.3V)... I try to change with "ROM_GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,GPIO_PIN_3)" but nothing.... If I use it just like an normal GPIO, It works, I can change the logic level.. but If i configurate it like SSI module It don't.. Anybody Can help me?
  • Hello user4165784,

    How have you configured the IO? If the IO is configured as FSS using GPIOPinConfigure and then you attempt to write using GPIOPinWrite it will not work. For the GPIOPinWrite API to work you need to configure it as a GPIO.

    Regards
    Amit
  • Thanks Amit!

    First time I have configured like as FSS, but after this I have changed the configuration, I have configured PA3 as a normal GPIO, accurately Output! :) I hope it will work :)
  • Hello ZsirosB.

    So is the issue resolved? If not then can you please share the configuration of IO, SSI and what in the data transfer that fails?

    Regards
    Amit
  • Hy Amit!

    I think yes.. I can change the logic level of PA3

    Here is my configuration(I hope I didn't miss anything):

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);

    ROM_GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    ROM_GPIOPinConfigure(GPIO_PA4_SSI0RX); //MISO
    ROM_GPIOPinConfigure(GPIO_PA5_SSI0TX); // MOSI

    ROM_GPIOPinTypeSSI(GPIO_PORTA_BASE,GPIO_PIN_5|GPIO_PIN_4|GPIO_PIN_2);

    //As you can see I didn't configure PA3 as FSS//
    And here is the PA3 Configuration:

    GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE,GPIO_PIN_3);
    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,GPIO_PIN_3);


    ROM_SSIConfigSetExpClk(SSI0_BASE,SysCtlClockGet(),SSI_FRF_MOTO_MODE_0,
    SSI_MODE_MASTER,1000000,8);

    ROM_SSIEnable(SSI0_BASE);

    In my SII init function I write GPIO_PIN_3 because in the default case CS have to be in inactive state.
    And the answer for your question: I can't test the communication because I didn't write the whole init sequence for the FT800, this problem was just a little part of a whole task! :) But thanks four your help Amit!:))

    Best regards,

    Zsiros B
  • Hello Zsiros,

    You can configure the FSS as a control from the SSI controller and it will remain in Inactive State when there is no data transfer. Only when a byte is to be transmitted will it become active low and then transition back to High.

    Regards
    Amit