Last edited 2 weeks ago

How to add ICache and Dcache support to your applications

Applicable for STM32MP21x lines, STM32MP23x lines, STM32MP25x lines

This article aims to:

  • describe the process of enabling Instruction Cache (ICache) and Data Cache (DCache) on the Arm® Cortex®-M33 processor.
  • explain how to configure the Memory Protection Unit (MPU) to support caching.
  • provide example code demonstrating these configurations.

1. Prerequisites[edit | edit source]

STM32MPU projects should have been previously generated thanks to STM32CubeMX. To know how to generate project via STM32CubeMX , refer to How_to_create_STM32MPU_projects_with_STM32CubeMX#Create_an_STM32MP2_series_project.

Then in the main.c file generated in the M33 folder, you must update the function with configuration given in chapters below.

2. Introduction to cache and memory protection unit (MPU)[edit | edit source]

Caches are high-speed memories that sit between the processor and main memory. They contain a copy of the data, present in main memory locations. This copy enables the processor to run applications at a faster speed by reducing the reading and writing time.

The Cortex®-M33 processor is built on the Armv8-M architecture and supports the following interfaces:

  • Code AHB (C-AHB) interface
  • System AHB (S-AHB) interface

A 16-Kbyte instruction cache (ICACHE) and a 16-Kbyte data cache (DCACHE) are integrated on the C-AHB and S-AHB interfaces, respectively, as illustrated in the following figure. For more information, refer to STM32MP25 reference manual.

How to add ICache and Dcache support to your applications 1751274995382.png

  • Icache: The instruction cache (ICACHE) is introduced on the C-AHB code bus of the Arm® Cortex®-M33 processor, to improve performance when fetching instructions and data from internal and external memories.
  • Dcache: The data cache (DCACHE) is introduced on S-AHB system bus of the Cortex®-M33 processor to improve the performance of data traffic to/from external memories.
  • MPU: The Memory Protection Unit (MPU) is a configurable component that enables privileged software to set memory access permissions. Using the MPU, privileged software can define multiple memory regions and assign specific access permissions and memory attributes to each region. These memory attributes determine the ordering and merging behavior, as well as caching and buffering properties for each region, depending on the processor’s implementation.

3. List of parameters used to configure the Memory Protection Unit (MPU)[edit | edit source]

3.1. Cache Attribute[edit | edit source]

These attributes inform the external memory system about the caching policy for the memory region (e.g., whether the region is cacheable or non-cacheable).

  • Inner Cache Attributes: The inner cache attributes determine how the processor's integrated caches (e.g., L1 and L2) handle the memory request.
  • Outer Cache Attributes: If the memory request goes beyond the integrated caches (e.g., to an external L3 cache or DDR memory)

3.2. Region Number[edit | edit source]

Identifies the specific MPU region to configure.

3.3. Base Address[edit | edit source]

The starting address of the memory region.

3.4. Limit Address[edit | edit source]

The end address of the memory region.

3.5. Access Permissions[edit | edit source]

Regions have independent read/write access permissions for privileged and unprivileged code.

3.6. Memory Attributes[edit | edit source]

Specifies cacheability, bufferability, and shareability.

3.7. Enable/Disable[edit | edit source]

Indicates whether the region is active.

3.8. Execute Never (XN) Attribute[edit | edit source]

Prevents code execution from the region if set.

4. Use cases[edit | edit source]

In the STM32MP2xx series, both Arm® Cortex®-A35 and Arm® Cortex®-M33 processors are present. The system boots using the Arm® Cortex®-A35 core, and then application code can be executed on the Arm® Cortex®-M33 core. Here, we provide examples specifically aimed at accessing and utilizing DDR memory from the Arm® Cortex®-M33. processor.

4.1. ICACHE MPU configuration[edit | edit source]

This configuration is typically used to define a code region (such as Flash memory) that is executable and read-only.

The MPU configuration itself is optional.
The processor can run using only the default memory map. However, defining this MPU region improves robustness and security by:

  • Enforcing read‑only access (no accidental writes to the program image).
  • Explicitly allowing execution only from this region.
  • Clearly separating code (executable, RO) from data (usually non‑executable, RW).


/* Configure region 0: Normal, Non-Shareable, RO, Any Privilege Level)*/

/* Region start = 0x0 Region end = 0x007FFFFF */

/* outer Cachable, write back, read and write allocate */
   MPU_Attributes_InitStruct.Attributes = OUTER(MPU_WRITE_BACK | MPU_NON_TRANSIENT | MPU_RW_ALLOCATE);
   MPU_Attributes_InitStruct.Number     = MPU_ATTRIBUTES_NUMBER0;
   HAL_MPU_ConfigMemoryAttributes(&MPU_Attributes_InitStruct);

   MPU_InitStruct.AccessPermission = MPU_REGION_ALL_RO;
   MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
   MPU_InitStruct.AttributesIndex  = MPU_ATTRIBUTES_NUMBER0;
   MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;
   MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
   MPU_InitStruct.BaseAddress      = 0x00000000;
   MPU_InitStruct.LimitAddress     = 0x007FFFFF;c
   MPU_InitStruct.Number           = MPU_REGION_NUMBER0;
   HAL_MPU_ConfigRegion(&MPU_InitStruct);

Summary of properties:

  • Address range: 0x00000000 – 0x007FFFFF, which will remap to 0x80100000-0x808FFFFF
  • Memory type: Normal
  • Cacheability: Cacheable
  • Access: Read Only, privileged and unprivileged
  • Execution: Enable (DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE).(It is configured to allow instruction fetch from it.)
  • Shareability: Non‑shareable (MPU_ACCESS_NOT_SHAREABLE)

4.2. ICACHE Init[edit | edit source]

Enabling the ICACHE in the STM32MP2 project requires configuring a remap region whenever the code is fetched from external memory (for example DDR or external RAM), so that instruction fetches are correctly routed through the ICACHE to that external target.

  ICACHE_RegionConfigTypeDef pRegionConfig = {0};
  pRegionConfig.TrafficRoute    = ICACHE_MASTER2_PORT;
  pRegionConfig.OutputBurstType = ICACHE_OUTPUT_BURST_INCR;
  pRegionConfig.Size            = ICACHE_REGIONSIZE_2MB;
  pRegionConfig.BaseAddress     = 0x00000000;
  pRegionConfig.RemapAddress    = 0x80100000;

  if (HAL_ICACHE_EnableRemapRegion(ICACHE_REGION_0, &pRegionConfig) != HAL_OK)
  {
  	 Error_Handler();
  }

  if (HAL_ICACHE_Enable() != HAL_OK)
  {
	  Error_Handler();
  }

4.3. DCACHE MPU Configuration for data section[edit | edit source]

This configuration defines a Normal, cacheable data region in DDR, intended purely for data (no code execution). It is non‑executable and non‑shareable, and allows read/write access at any privilege level.

The MPU setup for this DCACHE region is optional: the system can run without it, but enabling it improves robustness and security by:

  • Ensuring that no code can be executed from this DDR data area (mitigating code‑injection attacks).
  • Explicitly constraining access attributes (RW only, Normal memory, cacheable).

/* Configure region 1: Normal, Non-Shareable, RW, Any Privilege Level)*/

/* Region start = 0x80A00000 Region end = 0x80DFFFFF */

   MPU_InitStruct.AccessPermission = MPU_REGION_ALL_RW;
   MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
   MPU_InitStruct.AttributesIndex  = MPU_ATTRIBUTES_NUMBER0;
   MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_DISABLE;
   MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
   MPU_InitStruct.BaseAddress      = 0x80A00000;
   MPU_InitStruct.LimitAddress     = 0x80DFFFFF;
   MPU_InitStruct.Number           = MPU_REGION_NUMBER1;
   HAL_MPU_ConfigRegion(&MPU_InitStruct);

Summary of properties:

  • Address range: 0x80A00000 – 0x80DFFFFF (DDR data window)
  • Memory type: Normal (configured as cacheable)
  • Access: Read/Write, privileged and unprivileged
  • Execution: Disabled (DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE).This configuration is used to prevent certain types of malicious attack from taking control over program execution byinserting their code into memory, for example the Stack.
  • Shareability: Non‑shareable (MPU_ACCESS_NOT_SHAREABLE)

4.4. DCACHE MPU Configuration for shared memory section (accessible for both core A35 and M33)[edit | edit source]

This setup is typically used to define a non-cacheable, shareable memory region for data (not code execution), such as a section of DDR memory used by IPC, RPMsg.

/* Configure region 0: Normal, Outer-Shareable, RW, Any Privilege Level)*/

/* Region start = 0x81200000 Region end = 0x812FFFFF */

     /* outer Non-Cacheable */
   MPU_Attributes_InitStruct.Attributes = OUTER(MPU_NOT_CACHEABLE);
   MPU_Attributes_InitStruct.Number     = MPU_ATTRIBUTES_NUMBER1;
   HAL_MPU_ConfigMemoryAttributes(&MPU_Attributes_InitStruct);

   MPU_InitStruct.AccessPermission = MPU_REGION_ALL_RW;
   MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
   MPU_InitStruct.AttributesIndex  = MPU_ATTRIBUTES_NUMBER1;
   MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_DISABLE;
   MPU_InitStruct.IsShareable      = MPU_ACCESS_OUTER_SHAREABLE;
   MPU_InitStruct.BaseAddress      = 0x81200000;
   MPU_InitStruct.LimitAddress     = 0x812FFFFF;
   MPU_InitStruct.Number           = MPU_REGION_NUMBER1;
   HAL_MPU_ConfigRegion(&MPU_InitStruct);

Summary of properties:

  • Address range: 0x81200000 – 0x812FFFFF
  • Memory type: Normal
  • Cacheability: Non‑cacheable
  • Access: Read/Write, privileged and unprivileged
  • Execution: Disabled (XN)
  • Shareability: Outer‑shareable

4.5. DCACHE Init[edit | edit source]

This code initializes the data cache (DCACHE) peripheral and configures its read burst behavior.

  hdcache.Instance           = DCACHE;
  hdcache.Init.ReadBurstType = DCACHE_READ_BURST_WRAP;

 if (HAL_DCACHE_Init(&hdcache) != HAL_OK)
 {
   Error_Handler();
 }
Info white.png Information
Configuring an MPU region with a cacheable memory type does not mean that the data must be cached, but only indicates to the hardware that it might be cached. If a region is defined as cacheable, software takes responsibility for performing any necessary cache maintenance operations.

5. References[edit | edit source]