2019-04-23 07: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_D2
The 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 07:05 AM
It is not clear to us from the given information why you use 0x30001000 to setup the MPU region.
2019-04-24 08: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 04: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 05: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.