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 on an AM3359

Other Parts Discussed in Thread: AM3359, SYSBIOS, CODECOMPOSER

HEy together,

i have a problem with my SPI-Communication between a Sitara (AM3359) and a Concerto(F28M35). The Sitara is the SPI-Master. I think the problem is at the Sitara, because he stops the transmission after a couple of times. I transfer 3 Bytes per cycle.

The Code in the Sitara is:

 


The code in the main:

McSPIPinMuxConfig(MCSPI_INSTANCE_1);
McSPIInit(MCSPI_INSTANCE_1, 32, 0, MCSPI_MULTI_CH, MCSPI_CHANNEL_0);


    Task_Params_init(&taskParams);
    taskParams.priority = 1;
    taskParams.instance->name = "OutputJ9";
    taskParams.stackSize = 2048;
    Task_create(outputJ9, &taskParams, NULL);

The code from the task (OutputJ9) in a endless do-while-loop:

void outputJ9(UArg arg0, UArg arg1)
{
    unsigned char aktuellerZustand = 0;
    static unsigned int spicnt = 0;
    Semaphore_pend(switchReady, BIOS_WAIT_FOREVER);
    Semaphore_post(switchReady);

    do
       {
        //Send a random value over SPI to the concerto
        if (++spicnt % 1000 == 0)
        {
            unsigned char buffer[SPI_MSG_LENGTH_extern];
            LivecheckSPI_Sitara++;
            if (LivecheckSPI_Sitara >= 254)
            {
                LivecheckSPI_Sitara = 0;
            }


            buffer[0] = 1;
            buffer[1] = LivecheckSPI_Sitara;
            buffer[2] = 2;
   
            McSPICycle(MCSPI_INSTANCE_1, buffer, SPI_MSG_LENGTH_extern, MCSPI_CHANNEL_0);

            char logText2[255];
            sprintf(logText2, "Receive in char2: %d\n", buffer[0]);
            UARTPutString(uartInstance, logText2);
            char logText3[255];
            sprintf(logText3, "Receive in char3: %d\n", buffer[1]);
            UARTPutString(uartInstance, logText3);
            char logText4[255];
            sprintf(logText4, "Receive in char4: %d\n", (buffer[2]));
            UARTPutString(uartInstance, logText4);
        }
        Task_sleep(1);
    } while(1);

The code in the concerto is:

#include "SPI_Master_Slave.h"

extern Void slaveTaskFxn(UArg arg0, UArg arg1);

The code in the main of the m3:

 

   Task_Handle taskHandle;
    Task_Params taskParams;
    Error_Block eb;
    //static unsigned long ulMWRAllow;

    /* Call board init functions */
    Board_initGeneral();
    Board_initEMAC();

    SPI_Master_Slave_initSPI();

    TMDXDOCKH52C1_initDMA();

     /* Create SPI-Slave-task with priority 2 *///SW 27.01.2015
     Task_Params_init(&taskParams);
     taskParams.stackSize = 1024;
     taskParams.priority = 2;
     taskParams.instance->name = "slaveTask";
     taskHandle = Task_create((Task_FuncPtr)slaveTaskFxn, &taskParams, &eb);

The code in the "slaveTask" is:

/* Allocate buffers in .dma section of memory for concerto devices */
#ifdef MWARE
#pragma DATA_SECTION(masterSpiRxBuffer, ".dma");
#pragma DATA_SECTION(masterSpiTxBuffer, ".dma");
#pragma DATA_SECTION(slaveSpiRxBuffer, ".dma");
#pragma DATA_SECTION(slaveSpiTxBuffer, ".dma");
#endif

UChar masterSpiRxBuffer[SPI_MSG_LENGTH_extern];
UChar masterSpiTxBuffer[SPI_MSG_LENGTH_extern]; // = "Hello, this is master SPI";

UChar slaveSpiRxBuffer[SPI_MSG_LENGTH_extern];
UChar slaveSpiTxBuffer[SPI_MSG_LENGTH_extern];// =  "Hello, this is slave SPI";

int slaveSpiRxBufferINT[SPI_MSG_LENGTH_extern];
int LivecheckSPI_Concerto = 0;

 *  ======== SPI_Master_Slave_initSPI ========
 */
Void SPI_Master_Slave_initSPI(Void)
{
    //independent from Master or Slave
    // SSI0
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);//GPIO port D needs to be enabled so these pins can be used.

    GPIOPinConfigure(GPIO_PD0_SSI0TX);
    GPIOPinConfigure(GPIO_PD1_SSI0RX);
    GPIOPinConfigure(GPIO_PD2_SSI0CLK);
    GPIOPinConfigure(GPIO_PD3_SSI0FSS);

    GPIOPinTypeSSI(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1 |
                                    GPIO_PIN_2 | GPIO_PIN_3);

    System_printf("SPI_Master_Slave.c: Init SPI-Port successful\n");
    SPI_init();
}


/*
 *  ======== slaveTaskFxn ========

Void slaveTaskFxn (UArg arg0, UArg arg1)
{
    SPI_Handle slaveSpi;
    SPI_Params slaveSpiParams;
    SPI_Transaction slaveTransaction;
    UInt transferOK;

    slaveSpiTxBuffer[0] = 130;   
    slaveSpiTxBuffer[1] = 110;   
    slaveSpiTxBuffer[2] = 120;

    /* Initialize SPI handle with slave mode */
    SPI_Params_init(&slaveSpiParams);
    slaveSpiParams.mode = SPI_SLAVE;
    slaveSpi = SPI_open(Board_SPI0, &slaveSpiParams);
    if (slaveSpi == NULL) {
        System_abort("Error initializing SPI\n");
    }
    else {
        System_printf("SPI Slave initialized\n");
    }

    /* Initialize slave SPI transaction structure */
    slaveTransaction.count = SPI_MSG_LENGTH_extern;
    slaveTransaction.txBuf = (Ptr)slaveSpiTxBuffer;
    slaveTransaction.rxBuf = (Ptr)slaveSpiRxBuffer;
    // Enable the SSI0 module.
    SSIEnable(SSI0_BASE);

    while(1)
    {

        slaveSpiTxBuffer[0] = LivecheckSPI_Concerto;
        /* Initiate SPI transfer */
        transferOK = SPI_transfer(slaveSpi, &slaveTransaction);

        if(transferOK) {
            /* Print contents of slave receive buffer */
            System_printf("Slave: %s\n", slaveSpiRxBuffer);
            slaveSpiRxBufferINT[0] = (int)slaveSpiRxBuffer[0];
            System_printf("Slave0: %d\n", slaveSpiRxBufferINT[0]);
            slaveSpiRxBufferINT[1] = (int)slaveSpiRxBuffer[1];
            System_printf("Slave1: %d\n", slaveSpiRxBufferINT[1]);
            slaveSpiRxBufferINT[2] = (int)slaveSpiRxBuffer[2];
            System_printf("Slave2: %d\n", slaveSpiRxBufferINT[2]);
            LivecheckSPI_Concerto++;
            if (LivecheckSPI_Concerto >= 254)
            {
                LivecheckSPI_Concerto = 0;
            }
        }
        else {
            System_printf("Unsuccessful slave SPI transfer");
        }
        System_flush();
    }
    /* Deinitialize SPI */
    SPI_close(slaveSpi);
}
/*

This was the code of the sitara and concerto. The transmission starts and send the 3 Bytes for a couple of times and then it stops! It is not every time the same position, sometimes after 9, sometimes after 35 successful transmissions. If i switch the sitara off and after 1 second on again, the transmission starts from the beginning and stops after a couple of time again!

 

I saw that, sometimes the livecheck is in the first and sometimes in the last byte, so i think there is a problem, that there are some bytes lost or to much.

Does anybody have an idea what the problem can be?


Maybe i have to initialize a FIFO in the sitara? Like:

McSPITxFIFOConfig(MCSPI_INSTANCE_1, MCSPI_TX_FIFO_ENABLE, MCSPI_CHANNEL_0);
McSPIRxFIFOConfig(MCSPI_INSTANCE_1, MCSPI_RX_FIFO_ENABLE, MCSPI_CHANNEL_0);

Or is the problem the "MCSPI_MULTI_CH" in the sitara?  I think this mode means, that there wait more than 1 byte per cycle for the transmission!?

Can someone help me?

 

Regards,

Sebastian

 

 

  

 

  • Hi Sebastian,

    What software are you using?

  • Hey Biser,

    i use CodeComposer_v5.5 from Ti. The Sitara-Code is from the profinet_slave-example in "am335x_sysbios_ind_sdk_1.1.0.4".

    Or do you mean something different?

    I assume that the SPI_clk of the sitara (clockdivider =32-> -> 650ns) is too fast for the concerto, because the maximum SPi-clock of the M3 in slave_mode is (sys_clk/12)= 100Mhz/12 = 8,33MHz -> 12 Microseconds.

    If i send only 1 Byte, everything is ok. Although the clockdivider of the sitara is 32. But with more than 1 Byte, there are these problems!

    Regards,
    Sebastian
  • Sebastian, can you measure the SPI_CLK with a scope to ensure you are meeting the slave's max frequency? You may also have to double check that you have compatible clocking schemes set up between the master and slave.

    regards,
    James
  • Hey James,

    yes i already meassured the SPI_CLK and the clock from the Master (Sitara) and i saw that there is 650ns for one clock impuls. If you mean with "clocking shemes" that there are 8 Bits Data, then a short break from 2 Bits and than 8 Bits Data again, and the same again and again....than yes! The ChipSelect is switched low for every 8 Bits and is for the short moment (2 Bits) between the next 8 Data-Bits on high-level. Or do you mean something different?

    Regards,
    Sebastian
  • By clocking schemes, i meant clock and phase polarity. It looks like that is ok since you can get some data through. If you are measuring 650ns clock cycle time then that's about 1.5MHz which should be OK for Concerto (I looked at the spec for the F28M35 and thought I saw a max of 12.5MHz SPI clock, but wasnt' sure which port you were using).

    In the code, there should be some sort of status information in CHxSTAT or IRQSTATUS to determine what went wrong, maybe an over/under flow. If you check these to determine the error, maybe that will lead you to the issue.

    regards,
    James
  • Hey James,
    sry for my late reply.
    Yes it is a F28M35 and i calculated the same times.

    I was looking for CHxSTAT or IRQSTATUS, but i didn't found this register. Are this register in the sitara? Can you give me a more detailed description please?

    By the way, what is the difference between "Single channel" and "Multi channel" for the SPI at the Sitara?! I assumed, that i have to use it, because i want to transfer more than one Byte between Sitara and Concerto. Or does it mean i have more than one slaves connected to the Sitara, which works as Master.

    Regards,
    Sebastian