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.

CCS/TMS320F28377D: stable SPI regardless fixed CPU interrupts

Part Number: TMS320F28377D

Tool/software: Code Composer Studio

Dear,

I have two Delfino microcontrollers (MC) communicate over SPI communication. One is a master and the other is a slave. SPI communication is put inside the main for loop on CPU1 on each MC. Both MCs have also fixed 1 mili-second ISR_Timer0 interrupt routine. Ones started, SPI works as expected transferring 32-bit floats between master and slave, but some other time transferring is not as should be (floats are not as should be). I suppose that the fixed interrupts in the slave/master sometimes 'brake' continuous SPI float numbers exchange between MCs.

Could you give me your opinion how to get stable SPI transfers regardless fixed CPU interrupts?

Thank you,

Tihomir Zilic

  • Tihomir,

    I'm sorry to hear that you are having trouble with the SPI. Can you describe the issue you are having a bit more clearly? Is the data being sent in one direction only or is it full duplex? Which end appears to be having the trouble? Have you used an oscilloscope to check that your data is being transmitted properly?
    With the SPI module, once the data is written to the SPI data buffers, the SPI module handles the transfer without any CPU interference, so the Timer interrupt should cause an issue with an active transmission. However, if the SPI module is in the main loop, is it possible that the code to transmit the next data is never being called? If you are constantly interrupting the CPU and spending all of the time in an ISR, you may not ever reach the main loop.

    There are a few things that you might try. First, try out the code in a simplified state. Remove the Timer ISR and ensure that the SPI is able to communicate properly without any other system interference. Are you using the SPISTE signal? This helps to keep the modules synchronized.

    If you can share a bit more of what you have done to debug this so far, it would help me to more efficiently support you.
  • Mark,
    thank you for your support.

    Well, data is being sent bidirectional. Both master ans slave receive wrong data sometimes, but some other time everything goes right. I didn't use oscilloscope for additional checking.
    But, as you mentioned: 'If you are constantly interrupting the CPU and spending all of the time in an ISR, you may not ever reach the main loop', which means that this way having SPI in the main loop together with ISR timer is not good, do you agree? I need a way of stable SPI where it would never come in such situation. Also, I need to have fixed-interval ISR timer0 for some motor control tasks, reading sensors...
    The following code is SPI between master and slave sending 32bit floats as two parts of 16bits (because SPI buffers are 16bit) :

    SLAVE:

        for(;;)
        {

        // SPI begin, Transmit data 32 bit float over SPI which has 16 bit shift register
                 union mytypeSend data_sent;
                 union mytypeReceive data_reci;

                 data_sent.fl=s; //send float number - encoder reading

                 // Transmit data first 16 bits of 32 bit float number
                 spi_xmit(data_sent.ui[0]);
                 // Wait until data is received
                 while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) { } // 1 word = 16 bits
                 // Check against sent data
                 rdata1 = SpiaRegs.SPIRXBUF;
                 data_reci.ui[0]=rdata1;

                 // Transmit data second 16 bits of 32 bit float number
                 spi_xmit(data_sent.ui[1]);
                 // Wait until data is received
                 while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) { } // 1 word = 16 bits
                 // Check against sent data
                 rdata2 = SpiaRegs.SPIRXBUF;
                 data_reci.ui[1]=rdata2;
                 aM=data_reci.fl; //32 bit float contained from two 16 bits parts
                 SpiaRegs.SPIFFTX.bit.TXFFINTCLR=1;  // Clear Interrupt flag
                 SpiaRegs.SPIFFRX.bit.RXFFOVFCLR=1;  // Clear Overflow flag
                 SpiaRegs.SPIFFRX.bit.RXFFINTCLR=1;  // Clear Interrupt flag

        // SPI end

        }

    MASTER:

    for(;;)
        {
        // SPI begin, Transmit data 32 bit float over SPI which has 16 bit shift register
                 union mytypeSend data_sent;
                 union mytypeReceive data_reci;

                 data_sent.fl=1111.12345+bM; //some increasing float

                 // Transmit data first 16 bits of 32 bit float number
                 spi_xmit(data_sent.ui[0]);
                 // Wait until data is received
                 while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) { } // 1 word = 16 bits
                 // Check against sent data
                 rdata1 = SpiaRegs.SPIRXBUF;
                 data_reci.ui[0]=rdata1;

                 // Transmit data second 16 bits of 32 bit float number
                 spi_xmit(data_sent.ui[1]);
                 // Wait until data is received
                 while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) { } // 1 word = 16 bits
                 // Check against sent data
                 rdata2 = SpiaRegs.SPIRXBUF;

                 data_reci.ui[1]=rdata2;
                 aM=data_reci.fl; //32 bit float contained from two 16 bits parts
                 bM=bM+0.001;

                 SpiaRegs.SPIFFTX.bit.TXFFINTCLR=1;  // Clear Interrupt flag
                 SpiaRegs.SPIFFRX.bit.RXFFOVFCLR=1;  // Clear Overflow flag
                 SpiaRegs.SPIFFRX.bit.RXFFINTCLR=1;  // Clear Interrupt flag

        // SPI end
        }

    Is there some other way of getting stable SPI together with CPU fixed ISR timer0?
    Is it a good idea to have SPI inside the ISR timer0 interrupt on both master and slave, not in the main loop?

    Thank you again,
    Tihomir

  • Tihomir,

    Have you been able to resolve your issues?

    Tihomir Zilic said:
    which means that this way having SPI in the main loop together with ISR timer is not good, do you agree?

    I partially agree with your statement. It really depends on how your control loop is structured, and if you can ever make it into the main loop. You need to design your system so that you can capture measurements, compute tasks, and then act on them predictably in every cycle of your control loop. If your control loop tasks do not leave enough time to manage your housekeeping tasks, (comms, data logging, etc), you will need to optimize your system somewhere. Either by slowing down you loop time, or optimizing your control loop time. 

    It looks like you are using the SPI in a very manual, hands-on way that requires a lot of CPU interaction. If you enable the FIFO, you can write the two 16-bit words to the SPI and wait until the SPI has received both before interacting with the data. This will free up the CPU to do other things.This could cut some time out of the SPI loops. 

  • Dear Mark,

    I haven't resolved it yet.
    Now, I am trying to solve it using CPU2 only for SPI communication. SPI in the main loop on CPU2 and without ISR timer. CPU1 and CPU2 would communicate using shared memory... I hope it will work this way...

    Thanks for trying to help,

    sincerely Tihomir Zilic
  • Tihomir,

    That actually would be a reasonable approach. You can do your main control loop on one of the cores with the other managing communication. You can place the data in shared memory and then notify the other CPU using an IPC interrupt.

    If you have any additional questions, don't hesitate to post!
  • Dear Mark,
    thank you for your reply.
    I've already made an IPC, but didn't finish yet what I intended. I want to sent float32 array between CPUs. I successfully solved it with message RAM (but sending only one float32 bit). I want to do it using shared RAM, and I do not know could I send float 32 or I need to convert it to Uint32 like using message RAM. Note: when I used CPU1 and CLA, I could work directly with float32 numbers. Do you have some example of sending float32 between CPUs using shared RAM?
    Thanks, Tihomir Zilic
  • Tihomir,

    Sorry for the long delay. Have you been able to resolve your question? The simple answer is that the shared RAM is just a big dumb memory. You can use it how you see fit. If CPU1 stores a value in the RAM space and it is in a float32 format, CPU2 should be programmed to know that it is going to be picking up a float32 when it reads the shared RAM. There is no hardware that enforces any structure. Said in another way, if CPU1 programs a float32 value in your shared RAM, CPU2 could read it as two int16 values, which probably would not work.  In essence, CPU2 will interpret the data in the RAM however you tell it to interpret the data. The key is that your program should know where to pull data from and how to interpret it, even in a single core, simple system.

  • Dear Mark,

    I solved the issue but had spent too much time...
    I expected the help of TI experts one month ago.
    Sorry accepted...

    Regards,
    Tihomir Zilic
  • Glad to hear that you resolved your questions. Please create a new post in the future if you have any additional questions.