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 + 10; but on the SPI master side, at the very first time, it receive data SpiReturn = 0; SpiReturn = 10; SpiReturn = 11......and the next round, it will assign SpiReturn = 49, then SpiReturn = 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!
Solved! Go to Solution.
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)
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.
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.
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.
I added a line right after SPIS_Start
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
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.
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?
with first manually DMA request and manually load first byte with SPIS_WriteByteZero(s_txBuffer); I can finally have the correct data at the master side.
Still like to know if there is any less clumsy solution.