2023-03-13 01:59 PM
Hi everyone,
I'm trying to make a simple project consisting of STM32F750Z8T6 (taking instructions from QSPI), a 480x272 display (using LTDC), and a W9812G6KH-6I SDRAM (using FMC).
The project consists of a single screen representing an analog and a digital clock.
The project seems to work but suddenly a random hardfault occurs and I don't understand why.
Can anyone help me figure out what is the cause of the error?
Which settings did I set incorrectly
I share the project (Application + Booloader)
APPLICATION = https://files.fm/f/n4vjbjyca
BOOTLOADER = https://files.fm/f/b625v68z5
Best regards
2023-03-13 02:46 PM
Have a Hard Fault Handler that outputs actionable information and try and root-cause that, at least narrow the "random" failure to something a tad more specific.
Like exiting interrupt handlers, corrupt stacks, invalid pointers.
2023-04-20 06:14 AM
Hi,
For random hardfaults on a Cortex-M7-based MCU using external memories, the very first thing to check is the memory protection unit, this may be due to unexpected speculative accesses.
In short you should define a global MPU region disabling all accesses to external memory address range and then define one region per connected external memory, with exact size and appropriate attributes depending on usage, see : https://www.st.com/content/st_com/en/support/learning/stm32-education/stm32-moocs/STM32_MPU_tips.html
See as well :
Introduction to memory protection unit management on STM32 MCUs - Application note
Arm Cortex-M7 Processor Technical Reference Manual r1p2
Best regards,
Nicolas
2023-04-20 06:37 AM
Seems like something the Code Generator should be responsible for.. having awareness of the peripherals, memory floor-plan, etc.
2023-04-20 12:20 PM - edited 2023-11-20 09:14 AM
Hi all, thanks for support but I still have problems.
So I tried to enable one piece at time starting from a basic configuration: microcontroller and LCD.
I enable internal RAM for LCD buffer, QSPI for fetch instruction and I disabled Art accelerator, DMA2D, FMC, (FREERTOS is not enabled).. I loaded also an GUI example.
I think , clock is setted correctly:
I follwoing your hints, so I re-activated MPU and reconfgiured like this:
void MPU_Config(void)
{
MPU_Region_InitTypeDef MPU_InitStruct = {0};
/* Disables the MPU */
HAL_MPU_Disable();
/** 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 = 0xA0000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_8KB;
MPU_InitStruct.SubRegionDisable = 0x0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_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_NUMBER1;
MPU_InitStruct.BaseAddress = 0x90000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_16MB;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/* Enables the MPU */
HAL_MPU_Enable(MPU_HFNMI_PRIVDEF);
}
But when the program is running I got always the same problem:
:
I haven't more ideas. maybe I didn't understand how stm32f750 works, but it seem impossible that this simple programs does not work.
Can Boot application settings blcok the APP execution?
Thanks
2023-04-20 11:49 PM - edited 2023-11-20 09:14 AM
Hi,
Your MPU configuration misses the most important region, the one that disables all accesses to external memories :
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x00;
MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x87;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
The External RAM memory region is critical, since it is by default Normal memory type and executable and Cortex®-M7 may perform speculative reads to this area, even when there is no memory connected.
The recommendation is to create a safe background region, where the default attributes of the External RAM memory region will be changed (no speculative access allowed).
So, this MPU config makes 4GB not accessible except subregions set to 1 in MPU_InitStruct.SubRegionDisable structure member.
.SubRegionDisable means disable current MPU config for subregions set to 1.
In a given MPU region, there are 8 subregions. So if you divide 4GB (in this case) by 8 you will find 512MB. If you look at memory mapping of default MPU of ARM (4G), you can notice, there are 8 address ranges of 512MB.
There are 4 subregions (of 512M) targeted by this default MPU config in the range: 0x6000 0000 to 0xDFFF FFFF which corresponds to external memories range (FMC, QSPI, OSPI etc ..).
In the above MPU config, each subregion has a size of 512M. MPU_InitStruct.SubRegionDisable = 0x87, will prevent regions in yellow to being set by this config. These regions still in their default MPU config.
SubRegionDisable = 0x87 : 0b1000 0111 --> each bit set to 1 means: don't apply the current MPU config to that subregion.
Please try again with this region defined as MPU_REGION_NUMBER0 then change the region number of the other regions you defined for QSPI and QSPI control registers.
Best regards,
Nicolas
2023-04-21 12:05 AM
HI,
I both agree and disagree :)
There is indeed information on external RAM or FLASH memories in the CubeMX but not on their purpose.
External RAM could be used to store frame buffers or maybe application copied at runtime, the MPU configuration would then be completely different.
The same applies to external FLASH that could hold GUI assets (read-only, no execution allowed) or application (execution allowed).
Relying on the code generator without involving the user would lead to default configuration based on assumption from the tool.
That being said I agree that the warnings and guidance on MPU can still be improved.
Best regards,
Nicolas
2023-04-21 01:07 PM - edited 2023-11-20 09:15 AM
Hi,
I tried to follow your hints, but without success.
Using the following settings, is still not working. it crash!
void MPU_Config(void)
{
MPU_Region_InitTypeDef MPU_InitStruct = {0};
/* Disables the MPU */
HAL_MPU_Disable();
/** 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 = 0x00000000;
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_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 = 0xA0001000;
MPU_InitStruct.Size = MPU_REGION_SIZE_4KB;
MPU_InitStruct.SubRegionDisable = 0x0;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
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_NUMBER2;
MPU_InitStruct.BaseAddress = 0x90000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_512MB;
MPU_InitStruct.AccessPermission = MPU_REGION_PRIV_RO_URO;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/* Enables the MPU */
HAL_MPU_Enable(MPU_HFNMI_PRIVDEF);
}
Is there the possibility that Bootloader has some problem about MPU?
Must I copy the same settigns on it? I think no, because the App should reset all the necessary new settings.
2023-04-24 03:19 AM - edited 2023-11-20 09:15 AM
Hi All,
I have an update using these settings both for App both for Boot I got an performance improvement:
void MPU_Config(void)
{
MPU_Region_InitTypeDef MPU_InitStruct = {0};
/* Disables the MPU */
HAL_MPU_Disable();
/** 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_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 = 0x90000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_16MB;
MPU_InitStruct.SubRegionDisable = 0x0;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/** Initializes and configures the Region and the memory to be protected
*/
MPU_InitStruct.Number = MPU_REGION_NUMBER2;
MPU_InitStruct.BaseAddress = 0xA0000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_8KB;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_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_NUMBER3;
MPU_InitStruct.BaseAddress = 0xC0000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_16MB;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/* Enables the MPU */
HAL_MPU_Enable(MPU_HFNMI_PRIVDEF);
}
Respect the previous settings, the actual code block itselft after some minutes than some seconds of prevoius code.
I tried to enabled DMA2D accelerator on touchgfx settings and on CortexM7, changing tye of Flash interface to TCM and enbleing ART Accelerator.
But these changes doesn't solve.
(I remember you that I have only LTCD, QSPI , internal RAM and the project use External BOOT + APP. I'm using ST "gauge example" for my User interface).
What others settings are missing or can be wrong?
Thanks in advance.
bets regards
2023-04-25 12:04 AM
Hi,
I think the MPU is still to blame, could you try the following settings for the external RAM ?
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER3;
MPU_InitStruct.BaseAddress = 0xC0000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_16MB;
MPU_InitStruct.SubRegionDisable = 0x0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
It defines the region as "strongly ordered" which is preferable in your case since 2 masters are potentially concurrently accessing it (Cortex and DMA2D).
Best regards,
Nicolas