How to avoid a HardFault when ICACHE is enabled on the STM32H5 series
Introduction
This article presents a quick guidance on how to prevent HardFault occurrences when the ICACHE is enabled on the STM32H5 MCU.
1. Summary and description
This article explains why a HardFault may occur when accessing the following:
- Internal reference voltage (VREFINT)
- Internal temperature sensor (VSENSE)
- Unique device ID
- Package ID data
- How the CACHE intervenes in accessing data on the STM32H5 series.
2. Root cause
The internal reference voltage (VREFINT), the internal temperature sensor (VSENSE), the unique device ID, and the package ID data are located in RO and OTP areas.
By default, all the AHB memory range is cacheable. For OTP and RO regions, caching is not practical and MPU has to be used to disable local cacheability.
3. RO and OTP areas
The embedded flash memory offers a 2-Kbyte memory area to store read-only data. This area is mapped as described in the below table:

* VREFINT_CAL_ADR, TEMPSENSOR_CAL1_ADDR, and TEMPSENSOR_CAL2_ADDR are located in reserved information
OTP data is organized as 32 blocks of 32 OTP words, as shown in the below table:

It is also important to note that for 8-bit accesses, an AHB bus error is generated. For OTP and RO sectors in memory, a 6-bit ECC code is associated with each 16-bit data flash word. So, the embedded flash memory supports only16-bit or 32-bit write operations. Therefore, the burst access is not supported for these regions.
4. MPU configuration
You can refer to the following MPU configuration to disable cacheability for OTP and RO regions
#include "stm32h5xx_hal.h"
void MPU_Config(void);
/* MPU attribute setting */
#define DEVICE_nGnRnE 0x0U /* Device, noGather, noReorder, noEarly acknowledge. */
#define DEVICE_nGnRE 0x4U /* Device, noGather, noReorder, Early acknowledge. */
#define DEVICE_nGRE 0x8U /* Device, noGather, Reorder, Early acknowledge. */
#define DEVICE_GRE 0xCU /* Device, Gather, Reorder, Early acknowledge. */
#define WRITE_THROUGH 0x0U /* Normal memory, write-through. */
#define NOT_CACHEABLE 0x4U /* Normal memory, non-cacheable. */
#define WRITE_BACK 0x4U /* Normal memory, write-back. */
#define TRANSIENT 0x0U /* Normal memory, transient. */
#define NON_TRANSIENT 0x8U /* Normal memory, non-transient. */
#define NO_ALLOCATE 0x0U /* Normal memory, no allocate. */
#define W_ALLOCATE 0x1U /* Normal memory, write allocate. */
#define R_ALLOCATE 0x2U /* Normal memory, read allocate. */
#define RW_ALLOCATE 0x3U /* Normal memory, read/write allocate. */
#define OUTER(__ATTR__) ((__ATTR__) << 4U)
#define INNER_OUTER(__ATTR__) ((__ATTR__) | ((__ATTR__) << 4U))
/**
* @brief Configure the MPU attributes.
* @note The Base Address is RO area
* None
* @retval None
*/
void MPU_Config(void)
{
MPU_Attributes_InitTypeDef attr;
MPU_Region_InitTypeDef region;
/* Disable MPU before perloading and config update */
HAL_MPU_Disable();
/* Define cacheable memory via MPU */
attr.Number = MPU_ATTRIBUTES_NUMBER0;
attr.Attributes = INNER_OUTER(NOT_CACHEABLE);
HAL_MPU_ConfigMemoryAttributes(&attr);
/* BaseAddress-LimitAddress configuration */
region.Enable = MPU_REGION_ENABLE;
region.Number = MPU_REGION_NUMBER0;
region.AttributesIndex = MPU_ATTRIBUTES_NUMBER0;
region.BaseAddress = 0x08FFF800;
region.LimitAddress = 0x08FFFFFF;
region.AccessPermission = MPU_REGION_ALL_RW;
region.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
region.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
HAL_MPU_ConfigRegion(®ion);
/* Enable the MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}
void MX_ICACHE_Init(void)
{
/* USER CODE BEGIN ICACHE_Init 0 */
/* USER CODE END ICACHE_Init 0 */
/* USER CODE BEGIN ICACHE_Init 1 */
/* USER CODE END ICACHE_Init 1 */
/** Enable instruction cache in 1-way (direct mapped cache)
*/
if (HAL_ICACHE_ConfigAssociativityMode(ICACHE_1WAY) != HAL_OK)
{
Error_Handler();
}
if (HAL_ICACHE_Enable() != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ICACHE_Init 2 */
/* USER CODE END ICACHE_Init 2 */
}
5. How does the cache intervene in access to data in the STM32H5 series?
The STM32H503xx microcontrollers features an integrated ICACHE that combines instructions and data into a single cache. This cache is introduced on the C-AHB code bus of the Cortex®-M33 processor. This is to improve performance when fetching instructions (or data) from internal memories (SRAM1 and SRAM2).

The STM32H562xx, STM32H563xx, and STM32H573xx microcontrollers features:
- A DCACHE S-bus that connects the system bus of the Cortex®-M33 core to the BusMatrix via the data cache. This bus targets the external memories (FMC and OCTOSPI)
- An ICache that is connected via the fast C-bus to the internal flash memory and the internal SRAMs (SRAM1, SRAM2 and SRAM3), and it is connected via the slow bus to the external memories (FMC and OCTOSPI)

