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.

LM4F SSI never stop sending out data even if i stop putting data to the SSI TX FIFO

Hi ALL,

 

I am sorry to trouble you.

And I have a problem that need your help.

The MCU I work is LX4F230H5QR.

The SSI is configured as SPI and work in slave mode and configured as SSI_FRF_MOTO_MODE_0 .

But when I finished sending data to SSI TX FIFO, I can still see the data on the TX port with oscilloscope.

 

Below is my code, Please take a look and tell me if there is any problem.

I send 0x1122 to SSI TX FIFO every 200ms for 30 times.

But after sending finished, I can still measure the data ( never ending) on the TX port with oscilloscope.

This is really emergency, you are so appreciated to help me with this.

Thanks in advance.

 

#include "include/spitofpga.h"

#include "include/datatype.h"

#include "driverlib/timer.h"

#include "driverlib/rom.h"

#include "driverlib/timer.h"

unsigned short datafpga[512];

unsigned long datalengthspi;

unsigned short datathislength;

unsigned short uaspi[2]={0x1122,0x2233};

 

//*****************************************************************************

//

// SSIO Port Function Inits

//

//*****************************************************************************

void

SPIFPGAPortFunctionInit(void)

{

  //

  // Enable Peripheral Clocks

  //

  SysCtlPeripheralEnable(SPI_FPGA_SSI1_PERIPH);

  SysCtlPeripheralEnable(SPI_FPGA_GPIO_PERIPH);

  //

  // Enable SSI1 SSI0TX

  //

  GPIOPinConfigure(SPI_FPGA_SSITX);

  GPIOPinTypeSSI(SPI_FPGA_GPIO_BASE, SPI_FPGA_SSITX_PIN);

  //

  // Enable SSI1 SSI0FSS

  //

  GPIOPinConfigure(SPI_FPGA_SSIFSS);

  GPIOPinTypeSSI(SPI_FPGA_GPIO_BASE, SPI_FPGA_SSIFSS_PIN);

  //

  // Enable SSI1 SSI0CLK

  //

  GPIOPinConfigure(SPI_FPGA_SSICLK);

  GPIOPinTypeSSI(SPI_FPGA_GPIO_BASE, SPI_FPGA_SSICLK_PIN);

  //

  // Enable port PF0 for SSI1 SSI1RX

  // First open the lock and select the bits we want to modify in the GPIO commit register.

  //

  HWREG(SPI_FPGA_GPIO_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY_DD;

  HWREG(SPI_FPGA_GPIO_BASE + GPIO_O_CR) = 0x1;

  //

  // Enable SSI1 SSI0RX

  //

  GPIOPinConfigure(SPI_FPGA_SSIRX);

  GPIOPinTypeSSI(SPI_FPGA_GPIO_BASE, SPI_FPGA_SSIRX_PIN);

}

//*****************************************************************************

 // Init Timer4 for sending data to SSI1 every 200ms

void

TimerSendStatusTOFPGA(void)

{

  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);

  SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER4);

  TimerConfigure(TIMER4_BASE, TIMER_CFG_PERIODIC);

  TimerLoadSet(TIMER4_BASE, TIMER_A, 16000000);

  // Setup the interrupts for the timer timeouts.

  IntPrioritySet(INT_TIMER4A, 4 << 5);

  IntEnable(INT_TIMER4A);

  TimerIntEnable(TIMER4_BASE, TIMER_TIMA_TIMEOUT);

  TimerEnable(TIMER4_BASE, TIMER_A);

}

 

//*****************************************************************************

//

// Init SPI for Recorder

//

//*****************************************************************************

 

void

SPIFPGAInit(void)

{

  SPIFPGAPortFunctionInit();

  SysCtlPeripheralReset(SPI_FPGA_SSI1_PERIPH);

  SSIDisable(SPI_FPGA_SSI_BASE);

  SSIConfigSetExpClk(SPI_FPGA_SSI_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0,

                   SSI_MODE_SLAVE, SPI_FPGA_BITRATE, 16);

  SSIEnable(SPI_FPGA_SSI_BASE);

  TimerSendStatusTOFPGA();

}

 

 //Do nothing but clear interrupt status

void

SSI1IntHandler(void)

{

  unsigned long ulStatus;  

  ulStatus = SSIIntStatus(SPI_FPGA_SSI_BASE, true);

  SSIIntClear(SPI_FPGA_SSI_BASE, ulStatus);

}

 

char aa[50];

short success = 0;

void

Timer4IntHandler(void)

{

  TimerIntClear(TIMER4_BASE, TIMER_TIMA_TIMEOUT);

  success = SPIFPGASSSendDataptr(uaspi,1);

  //TimerDisable(TIMER4_BASE, TIMER_A);

}

 

//************************************************************************

//

// Test Code, Just for test Usage

// send Data to SPI

//

//************************************************************************

static int timesss = 30;

 

SPIFPGASSSendDataptr(unsigned short *senddata, short datalength)

{

    unsigned long ulData;

    if (timesss-- > 0)

    {

      ulData = (unsigned long)(senddata[0]);

     //Just use Uart to send debug message to indicate that transfer data to SSI has finished

      memset(aa,0,50);

      sprintf(aa,"R:%d\r\n",success);

      SendDataToUart((unsigned char *)aa, 50);

 

      return SSIDataPutNonBlocking(SSI1_BASE, ulData);

}

}

 

Below is the main file

 

int

main(void)

{

    //

    // Enable lazy stacking for interrupt handlers.  This allows floating-point

    // instructions to be used within interrupt handlers, but at the expense of

    // extra stack usage.

    //

    FPULazyStackingEnable();

    // Set the clocking to 80MHz.

    SysCtlClockSet(SYSCTL_SYSDIV_2_5  | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |

                       SYSCTL_XTAL_16MHZ);

   SPIFPGAInit();

   IntMasterEnable();

    while(1)

{

}

  • Hi,

    Some major problems:

    1. a) Your code contradicts your declared intent - your wish is to send a word 30 times, but you never count these x times. Shouldn't that be counted?
    2. b) You keep secret the value of SPI_FPGA_BITRATE - maybe SPI_FPGA_BITRATE * 16 * 30 to be less or equal than 200 ms? hard to know.
    3. c) You want to have a periodic process, which is good - so that's why you have a waveform on oscilloscope - if this correspond or not to your intent is hard to guess due to previous point. The waveform may be good or not, but is normal to have it due to calls: TimerInthandler->SPIFPGASSendDataPtr()->SSIDataPutNonBlocking().
    4. d) Not a good idea to use UART sending within other interrupts. Keep that outside timer interrupt - use your UART interrupt or just send a flag to main to process that.
    5. e) Not a good idea to have a blank while(1) loop - if your program(s) grow, it may lead you to subtle bugs, hard to discover. While TI uses that as demo in some examples is OK, but look for some serious  examples and that is not anymore the case.

    Petrei

  • Hi Petrei,

    First of all, thanks for your reply.

    This is a test program for test the communication between LM4F and FPGA. So the coding isn't good.

    For the first problem:

    1.  

    static int timesss = 30;

     

    SPIFPGASSSendDataptr(unsigned short *senddata, short datalength)

    {

        unsigned long ulData;

        if (timesss-- > 0)

        {

          ulData = (unsigned long)(senddata[0]);

         //Just use Uart to send debug message to indicate that transfer data to SSI has finished

          memset(aa,0,50);

          sprintf(aa,"R:%d\r\n",success);

          SendDataToUart((unsigned char *)aa, 50);

     

          return SSIDataPutNonBlocking(SSI1_BASE, ulData);

    }

    For the second:

    SPI_FPGA_BITRATE is 3.125M, so it is large enough.

    But would you please tell me why should multiply 16 and 30?

    For the third one:

    The waveform is ok on oscilloscope if i continue sending data through SPI, but from above code, i send the data 30 times, so there should be no data sending out after 30 times.

    For the forth one:

    It is only for debugging, i will remove it in formal version

    For the fifth one:

    I will add something like a sleep in while 1


    But i still don't understand why there is data sending out through TX after running for 30 times.

    Do you have any more suggestion for this?

    Thanks

  • Hi,

    For 1) - sorry - i missed timesss...

    For 2) - SPI_FPGA_BITRATE - I meant the period for that * 16 * 30 will give you the whole package duration, which should be less than 200 ms; but you confirm is OK?

    I suggest you to set the master mode for test and see if the problem persist .

    Petrei

  • Thanks again for you reply.

    I will try out the master mode tomorrow.

    As it is Midnight here in China.

    I will let you know the result, Thanks again.

  • @Petrei - Pardon - perhaps this simply "builds" upon your great assistance - but I suspect may be helpful...

    Followed this w/interest - when logic seemingly fails - time to reach for dreaded, "Errata" (Oct 17, 2012) ...  And the following reveals:

    You appear "snake-bit" in two areas:  First one - we can overcome... dial down from 80 to 50MHz (we confirm that works)

    change: SYSCTL_SYSDIV_2_5  to   SYSCTL_SYSDIV_4  to comply w/errata

    and:  Alas you are using the exact SSI Mode - below flagged/described!   (bloody rotten - your luck) 

    Appears you can overcome by operating the SSI clock at greater than 1.1MHz

    Again - poster Petrei has done the "heavy lifting" - hope this brief report helps resolve...

  • Also, to the original stated issue - the SSI continues to transmit even when you don't feed it data - this will always be the case in slave mode.  Since the SSI clocking is driven externally by the master, it has no choice but to send data whenever the master drives the clock, even if you haven't prepared any data to send.  If you stop feeding the FIFO, the data that's sent is not defined - but most probably will be either the last value you wrote to the FIFO send repeatedly, or it will cycle through the contents of the FIFO repeatedly.

  • slandrum said:
    SSI continues to transmit even when you don't feed it data - this will always be the case in slave mode.

    This is most excellent, vital commentary - imho - thank you Slandrum.

    Unsaid throughout is the behavior of the Master - and how this may be "originator/source" of this issue.

    This said - complying w/any/all Errata restrictions, or dictates (as past posted) should be first order of business...

  • Hi,

    @cb1_mobile and @slandrum - thanks for the info, I completely ignored the errata sheet ...

    Petrei

  • @Petrei - as did we all - dragged kicking/screaming when little else makes sense...

  • Hi slandrum,

    Thanks for your reply.

    Really help me a lot.

    Do you have any idea on how to solve this problem?

    Do i have to appy SSIDataPut(SSI1_BASE, 0x00) eight times (as the depth of TX FIFO is 8 deep) each time i finished sending data to the SPI master side?

    I want the TX port of SSI to be 0x00 each time after sending data, but not the last data i send.

    Do you have any suggestion about this? 

    Thanks in advance.

  • Perhaps unwise to fully dismiss (searched/discovered/gold-plate presented) Errata.  (this reporter exits...)

  • Hi All,

    I have found how to slove the problem, use DMA mode to send the SPI data.

  • If you are operating the MCU in desregard of published errata - one may "think twice" about "long-term" health of your device.  One device may "squeak by" errata guard-band - but multiple likely will not...