Hardfault exception when calling memset on STM32 - c

Starting up a STM32 i try to allocate memory for a struture pointed to by a pointer.
TLxbEvents *LxbEvents
memset((void*)LxbEvents, 0, sizeof(TLxbEvents));
Looking into the disassembly, it crashes always on the line
STMCS r0!,{r2-r3,r12,lr}
I could not find a document describing the STMCS instruction nether on ARM website or Google or elsewhere...
The registers at that point are
r0 0x2000D694
r2 0x00000000
r3 0x00000000
r12 0x00000000
lr 0x00000000
I tried to move the call to another routine, without any changes, checked the alignment and that also seems to be okay. Everytime the program runs into that line it crashes with a HardFault and according to some debug variables, it is caused by a watchdog reset, what i do not believe...
What does this line do and has someone an idea, what is causing the hard fault?

STMCS is an ARM instruction (base instruction is STM and CS is the conditional instruction suffix) It seems you are compiling your code in ARM mode, but STM32 is a Cortex-M core and only supports Thumb-2 instruction set variant. Double-check you build settings and compilation switches.

Related

Are ARM Cortex-M0 Stacking Registers Saved On $psp or $msp During Hardfault?

I have an issue where my Cortex-M0 is hard faulting, so I am trying to debug it. I am trying to print the contents of the ARM core registers that were pushed to the stack when the hard fault occurred.
Here is my basic assembly code:
__attribute__((naked)) void HardFaultVector(void) {
asm volatile(
// check LR to see whether the process stack or the main stack was being used at time of exception.
"mov r2, lr\n"
"mov r3, #0x4\n"
"tst r2, r3\n"
"beq _MSP\n"
//process stack was being used.
"_PSP:\n"
"mrs r0, psp\n"
"b _END\n"
//main stack was being used.
"_MSP:\n"
"mrs r0, msp\n"
"b _END\n"
"_END:\n"
"b fault_handler\n"
);
}
The function fault_handler will print the contents of the stack frame that was pushed to either the process stack or the main stack. Here's my question though:
When I print the contents of the stack frame that supposedly has the saved registers, here is what I see:
Stack frame at 0x20000120:
pc = 0xfffffffd; saved pc 0x55555554
called by frame at 0x20000120, caller of frame at 0x20000100
Arglist at unknown address.
Locals at unknown address, Previous frame's sp is 0x20000120
Saved registers:
r0 at 0x20000100, r1 at 0x20000104, r2 at 0x20000108, r3 at 0x2000010c, r12 at 0x20000110, lr at 0x20000114, pc at 0x20000118, xPSR at 0x2000011c
You can see the saved registers, these are the registers that are pushed by the ARM core when a hard fault occurs. You can also see the line pc = 0xfffffffd; which indicates that this is the LR's EXC_RETURN value. The value 0xfffffffd indicates to me that the process stack was being used at the time of the hard fault.
If I print the $psp value, I get the following:
gdb $ p/x $psp
$91 = 0x20000328
If I print the $msp value, I get the following:
gdb $ p/x $msp
$92 = 0x20000100
You can clearly see that the $msp is pointing to the top of the stack where supposedly the saved registers are located. Doesn't this mean that the main stack has the saved registers that the ARM core pushed to the stack?
If I print the memory contents, starting at the $msp address, I get the following:
gdb $ x/8xw 0x20000100
0x20000100 <__process_stack_base__>: 0x55555555 0x55555555 0x55555555 0x55555555
0x20000110 <__process_stack_base__+16>: 0x55555555 0x55555555 0x55555555 0x55555555
It's empty...
Now, if I print the memory contents, starting at the $psp address, I get the following:
gdb $ x/8xw 0x20000328
0x20000328 <__process_stack_base__+552>: 0x20000860 0x00000054 0x00000054 0x20000408
0x20000338 <__process_stack_base__+568>: 0x20000828 0x08001615 0x1ad10800 0x20000000
This looks more accurate. But I thought the saved registers are supposed to indicate where in flash memory they are located? So how does this make sense?
The comments by old_timer under your question are all correct. The registers will be pushed to the active stack on exception entry, whether this is PSP or MSP at the time. By default, all code uses the main stack (MSP), but if you're using anything other than complete bare metal it's likely that whatever kernel you're using has switched Thread mode to using the process stack (PSP).
Most of your investigations suggest that the PSP was in use, with your memory peek around the PSP and MSP being pretty much indisputable. The only bit of evidence you have for it having been the MSP is the results of the fault_handler function, for which you have not posted the source; so my first guess would be that this function is broken in some way.
Do also remember that one common reason for entering the HardFault handler is that another exception handler has caused an exception. This can easily happen in cases of memory corruption. In these cases (assuming Thread mode uses the PSP) the CPU will first enter Handler mode in response to the original exception, pushing r0-r3,r12,lr,pc,psr to the process stack. It will start executing the original exception handler, then fault again, pushing r0-r3,r12,lr,pc,psr to the main stack while entering the HardFault handler. There's often some unravelling to do.
old_timer also mentions using real assembly language, and I agree here too. Even though the ((naked)) attribute should be removing the prologue and epilogue (between them most of the possible 'compilerisms'), your code would simply be far more readable if it was written in bare assembly language. Inline assembly language has its uses, for example if you want to do something very low-level that you can't do from C but you want to avoid a call-return overhead. But when your entire function is written in assembly language, there's no reason to use it.

SystemInit function ends up at add odd address in Kiel ARM compiler

I'm seeing some weird behaviour in the Kiel compiler. This is the reset code, I'm using a generic STM32F103C8 board (which uses an M3 core), and the SystemInit function (which is provided by the Kiel libraries) has somehow ended up at an odd address (0800043D), you can see from the screenshot below that the pointer at 080001F8 contains this value and sure enough, when the instruction at the PC (BLX r0) is executed, a hard fault occurs. Has anyone seen this happen before? How can I get it to put the SystemInit function at an even address?
Also, my main() function seems to have ended up at an odd address as well... Shouldn't the compiler align these for me?
These 2 lines from the map file are interesting:
0x08000000 0x000000ec Data RO 1224 RESET startup_stm32f10x_md.o
0x080000ec 0x00000008 Code RO 1269 * !!!main c_w.l(__main.o)

Find which instruction caused a trap on Cortex M3

I am currently debugging a hard fault trap which turned out to be a precise data bus error on a STM32F205 Cortex-M3 processor, using Keil uVision. Due to a lengthy debugging and googling process I found the assembly instruction that caused the trap. Now I am looking for a way to avoid this lengthy process next time a trap occurs.
In the application note 209 by Keil it says:
PRECISEERR: Precise data bus error:
0 = no precise data bus error
1 = a data bus error has occurred, and the PC value stacked for the exception return points to the instruction that caused the fault. When the processor sets this bit it writes the faulting address to SCB->BFAR
and also this:
An exception saves the state of registers R0-R3, R12, PC & LR either the Main Stack or the Process Stack (depends on the stack in use when the exception occurred).
The last quote I am interpreting as such that there should be 7 registers plus the respective stack. When I look up my SP address in the memory I see the address that caused the error at an address 10 words higher than the stack pointer address.
My questions are:
Is the address of the instruction that caused the trap always saved 10 words higher than the current stack pointer? And could you please point out a document where I can read up on how and why this is?
Is there another register that would contain this address as well?
As you said, exceptions (or interrupts) on ARM Cortex-M3 will automatically stack some registers, namely :
Program Counter (PC)
Processor Status Register (xPSR)
r0-r3
r12
Link Register (LR).
For a total of 8 registers (reference : Cortex™-M3 Technical Reference Manual, Chapter 5.5.1).
Now, if you write your exception handler in a language other than assembly, the compiler may stack additional registers, and you can't be sure how many.
One simple solution is to add a small code before the real handler, to pass the address of the auto-stacked registers :
void myRealHandler( void * stack );
void handler(void) {
asm volatile("mov r0, sp");
asm volatile("b myRealHandler");
}
The register BFAR is specific to bus faults. It will contain the faulty address, not the address of the faulty instruction. For example, if there was an error reading an integer at address 0x30005632, BFAR will be set to 0x30005632.
The precise stack location of the return address depends on how much stack the interrupt handler requires. If you look at the disassembly of your HardFault_Handler, you should be able to see how much data is stored on the stack / how many registers are pushed in addition to the registers pushed by the hardware interrupt machinery (R0-R3, R12, PC, LR & PSR)
I found this to be a pretty good idea on how to debug Hard Faults, though it requires a bit of inline assembly.

Address of Instruction that Caused exception ARM

which register stores the address of instruction which caused an exception(eg DataAbort)
is it always lr-4 (in 32) or there is a specific register
in powerpc there is but in arm I dont know
For Cortex-A and Cortex-R, at entry to the Data Abort handler the LR of ABT mode will contain the address of the offending instruction +8 (no matter whether the offending instruction was in ARM state or Thumb state).
See section B1.8.3 (especially Table B1-7) of the ARM ARM for details.

ARM DCD working and Executing from RAM

I am using MBD9F126(ARM Cortex R4) micro-controller. In that I am flashing code into ROM and then I am executing the code from RAM after RAM copy. I am using the Green hills compiler. Before the RAM copy I am executing basic board Initialization code.
LDR r12, ADDRESS_START_PREINIT
BLX r12
ADDRESS_START_PREINIT:DCD Start_PreInit
Start_PreInit is board initialization function. IF I am giving like this after BLX it'll branch to RAM location. As RAM copy is not done yet so it goes to unknown area.
Instead of this If I am writing
bl Start_PreInit
Its working properly that is going to ROM location of code. I don't why compiler has such a behavior?
And also
ADDRESS_START_PREINIT:DCD Start_PreInit . Is it done during linking??
The bl Start_PreInit instruction works because the branch target is encoded in the instruction opcode as an offset relative to the current PC (r15). Since r15 is pointing to ROM, the target is another ROM address.
The blx r12 instruction branches to the absolute address that was loaded into the r12 register.
When you load the contents of ADDRESS_START_PREINIT into a register, what you're getting is the absolute address that the linker calculated for the Start_PreInit address. Apparently the linker has fixed that to the RAM absolute address.
You might be able to fix the problem with a linker configuration or by performing some transformation on r12 when it's loaded with the RAM address (something like (r12 - RAM_START) + ROM_START) before branching. Or use the pc-relative encoding instead of the register-absolute encoding for the branch instruction if the target address is in range.

Resources