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.
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.
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.
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.
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
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
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