cancel
Showing results for 
Search instead for 
Did you mean: 

Speculative access on Cortex®-M7 and Cortex®-M85 based STM32: A practical guide

Abdelhamid GHITH
ST Employee

Introduction

Modern processors often make speculative accesses to improve performance. In simple terms, the CPU may start reading instructions or data before it is certain they will be needed. This helps reduce delays and keeps the system running efficiently.
This article describes the speculative access on Cortex®-M7 and Cortex®-M85 and how to prevent it by software to avoid any unwanted behavior.

1. Speculative access behavior

The Cortex®-M7 and Cortex®-M85 implement a speculative mechanism. For most applications, speculation is beneficial to improve the core performance. However, in some applications, it can also create side effects if memory or peripherals are not configured carefully.

A key principle to remember is “System designers must not assume that the scope of speculation is fixed or definitively specified”. That means you should not rely on speculation behaving in a predictable way unless the memory system is explicitly protected against it.

If you are new to this topic, here is the basic idea:

  • The CPU tries to predict what it may need next.
  • It may access memory even before an instruction explicitly asks for it.
  • It may access memory even not explicitly accessed by the software.
  • These accesses do not always mean that the CPU uses the data.

This behavior can happen for:

  • Instruction fetches.
  • Data reads.
  • Cache linefills.
  • TCM memory (ITCM/DTCM) accesses.

Examples of speculative accesses

  • Instruction fetches can be initiated to any normal, executable memory address.
  • Data reads can be initiated to any normal memory type, read/write, or read-only memory address (even if the cache is disabled).
  • Cache linefills can be initiated to any cacheable memory address.
  • TCM reads can be initiated on any of the TCM interfaces.

In practice, this means that the CPU may touch memory locations that your code has not intentionally read yet.

2. When speculation does not happen

There are important exceptions where speculative read transactions are blocked:

  • Speculative instruction fetches on AXI are never made to memory addresses in an execute-never region.
  • Speculative data cache linefills on AXI are never made to noncacheable memory addresses.
  • Speculative data reads and speculative cache linefills are never made to device memory type addresses.
  • Speculative reads are never made on the peripheral AHB port.
  • Speculative writes are never made.

With the right memory attributes, you can reduce or prevent unwanted behavior.

3. Why it matters for application developers

Speculative access can affect system behavior if they reach memory or peripherals that are not prepared for early or unintended access. For example, it can create issues if memory regions contain:

  • Uninitialized RAM.
  • Sensitive peripherals.
  • Nonclocked hardware blocks.
  • Regions that should never be accessed early.
  • External memories with long wait states.

Because speculative access may happen unexpectedly, the system may show unwanted behavior even when the software appears to be correct.

Typical side effects and symptoms

The speculative access mechanism was introduced by Arm to enhance the core performance. However, it presents some side effects.

  • Sporadic ECC errors from noninitialized memory interfaces such as (TCM SRAM, AXI SRAM, or flash word with invalid ECC).
  • CPU may stall when accessing flash memory during erase or when accessing unconfigured peripherals: accesses to nonclocked peripherals such as external memory interfaces (XSPI or FMC etc.) when the kernel clock is disabled (PLLs or HSE disabled). 
  • Performance loss on external memories, because speculative reads can hit memory banks with large wait states (where the uninitialized memory interface timings are set to the highest by default after the MCU reset). One of the typical observed symptoms for performance loss is when the LCD is randomly flickering.

Unfortunately, there is no simple bit to set in the Cortex®-M that disables speculative access but the unwanted behavior can be prevented with the right initialization and MPU configuration.

4. How to protect against speculative access

Listed below are the main protective strategies. 

4.1 TCM regions and speculation

TCM regions are always treated as normal memory type and are therefore always subject to speculation. This has an important consequence: if TCM contents are not initialized, speculative access may trigger sporadic ECC errors. The recommended action is to initialize these memories (despite not being used by the application) before enabling the ECC errors reporting feature.

4.2 Other memory regions and speculation

For memory regions that are mapped on AXIM interface (not mapped on TCM) follow the recommendation below.

4.2.1 Protect against CPU speculation

A practical recommendation if there are memory regions that are not mapped to TCM and should not be speculatively accessed (like AXI memory-mapped regions). Arm recommends configuring them through the MPU as:

  • Device (or strongly-ordered if available) and mark them execute-never

This is one of the most effective ways to protect special regions.

4.2.2 Protect read sensitive devices: Use MPU attributes correctly

Memory regions marked as noncacheable/normal memory type must not be used to access read-sensitive peripherals, such as LCD, FPGA, FIFOs on external memory interfaces like FMC or XSPI.

Because read transactions to these regions may be repeated if the originating load instruction is interrupted. For peripherals where repeated read has a side effect, this can cause incorrect behavior.

Warning! Noncacheable normal memory should not be used with write-sensitive peripherals (as write can be repeated).

5. STM32CubeMX default MPU configuration

5.1 Configuring Cortex®-M7 with STM32CubeMX

When starting a project in STM32CubeMX with a product having Cortex®-M7 core, for example STM32H7xx or STM32F7xx, the tool proposes and recommends to the user to configure the MPU unit. This is to prevent any speculative access to the uninitialized external memories as shown in figure 1.

Figure 1. CubeMX pop-up for MPU configuration

enable_mpu.png

If the user clicks yes, STM32CubeMX generates the MPU_Config() function, relative to MPU configuration, in the main.c file. It generates in fact a background MPU configuration.

The generated code is as following:

  MPU_InitStruct.Enable = MPU_REGION_ENABLE;
  MPU_InitStruct.Number = MPU_REGION_NUMBER0;
  MPU_InitStruct.BaseAddress = 0x0;
  MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;  /* For the full memory range */
  MPU_InitStruct.SubRegionDisable = 0x87;   /* Except the internal memory address space */
  MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS; /* Disable any access to that memory space */
  MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; /* Disable any instruction fetch from that memory space */
  /* The next four lines: make that region attribute as strongly order */ 
  MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;  
  MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
  MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
  MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;

5.1.1 Explanation

Table 1 below shows the default memory attributes of the Cortex®-M7.

Table 1. The default memory attributes of the Cortex®-M7

1.png

The “External RAM” (0x6000 0000 – 0x9FFF FFFF) memory region is critical, since it is by default normal memory type and executable (XN=N). So, the Cortex®-M7 may perform speculative reads to this area, even when there is no external memory connected.

The idea is to create a safe background region (region 0), where memory the attributes of the “External RAM” memory region are changed to strongly-order to prevent any speculative access to that region.

This MPU configuration makes 4 GB (the total memory address range seen by the core) not accessible except subregions set to 1 in MPU_InitStruct.SubRegionDisable structure member.

Table 2. Memory regions to deactivate the access for the CPU with MPU background configuration

2.png

 

The SubRegionDisable means do not apply the MPU setting to the subregions having bits set to 1. In a given MPU configuration, a region is divided into 8 subregions of equal size. If you examine the default Arm MPU memory map covering the full 4 GB address space, notice that it is split into eight 512 MB address ranges (see Table 2).

As a result, four 512 MB subregions are selected by this MPU configuration over the range 0x6000 0000 to 0xDFFF FFFF (marked with yellow in table 2). It corresponds to the external memory interfaces such as FMC, QSPI, OSPI, and others.

MPU_InitStruct.SubRegionDisable = 0x87 = 0b1000 0111 means each bit set to 1. Do not apply the current MPU config to that subregion. Refer to Table 3 of the subregion’s summary.

Table 3. The subregion disable value to be set

mALLEm_3-1778072344937.png

If the application needs an external memory to be used, the user must configure and enable a new MPU region to allow access to that memory address range. Knowing that the previous background region number is set to 0. The user needs to start the new MPU region from region number 1.

5.2 Configuring Cortex®-M85 with STM32CubeMX2

As the Cortex®-M85 implements a memory protection unit (MPU) based on PMSAv8, the previous code from Cortex®-M7 should be changed to adapt with the new implementation. Cortex®-M85 MPU does not allow regions that overlap (no background region can be defined as for Cortex®-M7 example). However, the new implementation allows having a flexible start and size for the region. For more details, refer to: Armv8-M Memory Model and Memory Protection User Guide

STM32CubeMX2 configures attributes for external memory to prevent speculative access. It uses attribute index 0, configured as Device-nGnRnE (Device memory type, no Gathering, no Reordering, and no Early write acknowledgment) equivalent to strongly-ordered in Cortex®-M7.

Figure 2 shows the default configuration applied by STM32CubeMX2 for Cortex®-M85

Figure 2. MPU configuration to prevent speculative access in CubeMX2 for Cortex®-M85

default_mpu_mx2.png

 

CubeMX2 generates mx_cortex_mpu_init() function in the mx_cortex_mpu.c file as follows:

HAL_CORTEX_MPU_SetDeviceMemAttr(HAL_CORTEX_MPU_MEM_ATTR_0, 
HAL_CORTEX_MPU_DEVICE_MEM_NGNRNE);

This helps define external memory as a device type region, reducing speculation issues. A typical MPU region configuration for external memory protection may look like this:

p_region_config.base_addr = 0x60000000;
p_region_config.limit_addr = 0x9FFFFFFF;
p_region_config.access_attr = HAL_CORTEX_MPU_REGION_ALL_RW;
p_region_config.exec_attr = HAL_CORTEX_MPU_EXECUTION_ATTR_DISABLE;
p_region_config.priv_exec_attr = HAL_CORTEX_MPU_PRIV_EXECUTION_ATTR_DISABLE;
p_region_config.attr_idx = HAL_CORTEX_MPU_MEM_ATTR_0;
HAL_CORTEX_MPU_SetConfigRegion(HAL_CORTEX_MPU_REGION_0, &p_region_config);
HAL_CORTEX_MPU_EnableRegion(HAL_CORTEX_MPU_REGION_0);

5.2.1 Explanation

Region 0 configuration applies protection to the external memory range from 0x60000000 to 0x9FFFFFFF by allowing read and write access while disabling instruction execution and privileged execution. In addition, apply the device memory attribute defined in attribute index 0, nGnRnE.

This is a common and effective method for reducing the risk of speculative access to external memory. If the application needs to use external memory for code execution or as regular data memory, the MPU region base address and limit must be adjusted to permit access to the required address range. An additional MPU region may also be necessary to protect the portion of the external memory that is not in use.

6. Summary and takeaway

If you are designing your application memory protection, the key takeaway is that speculation is architecture-dependent and may extend beyond what software expects. Do not rely on side-effect free behavior unless the region is explicitly protected.

MPU policy should be used proactively for:

  • External memory
  • External peripherals
  • Unused or not-yet-initialized regions

Special care is needed when:

  • An address space is mapped but inactive (The peripheral kernel clock is OFF)
  • The region has read side effects
  • ECC initialization is incomplete

The key points to remember are to reduce side effects of speculative accesses, use the MPU to mark sensitive areas as:

  • Device (or strongly-ordered if available)
  • Execute-never

Avoid using noncacheable / normal memory type for read-sensitive/write-sensitive peripherals.

Related links 

Version history
Last update:
‎2026-05-20 6:51 AM
Updated by: