This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Debugging Jumps to random memory location

Other Parts Discussed in Thread: MSP430F5529, MSP430F5310, MSP430F5438A, MSP430F1612

I'm trying to debug a program but the problem I'm having is that when I press resume in debug the program would stop working and when I press pause, the disassembly shows that I so how manage to jump to some random memory location. But if I cycle power to the board without having the debugger plugged in, it runs normally. Not sure what to do, seems like my program counter is jumping all over the place when using the debugger and acts normally when its not used.

Any help would be great.

Current setup:

Lastest and greatest Code Composer

Custom PCB with msp430f5529 @ 20Mhz with vcore step up to level 2.

  • co tang87699 said:

    I'm trying to debug a program but the problem I'm having is that when I press resume in debug the program would stop working and when I press pause, the disassembly shows that I so how manage to jump to some random memory location.

    If you just run without stepping with the debugger does your application function correctly?  How do you know the memory location is random? Is this because you don't see any source code?  It is possible you stepped into a C library runtime function which you don't have the source for.

    Darren

  • No, that is the problem. I'm running the program with my debugger and it stopf functioning (program locks or freezes). The disassembly show the cursor stuck at a random program counter location where everyting is FF (or blanks) and the program hangs because the isn't any instruction to tell it where to go next. I can scroll it all the way up and I can see my program code. I troubleshooted to the point where I think  the problem is the _delay_cycle function. Using a loop with it inside caused it to go crazy only with the debugger. I re-wrote using a timer and everything running smoothly with the debugger now.

  • co tang87699 said:
    I think  the problem is the _delay_cycle function

    Unlikely. It's not a funciton at all. it is a so-called intrinsic (a compiler-specific instruction) that causes the compiler to emit some code that takes exactly the given number of CPU cycles to complete. This code does nothing. It just idles around for the given number of CPU cycles (plus the execution times of any interrupts that happen in-between).

    If you encounter random jumps, there ar eusually three reasons for this. Very common is that you have an interrupt enabled but not ISR for this. This causes the CPU to jump into the void when the interrupt triggers - which can be at a random moment, including instantly or never.

    Next is a index-out-of-bounds access. If you have an array of 100 bytes size and you write to index 100, you write behind the array, overwriting whatever there might be. There is no runtime-check. You may even use a negative index, overwriting ram before the array. If the overwritten position happens to be the stack, this may cause the processor to 'return' to an apparently random position rather than the place the current funciton was called from.

    Third is a stack overflow. if you use lots of local variables, recursions, nested interrupts or just too many nested function calls, teh stack will grow. And grow. And eventually it will grow into the area of your global variables. Not only overwriting them, but also being overwritten by any write to the global variables. Worst case, the stack falls out of ram area and anything written to it, including the return addresses, goes into the void and is then restord form the void as, likely, 0xffff. Causing the processor to 'return' to 0xffff and either rampage through memory or cause a reset.

  • Hello Jens-Micheal,

    The program I did doesn't use arrays nor have any nested interrupts of functions calls. The variable size is quite small, around 5 different variables all int's. The ISR seems like a likely culprit, although I did initialized a non-used ISR with a trap function. Either way, its working.

    A question I have is, is there a way to determine which interrupt triggers the trapped in the ISR_trap function? Because I was constantly getting a trap there until I clean my project and rebuilt. Then all was fine again....

  • Hello,

    Just thought I would add (for everyone else's benefit) that I've also seen jumps to random locations (though usually location 0x0) when the DCO is mis-programmed and the CPU is being accidentally overclocked. Most often this occurs on a function return when the stack can't be popped before the CPU wants the next instruction.

    ~Brian

  • co tang87699 said:

    A question I have is, is there a way to determine which interrupt triggers the trapped in the ISR_trap function? Because I was constantly getting a trap there until I clean my project and rebuilt. Then all was fine again....

    This is a great question. What I like to do with my programs is I add a file that has a separate ISR trap for every single unused ISR available in the part. Then you can see which ISR it is trapped in, which should give you a hint about what interrupt is causing the problem. I've attached an example file for the G2553 that I've used before:

    /* --COPYRIGHT--,BSD
     * Copyright (c) 2012, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * --/COPYRIGHT--*/
    #include <msp430.h>
    
    #pragma CHECK_ULP("-2")
    
    #pragma vector=ADC10_VECTOR
    __interrupt void ADC10_ISR(void)
    {
    	while(1)
    	{
    		_nop(); //TRAP HERE
    	}
    }
    
    #pragma vector=COMPARATORA_VECTOR
    __interrupt void COMPARATORA_ISR(void)
    {
    	while(1)
    	{
    		_nop(); //TRAP HERE
    	}
    }
    
    #pragma vector=NMI_VECTOR
    __interrupt void NMI_ISR(void)
    {
    	while(1)
    	{
    		_nop(); //TRAP HERE
    	}
    }
    
    #pragma vector=PORT1_VECTOR
    __interrupt void PORT1_ISR(void)
    {
    	while(1)
    	{
    		_nop(); //TRAP HERE
    	}
    }
    
    #pragma vector=PORT2_VECTOR
    __interrupt void PORT2_ISR(void)
    {
    	while(1)
    	{
    		_nop(); //TRAP HERE
    	}
    }
    
    #pragma vector=TIMER0_A0_VECTOR
    __interrupt void TIMER0_A0_ISR(void)
    {
    	while(1)
    	{
    		_nop(); //TRAP HERE
    	}
    }
    
    #pragma vector=TIMER0_A1_VECTOR
    __interrupt void TIMER0_A1_ISR(void)
    {
    	while(1)
    	{
    		_nop(); //TRAP HERE
    	}
    }
    
    #pragma vector=TIMER1_A0_VECTOR
    __interrupt void TIMER1_A0_ISR(void)
    {
    	while(1)
    	{
    		_nop(); //TRAP HERE
    	}
    }
    
    #pragma vector=TIMER1_A1_VECTOR
    __interrupt void TIMER1_A1_ISR(void)
    {
    	while(1)
    	{
    		_nop(); //TRAP HERE
    	}
    }
    
    #pragma vector=USCIAB0RX_VECTOR
    __interrupt void USCIAB0RX_ISR(void)
    {
    	while(1)
    	{
    		_nop(); //TRAP HERE
    	}
    }
    
    #pragma vector=USCIAB0TX_VECTOR
    __interrupt void USCIAB0TX_ISR(void)
    {
    	while(1)
    	{
    		_nop(); //TRAP HERE
    	}
    }
    
    #pragma vector=WDT_VECTOR
    __interrupt void WDT_ISR(void)
    {
    	while(1)
    	{
    		_nop(); //TRAP HERE
    	}
    }
    
    The C2000 team does something similar in their projects I think.

    Regards,

    Katie

  • Thanks Katie, I'll implement that right away. At least it'll give me another way of debugging.

  • Katie Enderle said:
    I add a file that has a separate ISR trap for every single unused ISR available in the part.

    The drawback of this approach is that you cannot set a breakpoint on each of these ISRs. No MSP supports so many hardware breakpoints, so you have to test them one by one.

    An alternative is to use some inline assembly:

    #pragma vector=ADC10_VECTOR
    __interrupt void ADC10_ISR(void)
    {
        ASM("MOV #1, R15");
        ASM("MOV #catch, R0"); // or "JMP #catch", depending on how close they are.
    }

    __interrupt void catch(void)
    {
        while(1)
        {
            _nop(); //TRAP HERE
        }
    }

    So every ISR loads R15 with a certain value and then jumps to the same catch loop where you can put your breakpoint.

  • Hi co tang,

    i am also curious with your question. I am having problem with debugging 5xx devices since the last two days, and it is very weird (sometime it even damaged my JTAG fuse). Everytime i do pause, the debugger will stop at address 0x200. 

    I found out that the cause of this is going into LPM0. If the code stays in active mode, the debugger works fine.

    Here is my test code:

    #include <msp430.h>
    
    #define GO_LPM
    
    void main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
      P1DIR |= 0x01;                            // P1.0 output
      TA0CCTL0 = CCIE;                             // CCR0 interrupt enabled
      TA0CCR0 = 50000;
      TA0CTL = TASSEL_2 + MC_1;                  // SMCLK, upmode
    
    #ifdef GO_LPM
      _BIS_SR(LPM0_bits + GIE);                 // Enter LPM0 w/ interrupt
    #else
      _BIS_SR(GIE);                 // Enter LPM0 w/ interrupt
      while(1);
    #endif
    }
    
    // Timer A0 interrupt service routine
    #pragma vector=TIMER0_A0_VECTOR
    __interrupt void Timer_A (void)
    {
      P1OUT ^= 0x01;                            // Toggle P1.0
    }
    
    

    you can test the code by enabling/disabling GO_LPM macro definition to see the differences when pausing the debugger.

    I tested on several PCs with MSP430F5438A, MSP430F5529, and MSP430F5310, and CCS v5.3.00090 with MSP430 DLL v3.2.5.4.

    If you are using LPM (low power mode), can you also try to remove the code and see if it solves the problem, and please let us know the result. I will also talk to the product team about this, and will let you know if we found something.

  • Jens-Michael,

    You are right. I usually don't put breakpoints in them - usually my code is failing at a deterministic point so I can usually tell if it has stopped (trapped in while(1)) - so then I just pause the debugger and I can see which Trap ISR it is sitting in spinning its wheels :-) I like your method though, that is pretty clever.

    -Katie

  • Leo Hendrawan said:

     Everytime i do pause, the debugger will stop at address 0x200. 

    I found out that the cause of this is going into LPM0. If the code stays in active mode, the debugger works fine.

    This sounds like EEM13 to me (from 5xx errata docs):

    EEM13

    EEM Module

    Function Halting the debugger does not return correct PC value when in LPM
    Description When debugging, if the device is in any low power mode and the debugger is halted, the program counter update by the debugger is corrupted. The debugger is unable to halt at the correct location.
    Workaround None.
    Note: This erratum applies to debug mode only.

  • Another question, what the clock speed of the USB Debugger? The thing with mine is that I noticed a lot is when I try to step through a section of code that I know it works and just stops working, I would have to hit stop and find that it jumped to some other memory location. This only happens with a debugger plugged in. I can power it up and it would work normally. That only other thing that I can think of is the MSP I'm using I usually max out the clock that it can handle.

  • co tang87699 said:
    Another question, what the clock speed of the USB Debugger?

    Good question. The FET usually has a 12MHz crystal, likely for the TUSB chip which can generate the 48MHz for USB operation from it. Since the FET uses an MSP430F1612 processor with maximum CPU clock frequency of 8 MHz, I guess, it is running on 12/2 = 6MHz.
    I read somewhere that the SBW frequency is 6MHz too. However, the FET firmware is not publicly available, so details are unknown.

    co tang87699 said:
    when I try to step through a section of code that I know it works and just stops working, I would have to hit stop and find that it jumped to some other memory location.

    There are some errata related to the debugger. See the errata sheet. Maybe look at the errata sheets of some other MSPs. It' spossibl ethat this is a known behaviour and just didn't made it itno the errata sheet of you rspecific MSP.

  • Jens-Michael Gross said:
    Another question, what the clock speed of the USB Debugger?

    Good question. The FET usually has a 12MHz crystal, likely for the TUSB chip which can generate the 48MHz for USB operation from it. Since the FET uses an MSP430F1612 processor with maximum CPU clock frequency of 8 MHz, I guess, it is running on 12/2 = 6MHz.
    I read somewhere that the SBW frequency is 6MHz too. However, the FET firmware is not publicly available, so details are unknown.[/quote]

    The JTAG TCK coming out of the MSP-FET430UIF is 2 MHz in frequency. I measured it with a scope probe.

  • Brian Boorman said:
    The JTAG TCK coming out of the MSP-FET430UIF is 2 MHz in frequency.

    SBW or 4-wire JTAG?
    Anyway, the 6MHz might have been the maximum frequency supported by the MSPs SBW logic, not the frequency actually used by the FET.
    (Since SBW uses a bi-directional data line, I don't see how the FET could switch the line direction with the speed of its MCLK, except with external logic)

  • The 2 MHz was measured on a 4-Wire JTAG interface, and was the maximum clock rate on the TCK. The clock period actually seems to vary based on the activity of the other JTAG lines (which is reasonable since it has to be all bit-banged I/O).

    I also agree with your assesment regarding pod behavior in SBW mode.

    I do find it quite interesting that we use an MSP430 to debug MSP430's.

  • Brian Boorman said:
    I do find it quite interesting that we use an MSP430 to debug MSP430's.

    It's even more interesting that the LaunchPad is cheaper than the 1216 on it alone. ;)

    It's even more interesting that the MSP used to program and debug other MSPs is actually an old and much slower type. Maybe switching to a 5x family MSP with 24MHz would double (or more) the debug and programming speed.
    Well, many years ago I used a PC to debug a PC through serial connection. The target was running the GEOS OS, the debug PC was running DOS-based compiler and debugger. Especially great for debugging the kernel and mouse and keyboard drivers :)

**Attention** This is a public forum