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 communication problem in LM4F230 micro controller..NO DATA IS COMING IN SPI DATA REGISTER.

The overall description of my problem is like this.I need to communicate master (am335x ) and slave (LM4F230H5QR) on SPI communication.I am using CCS for debugging and programming the slave.And whatever data is comming from master side salve is print that data on thermal printer.Everything is correct on printer firmware except spi configuration.

Master configuration is like this...

slave is connected at SPI0 of master(am335x).

frame format mode-- mode 0,

chip select is active low

Clk rate--3.5 MHZ.

as i checked on oscilloscope that correct data is flowing from master to slave.So interrupt occur on slave side but when i checked data register of  slave no data is actually coming, so i am not understanding where is actually problem behind.I think if oscilloscope show data it means problem is in slave side.so i need help to solve this problem. 

Slave side configuration....

master is connected to spi1 of slave.And my code is like this.

unsigned int Byte_Count=0;

uint32_t RcvData[20];

unsigned char RcvFlag =0;

main()

{

SysCtlClockSet(SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

spi_init();

while(1)

{

switch(RcvFlag)

{

case DATA_CAPTURE:

                                           print_data();           /*This will print data on thermal printer*/

                                           reset_buffer();        

}

}

}

spi_init()

{

  SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1);

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);
                                                                                                                       

GPIOPinConfigure(GPIO_PF0_SSI1RX);
GPIOPinConfigure(GPIO_PF1_SSI1TX);
GPIOPinConfigure(GPIO_PF2_SSI1CLK);
GPIOPinConfigure(GPIO_PF3_SSI1FSS);

SysCtlPeripheralReset(SYSCTL_PERIPH_SSI1);

SSIDisable(SSI1_BASE);

SSIConfigSetExpClk(SSI1_BASE , SysCtlClockGet() , SSI_FRF_MOTO_MODE_0 , SSI_MODE_MASTER , 3000000 , 8);

SSIEnable(SSI1_BASE);

SSIIntEnable( SSI1_BASE , SSI_RXFF | SSI_RXOR);

SSIIntRegister(SSI1_BASE , SPI_INTERRUPT_HANDLER);

}

//

// I register interrupt handler in startup_ccs.c

// and interrupt handler is shown below.

//

void SPI_INTERRUPT_HANDLER(void){
unsigned long ulStatus;

ulStatus =SSIIntStatus(SSI1_BASE, true);

SSIIntClear(SSI1_BASE, ulStatus);

while(SSIDataGetNonBlocking(SSI1_BASE, &RcvData[Byte_Count]))
{
Buffer[Byte_Count] = (unsigned char)(RcvData[Byte_Count] & 0x00FF); /* Store Serial Data */

if ( Buffer[Byte_Count] == 0x10 )  {             /*0x10 is used for delimiter */

RcvFlag = 2;
SSIIntDisable(SSI1_BASE, SSI_RXFF | SSI_RXOR );
break;
}

Byte_Count++;

if (Byte_Count >= 8) {

RcvFlag = 2;                                                       /* Buffer full Set command flag */
SSIIntDisable(SSI1_BASE, SSI_RXFF | SSI_RXOR);
break;
}
}
}

reset_buffer()

{

int l=0;

Byte_Count = 0;

for (l = 0; l < 8; l++){
Buffer[l] = 0x00;

SSIIntEnable( SSI1_BASE , SSI_RXFF | SSI_RXOR);
}

  • Actually in spi_init()  function,  i did incorrect typing.I typed SSI_MODE_MASTER instead of SSI_MODE_SLAVE. 

    SSIConfigSetExpClk(SSI1_BASE , SysCtlClockGet() , SSI_FRF_MOTO_MODE_0 , SSI_MODE_MASTER , 3000000 , 8);

    so actual finction is like this.

    SSIConfigSetExpClk(SSI1_BASE , SysCtlClockGet() , SSI_FRF_MOTO_MODE_0 , SSI_MODE_SLAVE , 3000000 , 8);

  • vikram shekhawat said:
    GPIOPinConfigure(GPIO_PF0_SSI1RX);

    You've made an unfortunate choice of Port and Pin - PF0 defaults as NMI - must be "liberated" via a special unlocking procedure.  MCU manual details.

    There may be more - if you wish to avoid this "unlock" - you may choose another Port/Pin which is listed as SSI1RX capable.  (there is not a requirement that each/every pin which make up a peripheral - emanate from a single port)

    More issues may exist - this jumped out as it catches many new users...

  • Thanks a ton for solving this issue,but i have one more issue.

    Now data is coming to data register but problem is this i am not able to get overall data it always taken the first byte. Suppose i am sending ABCDEFGHIJK from master side and always i am gettining AAAAAAAAAAA . Code for this is

    uint32_t RcvData;

    unsigned char Buffer[1008];

    int Byte_Count=0;

    void SPI_INTERRUPT_HANDLER(void){

    unsigned long ulStatus;
    // Get the interrrupt status.
    ulStatus =SSIIntStatus(SSI1_BASE, true);
    // Clear the asserted interrupts.
    SSIIntClear(SSI1_BASE, ulStatus);
    while(SSIDataGetNonBlocking(SSI1_BASE, &RcvData))
    {

    Buffer[Byte_Count] = (unsigned char)(RcvData & 0x00FF); /* Store Serial Data */

    if (Buffer[Byte_Count] == 0x4B) {
    UartRcvFlag = 2;
    SSIIntDisable(SSI1_BASE, SSI_RXFF | SSI_RXOR );
    break;
    }

    Byte_Count++;
    if (Byte_Count >= 12) {
    UartRcvFlag = 2; /* Buffer full Set command flag = Print data */
    SSIIntDisable(SSI1_BASE, SSI_RXFF | SSI_RXOR | SSI_RXTO);
    break;
    }
    }
    }

    spi_init()
    {

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

    HWREG(0x40025520)= 0x4C4F434B;          /*That is used for unlocking the NMI pin PF0*/

    HWREG(0x40025524)= 0x000000FF;         
    // The SSI0 peripheral must be enabled for use.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1);

    GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 |
    GPIO_PIN_3);
    // Configure the pin muxing for SSI0 functions on port A2, A3, A4, and A5.
    GPIOPinConfigure(GPIO_PF0_SSI1RX);
    GPIOPinConfigure(GPIO_PF1_SSI1TX);
    GPIOPinConfigure(GPIO_PF2_SSI1CLK);
    GPIOPinConfigure(GPIO_PF3_SSI1FSS);

    SysCtlPeripheralReset(SYSCTL_PERIPH_SSI1);

    SSIDisable(SSI1_BASE);

    SSIConfigSetExpClk(SSI1_BASE , SysCtlClockGet() , SSI_FRF_MOTO_MODE_0 , SSI_MODE_SLAVE , 3000000 , 8);

    SSIEnable(SSI1_BASE);

    SSIIntEnable( SSI1_BASE , SSI_RXFF | SSI_RXOR | SSI_RXTO);

    SSIIntRegister(SSI1_BASE , SPI_INTERRUPT_HANDLER);
    }

    reset_buffer(){

    Byte_Count=0;

    for (l = 0; l < 1008; l++)
    Buffer[l] = 0x00;

    SSIIntEnable( SSI1_BASE , SSI_RXFF | SSI_RXOR | SSI_RXTO);

    }

    main()

    {

    SysCtlClockSet(SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

    spi_init();

    IntMasterEnable();

    while (1) {

    switch (RcvFlag) {

    case 2:

                   print_data();

                   reset_buffer();

    default:

                       ;

    }

    }

    }

  •  

    vikram shekhawat said:
    Thanks a ton for solving this issue,but i have one more issue.
     

    Now that (just one more) would be a first! 

    Look here (your code extract): "while(SSIDataGetNonBlocking(SSI1_BASE, &RcvData))" 

    Might that benefit from @RcvData[0] ?  Have you created and/or allowed for the suggested SSI buffer?  (beyond the general data buffer you've listed?) 

    Note that you increment "Byte_Count" - but never RcvData!  (how then can you load/store following SSI bytes?)

    And... "The SSIDataGetNonBlocking function returns "true" when data was returned, and "false" when no data was returned."  Is this what you expected - or what you want?  Suggest a detailed re-reading of SW-DRL-UGxxxx to confirm this choice...

    You may wish to consider:

      // Receive the data using the "blocking" Get function. This function
     // will wait until there is data in the receive FIFO before returning.

            SSIDataGet(SSI0_BASE, &RcvData[ulindex]);

    Suspect that this may assist - especially as you seek to "unlock" the mysteries w/in SSI... 

  • The best way to solve this issue is to attach the debugger and set some breakpoints.  

    Configure the master to send one byte at a time "A" then "B" then "C" and so on.  Make the master only send one byte on a command or button presses.

    Set a breakpoint in the interrupt handler watch and step through as you handle the incoming byte(s). If the first byte goes correctly then let the system free run with breakpoint still set in int handler.  Make sure you don't go back to the int handler when there is no more traffic on the bus.  Send another byte and see what happens to this second byte.  After you establish and get things working at a slow controled single byte at a time rate then try two or more bytes at the same time in a packet.

    Use extra GPIO to toggle a pin high when in the interrupt handler and low when leaving the int handler.  Line up the scope with the actual data and the GPIO pin to see if interrupts are happening when and how they should also to see that interrupts are fast enough to process each byte.

    Dexter

  • Stellaris Dexter said:
    The best way to solve this issue

    One may agree that procedure suggested is a good way - but can it be the best way - when SW-DRL-UG dictate is violated?  To wit:

    23.2.2.6 SSIDataGetNonBlocking
    Gets a data element from the SSI receive FIFO.

    Prototype:
    long
    SSIDataGetNonBlocking(unsigned long ulBase, unsigned long *pulData)

    Parameters:
    ulBase specifies the SSI module base address.
    pulData is a pointer to a storage location for data that was received over the SSI interface.

    General procedures often fall short when measured against specific solutions - targeting known, "issues in question."  Thus - "best way" may be over-reach...

    The procedure as outlined is well-known - and effective - but tends to diminish the more difficult code review - which uncovered earlier PF0 issue far faster & easier than any general procedure...

  • Thanks for your reply............but i have some more doubts...

    Data which is coming from master is stored in receive FIFO which is 16x8 byte.and first 16 bits stored in data register and our buffer get this data .

    but my doubt  is ........is second 16 bits automatically stored in data register or not after first. If not should we need to make some configuration for this.

    second doubt is............where data (which is coming from master) is stored in memory. Is it stored in particular position or is it stored in some data section of memory.How can i find this data in memory...i am using CCS for debugging and programming.

      

  • vikram shekhawat said:
    ,but i have one more issue

    Appears not! 

    You now state, "Data which is coming from master is stored in receive FIFO which is 16x8 byte.and first 16 bits stored in data register and our buffer get this data."  Is this not dramatically different than your earlier report of receiving only "A" repeatedly?  Which report should we now believe - attend to?

    And such conflicting reports - minus any apology or explanation - confounds we "helpers" - ideal for, "krazy making!"

    Now - vendor's "general solution" surely best enables your solving this cascade of further issues/doubts...  (and accurate reporting (shows some care/concern for helpers) could not hurt...)

  • second 16 bits from the master is stored in the FIFO which is a part of the SSI peripheral until your software retrieves it.  As it is a FIFO it will go into the next available empty position in the FIFO.  when you extract data from the FIFO you choose where to put it in data memory but the selection of variables and pointers.  There is no way to access or view the contents of the FIFO aside from extract data from the FIFO.  Should the FIFO overflow i believe there is a overflow interrupt bit that will get set to indicate data may have been lost.  Generally due to not retrieving data fast enough from the FIFO.

    Think of the data register as the window through which you see the oldest data in the FIFO.  Once read next oldest becomes available at the data register.  New data is loaded at the back of the FIFO where it can not be seen due to older data in front of it.

    Dexter

  • Thanks for your reply and support....

    After a lots of debugging, now  i come to know where is the actual problem.

    Problem is ...........when data is coming from master (checked and conformed using oscilloscope) , suppose i am sending ABC only. So ABC should be stored in FIFO but receiver FIFO is taking only starting character (which is A) at a time, while it has to take the number of character i am transferring from master i.e.3. So other two character are not taken care by FIFO, that's why only A is printing all the time.

    I debug this after setting SSI_RXOR bit in SSIIntEnable

    SSIIntEnable(SSI1_BASE , SSI_RXOR);

    when i pressing enter 8 times from master then interrupt comes to slave, that shows only one byte is storing in receive FIFO, that i conformed after continuously checking data register.

    So do you have any idea about why only one character is coming to FIFO.How can we solve this data loss problem. 

    And again if we have facility  to see FIFO's data then we will sure about this problem.

    regards 

    Vikram Shekhawat

     

  • cb1_mobile said:

    "while(SSIDataGetNonBlocking(SSI1_BASE, &RcvData))" 

    Might that benefit from @RcvData[0] ?  Have you created and/or allowed for the suggested SSI buffer?

    Might the above - describe and cure - your latest adventure?