14 Replies Latest reply on May 24, 2013 3:38 PM by user_78878863

    SPI slave and DMA question

    donghua.gu

      I am using PSoC3 at the SPI slave end and SPI master is a ARM9 processor. I need to consistantly exchange block of data to PSoC3 through the SPI, so I set up the DMA on PSoC3 side. In my test program, I find SPI slave return data is shifted by one byte. For example, in PSoC3, I initialize spitxdata[i] = i + 10; but on the SPI master side, at the very first time, it receive data SpiReturn[0] = 0; SpiReturn[1] = 10; SpiReturn[2] = 11......and the next round, it will assign SpiReturn[0] = 49, then SpiReturn[1] = 10.... It seems Spi slave Tx does not put the tx data after receiving the first byte? Any suggestions?

         

      Here is some more details about my program. SPIS Rx/Tx buffer size = 4, only selected Interrupt On Tx FIFO Not Full and Interrupt On Rx FIFO Not Empty, rx_interrupt output connects to DMA_RX_S drq and tx_interrupt connects to DMA_TX_S drq, both DMA has hardware request set to level

         

       

         

      Attached is the related code.

         

       

         

      Thanks in advance for any suggestion!

        • 1. Re: SPI slave and DMA question
          donghua.gu

           sorry about the second post. the website told me it was a bad link, so I clicked "post again". Admin please remove other duplicated post. thanks

          • 2. Re: SPI slave and DMA question
            donghua.gu

             somehow, the attachment did not show up. Here goes again.

            • 3. Re: SPI slave and DMA question
              user_78878863

              Can you post your complete project  so we can look at it? E.g. how the DMA gets triggered, and how SPI is set up... The reason might be just something not related to your setup code.

                 

              Also, did you try to just use a SPI buffer of 40 bytes? Then the component should do all the work for you...

                 

              lastly, your receive DMA handling looks strange. There is a second TD in the DMA which just copies the first byte of the receive buffer to itself, over and over... (or actually it might do even stranger things given that the SRC base address is set to the peripherals instead of sRAM)

              • 4. Re: SPI slave and DMA question
                donghua.gu

                 The original project has lots of unrelated stuff, so let me try to make a new test version and post it later. But it is still not easy for you to test because my SPI master is a ARM 9 processor on a different board. 

                   

                For the test, I do set up entire 40 bytes both on master side and slave side. It is just the first byte is always zero, and the last byte of the first transfer from slave will show up as the first byte in 2nd transfer from master, so it is shifted by one.

                   

                And for the last part, I know it is strange, I got the example code from our support FAE, (he is on vacation now). In his email: It moves the first byte from first location of the buffer to the exact place, which does nothing. But, in the process of moving from the beginning of the buffer to the beginning of the buffer, it essentially resets the pointer for the DMA. So when the next SPI packet arrives, the first byte will go to rxBuffer[0].

                   

                I don't completely unstand the logic, but the example project have two TDs at both Tx and Rx side, I changed Tx side to one TD, it still works, but when I changed Rx side, all the sudden, I only got the same byte over and over, so I changed it back to two TDs.

                • 5. Re: SPI slave and DMA question
                  user_78878863
                          To the second DMA TD: OK, I understand. This is quite a neat solution to reset the DMA - otherwise this would have to be done in software AFAICS. To the SPI problem: can you observe the SPI transaction with a logic analyzer? (When I understand you right the problematic data is not on the PSoC side, but observed on the master side, right?) That way you can find out whether the PSoC is transmitting the data at the wrong place or not. This actually might be quite normal: when the master starts transmitting its data, it also is starting to receive data. But the first byte is only received fully when the first byte has been transmitted also fully. So it might be that the receive process on your master then puts the data to the second byte in the buffer. What kind of MCU is you master exactly?   
                  • 6. Re: SPI slave and DMA question
                    donghua.gu

                     SPI master is Atmel AT91SAM9261. 

                       

                    Before using DMA, I used to load SPI slave manually with SPSI_WriteByteZero(data), so I am very sure the master will correctly receive each byte in this case. The master side is still sending each byte separately but eventually will use DMA as well. That's after I get SPI slave side working first.

                    • 7. Re: SPI slave and DMA question
                      donghua.gu

                       I added a line right after SPIS_Start

                         

                      SPIS_WriteTxDataZero(0x55);

                         

                      so now the first byte I am getting at the master side is 0x55, then the second byte and beyond are the bytes I set up in s_txBuffer at the PSoC3 side. So it looks like the problem is still at the PSoC3 side and it is not loading the first byte into the register to prepare for the SPI transfer

                      • 8. Re: SPI slave and DMA question
                        user_78878863
                                But the question remains: do you know who is the culprit? Does the PSoC, when using DMA, really send out the bytes one too late (and with a leading zero especially)? Did you try to use a 40 byte SPI buffer, so the component does everything on its own )that way you won't need DMA at all)?   
                        • 9. Re: SPI slave and DMA question
                          user_78878863
                                  After reading deeper into the SPI Slave data sheet, I have an idea what might happen. Basically when you start the TX buffer is empty (nothing is loaded into A0 so there is nothing to transmit). Now when the master starts to write, it asserts SS and starts sending. In that moment, the SPI Slave sees that the TX buffer is empty, creates an IRQ and the the DMA fills in the first byte. But that is then too late to send it out, so it will get send only the second time. You can test that by adding an ISR to the tx_interrupt line. It should fire after the SPI has been initialized, and before the master sends for the first time. If it doesn't, then my idea above is correct. (Or you route it to a pin and check with a logic analyzer when interrupts are generated) If this is what happens, then you would just need to create the first DMA request manually (with CyDMAChSetRequest).   
                          • 10. Re: SPI slave and DMA question
                            user_78878863
                                    Stupid editor :( Does anybody know how to add paragraph breaks with this "small box editor"?   
                            • 11. Re: SPI slave and DMA question
                              user_14586677

                              I have found that if you delete all history in your browser, when the small

                                 

                              box shows up, then close the browser, reopen, small box goes away.

                                 

                               

                                 

                              Regards, Dana.

                              • 12. Re: SPI slave and DMA question
                                donghua.gu

                                 so I added a isr line to the tx_interrupt, and wrote some dummy code in the isr routine and set a break point. well the break point did not trigger. So that means it did not load the first byte?

                                   

                                I added CyDmaChSetRequest(S_TxChannel, CPU_REQ) into my Dma_S_Tx_Configuration, right after CyDmaChSetInitialTd and this time, the data on master side does not shift by one, it misses the first byte entirely, but the second byte is the second byte slave sends. So I guess it is a little bit better. 

                                   

                                When I manually request first DMA, it loads data, but does it push it all the way to SPIS register to be ready to send off?

                                • 13. Re: SPI slave and DMA question
                                  donghua.gu

                                   with first manually DMA request and manually load first byte with SPIS_WriteByteZero(s_txBuffer[0]); I can finally have the correct data at the master side. 

                                     

                                  Still like to know if there is any less clumsy solution.

                                  • 14. Re: SPI slave and DMA question
                                    user_78878863
                                            When I read the data sheet correctly (look at the function description) the "FIFO not full" state gets triggered when the accumulator gets set (A0). Starting the first DMA transaction manually writes only to the FIFO register, which might also be one byte to late. You might want to open a support case with Cypress about this, to get clarification of the actual behavior. Or you can try the solution with the 40 bytes TX buffer as suggested before - this doesn't use the DMA at all but an internal ISR to feed the SPI.   
                                    1 of 1 people found this helpful