STM32CubeMX 6.17.x and higher generates MPU/FLASH configuration that causes HardFault on STM32U385RGT6Q
Hello,
while investigating a HardFault on an STM32U385RGT6Q, I noticed several differences in the code generated by newer CubeMX versions.
At the moment I am unsure whether I have overlooked a configuration dependency or whether this is an actual CubeMX code generation issue.
Environment:
MCU: STM32U385RGT6Q
Flash Configuration:
Total Flash : 1 MB
Bank 1 : 512 kB
Bank 2 : 512 kB
Application Memory Layout:
0x08000000 - 0x080FDFFF Application Flash (1016 kB)
0x080FE000 - 0x080FFFFF Parameter Storage (8 kB)
Protection Settings:
Application Area:
Read Only by Privileged Code Only
Parameter Storage:
Read / Write by any Privileged level
In CubeMX Version 6.15.0 Flash and MPU initialisation look like this:
static void MX_FLASH_Init(void)
{
/* USER CODE BEGIN FLASH_Init 0 */
/* USER CODE END FLASH_Init 0 */
FLASH_OBProgramInitTypeDef pOBInit = {0};
FLASH_BBAttributesTypeDef FLASH_BBSecInitStruct = {0};
/* USER CODE BEGIN FLASH_Init 1 */
/* USER CODE END FLASH_Init 1 */
if (HAL_FLASH_Unlock() != HAL_OK)
{
Error_Handler();
}
/* Option Bytes settings */
if (HAL_FLASH_OB_Unlock() != HAL_OK)
{
Error_Handler();
}
pOBInit.OptionType = OPTIONBYTE_BOOTADDR;
pOBInit.BootAddrConfig = OB_BOOTADDR_NS0;
pOBInit.BootAddr = 0x08000000;
if (HAL_FLASHEx_OBProgram(&pOBInit) != HAL_OK)
{
Error_Handler();
}
if (HAL_FLASH_OB_Lock() != HAL_OK)
{
Error_Handler();
}
/* Block-based page protection */
FLASH_BBSecInitStruct.Bank = FLASH_BANK_1;
FLASH_BBSecInitStruct.BBAttributesType = FLASH_BB_PRIV;
FLASH_BBSecInitStruct.BBAttributes_array[0] = 0xFFFFFFFF;
FLASH_BBSecInitStruct.BBAttributes_array[1] = 0xFFFFFFFF;
if (HAL_FLASHEx_ConfigBBAttributes(&FLASH_BBSecInitStruct) != HAL_OK)
{
Error_Handler();
}
FLASH_BBSecInitStruct.Bank = FLASH_BANK_2;
FLASH_BBSecInitStruct.BBAttributes_array[0] = 0xFFFFFFFF;
FLASH_BBSecInitStruct.BBAttributes_array[1] = 0x7FFFFFFF;
if (HAL_FLASHEx_ConfigBBAttributes(&FLASH_BBSecInitStruct) != HAL_OK)
{
Error_Handler();
}
if (HAL_FLASH_Lock() != HAL_OK)
{
Error_Handler();
}
/* Launch Option Bytes Loading */
/*HAL_FLASH_OB_Launch(); */
/* USER CODE BEGIN FLASH_Init 2 */
/* USER CODE END FLASH_Init 2 */
}
void MPU_Config(void)
{
MPU_Region_InitTypeDef MPU_InitStruct = {0};
MPU_Attributes_InitTypeDef MPU_AttributesInit = {0};
/* Disables the MPU */
HAL_MPU_Disable();
/** Initializes and configures the Region 0 and the memory to be protected
*/
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.BaseAddress = 0x08000000;
MPU_InitStruct.LimitAddress = 0x080FDFFF;
MPU_InitStruct.AttributesIndex = MPU_ATTRIBUTES_NUMBER0;
MPU_InitStruct.AccessPermission = MPU_REGION_PRIV_RO;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/** Initializes and configures the Region 1 and the memory to be protected
*/
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.BaseAddress = 0x080FE000;
MPU_InitStruct.LimitAddress = 0x080FFFFF;
MPU_InitStruct.AccessPermission = MPU_REGION_ALL_RW;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/** Initializes and configures the Region 2 and the memory to be protected
*/
MPU_InitStruct.Number = MPU_REGION_NUMBER2;
MPU_InitStruct.BaseAddress = 0x20000000;
MPU_InitStruct.LimitAddress = 0x2002FFFF;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/** Initializes and configures the Region 3 and the memory to be protected
*/
MPU_InitStruct.Number = MPU_REGION_NUMBER3;
MPU_InitStruct.BaseAddress = 0x20030000;
MPU_InitStruct.LimitAddress = 0x2003FFFF;
MPU_InitStruct.AttributesIndex = MPU_ATTRIBUTES_NUMBER1;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/** Initializes and configures the Attribute 0 and the memory to be protected
*/
MPU_AttributesInit.Number = MPU_ATTRIBUTES_NUMBER0;
MPU_AttributesInit.Attributes = INNER_OUTER(MPU_WRITE_THROUGH|MPU_TRANSIENT
|MPU_R_ALLOCATE);
HAL_MPU_ConfigMemoryAttributes(&MPU_AttributesInit);
/** Initializes and configures the Attribute 1 and the memory to be protected
*/
MPU_AttributesInit.Number = MPU_ATTRIBUTES_NUMBER1;
MPU_AttributesInit.Attributes = INNER_OUTER(MPU_NOT_CACHEABLE);
HAL_MPU_ConfigMemoryAttributes(&MPU_AttributesInit);
/* Enables the MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}
In CubeMX Version 6.16.1 Flash and MPU initialisation looks like this:
so here Bank 2 of the Flash initializing is missing
static void MX_FLASH_Init(void)
{
/* USER CODE BEGIN FLASH_Init 0 */
/* USER CODE END FLASH_Init 0 */
FLASH_OBProgramInitTypeDef pOBInit = {0};
FLASH_BBAttributesTypeDef FLASH_BBSecInitStruct = {0};
/* USER CODE BEGIN FLASH_Init 1 */
/* USER CODE END FLASH_Init 1 */
if (HAL_FLASH_Unlock() != HAL_OK)
{
Error_Handler();
}
/* Option Bytes settings */
if (HAL_FLASH_OB_Unlock() != HAL_OK)
{
Error_Handler();
}
pOBInit.OptionType = OPTIONBYTE_BOOTADDR;
pOBInit.BootAddrConfig = OB_BOOTADDR_NS0;
pOBInit.BootAddr = 0x08000000;
if (HAL_FLASHEx_OBProgram(&pOBInit) != HAL_OK)
{
Error_Handler();
}
if (HAL_FLASH_OB_Lock() != HAL_OK)
{
Error_Handler();
}
/* Block-based page protection */
FLASH_BBSecInitStruct.Bank = FLASH_BANK_1;
FLASH_BBSecInitStruct.BBAttributesType = FLASH_BB_PRIV;
FLASH_BBSecInitStruct.BBAttributes_array[0] = 0xFFFFFFFF;
FLASH_BBSecInitStruct.BBAttributes_array[1] = 0xFFFFFFFF;
if (HAL_FLASHEx_ConfigBBAttributes(&FLASH_BBSecInitStruct) != HAL_OK)
{
Error_Handler();
}
/* Launch Option Bytes Loading */
/*HAL_FLASH_OB_Launch(); */
/* USER CODE BEGIN FLASH_Init 2 */
/* USER CODE END FLASH_Init 2 */
}
void MPU_Config(void)
{
MPU_Region_InitTypeDef MPU_InitStruct = {0};
MPU_Attributes_InitTypeDef MPU_AttributesInit = {0};
/* Disables the MPU */
HAL_MPU_Disable();
/** Initializes and configures the Region 0 and the memory to be protected
*/
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.BaseAddress = 0x08000000;
MPU_InitStruct.LimitAddress = 0x080FDFFF;
MPU_InitStruct.AttributesIndex = MPU_ATTRIBUTES_NUMBER0;
MPU_InitStruct.AccessPermission = MPU_REGION_PRIV_RO;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/** Initializes and configures the Region 1 and the memory to be protected
*/
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.BaseAddress = 0x080FE000;
MPU_InitStruct.LimitAddress = 0x080FFFFF;
MPU_InitStruct.AccessPermission = MPU_REGION_ALL_RW;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/** Initializes and configures the Region 2 and the memory to be protected
*/
MPU_InitStruct.Number = MPU_REGION_NUMBER2;
MPU_InitStruct.BaseAddress = 0x20000000;
MPU_InitStruct.LimitAddress = 0x2002FFFF;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/** Initializes and configures the Region 3 and the memory to be protected
*/
MPU_InitStruct.Number = MPU_REGION_NUMBER3;
MPU_InitStruct.BaseAddress = 0x20030000;
MPU_InitStruct.LimitAddress = 0x2003FFFF;
MPU_InitStruct.AttributesIndex = MPU_ATTRIBUTES_NUMBER1;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/** Initializes and configures the Attribute 0 and the memory to be protected
*/
MPU_AttributesInit.Number = MPU_ATTRIBUTES_NUMBER0;
MPU_AttributesInit.Attributes = INNER_OUTER(MPU_WRITE_THROUGH|MPU_TRANSIENT
|MPU_R_ALLOCATE);
HAL_MPU_ConfigMemoryAttributes(&MPU_AttributesInit);
/** Initializes and configures the Attribute 1 and the memory to be protected
*/
MPU_AttributesInit.Number = MPU_ATTRIBUTES_NUMBER1;
MPU_AttributesInit.Attributes = INNER_OUTER(MPU_NOT_CACHEABLE);
HAL_MPU_ConfigMemoryAttributes(&MPU_AttributesInit);
/* Enables the MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}
and in version CubeMX 6.17.0 / 6.18.1
so here Bank 2 of the Flash initializing is missing and the whole
MPU_Attributes_InitTypeDef MPU_AttributesInit = {0};
part is missing
Only the region configuration remains.
static void MX_FLASH_Init(void)
{
/* USER CODE BEGIN FLASH_Init 0 */
/* USER CODE END FLASH_Init 0 */
FLASH_OBProgramInitTypeDef pOBInit = {0};
FLASH_BBAttributesTypeDef FLASH_BBSecInitStruct = {0};
/* USER CODE BEGIN FLASH_Init 1 */
/* USER CODE END FLASH_Init 1 */
if (HAL_FLASH_Unlock() != HAL_OK)
{
Error_Handler();
}
/* Option Bytes settings */
if (HAL_FLASH_OB_Unlock() != HAL_OK)
{
Error_Handler();
}
pOBInit.OptionType = OPTIONBYTE_BOOTADDR;
pOBInit.BootAddrConfig = OB_BOOTADDR_NS0;
pOBInit.BootAddr = 0x08000000;
if (HAL_FLASHEx_OBProgram(&pOBInit) != HAL_OK)
{
Error_Handler();
}
if (HAL_FLASH_OB_Lock() != HAL_OK)
{
Error_Handler();
}
/* Block-based page protection */
FLASH_BBSecInitStruct.Bank = FLASH_BANK_1;
FLASH_BBSecInitStruct.BBAttributesType = FLASH_BB_PRIV;
FLASH_BBSecInitStruct.BBAttributes_array[0] = 0xFFFFFFFF;
FLASH_BBSecInitStruct.BBAttributes_array[1] = 0xFFFFFFFF;
if (HAL_FLASHEx_ConfigBBAttributes(&FLASH_BBSecInitStruct) != HAL_OK)
{
Error_Handler();
}
/* Launch Option Bytes Loading */
/*HAL_FLASH_OB_Launch(); */
/* USER CODE BEGIN FLASH_Init 2 */
/* USER CODE END FLASH_Init 2 */
}
void MPU_Config(void)
{
MPU_Region_InitTypeDef MPU_InitStruct = {0};
/* Disables the MPU */
HAL_MPU_Disable();
/** Initializes and configures the Region 0 and the memory to be protected
*/
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.BaseAddress = 0x08000000;
MPU_InitStruct.LimitAddress = 0x080FDFFF;
MPU_InitStruct.AttributesIndex = MPU_ATTRIBUTES_NUMBER0;
MPU_InitStruct.AccessPermission = MPU_REGION_PRIV_RO;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/** Initializes and configures the Region 1 and the memory to be protected
*/
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.BaseAddress = 0x080FE000;
MPU_InitStruct.LimitAddress = 0x080FFFFF;
MPU_InitStruct.AccessPermission = MPU_REGION_ALL_RW;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/** Initializes and configures the Region 2 and the memory to be protected
*/
MPU_InitStruct.Number = MPU_REGION_NUMBER2;
MPU_InitStruct.BaseAddress = 0x20000000;
MPU_InitStruct.LimitAddress = 0x2002FFFF;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/** Initializes and configures the Region 3 and the memory to be protected
*/
MPU_InitStruct.Number = MPU_REGION_NUMBER3;
MPU_InitStruct.BaseAddress = 0x20030000;
MPU_InitStruct.LimitAddress = 0x2003FFFF;
MPU_InitStruct.AttributesIndex = MPU_ATTRIBUTES_NUMBER1;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/* Enables the MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}
I am able to run my code in the Generated version of 6.15.0 and 6.16.1 but any higher cubeMX version causes a hardfault on a random RAM operation like creating lokal variables or copying memory.
The HardFault appears only after the MPU Memory Attribute configuration disappears.
If i manualy add the missing MPU memory Attribute configuration lines everything works just fine in every cubeMX version
In Addition to that i also would expect a different Flash initialization
The STM32U385RGT6Q contains:
128 Pages per Bank
The BB attribute configuration therefore requires:
4 x 32-bit attribute words per bank
Since my application uses:
Entire Bank 1
+
All of Bank 2 except the last two pages
I would expect something similar to:
FLASH_BBSecInitStruct.Bank = FLASH_BANK_1;
FLASH_BBSecInitStruct.BBAttributesType = FLASH_BB_PRIV;
FLASH_BBSecInitStruct.BBAttributes_array[0] = 0xFFFFFFFF;
FLASH_BBSecInitStruct.BBAttributes_array[1] = 0xFFFFFFFF;
FLASH_BBSecInitStruct.BBAttributes_array[2] = 0xFFFFFFFF;
FLASH_BBSecInitStruct.BBAttributes_array[3] = 0xFFFFFFFF;
HAL_FLASHEx_ConfigBBAttributes(&FLASH_BBSecInitStruct);
FLASH_BBSecInitStruct.Bank = FLASH_BANK_2;
FLASH_BBSecInitStruct.BBAttributes_array[0] = 0xFFFFFFFF;
FLASH_BBSecInitStruct.BBAttributes_array[1] = 0xFFFFFFFF;
FLASH_BBSecInitStruct.BBAttributes_array[2] = 0xFFFFFFFF;
FLASH_BBSecInitStruct.BBAttributes_array[3] = 0x3FFFFFFF;
HAL_FLASHEx_ConfigBBAttributes(&FLASH_BBSecInitStruct);
Only the final two pages of Bank 2 should remain writable for parameter storage.
However, recent CubeMX versions generate only the Bank 1 configuration or atleast missing have of all Pages.
Questions
Is the removal of HAL_MPU_ConfigMemoryAttributes() starting with CubeMX 6.17.x intentional?
If yes, where are MPU_ATTRIBUTES_NUMBER0 and MPU_ATTRIBUTES_NUMBER1 expected to be initialized?
Is the missing Bank 2 BB attribute generation a known issue?
Is CubeMX correctly handling custom Flash partitioning on STM32U385 devices?
Has anyone observed similar behaviour after migrating from CubeMX 6.15.x to newer versions?
Does this look like a CubeMX code generation regression, or is there an additional configuration step now required?
Any feedback from ST or other STM32U3 users would be greatly appreciated.
Thanks!
