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

STM32H7S3L8: MPU non-cacheable SRAM2 region prevents CPU writes

  • August 24, 2026
  • 0 replies
  • 11 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!