2

I'm trying to track down a problem on a MKV31F256 micro. The firmware immediately jumps to the hard fault handler on startup.

I'm able to set a breakpoint on the first assembly instruction in the reset handler and look at memory and the registers, and I was surprised to find the stack pointer was not set to the top of RAM (0x20008000). Rather, SP is set to 0x00000000

enter image description here

However, the initial stack value is correct in the vector table.

enter image description here

I was under the impression the Cortex M4 automatically loaded the first and second entry in the vector table into the SP and PC registers. Is this not the case?

I double checked on a different Cortex M4 micro (nRF52832) and SP is set correctly by the hardware on startup.

Is the automatic SP initialization an optional feature by the individual chip manufacturers?

CurtisHx
  • 995
  • 7
  • 12
  • Why do you have the `__asm volatile("ldr sp, =__stack");` line commented out? – brhans Feb 19 '20 at 13:42
  • @brhans that was my attempt at manually loading SP, but I didn't think about the `push {r4, lr}` instruction above it. If I have to, I'll write an assembly reset ISR that manually loads the SP, but I want to understand why this micro is not. – CurtisHx Feb 19 '20 at 13:45
  • The Cortex M4 I'm currently working with (STM32F427) has `ldr r0, =__RAM_segment_end__ mov sp, r0` as the 1st 2 instructions in the reset handler - but if I break before those get to execute my SP is already set to the expected value read from the 1st location in Flash (which is different to `__RAM_segment_end__` so it appears that it does load the SP at reset... Seems weird that yours doesn't. – brhans Feb 19 '20 at 13:50
  • 2
    In fact, the reference manual for your MKV31F256 specifically states in section 6.2.2 "Reads the start SP (SP_main) from vector-table offset 0" as the 1st step after a reset... very strange ... – brhans Feb 19 '20 at 14:04
  • `push {r4, lr}` with an invalid SP value will almost certainly cause a hardfault. I wonder if that instruction is even necessary though - it's not like you're ever going to 'return' from the reset handler. – brhans Feb 19 '20 at 14:27
  • @brhans you're correct. `push {r4, lr}` is causing a hardfault and is not necessary for the reset handler. It's there because the compiler doesn't know that the function will ever return. – CurtisHx Feb 19 '20 at 15:59
  • Does your compiler have a way to declare a 'naked' function like GCC's `__attribute__((naked)) `? Afaik this should then compile the function without all the 'extras'... – brhans Feb 19 '20 at 16:05

1 Answers1

1

I was under the impression the Cortex M4 automatically loaded the first and second entry in the vector table into the SP and PC registers. Is this not the case?

It should.
0x0 contains stack pointer.
0x4 contains reset handler address.

LR should also have been cleared to FF. I suspect your debugger is not resetting the core correctly.

Jeroen3
  • 21,976
  • 36
  • 73
  • Nailed it! My debugger was not resetting the core correctly. I'm using Segger J-Link and I was using the "MKV31F256xxx12 (allow security)" for debugged device. I changed it to "MKV31F256xxx12" and now everything is working. – CurtisHx Feb 19 '20 at 18:52