0

I am learning the Cortex-M with the MDK uVision IDE. I wrote a simple SysTick_Handler() to replace the WEAK default SysTick_Handler() which is a simple dead loop.

My SysTick_Handler():

enter image description here

The disassembly:

enter image description here

I am confused by the the highlighted assembly line. It is simply a dead loop.

Why is it there? Why the toolchain still generated it despite that I already overwrite the WEAK default implementation with my own SysTick_Handler?

I can still place a breakpoint at that line and it can be hit. And in that case, my code will never be executed.

But strange thing is, if I removed the breakpoint at that line, my code can then be reached. How is that possible?

artless noise
  • 21,212
  • 6
  • 68
  • 105
smwikipedia
  • 61,609
  • 92
  • 309
  • 482
  • 3
    It looks like the disassembly is not properly matched to your function, i.e. off by a few bytes. It would also affect a breakpoint. A dead loop is often used as the default interrupt handler for non-maskable interrupts. So it is to be expected to find such code somewhere in your binary. – Codo Oct 05 '20 at 09:32
  • 1
    I agree with @Codo. It's quite possible that debugger got somehow confused with the WEAK reference and took the wrong address. – domen Oct 05 '20 at 09:36
  • Yes I did keep the default implementation which is a dead loop. It is really misleading if a debugger can be confused this way... – smwikipedia Oct 05 '20 at 09:38
  • disassemblers struggle to just disassemble the machine code, with optimize code there is no reason to ever assume that the high level and low level match up, much less rely on this. Turn off the display of the high level language and you will be golden, well with an architecture like this that has half a chance at disassembling the machine code...If you want to accurately set a breakpoint dont use a debugger with a gui, figure it out yourself and use something like openocd with the telnet interface. – old_timer Oct 05 '20 at 17:55
  • 1
    That looks like a different handler that is an infinite loop, the nop there to align it on a word boundary. – old_timer Oct 05 '20 at 21:34
  • @old_timer That's very possible. Because I have several other dead loop handlers for other interrupt sources. And that very dead loop in question **can** be hit. I don't think a linker should still link a WEAK symbol in this case and a debugger to make such mistake. But it is listed under SysTick_handler though outside the curly brace, which makes it looks even more weird. Well a simple trial of the uVision IDE leads me to such strange result. I have to say it is disappointing. – smwikipedia Oct 06 '20 at 02:06

1 Answers1

0

(Thanks to all the hints the community provided. I think I can explain it now.)

The dead loop is part of my main() function, which is like below. The main() function is just above my SysTick_Handler in the same C file.

int main (void)
{
    LED_Initialize();
    SysTick->VAL = 0x9000;                                                                                   
    //Start value for the sys Tick counter
    SysTick->LOAD = 0x9000;                                                                                  
    //Reload value 
    SysTick->CTRL = SYSTICK_INTERRUPT_ENABLE|SYSTICK_COUNT_ENABLE;  //Start and enable interrupt
    while(1)
    {
        ;  // <========= This is the dead loop I saw!
    }
}

To double confirm, I modified the while loop to below:

int main (void)
{
    volatile int32_t jj = 0;
    LED_Initialize();
    SysTick->VAL = 0x9000;                                                                                  //Start value for the sys Tick counter
    SysTick->LOAD = 0x9000;                                                                                 //Reload value 
    SysTick->CTRL = SYSTICK_INTERRUPT_ENABLE|SYSTICK_COUNT_ENABLE;  //Start and enable interrupt
    while(1)
    {
        ;
        jj+=0x12345; // <====== add some landmark value
    }
}

The generated code is like this now:

enter image description here

Though it is still placed under the SysTick_Handler. I place a break point there to check what's really going on:

enter image description here

enter image description here

The R1 is the constant 0x12345. The R0 is the local variable jj. We can see the R1 does contain the landmark value 0x12345, which is added to R0 (jj). So it must be part of my while(1) loop in the main().

So, the disassembly is correct. Only that the debugger failed to provide a correct interleaving between the source and the disassembly.

And btw, remember to rebuild the target after modifying the code otherwise the uVision IDE debugger will not reflect the latest change....

smwikipedia
  • 61,609
  • 92
  • 309
  • 482