cancel
Showing results for 
Search instead for 
Did you mean: 

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

Claydonkey
Senior

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...

6 REPLIES 6
Claydonkey
Senior

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?

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 Venmo
Up vote any posts that you find helpful, it shows what's working..
Claydonkey
Senior

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")))  ;

Claydonkey
Senior

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?

Claydonkey
Senior

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 🙂

Claydonkey
Senior

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