cancel
Showing results for 
Search instead for 
Did you mean: 

Hard fault invalid state

ShawnP
Associate II

I'm trying to inject a simple wrapper around my timer interrput handler written in C - primarily for debug purposes to simplify debugging the state of registers and stack before the C code gets in and messes up the stack and state pushing all the junk it pushes to selectively save registers it's going to mess with etc. I just injected a little assembly (below) to forward the exception to my "real" handler giving me a break point prior to the 'C' code (vector table set to point to this wrapper).

I can run this in the debugger and I can break on the ldr instruction but if I proceed from there (either continue or single step) I end up in the hard fault hander with HFSR: 0x40000000 and CFSR: 0x20000 which seems to indicate and "invalid state" fault.

I'm fairly new to ARM so I'm sure it's something simple but it's got me beat.

NOTE: If I just set the vector table to point directly to my 'C' function everything works just fine - I end up in the 'C' function and everything operates as expected.

Any help would be appreciated.

Shawn

    .section	.text.TIM6_IRQHandler_Wrapper
TIM6_IRQHandler_Wrapper:
	ldr r0, =TIM6_IRQHandler
	add r0, #1
	bx r0
	.size	TIM6_IRQHandler_Wrapper, .-TIM6_IRQHandler_Wrapper

8 REPLIES 8

Doesn't TIM6_IRQHandler already load as an ODD number?

OR on 1, rather than ADD on 1

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ShawnP
Associate II

Yeah, you're probably right. But the original version of the code just had "bl TIM6_IRQHandler" - same result. So I figured I'd give adding 1 a shot. Then discovered I'm getting a hard fault even before getting to the branch - not even getting to the add instruction. BTW - based on your note I did two things 1) took out the add (same results) 2) changed add to ORR r0, #1 (same results)

What is the value of TIM6_IRQHandler ??

You said it worked when the value was in the Vector Table?

.word / dcd TIM6_IRQHandler

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

What are the first instructions in the TIM6_IRQHandler ?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ShawnP
Associate II

Value of TIM6_IRQHandler = 0x8000dc0 - taken from disassembly in wrapper code. And also cofirmed in disassembly for actual code below.

in the vector table code there is no /dcd switch - just .word TIM6_IRQHandler

	.word	TIM4_IRQHandler
	.word	TIM5_IRQHandler
	.word	TIM6_IRQHandler_Wrapper
	.word	TIM7_IRQHandler
	.word	TIM8_BRK_IRQHandler

right now TIM6_IRQHandler looks like this - just handing off to HAL. Will be gettiner more complicated later hence my desire to get a shim in place before I hit the C code.

void TIM6_IRQHandler(void)
{
  /* USER CODE BEGIN TIM6_IRQn 0 */
 
  /* USER CODE END TIM6_IRQn 0 */
  HAL_TIM_IRQHandler(&htim6);
  /* USER CODE BEGIN TIM6_IRQn 1 */
 
  /* USER CODE END TIM6_IRQn 1 */
}
          TIM6_IRQHandler:
08000dc0:   push    {r7, lr}
08000dc2:   add     r7, sp, #0
266         HAL_TIM_IRQHandler(&htim6);
08000dc4:   ldr     r0, [pc, #8]    ; (0x8000dd0 <TIM6_IRQHandler+16>)
08000dc6:   bl      0x80068bc <HAL_TIM_IRQHandler>
270       }

ShawnP
Associate II

Solved it thanks to your questions!! Your /dcd switch question got me to thinking what setting / switches are needed to set the LSB on the address. Then I looked at the .weak and .thumb_set

	.weak	TIM6_IRQHandler
	.thumb_set TIM6_IRQHandler,TIM6_IRQHandler_Wrapper

code in the startup module. Above is the "new" (working) version of the code and I set the vector table back to TIM6_IRQHandler and renamed the entry point in my C code to TIM6_IRQHandler_Main. Seems the .thumb_set statement sets the low bit in the vector. I had commented the .weak and .thumb_set statements out since I didn't need a weak label and I was setting the vector directly.

I need to do a bit more investigation to understand the full dynamics of the .weak, .thumb_set, the vector table and strong overrides. I think the linker somehow knows that when you override a weak address that the .thumb_set setting needs to be sticky.

Anyway, thanks a bunch for your help!!!

Shawn

DCD is the Keil/IAR equivalent to .word that GNU/GAS uses

Looking at the listing, or disassembly, file may show the bytes/words emitted by the Assembler. All the function addresses in the vector table should be odd.

On chips with an FPU watch for routines that push co-processor registers. These will fault if the co-processor is not enabled.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Piranha
Chief II

Someone already sorted it all out and reported:

https://community.st.com/s/question/0D53W00000dS8FcSAK/review-of-st-startup-code

Edited by moderation team to adjust to community guidelines