2022-04-14 06:59 AM
Hello,
Currently I'm working on a system using the : STM32G0B1.
I'm encountering some Hardfaults, for what I've seen on G0 finding the source of the hardfaults is complicated.
I've used an code of type :
typedef struct{
TByte rSHCSR_name[4];
TLongWord rSHCSR;
TByte rDFSR_name[4];
TLongWord rDFSR;
TByte SP_name[4];
TLongWord * StackPointer;
TByte R0_name[4];
TLongWord stacked_r0;
TByte R1_name[4];
TLongWord stacked_r1;
TByte R2_name[4];
TLongWord stacked_r2;
TByte R3_name[4];
TLongWord stacked_r3;
TByte R12_name[4];
TLongWord stacked_r12;
TByte LR_name[4];
TLongWord stacked_lr;
TByte PC_name[4];
TLongWord stacked_pc;
TByte PSR_name[4];
TLongWord stacked_psr;
TByte REG_DCRSR_name[4];
TLongWord REG_DCRSR;
TByte REG_DCRDR_name[4];
TLongWord REG_DCRDR;
TByte REG_DEMCR_name[4];
TLongWord REG_DEMCR;
}TsHardFaultRegisters;
TsHardFaultRegisters oHardFaultRegistersPSP;
void HardFault_Handler(void)
{
// Get the process stack pointer mandatory if we use an OS
oHardFaultRegistersPSP.StackPointer = (TLongWord *)__get_PSP();
// assembler call to avoir stack modifications
__asm volatile("B CpuDriver_PRV_CheckFaultStatusRegisters\n\t");
}
void CpuDriver_PRV_CheckFaultStatusRegisters(void)
{
// Get the 8 register stacked by the core
oHardFaultRegistersPSP.stacked_r0 = ((TLongWord) oHardFaultRegistersPSP.StackPointer[0]);
oHardFaultRegistersPSP.stacked_r1 = ((TLongWord) oHardFaultRegistersPSP.StackPointer[1]);
oHardFaultRegistersPSP.stacked_r2 = ((TLongWord) oHardFaultRegistersPSP.StackPointer[2]);
oHardFaultRegistersPSP.stacked_r3 = ((TLongWord) oHardFaultRegistersPSP.StackPointer[3]);
oHardFaultRegistersPSP.stacked_r12 = ((TLongWord) oHardFaultRegistersPSP.StackPointer[4]);
oHardFaultRegistersPSP.stacked_lr = ((TLongWord) oHardFaultRegistersPSP.StackPointer[5]);
oHardFaultRegistersPSP.stacked_pc = ((TLongWord) oHardFaultRegistersPSP.StackPointer[6]);
oHardFaultRegistersPSP.stacked_psr = ((TLongWord) oHardFaultRegistersPSP.StackPointer[7]);
}
Sometimes I get the above result.
In which case, the disassembly looks like:
Questions :
1/ on several hardfaults I get the BL involved. However, the LR register is always positionnated on the adresses after the BL.
I might be interpreting the LR value wrongly ?
2/ The PC counter is located before or after the involved commands.
Is the PC not placed on the commands because BL pushes it ?
3/BL command seems to be correctly working most of the time. As for what I understand BL and MOV command are always used together to call a function. Do you have any ideas on how I can debug my code?
Best regards!
2022-04-14 07:14 AM
>>I'm encountering some Hardfaults, for what I've seen on G0 finding the source of the hardfaults is complicated.
I would tend to disagree, Hard Faults are gross failures, and much easier to run to ground than latent or logic failures.
LR should reflect where its coming back too, but is can be stale as it only relates to the last subroutine call encountered.
PC should be what the handler pushed, it could be "imprecise" if it relates to a slightly earlier queued write operation that's being completed out of the write buffers. But its the best point to look at and work backward from. Again understand whats in all the registers as this provides immediate context.
Dumping the register going into the memcpy() would be very helpful
The CM0(+) is going to be particularly sensitive to unaligned memory when doing 32-bit reads/writes, to look at those pointer, and also the SP.
Is the fast memcpy checking for alignment?
Are you using too much stack space?
It is more probable that the R4 register is unaligned, and you're using it to read a 32-bit value from memory. ie arg_oIoFrame is unaligned
2022-04-14 08:28 AM
Hello again @Community member !
I'm trying to repeat my precedent HF.
Please correct me if I'm wrong, If i understand correctly LR is not exactly helpful (or not always)
PC being our best option 0x804'2248.
In the following case, issue arrives then at the (MOVS R5, R0) ?
I see R5 to 0x0000'0001 and R0 to 0x0000'0000
Or does it still comes from the BL and its memcmp?
Also, can you please tell me how to check if memcmp is checking for alignement ?
The best thing I know at the moment to align the code is :
#pragma data_alignment =8 //
which is already on the code (We are using uCos-II)
Thank you for the help!
2022-04-14 10:46 AM
Not sure what's going on here specifically, or if it's even in the hard fault. The structure is doing a really poor job of conveying detail cleanly. Could be an interrupt or task-switch related.
The SP looks LOW, how big is the stack this function is using, and how much local/auto variable space are you using?
LR is going to scope the area of interest. ie in a subroutine of general use, where it came from
We tend to dump context so we can get diagnostic data from the field, and independently of the debugger, so there's something more to go on than the app dying in a while(1)
https://github.com/cturvey/RandomNinjaChef/blob/main/KeilHardFault.c
Your prior example was dying at the instruction in the blue box, likely due to R4 content, not memcpy()
2022-04-20 04:16 AM
Hello @Community member ,
I solved the problem. But as always your comments are very interesting and helpful.
Actually, we are using two Banks (1 and 2) and I found recently an errata :
The solution was to deactivate the PRFTEN
I saw that some of the code is executed on the Bank 1 and then we change to use the code on Bank 2 ( and viceversa )
Bank 1 from page 0 to 127
Empty area from 128 to 255
Bank 2 from page 256 to 384
The symptom was several Hardfaults at different specific "zones"
I tested deactivating the PRFTEN and now I have no more HF issues
Best regards!