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.

TIMER Interrupt problem (msp430f5438 TinyOS)

Other Parts Discussed in Thread: CC2520

I'm trying to write a new platform for TinyOS using a f5438 and a CC2520.

I manage to compile Blink (the example app of TOS), but it's not working. I enabled just Timer0 and led0.

The problem is that the PC and SR values pushed before executing the Timer ISR (I tried TimerA0 and A1, with the same results), are not right.

At first I thought that might be a problem when waking up, so I added a task with an infinit loop to keep the system up, and the same happends.

 

(Tools mspgcc-4.4.5, tinyos-2.1.1, mspdebug 0.13, MSP-FETU430IF, Ubuntu 10.10.)

 

Start of the program

 

 

(mspdebug) regs

    ( PC: 05c00)  ( R4: 00b80)  ( R8: 00001)  (R12: 00334)  

    ( SP: 05bfe)  ( R5: 00000)  ( R9: 00001)  (R13: 00000)  

    ( SR: 00000)  ( R6: 00002)  (R10: 000ff)  (R14: 000f8)  

    ( R3: 00000)  ( R7: 00005)  (R11: 00005)  (R15: 00001)  

    05c00: 31 40 00 5c               MOV     #0x5c00, SP

    05c04: b2 40 80 5a 5c 01         MOV     #0x5a80, &0x015c

    05c0a: 3f 40 00 00               CLR     R15

    05c0e: 0f 93                     TST     R15

 

(mspdebug) md 0x5bfa
    05bfa: 0a 65 ca 65 f8 00 31 40 00 5c b2 40 80 5a 5c 01 |.e.e..1@.\.@.Z\.|
    05c0a: 3f 40 00 00 0f 93 05 24 2f 83 9f 4f ac 66 00 1c |?@.....$/..O.f..|
START TIMER A0 ISR
(mspdebug) run
Running. Press Ctrl+C to interrupt...
    ( PC: 05f8c)  ( R4: 00b80)  ( R8: 00001)  (R12: 00334)  
    ( SP: 05bfa)  ( R5: 00000)  ( R9: 00001)  (R13: 00000)  
    ( SR: 00000)  ( R6: 00002)  (R10: 000ff)  (R14: 000f8)  
    ( R3: 00000)  ( R7: 00005)  (R11: 00005)  (R15: 00001)  
    05f8c: 0f 12                     PUSH    R15
    05f8e: 0e 12                     PUSH    R14
    05f90: 0d 12                     PUSH    R13
    05f92: 0c 12                     PUSH    R12
    05f94: 4f 43                     CLR.B   R15
    05f96: b0 12 ec 5e               CALL    #0x5eec
    05f9a: 3c 41                     POP     R12
Dump of the Stack
(mspdebug) md 0x5bfa
    05bfa: 0a 65 ca 65 f8 00 31 40 00 5c b2 40 80 5a 5c 01 |.e.e..1@.\.@.Z\.|
    05c0a: 3f 40 00 00 0f 93 05 24 2f 83 9f 4f ac 66 00 1c |?@.....$/..O.f..|
This is what I get....
(mspdebug) run
Stepping over breakpoint #0 at 0x5f8c
Running. Press Ctrl+C to interrupt...
^C
    ( PC: 665ca)  ( R4: 00b80)  ( R8: 00001)  (R12: 00334)  
    ( SP: 05bfe)  ( R5: 00000)  ( R9: 00001)  (R13: 00000)  
    ( SR: 0050a)  ( R6: 00002)  (R10: 000ff)  (R14: 000f8)  
    ( R3: 00000)  ( R7: 00005)  (R11: 00005)  (R15: 00001)  
    665ca: ff 3f                     JMP     0x65ca
    665cc: ff 3f                     JMP     0x65cc
    665ce: ff 3f                     JMP     0x65ce
    665d0: ff 3f                     JMP     0x65d0
    665d2: ff 3f                     JMP     0x65d2
    665d4: ff 3f                     JMP     0x65d4
    665d6: ff 3f                     JMP     0x65d6
    665d8: ff 3f                     JMP     0x65d8
(mspdebug) 
This is the code i'm running

I've also tried on a different 5438, but the problem is exactly the same.

Thanks in advance

 

Jorge

  • The new MSPs with 430X core (including the 54xx) have a 20 bit address bus and 20 bit registers. The instructions, however, are backwards compatible to the old 16 bit core. For calls that leave the 16 bit address range, or come from outside, there are new instructions CALLA and RETA which push and pop 20 (32) bit to and from stack for the return address.

    With ISRs, however, Ti implemented a(normally) 100% compatible way: the upper 4 bit of the PC are pushed to the stack together with the status register, which has unused bits. This saves one cycle and two bytes stack.

    upon return from the ISR, the PC is assembled from these 4 status register bits and the 16 bit return address.

    In your case, it seems the status register isn't properly, so upon ISR return a wrong PC is assembled. This mechanism is built into the CPU core and not subject to the compiler-generated instructions. And normally it is transparent. But if you mess with the stack in your ISR, or mix 430 and 430x function calls and returns, you get into trouble.

  • Jens-Michael is correct, but I have an alternate suggestion: You code jumped off into the weeds, then the timer interrupt fired.

    From your stack dump, the return address of 665CA is correct. This is the address that sits on the stack as the return address for your interrupt handler, assembled from the upper 4 bits of SR plus the lower 16 bits of PC. This is reported by your memory dump of the stack at 05BFA at the top of your TimerA interrupt handler. This tells me the problem is not in your interrupt handler; you are already dead, you just don't know it yet.

    The real question is: How did 665CA finds its way onto the stack? 665CA is vacant memory, which will always fetch 3FFF (JMP PC, a nop). If you somehow jumped to 665CA, the cpu would sit and spin (firing NMI's, which in your code is stubbed to RETI's) until your timer interrupt fired.

    Since 0665CA is invalid memory, the question is how did it find its way onto the stack?

    -- Chip

     

  • You might try writing a stub handler for the NMI and see if your debugger will trigger a breakpoint on it. You might be able to gleen some more information that way.

    -- Chip

     

  • ChipD said:
    Since 0665CA is invalid memory, the question is how did it find its way onto the stack?

    Good question. Lett me narrow it down further: The TOS is 0A65. How can the upper byte of the saved status register be 65? Only 4 bits are userd for the PC storage, the rest is reserved, so where does the '5' come from (or more exactly the '4', as the '1' is the overflow bit)? I admit, I never checked the stack (I never used a debugger for the MSP), but this is strange. Even if the ISR was indeed called from the middle of the void, Bit 9..11 of the saved status register should be either all 0 or all 1. But maybe i'm on the wrong track and these three bits are always random.
    Also, it might be pure coincidence that the MSB of the saved PC and the MSB of the saved SP are both 0x65.

    Unfortunately, neither the complete ISR nor the code a 0x065ca (Is there code on this place at all?) has been posted. The assembly dum, not the C source.

    There's another possibility: the ISR isn't entered because of an interrupt. It is possible that the ISR is entered because the processor was running wild before (stack overflow? array out of bounds?). Then the values on the stack are neither status register nor return address, but something 'random'.
    Besides a stack overflow, this can happen if an interrupt occurs and no ISR is assigned. Then the processor will jump to 0xfffe (since the unoccupied vector points to 0xffff) and run wild, eventually arriving at some code.
    Also, it may be that the main funciton ends and the processor simply continues into the next function.
    It is up to the compiler to handle these last two cases, but there is no general rule what happens if main ends. MSPGCC assigns all unused vectors to a function the just does a RETI (which may still cause a system halt on newer MSPs as the IRQ remains unhandled), some compilers just leave the vectors pointing to 0xffff. Also, on end of main, some add code that puts the MCU into LPM, others just do nothing and end main, just like any other function, with a RET (which jumps to nowhere since there is no return address on the stack).

  • Hi guys, thank you very much for your fast reply, I'm attaching the C source, I can also upload the nesC file if you consider it would help.

    2781.app.zip

    Timer ISR is called just once, and the code is working fine, (with timer dissabled it stays on the infinit loop I set to it), the thing is that when the Interrupt gets called....

     

     

     

    the code of 0x065ca should be in the asm attached earlier, but the disassembly shows:

        65c8:       b0 12 34 5c     call    #0x5c34 

        65cc:       49 9b           cmp.b   r11,    r9

        65ce:       03 2c           jc      $+8             ;abs 0x65d6

    so, if that's the real address it's also wrong.
    This is minutes ago, same code as yesterday. this dump is from last instruction of Timer ISR.
    Running. Press Ctrl+C to interrupt...
        ( PC: 05fa8)  ( R4: 07fc0)  ( R8: 00001)  (R12: 00334)  
        ( SP: 05bfa)  ( R5: 00000)  ( R9: 00001)  (R13: 00000)  
        ( SR: 00003)  ( R6: 00002)  (R10: 000ff)  (R14: 000f8)  
        ( R3: 00000)  ( R7: 00005)  (R11: 00005)  (R15: 00001)  
        05fa8: 00 13                     RETI    
        05faa: 0f 12                     PUSH    R15
        05fac: 0e 12                     PUSH    R14
        05fae: 0d 12                     PUSH    R13
        05fb0: 0c 12                     PUSH    R12
        05fb2: 1f 42 6e 03               MOV     &0x036e, R15
        05fb6: 12 c3                     CLRC    
    (mspdebug) md 0x5bfa
        05bfa: 08 00 00 00 f8 00 31 40 00 5c b2 40 80 5a 5c 01 |......1@.\.@.Z\.|

    as you can see, now it might work as for what SR is concerned, but the PC is 0x0000!!!

     

    now, switching to another 5438, same code:

     

    (mspdebug) regs

        ( PC: 05fa8)  ( R4: 0ffff)  ( R8: 00001)  (R12: 00334)  

        ( SP: 05bfa)  ( R5: 00000)  ( R9: 00001)  (R13: 00000)  

        ( SR: 00003)  ( R6: 00002)  (R10: 000ff)  (R14: 000f8)  

        ( R3: 00000)  ( R7: 00005)  (R11: 00005)  (R15: 00001)  

    sig_TIMER0_A0_VECTOR+0x1c:

        05fa8: 00 13                     RETI    

    sig_TIMER0_A1_VECTOR:

        05faa: 0f 12                     PUSH    R15

        05fac: 0e 12                     PUSH    R14

        05fae: 0d 12                     PUSH    R13

        05fb0: 0c 12                     PUSH    R12

        05fb2: 1f 42 6e 03               MOV     &0x036e, R15

        05fb6: 12 c3                     CLRC    

    (mspdebug) md 0x5bfa

        05bfa: 0a 65 ca 65 f8 00 31 40 00 5c b2 40 80 5a 5c 01 |.e.e..1@.\.@.Z\.|

    same result as yesterday...

    jorge


  • Chip,

    thanks for your reply.

    I checked your suggestion, but the code works fine until the interrupt is serviced. I agree with your question, because the only one messing with the stack before 0x5f8c (first line of the ISR) is the uP itself, no matter what i've done before with the SP, the last 4 bytes should be the SR & PC. SR gets corrupt and then as you said, I'm already dead inside the ISR code.

    So the thing is that SR is getting corrupt somewhere, the rest of the operation is what it should. Bug CPU18 says something similar, but it's not the actual problem, I can see 3 nibbles repeated, but I wonder if this bug is related in some way.

    Upon servicing an interrupt service routine, the program counter (PC) is pushed twice

    onto the stack instead of the correct operation where the PC, then the SR registers are

    pushed onto the stack. This corrupts the SR and possibly the PC on RETI from the ISR.

    thanks again
    jorge

  • 1100 lines of assembly listing was tough to look at, 6700 lines of C preprocessor output is even worse! By "C source" Jens meant the 20 lines of code you added to the known working base of TinyOS.

    I am going to invoke Occam's Razor on this: This is most likely going to turn out to be a bug in the code you modified or added. It is highly unlikely that the TinyOS code is broken, and extraordinarily unlikely -- nigh on impossible -- that the MSP430 is broken.

    I suggest abandoning the post-mortem approach, which can be an endless timesink. Get back to a known working code base (the original, unmodified Blink app), and re-introduce tiny changes until it breaks again. Look for buffer overruns, uninitialized pointers, etc.

    -- Chip

     

**Attention** This is a public forum