cancel
Showing results for 
Search instead for 
Did you mean: 

Setup LI-cache on STM32H753

Gpeti
Senior II

I'm playing with the L1-cache of STM32H753.

What I am trying to do is to provoke -on purpose- an inconsistency between the cache and the RAM as follows:

  • set up the SRAM region as write-through cacheable
  • enable the data cache
  • write something to a variable in RAM -> data will be written to both cache and RAM
  • disable the cache without invalidating it
  • write something else to the same variable -> only the RAM will be modified, not the cache
  • enable back the cache, again without invalidating it
  • read the RAM -> I expect to read the old value and not the new one, because at this point there should be a hit in the cache as the cache line should still be valid and it should still contain the old value?

 

Here is the code:

 

volatile uint32_t someDummyVariable ;
int main(void)
{
    MPU_Region_InitTypeDef MPU_InitStruct;
 
    HAL_Init();
 
    /* Configure the MPU attributes as Write-through for SRAM */
    HAL_MPU_Disable();
    MPU_InitStruct.Enable = MPU_REGION_ENABLE;
    MPU_InitStruct.BaseAddress = 0x20000000;
    MPU_InitStruct.Size = MPU_REGION_SIZE_32MB;
    MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;    // -> means write through ?
    MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
    MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER0;
    MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
    MPU_InitStruct.SubRegionDisable = 0x00;
    MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
 
    /* Configure the MPU attributes as WT for the Flash */
    MPU_InitStruct.Enable = MPU_REGION_ENABLE;
    MPU_InitStruct.BaseAddress = 0x08000000;
    MPU_InitStruct.Size = MPU_REGION_SIZE_16MB;
    MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
    MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
    MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER1;
    MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
    MPU_InitStruct.SubRegionDisable = 0x00;
    MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;  
    HAL_MPU_ConfigRegion(&MPU_InitStruct);  
 
    HAL_MPU_Enable(MPU_HARDFAULT_NMI);
 
 
    SCB_EnableDCache();
 
    // write something in a variable in RAM -> thanks to write-through attribute 
    // it will be copied to real RAM, not only to the cache
    someDummyVariable = 0x12345678;
 
    // disable cache without invalidating it
    SCB->CSSELR = 0U;                       /* select Level 1 data cache */
    __DSB();
    SCB->CCR &= ~(uint32_t)SCB_CCR_DC_Msk;  /* disable D-Cache */
    __DSB();
    __ISB();
 
    // write something else to RAM -> will NOT be written to cache
    someDummyVariable = 0xAAAAAAAA;
 
    // enable cache again (without invalidating or cleaning it)
    __DSB();
    SCB->CCR |=  (uint32_t)SCB_CCR_DC_Msk;  /* enable D-Cache */
    __DSB();
    __ISB();
 
    // now we should read the old value that is still in the cache
    if ( someDummyVariable != 0x12345678 )
    {
        __NOP();
    }
 

 

I compiled with Keil v5, -O0. The variable write is done through a STR (I mean: no weird CPU optimisation, as far as I understood).

 

I checked the MPU registers values, the address of the RAM variable.

 

Is there something wrong in the algorithm and/or in the code ?

 

3 REPLIES 3
berendi
Principal

I think that write-through mode does not imply that the data will be written to cache. This feature is called write allocate, and is apparently not available in write through mode.

You can try reading back the first value to load it in the cache.

someDummyVariable = 0x12345678;
someDummyVariable;

If that doesn't work, a DMA transfer would be a sure way to create a cache inconsistency.

Gpeti
Senior II

From this link:

write allocate policy allocates a cache line for either a read or write which misses in the cache (and so might more accurately be called a read-write cache allocate policy). For both memory reads which miss in the cache and memory writes which miss in the cache, a cache linefill is performed. This is typically used in combination with a write-back write policy on current ARM processors

Write policy

Write-through. With this policy writes are performed to both the cache and main memory.

Write-back. In this case, writes are performed only to the cache, and not to main memory.(When a write happens which updates the cache, but not main memory, the dirty bit is set. If the cache later evicts a cache line whose dirty bit is set (a dirty line), it writes the line out to main memory.)

Gpeti
Senior II

Good idea for DMA.