MSP430F5249: Program counter is corrupted when setting breakpoint in timer ISR

Expert 1705 points
Other Parts Discussed in Thread: MSP430F5249, MSP430F5529, MSP430F5244, MSP-TS430RGC64C

Hi,

I'm debugging with MSP430F5249.

I have a question about breakpoint.

1. Set a breakpoint at the beginning of the timer interrupt.
2. Execute the code, and the code will stop at the beginning of the timer interrupt (where the breakpoint is set).
3. I execute "step into" within the timer interrupt.
4. After executing 3 several times, the program counter points out of the code.

I have confirmed that processes 1 to 4 occur many times.

Please tell me why the phenomenon of 4 occurs when "step into" is executed by the timer interrupt.

Thanks,

Koki

  • Hi Koki,

    Have you lowered your optimization settings in CCS? Does the disassembly screenshot show where the PC ends up? Are there any other interrupts enabled?

  • > Set a breakpoint at the beginning of the timer interrupt.

    → The optimization setting is as follows.

      

     

    > Does the disassembly screenshot show where the PC ends up? 

    → The code area of Flash from the .map file is up to 0xFF80.

      PC refers to the memory value of Bank B (out of code).

     

    > Are there any other interrupts enabled?

    → For interrupts, only the timer is used.

      In the timer interrupt, the timer interrupt is not disabled.

      "step into" is executed with the timer interrupt enabled.

     

    Thanks,

    Koki

  • Hi Koki,

    Your optimization settings picture didn't show up unfortunately. Also, are you using any low-power modes (LPMx) in your code? This can cause debugging issues in CCS where the part goes to sleep and the PC may be read incorrectly by CCS. I would recommend using the device in active mode when debugging. Also, to verify the timer code is working correctly, I would suggest toggling an IO at different parts of the code.

  • Hi, 

    >Your optimization settings picture didn't show up unfortunately.

    →Sorry, the optimization setting is as follows.

    >Are you using any low-power modes (LPMx) in your code?

    → Yes, I'm using LPM3 in my project.

       1. Enter LPM3 in main ()

       2. Change to Active mode from LPM3 at the beginning of Timer interrupt

       3. Execute "step into" in the Timer interrupt

       4. PC shows incorrect value when returning from Timer interrupt to main ()

      Is it related to LPMx that the PC shows incorrect values?

      

    >This can cause debugging issues in CCS where the part goes to sleep and the PC may be read incorrectly by CCS.

    >I would recommend using the device in active mode when debugging.

    →Is there any document that describes the above description?

     If not, please tell me more about the above.

     

    Thanks,

    Koki

  • Hi Koki,

    The formatting of your replies make it hard to distinguish between your comments and my previous comments. Please use the Quote feature in the thread to make everything easier to read. After clicking Reply, highlight text above and a "Quote" icon will pop up. Click that to insert whatever is highlighted to insert a quote. I've done that with your latest comments.

    Sorry, the optimization setting is as follows.

    I'm sorry but your picture did not show up. After clicking Reply, go to Insert > Image/video/file > Upload > (select image, preferably .jpg or .png) > Ok.

    Is it related to LPMx that the PC shows incorrect values?

    Most likely. I would highly suggest using Active mode or worst case, LPM0, during an active debug session. If you're using LPM3, then SMCLK is disabled. For LPM0, SMCLK is optionally active, meaning if there's a clock request for it, it will remain active.

    Is there any document that describes the above description?

     If not, please tell me more about the above.

    You can find the operating modes in Table 1-2 in the user's guide. It's important to understand the operating modes, and since they affect the system clocks, this can affect debugging.

  • I'm sorry but your picture did not show up. After clicking Reply, go to Insert > Image/video/file > Upload > (select image, preferably .jpg or .png) > Ok.

    I'm Sorry, the optimization setting is as follows.

     

    Most likely. I would highly suggest using Active mode or worst case, LPM0, during an active debug session. If you're using LPM3, then SMCLK is disabled. For LPM0, SMCLK is optionally active, meaning if there's a clock request for it, it will remain active.

    The current TimerB0 clock source is ACLK.

    From the table below, ACLK is Active for LPM3.


    So I don't think what you're saying is true this time around.

    Just in case, I set the clock source of TimerB0 to SMCLK and operated it with LPM0, but the same phenomenon (PC shows an incorrect value) occurred.

     

    Details of the program I am currently running is as follows.

    The entire program consists of main () and Timer B0 interrupt.

     ■ main ()

    Repeating with while (1)

    Enter LPM3 → no operation→ Enter LPM3 → no operation→....

     ■ Timer_B0 interrupt

    Enter to Active mode  → Add Offset to TBCCR0 → no operation → return to main ()

    It is a source code that repeats main () → timerB0 → main () → timerB0 () → ....

    This time, set a breakpoint at the timing of transition to timer B0 and execute "step into".

    Then, when returning from Timer_B0 () to main (), the PC will show an incorrect value.

    If I do not excute "step into" (press the resume button to restart the program), the PC will show the correct value and the program will continue to run.

    It's device- and program-independent, and I think it's a problem with CCS's debug approach, but I'm not sure why.

    Best,

     

    Koki

     

  • The optimizations look fine. It could be a CCS issue or limitation. What happens if you disable interrupts when assembly stepping in CCS? Also, what version of CCS are they using?

    http://software-dl.ti.com/ccs/esd/documents/users_guide/ccs_debug-main.html#program-memory-load-options

  • Hi, James

    What happens if you disable interrupts when assembly stepping in CCS?

    I disabled interrupts in the CCS settings, but PC was show an incorrect value(0x1C0B0).

     In the correct behavior, the PC is return to 0x17f10.

      

    what version of CCS are they using?

    CCS Version: 10.2.0.00009.

    Thanks,

  • Thanks for those details. I tried to duplicate the issue using CCS v10.3 and a MSP430F5529 LaunchPad. I imported the MSP430F55xx_tb_05.c code example which uses ACLK as the Timer B clock source. I set a breakpoint at the beginning of the Timer B0 interrupt service routine (ISR) and ran the code. At the breakpoint, I clicked "Step Into". Then, I clicked Run again. I did this over and over and never had an issue.

    I do not have a MSP430F5249 device, but please share your code so I can try to replicate the issue on the MSP430F5529.

  • Hi, James

    I also have an MSP430F5529 LaunchPad.

    Therefore, I verified the operation with MSP430F5529 LaunchPad.

    please share your code so I can try to replicate the issue on the MSP430F5529.

    It doesn't always happen, but when I verified the operation several times, the phenomenon that "PC shows incorrect value" occurred.

    I will attach the source code.

    3201.main.c
    #include <msp430.h>
    
    #define set_LPM_Mode(x) __bis_SR_register(x)
    static const unsigned short SET_LP_MODE[5]={GIE, LPM0_bits|GIE, LPM1_bits|GIE, LPM2_bits|GIE, LPM3_bits|GIE};
    unsigned int count=4;
    
    #define LPM3_CLR() __bic_SR_register_on_exit( LPM3_bits )
    #define TB0_CNT (8192)       /* 0.5sec = 8192 / 16384 */
    
    int main(void)
    {
    
        WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
        TB0CCTL0 = CCIE;                                    // TBCCR0 interrupt enabled
        TB0CCR0 = TB0_CNT;                                  // TB0_CNT / 32768Hz
        TB0CTL = TBSSEL__ACLK | MC__CONTINOUS | ID_1 | TBCLR;       // ACLK, continuous mode
    
        while(1)
        {
            set_LPM_Mode(SET_LP_MODE[count]); // Enter LPM3
            __no_operation();                 // For debugger
        }
    }
    
    /* Timer0_B0 interrupt service routine */
    #pragma vector = TIMER0_B0_VECTOR
    __interrupt void INT_Timer0B0ISR (void)
    {
        LPM3_CLR();
        TB0CCR0 += TB0_CNT;                         /* Add Offset to TBCCR0 */
        __no_operation();                 // For debugger
        return;
    }
    

    Thanks,

    Koki

  • Hi Koki,

    The issue is caused by trying to single step across the LPM entry (not exit) in main(). If you don't do that, you can single step throughout the rest of the code without issues. Instead, when you reach the LPM entry function set_LPM_Mode(), click the green and yellow "Run" button to enter LPMx.

    If you encounter the scenario where your program counter points to an unknown or undesired location, just click the Run button and it should return correctly and continue. This seems to indicate that the JTAG communication is interrupted or corrupted when the CPU goes to sleep.

  • Hi, James

    This is only a problem with the debugging method, right ?

    This seems to indicate that the JTAG communication is interrupted or corrupted when the CPU goes to sleep.

    If you would like to know more about the above, and if there is any applicable documentation, please let me know.

    Thanks,

    Koki

  • This is only a problem with the debugging method, right ?

    That's correct. If you removed the LPM and just used active mode, the issue should not happen.

    If you would like to know more about the above, and if there is any applicable documentation, please let me know.

    This behavior seems very similar to the EEM13 errata for the MSP430F5529 device. I'm checking to see if that errata applies to the MSP430F5249 or not. In the meantime, I would just use the workaround that I described earlier or switch to active mode when debugging.

  • Hi, James

    . I'm checking to see if that errata applies to the MSP430F5249 or not.

    In fact, the device to be commercialized is MSP430F5244.

    Explaining the current situation in detail, the same phenomenon occurs in MSP430F5249 and MSP430F5244.

    Therefore, I would appreciate it if you could check not only MSP430F5249 but also MSP430F5244 for errata.

    Thanks,

    Koki

  • Explaining the current situation in detail, the same phenomenon occurs in MSP430F5249 and MSP430F5244.

    Therefore, I would appreciate it if you could check not only MSP430F5249 but also MSP430F5244 for errata.

    Yes, that's not surprising since they are just memory variants.

    I can verify the EEM13 exists on F5529. In the CCS project with LPM3 entry and exits, I ran the code, placed a breakpoint in the ISR, code halted there, removed breakpoint, ran code and then clicked Pause. The PC got lost.

    Can they try this process on the F524x? If the same thing happens, then I suspect it is the same errata. Regardless, I would encourage your customer to continue their software development and perhaps not use LPM when debugging.

  • Hi,

    Can they try this process on the F524x?

    Yes, we have already confirmed.

    The same phenomenon has been confirmed using the above code on our F524x (F5244 and F5249).

    I suspect it is the same errata.

    If you can confirm the phenomenon, do you plan to issue an errata?

    I would encourage your customer to continue their software development and perhaps not use LPM when debugging.

    Yes, I will tell my customer.

    Thanks,

     

    Koki

  • Thanks for confirming. Before updating or issuing an errata, we'll need to verify on our side. With the upcoming US holiday, this could take me a week or two. If you don't hear back from me after two weeks, please reply to this thread asking for an update.

  • Hi Koki,

    I wanted to update you with the latest status. I'm still waiting on the samples to be delivered, so I can verify this behavior. Thanks for your patience, and I'll try to update you after receiving the samples or next week if they haven't been received by then.

  • Hi,

    Thank you! I am waiting for your contact.

    I would be grateful if you could get information on whether the errata will be applied first from MSP430F5244. (This is because the device my customer is using is MSP430F5244.)

    Also, in our results, it occurs only once in multiple times, so please verify it multiple times.

    Best,

    Koki

  • Hi Koki,

    Thanks for your patience. I finally received the F5249 samples and was able to locate the corresponding MSP-TS430RGC64C target board.

    Initially, I was able to replicate this issue using the customer's code. However, the behavior was not consistent with the behavior related to the EEM13 errata on the F5529 device.

    Digging deeper, I discovered that the root cause for this issue is related to the preprocessor macros used for the intrinsic functions.

    #define set_LPM_Mode(x) __bis_SR_register(x)
    static const unsigned short SET_LP_MODE[5]={GIE, LPM0_bits|GIE, LPM1_bits|GIE, LPM2_bits|GIE, LPM3_bits|GIE};
    #define LPM3_CLR() __bic_SR_register_on_exit( LPM3_bits )

    After I removed these macros and simply using the intrinsic functions directly in the code, I could NOT replicate the issue. As I mentioned above, the trigger for this issue was single-stepping into the LPM3 entry function, but now this can be done and the PC is not corrupted. Here's the code that I used.

    #include <msp430.h>
    
    #define TB0_CNT (8192)       /* 0.5sec = 8192 / 16384 */
    
    int main(void)
    {
    
        WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
        TB0CCTL0 = CCIE;                                            // TBCCR0 interrupt enabled
        TB0CCR0 = TB0_CNT;                                          // TB0_CNT / 32768Hz
        TB0CTL = TBSSEL__ACLK | MC__CONTINOUS | ID_1 | TBCLR;       // ACLK, continuous mode
    
        while(1)
        {
            __bis_SR_register(LPM3_bits + GIE);       // Enter LPM3, enable interrupts
            __no_operation();                         // For debugger
        }
    }
    
    /* Timer0_B0 interrupt service routine */
    #pragma vector = TIMER0_B0_VECTOR
    __interrupt void INT_Timer0B0ISR (void)
    {
        __bic_SR_register_on_exit(LPM3_bits);   // Exit LPM3
        TB0CCR0 += TB0_CNT;                     /* Add Offset to TBCCR0 */
        __no_operation();                       // For debugger
        return;
    }
    

    Also, the "return" at the end of the ISR is not needed.

    /* Timer0_B0 interrupt service routine */
    #pragma vector = TIMER0_B0_VECTOR
    __interrupt void INT_Timer0B0ISR (void)
    {
        __bic_SR_register_on_exit(LPM3_bits);   // Exit LPM3
        TB0CCR0 += TB0_CNT;                     /* Add Offset to TBCCR0 */
        __no_operation();                       // For debugger
        return;
    }

    Please have your customer try this on their device. Also, please note that I was not able to test this on the F5244 since there is not a target board that supports this device. However, because these devices are so similar (basically a memory variant), then the root cause is most likely the same for both devices.

    Please let me know if this resolves their issue.

  • Hi,

    Thank you for checking.

    As a result of changing the program description method, the phenomenon of "setting the PC to an incorrect location" no longer occurs.

    Are there any other intrinsic functions that need to be handled with care, including this phenomenon (__bis_SR_register)?

    Thanks,

    Koki

  • Hi Koki,

    Thanks for confirming that this resolved their issue. I would not recommend redefining or redeclaring any of the original intrinsic functions. You can find all MSP430 intrinsics in Table 6-5 in the MSP430 Optimizing C/C++ Compiler User's Guide.

    Please mark this thread resolved.