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.

MSP430 emulator problem stepping through interrupt

Other Parts Discussed in Thread: MSP430F5437A

I am having a problem and wanted to see if any one else has seen this.

I am using a MSP430F5437A which I am debugging using the MSP-FET430UIF emulator in CCS4.2.1.

I have a timer interrupt that is executing, fine normally, but when I try single stepping through the code, the code mysteriously jumps over the RETI instruction and erroniously starts executing an unrelated subroutine ( not an interrupt) that happens to get linked in the space following the ISR.

For brevity, I will post only the entries and exits of these reoutines, which should give you an idea of what is going on:

The Timer0_A0 ISR  C code looks like this ( the .... is a lot of counter and LED code unrelated to the problem:

#define FLAG_WAKE       (P2OUT |= BIT0)

#pragma vector = TIMER0_A0_VECTOR

__interrupt void Timer0A0_ISR(void)
{
    int i;
    FLAG_WAKE;        //indicate ISR state
     i=TA0IV;                      //clear flags

    if (nav_ticks > 0){
        nav_ticks--;
    }
    else {
         nav_ticks = nav_time;
        nav_pend = true;
    }
   ...

   _nop();
    __bic_SR_register_on_exit(CPUOFF);// Clear LPM0 bits from 0(SR)
    _nop();
}

The disassembly entry looks like this:

         Timer0A0_ISR:
0x07B08:   8321                DECD.W  SP
0x07B0A:   D3D2 0203           BIS.B   #1,&Port_1_2_P2OUT
0x07B0E:   4291 036E 0000      MOV.W   &Timer0_A5_TA0IV,0x0000(SP)
0x07B14:   9392 2052           CMP.W   #1,&nav_ticks
0x07B18:   3803                JL      (C$L5)
0x07B1A:   8392 2052           DEC.W   &nav_ticks
0x07B1E:   3C05                JMP     (C$L6)

         C$L5:
0x07B20:   4292 8A90 2052      MOV.W   &nav_time,&nav_ticks
0x07B26:   4392 2054           MOV.W   #1,&nav_pend

The disassembly exit looks like this:

         C$L11:
0x07B6C:   4303                NOP
0x07B6E:   C0B1 0010 0002      BIC.W   #0x0010,0x0002(SP)
0x07B74:   4303                NOP
0x07B76:   5321                INCD.W  SP
0x07B78:   1300                RETI
         some_init:
0x07B7A:   150A                PUSHM.W #1,R10
0x07B7C:   8321                DECD.W  SP
0x07B7E:   403C 8A7C           MOV.W   #0x8a7c,R12
0x07B82:   12B0 7E00           CALL    #somesend
0x07B86:   4C81 0000           MOV.W   R12,0x0000(SP)
0x07B8A:   430A                CLR.W   R10

 

 

In the above code, when single assembly stepping, the code makes it through the ISR to the end of the C$L11 part, and makes it to the INCD.W  SP instruction. When this instruction is executed with the assembly single step, the processor stops on the PUSH instruction at the start of someinit rather than stopping on the RETI instruction. During this time, the stack and stack pointer are all behaving as expected. The return stack has the right values for the routines. The SP gets incremented by the INC.W SP instruction, but the RETI is skipped and has no effect on the SP, PC, or SR. It looks like the INC.W SP may have also incremented the PC, thus skipping the RETI instruction, but this is only conjecture.

When this code is run without single stepping, it does not exibit this bahavior.

Any comments are appreciated.

  • Hi Bill,

    Welcome to the forum.

    For what it's worth, I duplicated your experience with INCD  SP immediately prior to a RETI.  It seems to occur for any single-word instruction where the destination is the SP.  But only when it immediately precedes a RETI.

    The erratasheet already has a few "debug-only" erratum, and I think you found another one that isn't yet documented.  (For example see CPU39 where the effect is the same.)

    Not bad for your first post.  ;-)

    Jeff

  • This one is particularly annoying since this is how the C compiler constructs the ISR using the predefined macros. This code would be repeated anytime you have a local variable in an ISR. I am surprised that I am the first to come across this.

    Knowing that it is the SP manipulation that causes the problem allows me to write around the problem. I guess I can rewrite the routine to not use a variable or change the variable to a global so that it does not have to adjust the stack before the  RETI.

    Thanks for your help.

  • Usually I see a POP Rxx instruction at the end of the ISR before the RETI.  That code would be safe since the destination is another register, not the SP.  That might be why you're the "first".

    Does your [...] code take the address of <i> or maybe do you have some compiler optimizations turned on even though you are debugging?  Both of these could cause your local var to be stored on the stack instead of in a register.

    One more quick observation.  TA0 has two interrupt vectors; one for CCR0 and one for all the others.  You might not want to read TA0IV from the CCR0 ISR.  CCR0 interrupt acceptance is special because it automatically clears the request flag.  You don't need to read TA0IV, and if you do you might accidentally erase an interrupt request from some other TA0 channel (eg, CCR1, CCR2, etc) without handling it.

    Jeff

  • Bill Hunter said:
    Knowing that it is the SP manipulation that causes the problem allows me to write around the problem.

    The code is executed correctly. It's the EMM/debugger combot that adds an additional 2 to the PC when single-stepping.

    So the solution would be to simply not single-step to the RETI instruction. :)

    There are a lot of debugger-related errata: EMM6, EMM13, also CPU27

**Attention** This is a public forum