2019-04-23 7:28 AM
This project uses STM32Cube_FW_H7_V1.3.2.
On STM32H7 I'm using DMA for SPI transfer. I use SPI1 and SPI4, both in D2 domain, together with RAM_D2.
In the linker file I added:
.dma_buffer :
{
. = ALIGN(4);
*(.dma_buffer)
} >RAM_D2The buffer is declared like:
uint8_t buf[2048] __attribute__ ((section(".dma_buffer"))) __attribute__ ((aligned (32)));Transmitting using DMA works:
/* Mem-to-Peri */
SCB_CleanDCache_by_Addr((uint32_t*)(((uint32_t)buf) & ~(uint32_t)0x1F), len + 32);
errorcode = HAL_SPI_Transmit_DMA(interface->hspi, (uint8_t*) buf, len);Receiving data from SPI without using DMA also works, I get valid data in.
But if I use DMA, the buffer gets filled with 0's after cache invalidation:
/* Peri-to-Mem */
errorcode = HAL_SPI_Receive_DMA(interface->hspi, (uint8_t*) buf, len);
/* Some code to wait for the transfer to be finished */
wait_dma_rx_ended(interface);
SCB_InvalidateDCache_by_Addr((uint32_t*)(((uint32_t)buf) & ~(uint32_t)0x1F), ((len+31)/32)*32);I also configured the MPU, but I think it is not needed when using the cache maintenance functions.
void MPU_Config(void)
{
MPU_Region_InitTypeDef MPU_InitStruct = { 0 };
/* Disable the MPU */
HAL_MPU_Disable();
/* Initialize and configure the Region and the memory to be protected */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.BaseAddress = 0x30001000;
MPU_InitStruct.Size = MPU_REGION_SIZE_8KB;
MPU_InitStruct.SubRegionDisable = 0x0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/* Enable the MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}My SPI and DMA in initialized like this:
So the problem is I do not receive valid data when using DMA, but I do get valid data when not using DMA. So I think the SPI is configured correctly for the device.
Using DMA, if I don't invalidate the cache, I see the same data in the buffer as before calling HAL_SPI_Receive_DMA, which is expected. But after cache invalidation (calling SCB_InvalidateDCache_by_Addr), I do read all 0's, instead of valid data, which is not expected.
Using DMA transmit SPI works just fine, as does SPI receive without DMA.
What can I do to troubleshoot the problem further?
Has anybody seen this behavior on STM32H7 MCU's?
Once the problem is solved, I can explain which change worked, and provide the updated code on github to help others:
https://github.com/bkht/KSZ8851SNL_no_LwIP
Thank in advance for help!
2019-04-24 7:05 AM
It is not clear to us from the given information why you use 0x30001000 to setup the MPU region.
2019-04-24 8:41 AM
Apparently a small 8KB window. Thought you needed equivalent granularity/alignment. Not sure a 4KB alignment on an 8KB window is super productive.
The test would probably be better is applied more broadly, and the transfer address was actually displayed/validated as falling within the window.
2019-04-24 10:26 AM
Thank you. I tried 0x30000000 too, I use cache maintenance functions, so the MPU configuration would likely not be required at the moment. But both locations are in RAM_D2, so I didn't see a problem with that. What problem do you see in it? It is not clear enough to me, to understand it.
Using HAL_SPI_Receive, it receives correct data, I do not have the D Cache problems then, because the MCU handles the traffic, instead of the DMA.
Using HAL_SPI_Receive_DMA gives no error, it generates the expected a SPI RX DMA interrupt, but followed by SCB_InvalidateDCache_by_Addr it received all 0x00's. (buffer located at RAM_D2 0x30000000).
This project uses STM32Cube_FW_H7_V1.3.2.
There is also erata for SPI, maybe this affects me too:
2.12.1 Spurious DMA Rx transaction after simplex Tx traffic
So I can try the workaround, resetting the SPI peripheral.
2019-05-01 11:28 PM
Thanks, I noticed it. I changed it back to 0x30000000, but it seems not the solution, both regions are located in RAM_D2, or am I missing something?
2019-06-28 4:38 AM
Hi Jack,
Did you find any solution for this problem?
We are facing same problem with SPI+DMA on stm32h7.
calling HAL_SPI_Receive_DMA gives all 0's after calling HAL_SPI_Transmit_DMA.
Thanks in Advance.
2019-09-26 5:05 PM
Hi,
I also have the same problem. Some solution? ST guys, a little help please?
Please ST, put the F7 SPI in newer H7s. H7 SPI is ridiculous. It is complex, slow and doesn't works with DMA.
We’re moving the ST Community to a new platform to give you a better and more reliable community experience.