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.

Problem transmitting data via SSI when using bootloader code



Hi,

I am having a problem transmitting data via the SSI using the bootloader code.  The processor I am using is the LM4F232H5QD and my debugger is the Blackhawk USB560 JTAG Emulator.  The processor is set up in slave mode with SSIData Size set to 8.  The slave processor  generates a one millisecond interrupt to the master processor to indicate that the slave has data to transmit.   I am trying to transmit 128 bytes and it stops after transmitting 8 bytes.  It hangs in the while loop waiting for SSI_SR_TNF to indicate that the transmit FIFO is not full.  I have checked the TNF bit and the TFE bit in the status register and they are both zero indicating that the transmit FIFO is full and not empty per the data sheet.  The code I am using is from the Stellaris/boot_loader directory.

SSI setup code:

   //
    // Enable the clocks to the SSI and GPIO modules.
    //
    HWREG(SYSCTL_RCGC2) |= SYSCTL_RCGC2_GPIOA;
    HWREG(SYSCTL_RCGC1) |= SYSCTL_RCGC1_SSI0;

    //
    // Make the pin be peripheral controlled.
    //
    HWREG(GPIO_PORTA_BASE + GPIO_O_AFSEL) |= SSI_PINS;
    HWREG(GPIO_PORTA_BASE + GPIO_O_DEN) |= SSI_PINS;

    //
    // Set the SSI protocol to Motorola with default clock high and data
    // valid on the rising edge.
    //
    HWREG(SSI0_BASE + SSI_O_CR0) = (SSI_CR0_SPH | SSI_CR0_SPO |
                                    (DATA_BITS_SSI - 1));

    //
    // Enable the SSI interface in slave mode.
    //
    HWREG(SSI0_BASE + SSI_O_CR1) = SSI_CR1_MS | SSI_CR1_SSE;

ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3);

ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, 0);

 

Send function:

/*
 * This function sends data through the SSI port in slave mode.  This function
 * will not return until all bytes are sent.
 */
void blSSISend(const unsigned char *pucData, unsigned long ulSize)
{
    unsigned long i = 0;

    // Cause interrupt to master so the data will be clocked out.
    HWREG(GPIO_PORTF_BASE + (GPIO_O_DATA + (GPIO_PIN_3 << 2))) = GPIO_PIN_3;
    // Delay for approximately 1 msec
    for(i = 0; i < 5500; i++)
    {
    }
    HWREG(GPIO_PORTF_BASE + (GPIO_O_DATA + (GPIO_PIN_3 << 2))) = 0;

    //
    // Send the requested number of bytes over the SSI port.
    //
    while(ulSize--)
    {
        //
        // Wait until there is space in the SSI FIFO.
        //
        while(!(HWREG(SSI0_BASE + SSI_O_SR) & SSI_SR_TNF))
        {
        }

        //
        // Write the next byte to the SSI port.
        //
        HWREG(SSI0_BASE + SSI_O_DR) = *pucData++;
    }

    //
    // Empty the receive FIFO.
    //
    while(HWREG(SSI0_BASE + SSI_O_SR) & SSI_SR_RNE)
    {
        HWREG(SSI0_BASE + SSI_O_DR);
    }
}

Call to blSSISend:

blSSISend(testBuffer, 128);

Buffer to transmit:

uint8 testBuffer[128] = {0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x10,0x11,0x12,0x13,0x14,0x15,0x16,
                        0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,
                        0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,
                        0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
                        0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
                        0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,
                        0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,
                        0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44};

Buffer that the master receives:


11 12 13 14 15 16 17 18 11 11 11 11 11 11 11 11
11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11
11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11
11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11
11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11
11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11
11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11

 

 

  • The slave cannot transmit data unless the master is providing the clock to drive the data transmission.

    SPI transmission is always simultaneously bi-directional, and is always driven by the master.  If the master is not transmitting, then the slave cannot either.

  • My code uses an interrupt to the master to signal that there is data available to be clocked in.  The master is clocking in the data and only gets the first 8 bytes of the 128 trying to be sent.

  • Hello Susie Johnson,

    As slandrum indicated, I would suspect some issue with the signalling from the master. Do you have a logic analyzer available to monitor the SSI pins for this sequence?

  • Hi Mitch,

    Thank you for your response.  We used the logic analyzer on Monday to troubleshoot the problem just to make sure that the master was indeed clocking the data.  Here are some logic analyzer traces along with a trace of the debugger screen when it is hung in the while loop waiting for the SSI_SR_TNF bit to be set indicating that the FIFO can accept more data.

    The master is clocking in the data.

    Below is the data that the slave is trying to transmit:

    uint8 testBuffer[128] = {0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x10,0x11,0x12,0x13,0x14,0x15,0x16,
                            0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,
                            0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,
                            0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
                            0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
                            0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,
                            0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,
                            0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44};

    Below is the data that the master is clocking in:

    11 12 13 14 15 16 17 18 11 11 11 11 11 11 11 11
    11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11
    11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11
    11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11
    11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11
    11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11
    11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11

    The bits in the status register indicating that the FIFOs have been emptied seem to not be working.

    Thanks,

    Susie J.

  • I don't know why the TNF and TFE bits are not behaving properly.

    I do note some things that are not quite correct in your comments and in your code.

    Your send function will return when the last data has been placed in the FIFO, not when it's actually been sent.  It will still take time for that last data to clock out.

    Your code to clear the receive FIFO at the end of the function will flush out the receive FIFO, but you will still have data transmitting after you return from the function, so more data will accumulate in the receive FIFO after you return.

  • This code came with the TI StellarisWare I downloaded.  It's in the boot_loader directory.  I didn't alter it in hopes that it would just work. 

  • Hi Susie J.,

    The logic analyzer traces look good.

    On the code side, I don't think the "stall" at 8 bytes of data is a coincidence. And I think I can make out in your CCS screen shot that the SSIRIS is showing RX Overrun. For proper behavior I think you will want to change that code to include a dummy read for each write. The bootloader example uses that function to send small amounts of data and so it can probably get away with adding 1-3 bytes into the TX FIFO and then performing a looped dummy read to clear the RX FIFO. For larger transfers (> FIFO size), I believe you will want to keep the TX write/RX read in sync.

  • Hi,

    I discovered the source of the problem.  At the first of the send function, I am generating a one millisecond interrupt pulse to the master to indicate that the slave has a message to send.  The interrupt to the master is rising edge triggered so the master is trying to clock data while the slave is still in the counter loop (not filling the FIFOs).  I reduced the loop time to one microsecond and now the data is being clocked out correctly.  We are planning to change the interrupt trigger to falling edge today to take care of the problem.  We are using uDMA with the SSI communications so we were not seeing this problem in normal operation. Thanks for all the help.

    Susie J.

  • @Susie Johnson:

    Your posts are always well detailed and carefully constructed/considered - bravo! (should be modeled by those who post, "does not work!")

    Your thoughtfulness & kindness in "closing the loop" is also most excellent - provides great value to any/all follow-on readers.  (includes this reporter)

    Thank you...