2023-01-18 10:47 AM
Hey guys, how are you?
It's been a long time that i'm facing a issue with STM32WB CPU2, most of the times i just fix it without really knowing the cause of it.
Basically what happens is after power-up CPU2 simply won't initialize on the first try. I have a loop on my main application waiting for CPU2 to boot. Since it doesn't boot, my WDT kicks, microcontroller gets reseted and then in this second try CPU2 initialize properly. I debugged CPU2 fault register and accused a hard-fault in CPU2, that i'm not very sure what can be.
The weirder of all of this is that small changes on my firmware compiled binary stop this problem. Last time this occurred, (after a ton of researching and some trial and error) i had to add a static char array of 4 bytes. This changed the .bin size and the problem simply disappeared. If i added a static variable that didn't change the .bin size (due to binary padding during compilation), the problem still happened.
I compared the generated binaries files in both of this occasions (with and without this static variable) and i saw some differences that i'm not sure what are exactly in the first 800 positions of the binaries. I tough that such small change wouldn't make a big difference like that in the binary. Here's the difference that i saw. The one on the left is the binary that CPU2 works fine.
This application i develop it has a SBSFU Bootloader that can (or not) be attached to it. Another weird thing is that if I generate the sbsfu + application binary file (using the application binary file that CPU2 hard faults, demonstrated in the image above), everything works smooth and CPU2 DOESN'T HARD FAULT. The supposed part of the firmware that i'm showing in the image above is also changed in this SBSFU + App binary, as shown in the picture below. I expected that this SBSFU + App binary would be just an attachment from both bootloader and application binary, but still it changed a part of what supposedly is my application. Probably this changes are due some bootloader handlings that application has when is compiled for SBSFU usage, such as self-test, vector table and etc. But i still tough that this wouldn't change this first positions of the application.
I'm sorry for the long text, i'm investigating this problem for months.. all the time this occur to me i just fix it without really knowing why (sometimes deliveries are more important than causes :confounded_face: ). When this happens, i just rollback the changes on my code and try it to rewrite on a different manner, looking for some code mistake that the compiler didn't catch it, i don't know.
That is my whole problem.. one quick question that you guys can aswer me is, aren't this first positions the ISR Vector table? Why the heck a small change would impact this part of the binary?
If you guys could give me at least some hint on how to solve this CPU2 problem.
Regards,
Matheus
2023-01-21 03:48 AM
Hello Matheus,
I have no idea why you get such behaviour.
One thing regarding the small change in code leading to big change in binary.
If you look at your symbols mapping file, you should see that the change you made will create new code or data mapped in flash before the vector table.
As the beginning of the binary contains the address of all vectors in the vector table, changing the mapping of vectors will change all the vector table addresses.
So, if you want to make tests leading to small changes in the flash mapping, you need to understand who the linker maps the different content in flash, looking at you linker file and the resulting map file.
In order to investigate your issue, I would debug the boot to understand at which point the CPU2 fails to check system state at that point and try to find root cause
Best regards
Jocelyn
2023-01-23 08:06 AM
HI @Jocelyn RICARD
I started debugging the flash. I wnt to check how the flash status register were and this is what i found:
FLASH_FLAG_MISERR: 0
FLASH_FLAG_PGSERR: 1 (Is 1 with or without hardfault)
FLASH_FLAG_PGAERR: 1 (Is 1 with or without hardfault)
FLASH_FLAG_SIZERR: 0
FLASH_FLAG_FASTERR: 0
FLASH_FLAG_OPTNV: 0
FLASH_FLAG_RDERR: 0
FLASH_FLAG_OPTVERR: 0
FLASH_FLAG_BSY: 0
FLASH_FLAG_CFGBSY: 1 (When hardfault) 0 (when CPU2 boots normal)
FLASH_FLAG_WRPERR: 0
FLASH_FLAG_PROGERR: 0
FLASH_FLAG_OPERR: 0
FLASH_FLAG_EOP: 0
FLASH_FLAG_PESD: 0
FLASH_FLAG_ECCC: 0
FLASH_FLAG_ECCD: 0
Even with that 4 bytes adding to the binary and no more CPU2 hardfaulting happening, both FLASH_FLAG_PGSERR and FLASH_FLAG_PGAERR are still in 1.
Does this gives you any clue? What possibly CFG_BUSY could have to do with CPU2 hardfault?
Regards, Matheus
2023-01-23 02:45 PM
Hello Matheus,
This is strange indeed.
Here you show content of FLASH CPU2 status register (C2SR).
So, it has to do with CPU2 flash access.
Have you changed anything in SBSFU ?
In your application are you trying to access CPU2 flash or requesting a service that could lead in flash modification ?
Last guess, are you trying to modify flash in your code that would be mapped in CPU2 area?
I'm not specialist of WB device so I may miss something.
Best regards
Jocelyn
2023-01-23 04:51 PM
Hello @Jocelyn RICARD ,
Actually i was debugging FLASH_SR, but first thing tomorrow i'll check the state of C2SR. Regarding your questions.
Have you changed anything in SBSFU ?
A: Not actually. I believe things work well with SBSFU due to the linker manipulation (Binary size needs to be divisible by 16) that i must do in order to be able to generate a AES encrypted image.
In your application are you trying to access CPU2 flash or requesting a service that could lead in flash modification ?
A: My application access STM32 flash, but not CPU2 flash area. All the functions for flash modification i got it from EEPROM Emulation API that ST provided. I don't use EEPROM Emulation itself but i kept the flash interface functions, since it got all the hw semaphores handling in the way that it should be.
I'll comeback tomorrow with the C2SR register values.
Best regards,
Matheus
2023-01-24 01:33 AM
Hello,
To find the root cause of your issue, which part of code generate the flash error, you can use MPU by adding the following code:
In main.c file:
static void MPU_AccessPermConfig(void);
/**
* @brief This function configures the access right using Cortex-M4 MPU regions.
* @param None
* @retval None
*/
static void MPU_AccessPermConfig(void)
{
MPU_Region_InitTypeDef MPU_InitStruct;
/* Disable MPU */
HAL_MPU_Disable();
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0;
MPU_InitStruct.Size = MPU_REGION_SIZE_1MB;
MPU_InitStruct.AccessPermission = MPU_REGION_PRIV_RO;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/* Enable MPU (any access not covered by any enabled region will cause a fault) */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
return;
}
Call this function after SystemClock_Config like this:
SystemClock_Config();
MPU_AccessPermConfig();
In stm32wbxx_it.c file:
/**
* @brief This function handles Memory management fault.
*/
void MemManage_Handler(void)
{
/* USER CODE BEGIN MemoryManagement_IRQn 0 */
/* USER CODE END MemoryManagement_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
/* USER CODE END W1_MemoryManagement_IRQn 0 */
}
}
Add a breakpoint in MemManage_Handler function.
Run your project with debugger and check if fault exception occurs and look call stack when the fault occurs to see cause of this fault.
Best Regards
2023-01-25 07:16 AM
Hi @Remy ISSALYS
I added the MPU functions you advised. I had some unexpected behaviours. Firstly i had a HardFault on HAL_InitTick(). Then i had a hardfault on my IWDG initialization. I then commented my IWDG and the code ran.
I had a CPU2 hardfault but, since i had to comment a few thing so that MPU could run, i'm not sure if this hardfault has the same cause than the problem i was mentioning earlier. Regarding the MemManage_Handler, i added a breakpoint and the code didn't reach there. The FLASH_SR register are different also, so i really i forced another kind of hardfault that it was not the one i was having earlier.
Also, the problem i was having I didn't have it when i had a debug session running (not sure due timing or something else, but it never happened). This i think is also super strange, why would my debug interfere on how CPU2 works?
REgards,
Matheus
2023-01-30 04:53 AM
Any hint @Remy ISSALYS ?
2023-01-30 08:04 AM
Hello,
Can you summarize your setup and how do you reproduce the issue? You are using the STM32WB5M with your custom usb loader and a BLE app. If I understand well each time you powered-up your board the CPU2 won't initialize on the first try and after a reset generate by the WDT, everything works well ?
When the CPU2 didn't initialize, you see the Hardfault keywork (0x1170FD0F) at 0x20030000 and flash in error (FLASH_FLAG_PGSERR, FLASH_FLAG_PGAERR and FLASH_FLAG_CFGBSY =1), is it right?
In your description it seems that CPU1 causes the flash error which prevent CPU2 starts. To ensure that the MPU is well configured, you can try to generate a flash error by adding the following code for example:
uint32_t *p = (uint32_t *) 0x00000000;
*p = 13;
If the MPU works well and didn't trig in your app maybe it's your bootloader which causes the flash error, can you check the value FLASH_SR register when you jump on your app from your bootloader? If the flash is in error, you can use the MPU in your bootloader to see which instruction causes this error.
In addition can you share the C2SR register values?
Best Regards
2023-01-30 03:41 PM
Hello @Remy ISSALYS
"Can you summarize your setup and how do you reproduce the issue? You are using the STM32WB5M with your custom usb loader and a BLE app."
A: I'm using a STM32WB5M but i'm not using SBSFU in this case, its just the firmware itself running on the board. The error occurs when i'm not using SBSFU. The firmware configured and running alongside the bootloader works fine.
"f I understand well each time you powered-up your board the CPU2 won't initialize on the first try and after a reset generate by the WDT, everything works well ?"
A: It's correct. If i disable my WDT, my application keeps locked in a loop awaiting for CPU2 to boot.
"When the CPU2 didn't initialize, you see the Hardfault keywork (0x1170FD0F) at 0x20030000 and flash in error (FLASH_FLAG_PGSERR, FLASH_FLAG_PGAERR and FLASH_FLAG_CFGBSY =1), is it right?"
A: That's correct.
"In your description it seems that CPU1 causes the flash error which prevent CPU2 starts. To ensure that the MPU is well configured, you can try to generate a flash error by adding the following code for example:"
A: I added the piece of code you suggested. The MemManage_Handler got called in this forced situation, so i think is everything all right with MPU setup.
"In addition can you share the C2SR register values?"
A: I checked C2SR and all the values were zeroes, hardfaulting or not.
Just a few more details.. my application uses RTOS with BLE App, so i had to manually modify the BLE code to execute properly with the OS. I did what was instructed by a ST Employee in some post here in this forum.
Also, as i mentioned above, the fault doesn't happen if i have a debug (STLink) hooked to the board. It doesn't need to even have a debug session running, just the ST-Link wires connected and the ST-Link powered up, the fault does not happen .
Regards, Matheus