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.

assemblerprogramming for Launchpad with IAR workbench/ Problems with the call function

Other Parts Discussed in Thread: TEST2

Hello, I started programming launchpad in assembler and I have up to now,not even any problem. But when I try to use a simple call function, chip works strange. I work on IAR workbench, may be I forgot something at the beginning of my code. Sometimes following warning : The stackpointer for stack ( now 0x282) is outside the stackrange 0x280,but why ? Here my code : #include "msp430.h" ; #define controlled include file NAME main ; module name PUBLIC main ; make the main label vissible ; outside this module ORG 0FFFEh DC16 init ; set reset vector to 'init' label RSEG CSTACK ; pre-declaration of segment RSEG CODE ; place program in 'CODE' segment init: MOV #280h, SP ; set up stack main: NOP ; main program mov #0FEh,R5 MOV.W #WDTPW+WDTHOLD,&WDTCTL ; Stop watchdog timer call #0F816h nop nop test: dec.w R5 jnz test ret END
  • Maybe from my debugging example you can understand stack behaviour...

            mov.w #WDTPW + WDTHOLD, &WDTCTL
            mov.w #00280h, SP

            call #DbgStr
            db 'Device ', 0
            mov.w &00FF0h, R15
            call #DbgWordHex
            call #DbgCR
            call #DbgRegs
            call #DbgCR
            call #DbgSR
            call #DbgCR
            push.w #01234h
            push.w #05678h
            push.w #0ABCDh
            call #DbgStack
            call #DbgCR
            pop.w R15
            pop.w R15
            pop.w R15

    ...

    Device 5529
    R4:0002 R5:00CC R6:0021 R7:0000 R8:FFFF R9:FAF4
    R10:EF76 R11:7FC9 R12:FFFF R13:FFFE R14:0007 R15:5529
    SR:0000 0000000000000000
    SP:027A 027A: CD AB 78 56 34 12 FF 3F ; ═źxV4. ?

  • Your "call #0F816h" instruction actually works as you intended. It loops 254 times decrementing R15 to 0 and returns to main. The problem is after that and the two "nop", the CPU falls off the cliff into "test: " (at 0F816h) unintentionally. It loops 65538 times decrementing R15 to 0 again. The "ret" instruction drives the CPU nuts.

  • Thank you for your response. Sorry, but I forgot to finish main function, for instance with a jump instruction .But after that,call instruction works, but to the wrong address! It always jump to the ret instruction and not to the beginning of the subroutine. I just work with atmel`s and there was no similar problem. So I try to simulate the call fünction, and it works! Strange isn`t it ? What could be the reason ? Here my code : init: MOV #280h, SP ; set up stack main: main: NOP ; main program mov #0FEh,R5 bis.b #01000001b,&P1DIR ; make P1.0 and P1.6 output ; all others are inputs by default bic.b #00000001b,&P1OUT ; clear P1.0 (red off) bis.b #01000000b,&P1OUT ; set P1.6 (green on) MOV.W #WDTPW+WDTHOLD,&WDTCTL ; Stop watchdog timer test2: decd SP ;call #test mov PC,0(SP) ;call #test mov.w #test,PC ;call #test nop xor.b #0FFh,P1OUT ;toggle P1.0 and P1.6 jmp test2 test: dec.w R5 jnz test add.b #4,0(SP) ;ret MOV @SP+,PC ;ret END
  • call #label / ret pair is working OK on MSP430 with IAR assembler. I really don't understand what is your problem, and why you are not using standard subroutine calls, but playing with PC/stack. You want to improve/invent something? If something is not clear, please post source in some readable format, not everything in one line that need to be decoded.

  • Thank you for your answer, but always when I copy my code inside it crashed to one line and I don`t find the settings for a readable format. I don`t want to invent something new, but call #label / ret really don`t work with my IAR assembler. The call instruction always jump to the ret and back to the main program.
  • Hi Christian,

    Your asm code that simulates the "CALL" instruction does it wrong.  Your asm code that simulates the "RET" instruction also does it wrong. Also the two wrong implementations are not magically compatible with each other.

    I suggest you go back to your original code using CALL and RET, and post it completely, in a readable format.  We can probably find your mistake if you do that.

    Jeff

  • Copy your code first to some non-formating text editor like notepad, and after this copy from notepad to forum. On this way it will be in readable format.

    With MSP430, I am using only IAR assembler (win xp cmd prompt) without any other tools, and didn't have any problems till now. I also have my own log debug lib (because I don't use any break-point style debugger) that is based on stack manipulation, and don't have any problems with it.

    http://forum.43oh.com/topic/2646-software-debugging-without-hardware-tools

    Just put here pure example (few lines) that cause you the problem with call #label / ret, and please use labels, not addresses.

  • Hello zrno, First by copying it look`s good and after sending its crashed. I just have used a texteditor at the last time, so I will try anotherone now. #include "msp430.h" ; #define controlled include file NAME main ; module name PUBLIC main ; make the main label visible ; outside this module ORG 0FFFEh DC16 init ; set reset vector to 'init' label RSEG CSTACK ; pre-declaration of segment RSEG CODE ; place program in 'CODE' segment init: MOV #280h, SP ; set up stack main: main: NOP ; main program mov #0FEh,R5 bis.b #01000001b,&P1DIR ; make P1.0 and P1.6 output ; all others are inputs by default bic.b #00000001b,&P1OUT ; clear P1.0 (red off) bis.b #01000000b,&P1OUT ; set P1.6 (green on) MOV.W #WDTPW+WDTHOLD,&WDTCTL ; Stop watchdog timer test2: ;decd SP ;call #test emulating ;mov PC,0(SP) ;call #test ;mov.w #test,PC ;call #test call #test nop xor.b #0FFh,P1OUT ;toggle P1.0 and P1.6 jmp test2 test: dec.w R5 jnz test ;add.b #4,0(SP) ;ret emulating ;MOV @SP+,PC ;ret ret END
  • sorry the same problem !!
  • Christian Lankes said:
    Thank you for your response. Sorry, but I forgot to finish main function, for instance with a jump instruction .But after that,call instruction works, but to the wrong address! It always jump to the ret instruction and not to the beginning of the subroutine. I just work with atmel`s and there was no similar problem. So I try to simulate the call fünction, and it works! Strange isn`t it ? What could be the reason ? Here my code : init: MOV #280h, SP ; set up stack main: main: NOP ; main program mov #0FEh,R5 bis.b #01000001b,&P1DIR ; make P1.0 and P1.6 output ; all others are inputs by default bic.b #00000001b,&P1OUT ; clear P1.0 (red off) bis.b #01000000b,&P1OUT ; set P1.6 (green on) MOV.W #WDTPW+WDTHOLD,&WDTCTL ; Stop watchdog timer test2: decd SP ;call #test mov PC,0(SP) ;call #test mov.w #test,PC ;call #test nop xor.b #0FFh,P1OUT ;toggle P1.0 and P1.6 jmp test2 test: dec.w R5 jnz test add.b #4,0(SP) ;ret MOV @SP+,PC ;ret END

    When you inserted statements in your main, all the instructions after that are moved to higher locations and your call is no longer calling the beginning of test: but rather the ret instruction at the end.

    I think you might have meant something like this:

    #include <msp430.h>
     RSEG RESET
     DC16 init ; set reset vector to 'init' label


     RSEG CODE ; place program in 'CODE' segment
    init: MOV #280h, SP ; set up stack
    main: NOP ; main program
     bis.b #01000001b,&P1DIR ; make P1.0 and P1.6 output
                             ; all others are inputs by default
     bic.b #00000001b,&P1OUT ; clear P1.0 (red off)
     bis.b #01000000b,&P1OUT ; set P1.6 (green on)
     MOV.W #WDTPW+WDTHOLD,&WDTCTL ; Stop watchdog timer
    test2: mov #0FEh,R5      ; subroutine "test" needs R5 but will destroy it, so we need to set R5 every time          
     call #test              ; do not use "call #0F82Eh"
     nop
     xor.b #01000001b,&P1OUT ;toggle P1.0 and P1.6
     jmp test2


    test: dec.w R5
     jnz test
     ret


     END

  • init: MOV #280h, SP ; set up stack main: --------------------------------------------------------------- main: NOP ; main program --------------------------------------------------------------- mov #0FEh,R5 --------------------------------------------------------------- bis.b #01000001b,&P1DIR ; make P1.0 and P1.6 output --------------------------------------------------------------- ; all others are inputs by default --------------------------------------------------------------- bic.b #00000001b,&P1OUT ; clear P1.0 (red off) --------------------------------------------------------------- bis.b #01000000b,&P1OUT ; set P1.6 (green on) --------------------------------------------------------------- MOV.W #WDTPW+WDTHOLD,&WDTCTL ; Stop watchdog timer --------------------------------------------------------------- test2: --------------------------------------------------------------- ;decd SP ;call #test emulating --------------------------------------------------------------- ;mov PC,0(SP) ;call #test --------------------------------------------------------------- ;mov.w #test,PC ;call #test --------------------------------------------------------------- call #test --------------------------------------------------------------- xor.b #0FFh,P1OUT ;toggle P1.0 and P1.6 --------------------------------------------------------------- jmp test2 --------------------------------------------------------------- test: --------------------------------------------------------------- dec.w R5 --------------------------------------------------------------- jnz test --------------------------------------------------------------- ;add.b #4,0(SP) ;ret emulating --------------------------------------------------------------- ;MOV @SP+,PC ;ret --------------------------------------------------------------- ret --------------------------------------------------------------- END
  • There is nothing wrong with code here, except thing noted by OCY. After calling test R5 value will go every time from 0 to $FFFF, and after this return to toggling P1.

    init:  MOV #280h, SP ; set up stack
    main:  NOP ; main program
           mov #0FEh,R5
           bis.b #01000001b,&P1DIR ; make P1.0 and P1.6 output all others are inputs by default
           bic.b #00000001b,&P1OUT ; clear P1.0 (red off)
           bis.b #01000000b,&P1OUT ; set P1.6 (green on)
           MOV.W #WDTPW+WDTHOLD,&WDTCTL ; Stop watchdog timer

    test2: call #test
           xor.b #0FFh,P1OUT ;toggle P1.0 and P1.6
           jmp test2

    test:  dec.w R5
           jnz test
           ret

  • Hello Zrno, I delete some old programs and some "old environmental variables" in the windows system and now it works. Thank you for answering, also to OCY !
  • Christian Lankes said:
    call #0F816h nop nop test: dec.w R5 jnz test ret

    Two things: what is at 0xF816? Doe sit mess with the stack?
    YOu initialize the stack to 280h at beginning of main. The stack contains nothing yet. But at the end of main you return to something. To where? You come form nowhere (through teh reset vector) and you have initialized the stack. There is no return address on the stack. You fetch a word from the stack that youu didn't put there, fetching a return address from the void. And the debugger rightfully complains.

**Attention** This is a public forum