Skip to main content
MMarx.1
Associate II
August 24, 2026
Solved

STM32H7S3L8: MPU non-cacheable SRAM2 region prevents CPU writes

  • August 24, 2026
  • 2 replies
  • 76 views

Hi,

I am using an STM32H7S3L8 with D-Cache enabled and want to place DMA buffers in a dedicated non-cacheable SRAM region.

My linker script places the DMA section in SRAM2:

SRAMAHB  (rw)  : ORIGIN = 0x30000000, LENGTH = 16K
SRAM_DMA (xrw) : ORIGIN = 0x30004000, LENGTH = 16K

.dma_buffer (NOLOAD) :
{
. = ALIGN(32);
__dma_buffer_start__ = .;

KEEP(*(.dma_buffer))
KEEP(*(.dma_buffer*))

. = ALIGN(32);
__dma_buffer_end__ = .;
} > SRAM_DMA

The DMA buffer is correctly linked at 0x30004000.

I configured the MPU according to the non-cacheable DMA buffer strategy described in ST's article. The relevant configuration is:

 

static void MPU_Config(void)
{
MPU_Region_InitTypeDef MPU_InitStruct = {0};

/* Disables the MPU */
HAL_MPU_Disable();

/* Disables all MPU regions */
for(uint8_t i=0; i<__MPU_REGIONCOUNT; i++)
{
HAL_MPU_DisableRegion(i);
}

/** Initializes and configures the Region and the memory to be protected
*/
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.BaseAddress = 0x0;
MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
MPU_InitStruct.SubRegionDisable = 0x87;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;

HAL_MPU_ConfigRegion(&MPU_InitStruct);

/** Initializes and configures the Region and the memory to be protected
*/
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.BaseAddress = 0x70000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_32MB;
MPU_InitStruct.SubRegionDisable = 0x0;
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_CACHEABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;

HAL_MPU_ConfigRegion(&MPU_InitStruct);

/** Initializes and configures the Region and the memory to be protected
*/
MPU_InitStruct.Number = MPU_REGION_NUMBER7;
MPU_InitStruct.BaseAddress = 0x30004000;
MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;

HAL_MPU_ConfigRegion(&MPU_InitStruct);
/* Enables the MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

}

Immediately after initialization I tested SRAM1 and SRAM2 directly:

volatile uint32_t *p1 = (volatile uint32_t *)0x30000000;
volatile uint32_t *p2 = (volatile uint32_t *)0x30004000;

*p1 = 0x11223344;
*p2 = 0x55667788;

// __DSB();

volatile uint32_t a = *p1;
volatile uint32_t b = *p2;

The result is:

a = 0x11223344   // OK
b = 0x00000000 // unexpected

If I completely disable the MPU, both accesses work and b == 0x55667788.

I also tried disabling all other MPU regions and leaving only region 7 enabled, with the same result: SRAM1 works but SRAM2 reads back as zero.

The MPU registers for region 7 look correct:

RBAR = 0x30004007
RASR = 0x1300001b

Decoded:

Base   = 0x30004000
Region = 7
Size = 16 KB
AP = 3 (Full Access)
TEX = 0
S = 0
C = 0
B = 0

I have also tested TEX = 1 and different shareable settings without success.

Since 0x30004000 works correctly when the MPU is disabled, but becomes unwritable/read-as-zero when the MPU region is enabled, I suspect I am missing an STM32H7S3-specific MPU/SRAM2 requirement.

Is there anything special required to configure SRAM2 (0x30004000) as non-cacheable DMA memory on STM32H7S3L8?

Thanks!

Best answer by MMarx.1

I tried it, but unfortunately it didn’t work. 

Because I did “try and error” for 2 days already, I now switch to manual Clean/Invalidate the DCache. This works as expected. I guess I did a configuration failure somewhere.

 

Thank you for your support.

2 replies

emilyrose
Visitor II
August 25, 2026

I noticed one thing in your MPU setup. You have SubRegionDisable = 0x87, which disables subregions 0, 1, 2 and 7. Since you're testing a write at 0x30004000, that address falls into subregion 0.

Could you try changing it to 0x00 just for the test? If the write starts working, then the problem is likely the subregion mask rather than SRAM2 itself.

If that works, you can then adjust the mask based on the exact SRAM2 range you want to use.

MMarx.1
MMarx.1AuthorBest answer
Associate II
August 25, 2026

I tried it, but unfortunately it didn’t work. 

Because I did “try and error” for 2 days already, I now switch to manual Clean/Invalidate the DCache. This works as expected. I guess I did a configuration failure somewhere.

 

Thank you for your support.