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/TMS320F2808: SPI Register RXFIFO and TXFIFO problems

Part Number: TMS320F2808
Other Parts Discussed in Thread: TMS570LS3137, C2000WARE

Tool/software: Code Composer Studio

Hi everyone,

This question of mine is related to the question I asked this month. My problem is this:

For instance, I send 3x1 uint16 vector from Arduino(Master) to TMS320F2808(Slave) and there is nothing wrong with the receive of data since at SPIRXBUF I see the correct data but since I use FIFO, the RXFFOVF bit is always 1, which means that more than 16 words is received by the FIFO even if I send less than 3 words continuously. Furthermore, I simply multiply this 3x1 vector by a constant on the slave side and send it back to the master. There is this second problem: Even if I send 3 words to the master, at FIFO buffer I see that transmit FIFO contains 16 words and 13 words respectively and repeatedly. I do not know why this happens. I am open to any help. 

Thanks.

  • Çevikalp,

    Are you repeatedly sending the same data over and over? do you ever see data corruption?
    Can you send a screen capture of the SPI registers view in CCS after a transfer?
    Do you reset/clear the RXFFOVF flag or the FIFOs ever? do the FIFO counters end up back at 13/16?

    -Mark
  • -Yes, I am repeatedly sending the same data over and over. I see data corruption from time to time. It is sometimes corrupted, sometimes not but there is a regular shift of data. By corruption, I mean instead 0xAA, 0xFF is sent.

    -No, I do not reset/clear the RXFFOVF flag because I generate the code for this operation from a Simulink model. As far as I know, I do not have an access for that flag to reset. I understand about the FIFO Registers by constantly following the SPIA Registers in CCS.

    This is Spia Register after a transfer. As it can be seen, RXFFOVF bit (SPIFFRX.15) is 1 continuously. I simply send [25 26 27] 3x1 vector and send [50 51 52] 3x1 back. I see the last element of the vector in registers all the time.

    I forgot to mention that if I send Nx1 vector from master to slave and do some operations with it, it is sent back as shifted. For instance, [1 2 3 4] is sent back as [4 1 2 3]. I also noticed that while this happens, RXFFOVF bit is 1 and when I read the explanation for it in the datasheet, it says that if that bit is 1, the first word received is lost.

  • I am still looking for help.
  • Çevikalp,

    I am still catching up from the long weekend, I appreciate your patience.

    Is all of your code generated from MATLAB/Simulink models? Can you implement or export your Simulink code to a CCS project so that you can test the SPI configuration code? If you are able to export your SPI code to a CCS project, you will be able to directly mess around with the code. It will help you reach a better understanding of what is going on here.

    I would imagine that you have access to the RXFFOVFCLR bit through the Simulink. If not, I strongly recommend contacting Matlab support to include this feature.

    What you are telling me is that you are experiencing overflow. This does not randomly occur. Can you set your RX interrupt level to less than 16 words? Try setting it to 8 words. and interrupt before you hit the full FIFO depth.

    Another thought I had while typing this up: Since the F2808 is the slave, it is possible that you enable the SPI module well before enabling the interrupt. i.e. the SPI is enabled, but the interrupt is not. After just 4 bursts of 4 words, you are at risk of overflow. Please check your program timing. Add GPIO toggles at different checkpoints in the code related to SPI initialization. Plot on a scope that GPIO against master data transmits.


    -Mark
  • -Yes, all of my code is generated from Simulink model. I did implement my code in CCS as a project. What do you mean by "SPI Configuration code"? Which part do you say? I believe that as well, I have been playing with it for a while but I haven't come up with a certain solution yet. I need some guidance.

    -No, unfortunately I do not have any access to that bit through Simulink.

    -OK, I will set it and try again but I don't think it will change things.

    -How do I check my program timing? From where? Can you give me an example of doing those things and also adding GPIO toggles?
  • 1. I am referring to the code in which you configure the SPI control registers.

    2. I recommend filing this as a bug/feature request with the Matlab/Simulink team. seems like fault checking and recovery should be included.

    3. It seems like you are both new to C2000 and MCU programming in general.

    I recommend reading the SPI User's Guide http://www.ti.com/lit/sprug72.
    Run any the SPI example programs found here: http://www.ti.com/tool/sprc191 
    And look at the F2808 Workshop material: http://processors.wiki.ti.com/index.php/C2000_Archived_Workshops#F2808_Workshops 

    By GPIO toggle debugging, I am referring to simply using a spare GPIO and switching it from 1 to 0 and back at certain events in your initialization code. You can do different toggle patterns or pulse widths to indicate different events in your system. Observe that GPIO  along with the incoming SPI messages to determine the sequence of events.

    -Mark

  • In your previous post, you mentioned about enabling SPI module and interrupt. In this case, which interrupt are you referring to?

  • Mark,

    Can you add me on LinkedIn? I have sent you a request already. I want to discuss it with you from there.

  • Çevikalp,

    Sorry, but I would rather keep all support related queries on here. It is beneficial to everyone who may come in with the same questions.

    I was referring to the SPI RX interrupt. If you receive more than 4 bursts of 4 words between enabling the SPI module and enabling the interrupt, you are at risk of overflow. I don't know your initialization scheme or the order of operations of your program, so this is just my professional opinion of what could be going on.

    - What is the SPI master device?
    - Does the master begin transmitting before the F2808 SPI Slave is enabled?
    - Is there a possibility that 4 bursts of 4 words are transmitted by the master between the SPI module being enabled and the SPI interrupt being enabled and serviced the first time? Using the GPIO toggle debug method and an oscilloscope really will help you be able to answer this question.
    - Consider breaking the application code down to the bare bones. Create a simple SPI slave code that can receive and handle the master data appropriately.Then slowly add in the rest of your application code.

    Thanks,
    Mark
  • I have an unused SPI RX Interrupt for the SPI Module. The code that I have been running is as follows:

    What we need to see is that first c2000_flash_init() and init_board() functions are called. Then the initialization, step and terminate functions for the model are operated. Then I simply have a model which receives something from the master, do some mathematical manipulation on it and send back to it. The code generated from it will not really help us at this stage, so I am not sharing it. I would like to share the init_board() function with you, maybe it will help you to understand the problem better.

    Also, init_GPIO and init_SPI_A functions are as follows:

    After these codes, our Simulink model begins to run repeatedly.

    -Our SPI master device is TMS570LS3137.

    -Actually I am not sure about it. Master and slave devices are both being operated separately from CCS.

    -There might be an issue like that, I am not sure. After sharing my codes, can you give an idea about where to use GPIO toggle debug method in my source code. In SPI RX Interrupt? Or where?

    Lastly, our current case is as follows:

    1- When master sends a vector to slave, slave does some mathematical calculations on it(at this point, nothing) and sends back to the master. At this point, at the very beginning, 16 words of dummy data is sent from slave to master. Then the manipulated data by the slave is sent to the master. Also, data received by master is shifted 1 word. An example:

    Master->[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]

    Master sends this. At the same time, slave sends

    Slave->[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0](SPI Receive block has an initial condition of 0, probably it is sent.)

    Then, manipulated data is sent as:

    Slave->[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]

    Next Master sample:

    Master->[21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36]

    Next Slave sample:

    Slave->[16 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35]

    As it can be seen, the first word of second sample on SOMI is last word of first sample on MOSI. Hope this clarifies the situation.

    2- When slave just sends something to the master regardless of what it is receiving, first 16 words(1 word=16 bit) are sent without any delay or shift. Next 16 words begin to shift. Sometimes it sends same words twice, three times, etc. For instance, slave sends something like [10 11 12 13 14 15 16 17]. Here is how it goes:

    [10 11 12 13 14 15 16 17]

    [10 11 12 13 14 15 16 17]

    [17 10 11 12 13 14 15 16]

    [10 10 11 12 13 14 15 15]

    .

    .

    .

    etc.

  • Çevikalp Sütunç said:
    -Actually I am not sure about it. Master and slave devices are both being operated separately from CCS.

    Can you try putting a breakpoint after each word the master sends (this breakpoint should be on the master MCU), let the slaves free RUN. by nature since there are no SPI clocks, the slaves will not progress and send data on their own. observe the state of the slave. did it receive the word? did it swap it as expected? is the proper word staged/loaded in the TXBUF as expected?

    Çevikalp Sütunç said:
    -There might be an issue like that, I am not sure. After sharing my codes, can you give an idea about where to use GPIO toggle debug method in my source code. In SPI RX Interrupt? Or where?


    You can literally put the GPIO toggle code anywhere. Useful places would be in you before flash init, at start of board init, after PLL init, after SPI GPIO init, and after SPI init, and then at the start and end of your SPI receive function. These allow you to know where your code is in real time vs the Master sending data.

    Çevikalp Sütunç said:
    As it can be seen, the first word of second sample on SOMI is last word of first sample on MOSI. Hope this clarifies the situation.


    This makes sense. No matter what the Slave will transmit whatever is in the buffer. If you tried to do a single word loopback you will see that the data the master receives is shifted by one. (the SPI loopback example in c2000ware/code examples) 

    Çevikalp Sütunç said:
     When slave just sends something to the master regardless of what it is receiving, first 16 words(1 word=16 bit) are sent without any delay or shift. Next 16 words begin to shift. Sometimes it sends same words twice, three times, etc.


    It looks to me like you are trying to replace the data the master sent in real time. By nature it will always be one word behind. You haven't shown any scope captures of the data.

    • Is there any time between the 16 bit words so the slave has time to grab what is in the RX buffer, manipulate it (or not), then place it in the TX buffer before the next word is started by the master?  
    • Please share just a snippet of the code where your slave is handling the received data and replacing it to be transmitted.

    I think we are at the point where you need to break down the problem in to the simplest pieces. Do not move to the next part until you understand how each previous step is working. 

    1. Start with a simple 1 Master  to 1 slave sending 16 words to the master unmodified. - notice the received words is shifted by 1 from the slave. 
    2. Increase complexity by adding message manipulation.
    3. Increase complexity by adding other application code.

    Everything I am suggesting is really just basic debug skills- breaking the problem down to the pieces that matter, and being meticulous with what we are doing. Before we do any test, we think about how that test should behave if it worked properly. If it does not work as expected, you dig deeper.

  • FYI. I got my threads mixed up and edited this post removing comments about multiple slaves as I am working two reasonably similar threads. Sorry for the confusion
  • -No there is no time between the 16 bit words.

    This is SPI Receive part:

    SPI Transmit:

  • Hi,

    I think my question of time between spi words was the wrong one (my thread confusion) I should have asked: Is there time between 16-word bursts? 

    It would appear that you are not using interrupts, which is ok, but I am not sure if you have the timings down of when things are executing your TX and RX code.If you look at your receive code you wait until the FIFO is full (or overflowed) to read the received data. Consider doing multiple reads of less than 16 words (2 reads of 8 words, 4 reads of 4 words, 8 reads of 2 words along with a total burst count to ensure that you have received 16 words.

    Also, looking at the SPI FIFO enable code shared previously, you are not properly enabling the either the SPI TX FIFO or the SPI RX FIFO enhancements. Your SPI init  code does not touch the receive FIFO enable bit. Please refer to the spi_loopback example provided in the header file examples. It shows a simple master loopback example, but with the SPI configured for 16 words receive FIFO as well as polling on the SPIRXFFST bit to ensure that you are only reading what has been received in the FIFO. you can also look at the spi_loopback_interrupts example for how to use the SPI with interrupts.

    -Mark

  • -It would appear that you are not using interrupts, which is ok, but I am not sure if you have the timings down of when things are executing your TX and RX code.If you look at your receive code you wait until the FIFO is full (or overflowed) to read the received data. Consider doing multiple reads of less than 16 words (2 reads of 8 words, 4 reads of 4 words, 8 reads of 2 words along with a total burst count to ensure that you have received 16 words.

    Actually I want to use interrupts but I think I need to learn more about them before using them. For instance, I think interrupt functions related to SPI may be handy but I do not know how to use them. I can not add timings between RX and TX in Simulink, I also need to look for that. By saying multiple reads, for instance consider 4 reads of 4 words, is it going to be something like

    if (SpiaRegs.SPIFFRX.bit.RXFFST >=4)

    It will start to write the words inside RX fifo to RXBUF as soon as RX FIFO contains more than 4 words and maybe that will prevent data shift. Will I ensure that I have received 16 words by checking RXFFOVF bit?

     

     

    Okay, I will consider the things you said and reply back as soon as possible. Thanks for the help.

  • This is one approach if not using interrupts. It is a blocking read for the full 16 words in pseudo code.

    You are looping until you have read 16 words, then you read the data in 4 word chunks then you return the data array.  

    blockingRead16w(rxdataArray){
        wordsRead = 0
        while(wordsRead <16){
            while(RXFFST<=4){} // poll for more than 4 words in fifo
            for(i=0,i<4,i++){
                rxDataArray[wordsRead] = SPIRXBUF // read and store rxbuf data
                wordsRead++ // increment counter
            }
        }
    }
    

    You don't want to wait until you hit an overflow condition. that means at least one word has ALREADY been overwritten.

    The example above is a blocking function so the application will sit there waiting until all 16 words have been received. At 1 or 2 MHz SPICLK, this would be a long time. As such, I definitely suggest the interrupt approach. Set the RX interrupt level to 4 or 8, then read and store the data until there is no words left in the FIFO. find some global way to track that you are at 16 words and then do your data manipulation. It all depends on how you want the data flow to look:

    • If you need to loopback each word, you should just load the TXBUF with the received word immediately (like the spi_interrupts example does).
    • If you need to process the full transmission then loop it back in the next 16 word transfer, then store the data until you receive 16 words, do your data manipulation, then write the modified 16 words to the TXBUF. Your master needs to allow the slave enough time to receive the 16 words, process, then load 16 words of data before it starts the next transmission.

    Please study the SPI module and mess around with it until you grasp how it works.Hopefully the information I have given you gets you off the ground. 

  • My problem is solved for now. Thank you for your help Mark.