cancel
Showing results for 
Search instead for 
Did you mean: 

I am using STM32H7 HAL_SPI_transmitreceive_DMA, where are all internal buffers and how to refresh data?

pflunzi
Associate III

Hi,

I am using an STM32H753 connected to a raspberry PI via SPI. The STM32 is connected as slave. With CubeMX I configured the STM32 to be an SPI Slave with both DMAs configured as circular. I am having a struct with live data (refreshed every 10ms) and the raspberry can ask anytime for the data. For this, I am starting TM32H7 HAL_SPI_transmitreceive_DMA before the main loop. After placing the struct with live data into the D2-Memory, I could get correct data via DMA on the raspberry.

Unfortunately it seems that there is a buffer anywhere, which buffers a part of the struct. So when I stop requesting data from the STM32 and ask after 5 minutes again, the first data I get is 5 minutes old.

Is there a way to trigger a refresh of the data for SPI? I tried different things, like taking only software NSS, use the CS-Pin as interrupt source and then start a HAL_SPI_transmitreceive_IT or HAL_SPI_transmitreceive_DMA with non-circular buffer and then clear the SPI_CR1_SSI Bit in CR1 register, but it seems to slow, so that I only get corrupted data.

Can somebody tell me the fastest way to refresh the buffered data (I actually don't know whether it is an SPI or an DMA buffer problem)? I don't refresh the data when the CS-Pin is low, so there should always be valid data and I don't need any buffers at all.

edit: The old data ist still in Buffer when I do not use the DMA, so I would guess it is something SPI related.

7 REPLIES 7
Bubbles
ST Employee

Hi @pflunzi​,

yes, there's a FIFO integrated in the SPI peripheral. It's described in the reference manual, you can anytime test how much data is in the FIFO. Procedure to empty the FIFO is also described there.

BR,

J

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

pflunzi
Associate III

Hi,

if I am watching the TXBuffer, there actually is the correct value inside and it changes with time. The first value I got was another than I could see in the buffer (it was the old one from the last time I used SPI)


_legacyfs_online_stmicro_images_0693W00000bizADQAY.pngI also use the CS pin as an interrupt source ,and also tried this (I think this is the part you are referring to)

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if (HAL_GPIO_ReadPin(PI_CS0_GPIO_Port, PI_CS0_Pin) == GPIO_PIN_RESET)
	{
		__HAL_SPI_ENABLE(&hspi1);
	}
	else
	{
		__HAL_SPI_DISABLE(&hspi1);
		//SET_BIT(hspi1.Instance->CR1, SPI_CR1_SSI);
	}
}

pflunzi
Associate III

Some additional information.

I tried to following to make sure it is a problem I am having with the microcontroller and not the raspberry.

I heated the element a bit, so that it cools down to have a decreasing temperature. The values I get have a noise in the range of 10mK, so two consecutive measurements only differ by 0.01.

I took two measurements to make sure I got the real temperature. Then I waited ~30s and resetted the microcontroller. After additional ~30s I read the temperature two times. The first temperature I got was between the first one and the last one. This somehow prooves that I got the value from when the micocontroller was resetted.


_legacyfs_online_stmicro_images_0693W00000bizMEQAY.png

No, I don't think we're on the same page. You are referring to SW, while the FIFO is HW. Chapter 50 in the part manual describes the SPI HW behavior, including the FIFO. Here:

STM32H742, STM32H743/753 and STM32H750 Value line advanced Arm®-based 32-bit MCUs - Reference manual

The SPI is designed to transfer whole messages. The unorthodox approach you choose means that the DMA will prepare data in the FIFO even if the raspberry is not going to read it immediately. But the data (2 bytes I believe) stays inside the SPI buffer.

Jarda

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Hi, I read the part, that is why I am disabling and enabling the SPI. I am using the HAL_macro __HAL_SPI_ENABLE(&hspi1), but it is the same as setting and resetting the SPE bit.

During the transfer I am transferring 84 Byte, the temperature I am referring to is a float and it is located on Byte 4-7, so the 2 byte buffer you are writing about could not really have an effect, even if it is not flushed with the SPE bit.

You said it is an unorthodox approach, I am willing to change to any other approach, but actually I cannot think of any other approach, since as slave you never know when the master asks you something, so I can only think of having latest data available.

Hi @pflunzi​ ,

I wrote that because the usual way of communication is that the message length is known and the whole message is sent. Your previous description gave me an impression that some unsent data are left in the Tx buffer.

BR,

J

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Hi, no, I am sending and receiving 84 Bytes, then CS goes high and I disable SPI to flush buffers. When CS goes low I am enabling SPI, shortly after the transfer begins (a few µs). At the transfercomplete interrupt I am also disabling SPI. I still have no clue why so much old data (it is more than 2 Bytes) is send. Maybe I also should disable and enable DMA in the same places where I disable SPI. Since the DMA is in circular mode, it might be that after the SPI transfer it starts again to fill the buffer. But I thought the DMA should be somehow synced to the state of SPI.

Honestly I don't know how to get latest data and I don't know why my case should be so special. I am having changing data, and I want to send the latest via SPI. All I could think about might be a syncing mechanism, like before the master requests data via SPI, MOSI changes to a low level, then the data in the microcontroller is prepared, when data is prepared, MISO changes to low level. Then the master starts the normal SPI transfer.

Edit: I also tried to only use the DMA in normal mode or use the HAL_SPI_transmitreceive_IT()-function when CS is going down, but the transfer begins to early (unfortunately I cannot change the time between CS and first clock cycle). I find this quite surprising since those functions are quite short.