We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
I'm trying to make one region of SRAM non cacheable for DMA buffers. But what I have found is that when I do that, the first atomic operation bus faults (eg RTOS mutex).
Here's an example where I made all of SRAM normal memory non cacheable (TEX=1 B=0 C=0 S=1) for testing:
// all SRAM non cacheable MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER0; MPU_InitStruct.BaseAddress = 0x20000000; MPU_InitStruct.Size = MPU_REGION_SIZE_1MB; MPU_InitStruct.SubRegionDisable = 0x00; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
It does not matter what the atomic operation is; it faults on the `ldrex` instruction. I've checked alignment and the access is on a 32 bit boundary. Actual memory location can be in DTCM or SRAM1 and it will fault in both.
If I change the MPU region to 'normal memory non cacheable non sharable (TEX=1 B=0 C=0 S=0)' then it will not fault but it appears that caching is still enabled for that memory region.
The manual states:" LDREX and STREX operations must be performed only on memory with the Normal memory attribute. "
Check also the notes on "shareable" attribute!
My understanding is that both (TEX=1 B=0 C=0 S=1) and (TEX=1 B=0 C=0 S=0) are normal memory types.
I'll look into this further as the bus fault would indicate that I am wrong.
Robert Grey said:Actual memory location can be in DTCM
DMA will not work with DTCM!
DMA works just fine using DTCM memory via the AHBS bus. However I have the SRAM divided into DTCM and SRAM1/SRAM2 memory and have placed the DMA buffers in SRAM1/SRAM2. My problem is that I cannot get the MPU to disable caching on that memory.
Which chip is it? Maybe it helps to clear thing. M7 is not M7.
Sounds like an STM chip. Anyway, I do set the DEVICE attribute for non-cacheable regions. And of course keep this region at minimum size for the DMA only.
Robert Grey said:It does not matter what the atomic operation is; it faults on the `ldrex` instruction.
Ok, I can confirm the behavior for an STM32H7.
On an i.MXRT1064 (also CM7) it works with shared attribute set. But this chip is designed for multi-core (1171 has CM7 and CM4). Which might be the difference. Shared attribute makes no sense on STM32H7.
Sadly, this also seems to be a problem on the dual-core STM32H755. Mapping an SRAM bank as Normal, Noncacheable, Shareable memory causes LDREX to bus fault on the Cortex-M7 core. Interestingly, LDREX does _not_ fault on the Cortex-M4 core.
From https://www.st.com/resource/en/application_note/dm00272912-managing-memory-protection-unit-in-stm32-mcus-stmicroelectronics.pdf (emphasis mine):
The S field is for a shareable memory region: the memory system provides data synchronization between bus masters in a system with multiple bus masters, for example, a processor with a DMA controller. A strongly-ordered memory is always shareable. If multiple bus masters can access a non-shareable memory region, the software must ensure the data coherency between the bus masters. The STM32F7 Series and STM32H7 Series do not support hardware coherency. The S field is equivalent to non-cacheable memory.