Skip to main content
Stou.1
Associate
July 1, 2021
Solved

STM32H7 - Using ADC with DMA is corrupting memory.

I'm having trouble using ADC with DMA. It is working correct, I'm getting the correct result. But DMA is corrupting another data which is not related with DMA in runtime. I'm also using Ethernet, because of it, I can not disable D-Cache.

I do my Ethernet, DMA, MPU configurations according to the following article (without RTOS)

https://community.st.com/s/article/How-to-create-project-for-STM32H7-with-Ethernet-and-LwIP-stack-working

And also I read

https://community.st.com/s/article/FAQ-DMA-is-not-working-on-STM32H7-devices

But like I say, I do not want to disable d-cache.

I use example in STM32Cube repository to use ADC with DMA:

void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc)
{
	if(hadc == &hadc1)
	{
		/* Invalidate Data Cache to get the updated content of the SRAM on the first half of the ADC converted data buffer: 32 bytes */
		SCB_InvalidateDCache_by_Addr((uint32_t *) &adc1.m_rawResult[0], 7);
	}
	if(hadc == &hadc3)
	{
		/* Invalidate Data Cache to get the updated content of the SRAM on the first half of the ADC converted data buffer: 32 bytes */
		SCB_InvalidateDCache_by_Addr((uint32_t *) &adc2.m_rawResult[0], 8);
	}
}
 
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
	if(hadc == &hadc1)
	{
		/* Invalidate Data Cache to get the updated content of the SRAM on the first half of the ADC converted data buffer: 32 bytes */
		SCB_InvalidateDCache_by_Addr((uint32_t *) &adc1.m_rawResult[4], 7);
	}
	if(hadc == &hadc3)
	{
		/* Invalidate Data Cache to get the updated content of the SRAM on the first half of the ADC converted data buffer: 32 bytes */
		SCB_InvalidateDCache_by_Addr((uint32_t *) &adc2.m_rawResult[4], 8);
	}
}

Thank you!

This topic has been closed for replies.
TDK
TDKBest answer
July 1, 2021

Put the buffer in its own array and use the aligned directive:

uint32_t aligned_array[16] __attribute__ ((aligned (32)));

You can verify in the map file that it gets aligned to a 32-byte boundary

 0x00000000200000e0 aligned_array

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

7 replies

TDK
July 1, 2021

Is adc1.m_rawResult aligned to 32-byte cache boundary and is there nothing else within that 32-bytes?

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

Note that the address you pass to SCB_InvalidateDCache_by_Addr needs to be aligned, which yours can't be (since you pass addresses 16 bytes away from each other.

/**
 \brief D-Cache Invalidate by address
 \details Invalidates D-Cache for the given address
 \param[in] addr address (aligned to 32-byte boundary)
 \param[in] dsize size of memory block (in number of bytes)
*/
__STATIC_INLINE void SCB_InvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize)

"If you feel a post has answered your question, please click ""Accept as Solution""."
Stou.1
Stou.1Author
Associate
July 1, 2021

Thanks a lot for your answer. I'm unexperienced to use of cache. How can I align it to 32-byte boundary. I was just define it as unsigned short m_rawResult[CHANNEL_SIZE];

TDK
TDKBest answer
July 1, 2021

Put the buffer in its own array and use the aligned directive:

uint32_t aligned_array[16] __attribute__ ((aligned (32)));

You can verify in the map file that it gets aligned to a 32-byte boundary

 0x00000000200000e0 aligned_array

"If you feel a post has answered your question, please click ""Accept as Solution""."
Stou.1
Stou.1Author
Associate
July 1, 2021

Thank you so much :) But I missed a point. You said 'since you pass addresses 16 bytes away from each other' why? May you suggest from which document/source can I access the information about this?

TDK
July 1, 2021

> You said 'since you pass addresses 16 bytes away from each other' why?

Two of your lines are as follows:

SCB_InvalidateDCache_by_Addr((uint32_t *) &adc2.m_rawResult[0], 8);
...
SCB_InvalidateDCache_by_Addr((uint32_t *) &adc2.m_rawResult[4], 8);

Since m_rawResult is an array of uint32_t (4 bytes each), these two addresses are 4*4=16 bytes away from each other. Thus, they cannot both be aligned to a 32-byte boundary.

If your buffer is exactly 32 bytes, you could invalidate the entire buffer on each call.

"If you feel a post has answered your question, please click ""Accept as Solution""."
Stou.1
Stou.1Author
Associate
July 1, 2021

It was so clear. I'm very thankful.