2021-07-01 12:26 AM
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)
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!
Solved! Go to Solution.
2021-07-01 07:12 AM
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
2021-07-01 06:47 AM
Is adc1.m_rawResult aligned to 32-byte cache boundary and is there nothing else within that 32-bytes?
2021-07-01 06:49 AM
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)
2021-07-01 07:04 AM
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];
2021-07-01 07:12 AM
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
2021-07-01 07:27 AM
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?
2021-07-01 07:46 AM
> 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.
2021-07-01 12:28 PM
It was so clear. I'm very thankful.