cancel
Showing results for 
Search instead for 
Did you mean: 

Preserving SPI data in DMA circular mode

Hrishikesh
Senior

I'm trying to establish communication between a Raspberry Pi and an STM32F407. The Pi is Master and the F407 is a full duplex slave. The SPI is configured with circular mode DMA. When the data is sent from the Pi, I do receive it at the F407. However, the moment that transaction ends, the receive buffer in the F407 becomes 0x00 again wiping away all received data. I'm guessing this is because of the circular DMA?

I tried creating a copy of the original receive buffer in the HAL_SPI_TxRxCpltCallback function but that did not work. It seems to get called after the If I configure the DMA in normal mode, the SPI transaction runs once and then stops whereas I want it to run continuously in the background.

How do I solve this?

1 ACCEPTED SOLUTION

Accepted Solutions

I found the fix. You have to do a read before the write. I was doing it the other way around. Its some weird spidev thing.

View solution in original post

6 REPLIES 6
TDK
Guru

Data is only wiped out if it is overwritten. In circular mode, this will happen when and if the master keeps sending data. If the master only sends enough data to fill the buffer once, it will not be overwritten.

Use a buffer large enough to avoid data being overwritten before you can read it and/or improve your response time to read data faster.

If you feel a post has answered your question, please click "Accept as Solution".

> If the master only sends enough data to fill the buffer once, it will not be overwritten.

This is my understanding too. However, it does not seem to work that way. I've attached a small video that shows what happens. Watch the values on the top right of the screen. The RPi first writes values, waits for a half second, and then reads the values from the F407. On the STM32 side, there are two different buffers for RX and TX. If I only TX from the RPi then the values persist in the F4 RX buffer. However, the moment I do the read from the F4, the values in the RX buffer in the F4 get erased. All buffers are 53 bytes wide. Here is the RPi code,

import spidev
import time
 
spi = spidev.SpiDev()
spi.open(0, 0)
 
spi.max_speed_hz = 10000000
spi.mode = 0
 
tx_buffer = [0xCB, 0xFE, 0x81, 0x80, 0x00, \
             0x00, 0x00, 0x00, 0x00, 0x00, \
             0x00, 0x00, 0x00, 0x00, 0x00, \
             0x00, 0x00, 0x00, 0x00, 0x00, \
             0x00, 0x01, 0xFF, 0x00, 0x00, \
             0x00, 0x00, 0x00, 0x00, 0x00, \
             0x00, 0x00, 0x00, 0x00, 0x00, \
             0x00, 0x00, 0x00, 0x00, 0x00, \
             0x00, 0x00, 0x00, 0x00, 0x00, \
             0x00, 0x00, 0x00, 0x00, 0x00, \
             0x00, 0x00, 0x00]
 
rx_buffer = [0]*53
 
spi.writebytes(tx_buffer)
time.sleep(0.5)
rx_buffer = spi.readbytes(53)
 
print ("tx_buffer", " = ", tx_buffer, end = "\n")
print ("rx_buffer", " = ", rx_buffer, end = "\n")
print ("\n")
#time.sleep(0.1)
 
spi.close()

What is this, python?

 

I don't think there are many people here using python or whatever tool are you using. You may want to seek help at dedicated fora, if such exist. Are you sure spi.readbytes() does not need to have the buffer's address to be supplied as parameter?

Okay, so this is the RPi side of code? That won't help much with problems at the 'F4 side.

As TDK said, data change because you overwrite them.

JW

Yes this is the RPI side of the code. As you can see, I'm writing and reading only once. So the transmission occurs exactly once (as seen in the video). Which is why this is puzzling.

TDK
Guru

> However, it does not seem to work that way.

I assure you it does work that way. I have used it in this fashion on many projects. Your bug is somewhere else, probably in the code on the STM32F4.

If you feel a post has answered your question, please click "Accept as Solution".

I found the fix. You have to do a read before the write. I was doing it the other way around. Its some weird spidev thing.