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.

SSI peripheral SS pin query

Other Parts Discussed in Thread: TM4C123GH6PM

Dear all,

 I am using SSI0 peripheral of TM4C123GH6 for communicating with the 25AA02 eeprom. I am using this initalization code:

=========================================================================================================================

SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);


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


GPIOPinTypeSSI(GPIO_PORTB_BASE, GPIO_PIN_4 | GPIO_PIN_6 | GPIO_PIN_7|GPIO_PIN_5);
GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4|GPIO_PIN_5);

UARTConfigSetExpClk(UART1_BASE, SysCtlClockGet(), 9600,(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));

SSIDisable(SSI0_BASE); // disables th SSI module as required for init

SSIClockSourceSet(SSI0_BASE, SSI_CLOCK_SYSTEM); // sets the system clock as the source of clock


SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0,SSI_MODE_MASTER, 400000, 8);// defines base, System clk, Mode 0 = SPH = SPO = 0,Master, 400 KHz, no. of bits = 8 = 1 byte transfer

SSIEnable(SSI0_BASE); // enables SSI


SysCtlDelay(100000);

========================================================================================================================

What i was thinking is that when we use the APi fn   SSIDataPut(SSI0_BASE,0x54);   does the peripheral automatically make SSI0Fss =0 automatically, or we have to do it through the GPIO command ? If so, then  how can we arbitrarily control Fss pin, as required sometimes by the Protocol explained in the datasheet of the 25AA02 chip.

  • Hello Turjasu,

    The API will cause the SSIFSS pin to be driven low only when the data transmission is to be done. If an arbitrary control of FS is require (prefer the word specialized instead of arbitrary), then the SSIFSS pin needs to be in GPIO Mode

    Regards
    Amit
  • Amit Ashara said:
    prefer the word specialized instead of arbitrary

    Might "User Toggled" (control of SSIFSS) be even better?  (though true - specialized trumps arbitrary...)

    User Toggled better specifies that it's the user's code which bears "full responsibility" for SSIFSS's level transitions - to insure they meet the Slave's requirements. 

    Specialized proves bit too vague/inexact - while Slave SPI tech writer would (properly) protest the labeling of his SPI signals as, "arbitrary!"

  • Hello cb1,

    Yes, "User Toggled" would be the most apt word and it indeed is controlled by configuring the SSIFSS pin GPIO mode. The only thing would be that synchronizing it to a sub-word read/write during a transmission may not be possible w/o software changes.

    Regards
    Amit
  • Amit Ashara said:
    ...synchronizing it to a sub-word read/write during a transmission may not be possible w/o software changes.

    Indeed - yet that would hold true if we "called" the process "specialized" too.   Exactness of definition imposes no "extra" demands upon the software...

  • Hello Sir,

    I understand that if I have to "user-toggle" the SS pin then its code depandant as to how and when to activate the chip, so as to sync with the data txn. However, in the datasheet of TM4C123GH6 (SSI section) I find that there is one mode "Continuous transfer" and one as "Single transfer". But how to manage these two types separately using Tivaware API ? or even without it.

    As because for an example, where I send say three bytes of data to an SPI slave : 0x06, then 0x02 and then 0xfe. Here 0x06 will be in single mode (that is the SSI0Fss should go high after this value is sent) whereas 0x02 and 0xfe will be in Continuous mode (that is the SSI0Fss should only go high at the final stage after the 0xfe is gone).

    If this is possible through any SSI API, then I donot need to control the Fss as "User toggled"

    Please suggest
  • Hello Turjasu,

    The continuous transfer mode refers to the fact that if there is data always in the FIFO then how the SSI Core would behave v/s Single data in the FIFO. There is no specific API for the same. As long as the CPU or uDMA ensures that the TXFIFO is not running empty the continuous mode would be initiated.

    In the specific example you mentioned then you would need the SSIFSS pin to be GPIO controlled for TM4C123 devices. Otherwise method would be to write 0x06, wait for the SSI Busy to go low, then in quick succession write 0x02 and 0xFE. However if an interrupt happens between the two bytes, then the chances of the FSS being low would be less. Hence a GPIO controlled method would be preferred.

    Regards
    Amit
  • Dear amit,

    Im facing a strange problem and have no clue. Here it goes:

    As i said bore, I am sending commands 06h, after which a positive pulsing of SCLK is needed, then im sending 02h, 01h and finally ACh to 25AA02 SSI EEPROM from Microchip. Then after a delay of about 1 sec, Im sending 03h, followed by 01h and then Im reading through the SSI Rx line. The idea is that in the first stage im writing 0xac to memory SSI EEPROM location 01h, and after the sufficient writing time (that is given as 5ms in its datasheet, Im allowing 1 second fo my understanding) im trying to read back the same data from that same memory location 01h inside the EEPROM. However, in the last line Im comparing the received value and if it matches the written data, I flash an LED at PD4.

    I had succeeded with this bit banged code below:

    /*
    * main.c
    */

    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "driverlib/ssi.h"
    #include "inc/tm4c123gh6pm.h"
    uint8_t slave_data = 0x0;
    uint8_t TestData = 'W';

    void main(void)
    {
    SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE,GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_5);
    GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE,GPIO_PIN_2);
    GPIOPinTypeGPIOInput (GPIO_PORTA_BASE,GPIO_PIN_4);

    GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_2, 0); // MAKE CS' = 0
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0xff); // MAKE sclk = 1
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, 0xff); // MAKE CS' HIGH
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, 0); // MAKE CS' = 0
    ////////////////// send wren signal /////////////////////////
    slave_data = 0x06;
    int i;
    for(i=0;i<8;i++)
    {
    if((slave_data & 0x80) == 0x80)
    {
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_5, 0xff); // MAKE mosi = 1
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0); // MAKE sclk = 0
    SysCtlDelay(2);
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0xff); // MAKE sclk = 1
    }
    else
    {
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_5, 0); // MAKE mosi = 1
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0); // MAKE sclk = 0
    SysCtlDelay(2);
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0xff); // MAKE sclk = 1
    }
    slave_data <<= 1;
    }

    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, 0xff); // MAKE CS' HIGH
    SysCtlDelay(2);
    ////////////////////// send write command ////////////////////////
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, 0); // MAKE CS' LOW
    slave_data = 0x02;
    // int i;
    for(i=0;i<8;i++)
    {
    if((slave_data & 0x80) == 0x80)
    {
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_5, 0xff); // MAKE mosi = 1
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0); // MAKE sclk = 0
    SysCtlDelay(2);
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0xff); // MAKE sclk = 1
    }
    else
    {
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_5, 0); // MAKE mosi = 1
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0); // MAKE sclk = 0
    SysCtlDelay(2);
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0xff); // MAKE sclk = 1
    }
    slave_data <<= 1;
    }

    //////////////////////////////SEND ADDRESS///////////////////////////////////
    slave_data = 0x01;
    // int i;
    for(i=0;i<8;i++)
    {
    if((slave_data & 0x80) == 0x80)
    {
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_5, 0xff); // MAKE mosi = 1
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0); // MAKE sclk = 0
    SysCtlDelay(2);
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0xff); // MAKE sclk = 1
    }
    else
    {
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_5, 0); // MAKE mosi = 1
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0); // MAKE sclk = 0
    SysCtlDelay(2);
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0xff); // MAKE sclk = 1
    }
    slave_data <<= 1;
    }
    ////////////////////////////SEND DATA ////////////////////////////////////////
    slave_data = TestData;
    // int i;
    for(i=0;i<8;i++)
    {
    if((slave_data & 0x80) == 0x80)
    {
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_5, 0xff); // MAKE mosi = 1
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0); // MAKE sclk = 0
    SysCtlDelay(2);
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0xff); // MAKE sclk = 1
    }
    else
    {
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_5, 0); // MAKE mosi = 1
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0); // MAKE sclk = 0
    SysCtlDelay(2);
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0xff); // MAKE sclk = 1
    }
    slave_data <<= 1;
    }

    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, 0xff); // MAKE CS' HIGH
    //////////////////////////////END OF WRITE////////////////////////////////////////
    GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_2, 0xff); // MAKE CS' HIGH
    SysCtlDelay(200000); // 200 MS DELAY

    ///////////////////////////////READ SEUENCE///////////////////////////////////////
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, 0); // MAKE CS' LOW
    //////////////////////////////////////SEND READ COMMAND 03 ////////////////////////////////////////
    slave_data = 0x03;
    // int i;
    for(i=0;i<8;i++)
    {
    if((slave_data & 0x80) == 0x80)
    {
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_5, 0xff); // MAKE mosi = 1
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0); // MAKE sclk = 0
    SysCtlDelay(2);
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0xff); // MAKE sclk = 1
    }
    else
    {
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_5, 0); // MAKE mosi = 1
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0); // MAKE sclk = 0
    SysCtlDelay(2);
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0xff); // MAKE sclk = 1
    }
    slave_data <<= 1;
    }
    //////////////////////////////////////////SEND READ ADDR ////////////////////////////////////////
    slave_data = 0x01;
    // int i;
    for(i=0;i<8;i++)
    {
    if((slave_data & 0x80) == 0x80)
    {
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_5, 0xff); // MAKE mosi = 1
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0); // MAKE sclk = 0
    SysCtlDelay(2);
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0xff); // MAKE sclk = 1
    }
    else
    {
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_5, 0); // MAKE mosi = 1
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0); // MAKE sclk = 0
    SysCtlDelay(2);
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0xff); // MAKE sclk = 1
    }
    slave_data <<= 1;
    }
    //////////////////////////////////////////READ VALUE TO REGISTER / VAR : slave_data //////////////////////////////////
    slave_data = 0 ;
    uint32_t temp = 0;

    for(i=0;i<8;i++)
    {
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0); // MAKE sclk = 0
    SysCtlDelay(2);
    temp = GPIOPinRead(GPIO_PORTA_BASE,GPIO_PIN_4);
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0xff); // MAKE sclk = 1
    if(temp == 0x10)
    {
    slave_data |= 0x01;

    }
    else
    {
    slave_data &= ~0x01;
    }
    if(i<7) slave_data <<= 1;
    }

    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, 0xff); // MAKE CS' LOW


    while(1)
    {
    if(slave_data == TestData)
    {
    GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_2, 0xff); // MAKE CS' LOW
    SysCtlDelay(10000000);
    GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_2, 0); // MAKE CS' LOW
    SysCtlDelay(10000000);
    }
    }

    }

     ///////////////////////////////////////////////////////////////Peripheral Code//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    Now this same thing im trying to do with the SSI0 Peripheral with the following code, keeping in mind what you have written in your previous blogs

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    /*
    * main.c
    */

    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "driverlib/ssi.h"
    #include "inc/tm4c123gh6pm.h"
    uint8_t slave_data = 0x0;
    uint32_t reply[];

    void main(void)
    {
    SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);


    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);

    GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_2);
    // GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3);
    SSIDisable(SSI0_BASE); // disables th SSI module as required for init


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

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


    SSIClockSourceSet(SSI0_BASE, SSI_CLOCK_SYSTEM); // sets the system clock as the source of clock

    SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0,SSI_MODE_MASTER, 100000, 8);// defines base, System clk, Mode 0 = SPH = SPO = 0,Master, 400 KHz, no. of bits = 8 = 1 byte transfer

    SSIEnable(SSI0_BASE); // enables SSI

    // SSI0_CR1_R |= SSI_CR1_LBM;
    SysCtlDelay(100000);

    // GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0xff);

    // GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0);

    SSIDataPut(SSI0_BASE,0x06);
    while(SSIBusy(SSI0_BASE));// waiting since this will be a single mode transfer

    SysCtlDelay(100000);

    // GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0xff);

    // GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0);


    SSIDataPut(SSI0_BASE,0x02);
    // while(SSIBusy(SSI0_BASE)); // blocked waiting because continuous mode is needed

    SSIDataPut(SSI0_BASE,0x01);
    // while(SSIBusy(SSI0_BASE));

    SSIDataPut(SSI0_BASE,0xac);
    while(SSIBusy(SSI0_BASE));

    // GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0xff);

    SysCtlDelay(1000000);

    // GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0);


    SSIDataPut(SSI0_BASE,0x03);
    // while(SSIBusy(SSI0_BASE));

    SSIDataPut(SSI0_BASE,0x01);
    // while(SSIBusy(SSI0_BASE));

    SSIDataGet(SSI0_BASE,reply);
    while(SSIBusy(SSI0_BASE));

    // GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0xff);

    if(reply[0] == 0xac) GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_2,0xff);

    while(1);


    }

    /////////////////////////////////////////////////

    This code is NOT able to fetch the written data. May be the data is not getting written also.

  • Hello Turjasu

    1. In Moto Mode-0 the FSS will pulse between transactions (please see data sheet) even in continuous mode.

    2. You can instead control the FSS pin as a GPIO Making it low before writing the data and making it high after the SSIBusy condition is false.

    Regards
    Amit
  • Dear amit,

    I have alsotried using the Fss line as GPIO and triggered it alsolutely at my s/w control. However, this too was of no use. Please see the code below:

    ================================================================================

    /*
    * main.c
    */

    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "driverlib/ssi.h"
    #include "inc/tm4c123gh6pm.h"
    uint8_t slave_data = 0x0;
    uint32_t reply[];

    void main(void)
    {
    SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);


    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);

    GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_2);
    GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3); //   Making the SSI0Fss as GPIO type
    SSIDisable(SSI0_BASE); // disables th SSI module as required for init


    GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    // GPIOPinConfigure(GPIO_PA3_SSI0FSS);   // disabling the peripheral command of Fss
    GPIOPinConfigure(GPIO_PA4_SSI0RX);
    GPIOPinConfigure(GPIO_PA5_SSI0TX);

    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_2 | GPIO_PIN_4|GPIO_PIN_5);


    SSIClockSourceSet(SSI0_BASE, SSI_CLOCK_SYSTEM); // sets the system clock as the source of clock

    SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0,SSI_MODE_MASTER, 125000, 8);// defines base, System clk, Mode 0 = SPH = SPO = 0,Master, 125 KHz, no. of bits = 8 = 1 byte transfer

    SSIEnable(SSI0_BASE); // enables SSI

    // SSI0_CR1_R |= SSI_CR1_LBM; // Disabled the Loopback
    SysCtlDelay(100000);

    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0xff);// Made the SS = 1

    SysCtlDelay(100000);

    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0); // Dropped down SS to select slave 25AA02

    SSIDataPut(SSI0_BASE,0x06);   // sent the 0x06 as the required Write enable WREN command as per microchip Datasheet
    while(SSIBusy(SSI0_BASE));

    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0xff);// Pulsed high SS

    SysCtlDelay(100000);

    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0); // pulled low SS for sending the remaining commands

    SSIDataPut(SSI0_BASE,0x02);  // Cmd for Write cmd to SPI EEPROM as per datasheet
    SSIDataPut(SSI0_BASE,0x01); // Mem. location inside EEPROM
    SSIDataPut(SSI0_BASE,0xac); // test data
    while(SSIBusy(SSI0_BASE));  // wait till bzy

    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0xff); // pulled high to complete write process

    SysCtlDelay(1000000); // Twc

    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0);// Pulled low to enable slave to send read commands

    SSIDataPut(SSI0_BASE,0x03); // read cmd
    SSIDataPut(SSI0_BASE,0x01); // mem area to read from
    while(SSIBusy(SSI0_BASE));

    SSIDataGet(SSI0_BASE,reply); // get the data to the pointer loc 0 of array reply
    //reply[0] = SSI0_DR_R; // was just testing with direct commands
    while(SSIBusy(SSI0_BASE));


    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0xff); // finish communic.

    if(reply[0] == 0xac) GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_2,0xff); // if data matches, glow LED at PD2

    while(1);


    }

     

    This code is not working, infact I should say, it is unable to get the data. Please suggest if Im doing something wrong. Hardware part is OK because Im getting the output using the bit banged code.

  • Hello Turjasu,

    Should have thought about it earlier. The SSI Data module when sends a data also receives a byte. So after every SSIDataPut you would need to read out the RXFIFO by using SSIDataGet or you can read out the RXFIFO (flush the FIFO) after a string of SSIDataPut.

    During the read phase the same applies. However for the 3rd byte time frame you need to do a SSIDataPut (dummy write) so that the clock is issued and the response on the MISO captured to the RXFIFO

    Regards
    Amit
  • Dear amit,

      Finally the code has worked with the peripheral. Here it is:

    ======================================================================

    /*
    * main.c
    */

    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "driverlib/ssi.h"
    #include "inc/tm4c123gh6pm.h"
    uint8_t test_data = 0x78;
    uint32_t reply[];

    void main(void)
    {
    SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);


    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);

    GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_2);
    GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3);
    SSIDisable(SSI0_BASE); // disables th SSI module as required for init


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

    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_2 | GPIO_PIN_4|GPIO_PIN_5);


    SSIClockSourceSet(SSI0_BASE, SSI_CLOCK_SYSTEM); // sets the system clock as the source of clock

    SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0,SSI_MODE_MASTER, 125000, 8);// defines base, System clk, Mode 0 = SPH = SPO = 0,Master, 400 KHz, no. of bits = 8 = 1 byte transfer

    SSIEnable(SSI0_BASE); // enables SSI

    // SSI0_CR1_R |= SSI_CR1_LBM;
    SysCtlDelay(100000);

    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0xff);

    SysCtlDelay(100000);

    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0);

    while(SSIDataGetNonBlocking(SSI0_BASE, reply));

    SSIDataPut(SSI0_BASE,0x06);
    while(SSIBusy(SSI0_BASE));

    while(SSIDataGetNonBlocking(SSI0_BASE, reply));


    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0xff);

    SysCtlDelay(100000);

    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0);

    SSIDataPut(SSI0_BASE,0x02);
    SSIDataPut(SSI0_BASE,0x01);
    SSIDataPut(SSI0_BASE,test_data);
    while(SSIBusy(SSI0_BASE));
    while(SSIDataGetNonBlocking(SSI0_BASE, reply));


    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0xff);

    SysCtlDelay(1000000);

    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0);

    SSIDataPut(SSI0_BASE,0x03);
    SSIDataPut(SSI0_BASE,0x01);
    SSIDataPut(SSI0_BASE,0x00); // dummy write
    while(SSIBusy(SSI0_BASE));
    while(SSIDataGetNonBlocking(SSI0_BASE, reply));

    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0xff);

    if(reply[0] == test_data) GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_2,0xff);

    while(1);


    }

    ===========================================================================================

    However, there are a few things I have noticed and would like to share for anyone else who might benefit:

    • while(SSIDataGetNonBlocking(SSI0_BASE, reply)); is needed to flush off any garbage data that migh have been lying in the RX FIFO
    • SSIDataPut(SSI0_BASE,0x06);
      while(SSIBusy(SSI0_BASE));

      while(SSIDataGetNonBlocking(SSI0_BASE, reply));

      This part of the code, writes 0x06 to the SPI EEPROM, and at the same time, since its output is at Z state, the read in values will be 0xff. However, Non blocking API was used to ensure that even if nothing is there at fifo, the function call doesnt hang

      AND:

      SSIDataPut(SSI0_BASE,0x00); // dummy write
      while(SSIBusy(SSI0_BASE));
      while(SSIDataGetNonBlocking(SSI0_BASE, reply));

          A dummy write is needed even after all the data transmission / configuration bytes are sent, so that the peripheral may generate the clocks for the RX to occur, that is later read by the non blocking read API (as you have suggested!

    Thanks a lot Amit and everyone for your help. This is done for now. Hoping to move into communicating with ENC28J60 for a webserver (not able to use the 1294 flavor though)