Skip to main content
Associate III
August 4, 2022
Question

Creating a non cacheable area of RAM on STM32H7A (B)

  • August 4, 2022
  • 6 replies
  • 3274 views

Using the linker script - How would I assign an area of AXI SRAM1 that is not cacheable by DCache? I am currently having problems with DMA transfers to the PWM peripheral when DCache is enabled (I think this is because I am sending 8bits to the HAL_TIM_PWM_Start_DMA and DCache likes aligned WORDS (I believe...)). I have tried Invalidating the cache - which doesn't yield any positive results and it seems the DMA/Peripheral cannot address the DTCRAM banks (AHB_SRAM 1 + ") which are uncacheable.

Is it possible to assign an area of AXI RAM, using the linker script and/or the startup script, to be uncachable?

A good starting point seems to be suggested by another ARM mcu manufacturer ...

http://ww1.microchip.com/downloads/en/DeviceDoc/How_to_Create_Non-Cacheabl_%20Memory_Region_on_Cortex-M7_(SAME70)_MCU_Using_MPLAB_Harmonyv3_DS90003260A.pdf

but are there uncachable areas of the AXI RAM?

The same could be asked of non cacheable FLASH as looking at the STM32H7B block diagram I see that it is connected to the same AXI Bus Matrix

In addition I may have a look at the MPU but it seems incredible hard to configure...

Any advice is most welcome...

This topic has been closed for replies.

6 replies

Associate III
August 4, 2022

I've tried the MPU with the following

MPU_InitStruct.Enable = MPU_REGION_ENABLE;

 MPU_InitStruct.Number = MPU_REGION_NUMBER0;

 MPU_InitStruct.BaseAddress = 0x240C00000;

 MPU_InitStruct.Size = MPU_REGION_SIZE_256KB;

 MPU_InitStruct.SubRegionDisable = 0x87;

 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;

and the results are somewhat improved but how to you allocated variables to specific memory addresses?

Tesla DeLorean
Guru
August 4, 2022

If you're sending stuff (ie MCU->MEM->DMA->TIM), Invalidating the cache is entirely the WRONG strategy. CLEAN == FLUSH, INVALIDATE == NUKE FROM ORBIT, the latter will do so much collateral damage, it'll burn what's in the write buffers, and whatever is destined for memory.

>>and the results are somewhat improved but how to you allocated variables to specific memory addresses?

You attribute variables specifying a named section they dwell in.The linker is then responsible for honouring this.

For things you don't even tell the linker about, you can just use pointers. Complex things, structures, with pointers.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Associate III
August 4, 2022

In addition to the MPU settings is this a step in the right direction?>??

RAM (xrw) : ORIGIN = 0x24000000, LENGTH = 768K
 RAM_NOCACHE (xrw) : ORIGIN = 0x240C0000, LENGTH = 256K
 
 .DATA_RAM_NOCACHE (NOLOAD) :
 {
 } >RAM_NOCACHE

and

buff[SIZE] __attribute__((section (".DATA_RAM_NOCACHE"))) ;

Associate III
August 4, 2022

Would I be right in thinking that the above comment does not work for pointers i.e the linker needs to specify something like *(.DATA_RAM_NOCACHE*) . It's just that I'm getting random silly addresses when storing pointers to this area of RAM. If that is correct would you also need some initialization in the startup script?

Associate III
August 4, 2022

I think I've done it!!!

.DATA_RAM_NOCACHE :
 { . = ALIGN(4);
 _snocachedata = .; 
 *(.DATA_RAM_NOCACHE) 
 *(.DATA_RAM_NOCACHE*) 
 . = ALIGN(4); 
 _enocachedata = .; 
 } >RAM_NOCACHE
 
 _sinocachedata = LOADADDR(.DATA_RAM_NOCACHE);

in the linker

.word _sinocachedata
/* start address for the .nocache section. defined in linker script */
.word _snocachedata
/* end address for the .nocache section. defined in linker script */
.word _enocachedata
 
 ldr r0, =_snocachedata
 ldr r1, =_enocachedata
 ldr r2, =_sinocachedata
 movs r3, #0
 b LoopCopyDataInit

 This in conjunction with the MPU seems to yield the expected result :)

Associate III
August 4, 2022

A new problem however. The DMA will have to acquire data from FLASH in the final solution... Can MPU and the linker start up setup be used for this area?

Disregard this - the pointer to the const array was the important part that needed to be kept out of cache. The data itself seems to fine left as is