gdbmicrocontrollercortex-mthumb

Why there is a dead loop in the generated assembly for a Cortex-M interrupt handler?


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?


Solution

  • (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....