trouble understanding RETI instruction

Hi

I am having trouble understanding RETI instruction. Being a novice at MSP430 architecture, have begun exploring by writing simple snippets. I am trying to blink a LED using a timer. I want to control the dutycycle of the flashing.

My query is that after exiting the ISR on RETI, which instruction does the control flow go to. Have tried debugging via different methods but its still unclear. Here is my code. PLzz help.

;***************************************************************************** .cdecls C,LIST,"msp430x11x1.h" ; Include device header file

;***************************************************************************** ;---------------------------------------------------------------------------- .text ; Progam Start ;----------------------------------------------------------------------------- RESET mov.w #300h,SP ; Initialize stackpointer StopWDT mov.w #WDTPW+WDTHOLD,&WDTCTL ; Stop WDT SetupP1 bis.b #04h,&P2DIR ; P1.0 output SetupC0 mov.w #CCIE,&CCTL0 ; CCR0 interrupt enabled mov.w #0ffffh,&CCR0 ; SetupTA mov.w #TASSEL_2+MC_2,&TACTL ; SMCLK, contmode ; bis.w #CPUOFF+GIE,SR ; CPU off, interrupts enabled nop ;----------------------------------------------------------------------------- TA0_ISR; Toggle P1.0 ;----------------------------------------------------------------------------- xor.b #04h,&P2OUT ; Toggle P1.0 add.w #10,&CCR0 ; Add Offset to CCR0 reti ;----------------------------------------------------------------------------- ; Interrupt Vectors ;----------------------------------------------------------------------------- .sect ".reset" ; MSP430 RESET Vector .short RESET ; .sect ".int09" .short TA0_ISR .end

--------------------------------------- Posted through

formatting link

Reply to
jack_e
Loading thread data ...

It goes to where it would have gone, had the interrupt not happened. When an interrupt occurs, the program counter (which is the address of the next instruction to be executed) is pushed onto the stack, followed by the status register. The interrupt code is executed and then, triggered by the RETI instruction, the status register and program counter are restored from the stack and execution continues.

--
Rich Webb     Norfolk, VA
Reply to
Rich Webb

The Program Counter return to where it was before the ISR. To understand exactly what happens you have to read the datasheet of the MSP430.

Bye Jack

Reply to
Jack

On the vague hope that this isn't homework, or that if it is you will still actually learn from the process and retain the answer, here is what happens:

You are setting the processor to sleep (shutting it off.) Once that instruction is fetched, to be executed, the program counter (PC register, or R0) is set to the following instruction _before_ the CPU actually stops. So right then, the PC register points to the NOP instruction in your code. Then it stops. It just sits there, waiting. (Note that you've also set up the stack pointer, R0, to point into memory, too, and that the control bits that placed the CPU to sleep in the first place reside in the status register, R2.)

So, you've got the stack pointer R1 pointing into RAM, the program counter R0 pointing at the NOP, and you've just changed the status register R2 so that the processor is forced to stopped running. However, the timer keeps on running.

At some later point in time, the timer initiates an interrupt. When that happens, two registers, R0 and R2, are automatically added to the stack (which means that R1 is used as a memory pointer and automatically adjusted, as well.) Then the program counter, after having been saved onto the stack, is modified to the value located in the associated interrupt vector (you've added that with the 'short' pointer in your code and it resides in the flash memory) and the status register, R2, is modified so that the processor starts running, again. This causes the first instruction in the interrupt vector code to be executed.

When that code gets to the RETI, it restores the values of R0 and R2 from the stack (where R1 points, modifying R1 also during this process.) R0 will now point back at the NOP instruction. However, since R2 was just restored and since the saved value has the old settings where you'd ordered the CPU asleep, the CPU stops running again and does NOT attempt to run the NOP. There it sits until the timer starts another interrupt event and the process repeats.

Jon

Reply to
Jon Kirwan

Are you sure? I am not familiar with MSP430, but i could imagine, that with the RETI it jumps to the nop and then runs again into the ISR routine, which surely is not wanted. With the next reti, it does something unknown or undefined.

I would think, it should be somthing like the following:

--------------------snip-------------------------------------------------

Blub: ;Label for the jump bis.w #CPUOFF+GIE,SR ; CPU off, interrupts enabled nop jmp Blup ; endless loop to avoid running in the ISR

;----------------------------------------------------------------------------- TA0_ISR; Toggle P1.0 ;----------------------------------------------------------------------------- xor.b #04h,&P2OUT ; Toggle P1.0 add.w #10,&CCR0 ; Add Offset to CCR0 reti ;-----------------------------------------------------------------------------

----------------------snip-----------------------------------

best regards

Stefan

Reply to
Stefan Brröring

I'm pretty sure, yes. Having written such code on the MSP430 and being somewhat familiar with the cpu. The code example I read, if I read it correctly, was probably working -- in so far that the interrupts operated without causing the PC register to run amok.

No, it works as I described it working. Fairly nifty.

Jon

Jon

Reply to
Jon Kirwan

_Always_, the action of an interrupt is to save enough of the processor state that you can run some sort of an ISR and then return in a way that _only_ disturbs the interrupted code by stealing some time from it. A processor that has an interrupt process that does not save all this necessary information (and it can be a startlingly small set, leaving much to the programmer), is known colloquially among engineers as "a @#$%ed up piece of *&%^", and if it happens to make it into silicon it doesn't make it onto the market.

_Usually_ when the processor gets interrupted it finishes whatever instruction it's executing, then branches*. When it finishes the interrupt it returns to the instruction just after the one that was in process when the interrupt was noted.

If I'm reading your code correctly, you do some set up, then you put the processor to sleep. When your interrupt happens the processor will be at the "bis.w" instruction, so it'll return to the nop. Since you're missing a loop instruction to branch back to the "bis.w" instruction, your code will then erroneously fall through to the ISR which will get executed, including the reti instruction. Since the various registers will at this point have obsolete or random values in them, the reti instruction will do Bad Things, and your code will go nuts.

  • In a pipelined processor, this used to mean that the pipeline gets flushed, at the cost of some execution time. This probably still happens unless the chip designer is insane.
--

Tim Wescott
Wescott Design Services
http://www.wescottdesign.com

Do you need to implement control loops in software?
"Applied Control Theory for Embedded Systems" was written for you.
See details at http://www.wescottdesign.com/actfes/actfes.html
Reply to
Tim Wescott

Actually, no. The CPU control resides in the status register. The code uses an instruction, prior to the NOP, to turn off the CPU. When the interrupt takes place, this status register (and the cpu control bits) gets placed on the stack. The CPU is turned on and the interrupt serviced. However, when the RETI takes place, the status register is reloaded from the stack, changing the cpu control bits back to sleeping mode... on the NOP, again. It just stops, is all, and waits.

It doesn't fall through. I can provide some (nearly identical) operating code that I've written for the MSP430, if you have an MSP430 system floating about and want to test the idea.

Jon

Reply to
Jon Kirwan

Thats just the same, what i would believe as i mentioned in the other post. But i am not yet familiar with MSP430, just got the launchpad from TI. But Jon seam to be sure, that the processor will go back to sleep mode after the RETI before executing the nop.

Best regards

Stefan

Reply to
Stefan

;*****************************************************************************

;*****************************************************************************

;-----------------------------------------------------------------------------

;-----------------------------------------------------------------------------

;-----------------------------------------------------------------------------

;-----------------------------------------------------------------------------

;-----------------------------------------------------------------------------

[ snip ]

It is my understanding that the "bis.w" causes the MSP430 to enter the "LPM0" low-power mode, in which the program does not run (SR.CPUOFF is set). The PC is left pointing at the next instruction, the "nop". The "nop" is not executed, since the program does not run. If the processor can be said to "be" anywhere, it "is" at the "nop", since the PC points to the "nop".

When the interrupt happens, the processor stores the PC and the SR (the status register) on the stack, clears the SR bits CPUOFF and GIE to let the program run and to disable interrupts, and enters the interrupt handler.

When the interrupt handler executes RETI, the processor pops the SR and PC off the stack. If the interrupt handler did not modify the stacked values, the processor goes back to LPM0 mode (program stopped) with the PC still pointing at the "nop". The "nop" is not executed. New interrupts can come in, and be handled, and the processor always returns to sleep at the "nop".

For that to happen, the interrupt handler would have to change the stacked SR by turning off its CPUOFF bit, for example by "bic #CPUOFF,0(SP)". If that were done, the RETI would restore the PC to point at the "nop" and restore the SR with CPUOFF cleared, meaning that the processor would continue to execute from the "nop" (and fall through to the ISR in this code).

Changing the stacked SR is the normal way to make a sleeping MSP40 program wake up after an interrupt, but of course the resumption point should then contain some useful code, and not be as in the OP's case.

--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .
Reply to
Niklas Holsti

;*****************************************************************************

;*****************************************************************************

;-----------------------------------------------------------------------------

;-----------------------------------------------------------------------------

;-----------------------------------------------------------------------------

;-----------------------------------------------------------------------------

;-----------------------------------------------------------------------------

I misunderstood the sleep action of the MSP430, then (it seems weird, but functional).

--

Tim Wescott
Wescott Design Services
http://www.wescottdesign.com

Do you need to implement control loops in software?
"Applied Control Theory for Embedded Systems" was written for you.
See details at http://www.wescottdesign.com/actfes/actfes.html
Reply to
Tim Wescott

Without actually having used one, it's reasonable to imagine that way. It's unreasonable to express an opinion about it without first checking when you know that you don't know the processor. Except, of course, in a forum like this where no one can reasonably expect researched answers. So it's entirely reasonable, anyway. ;)

-- yes, I'm being argumentative only because I'm in 'that mood' today.

It's largely whether or not a cpu designer decides to cause the bits that control the sleep state of the processor to be saved and restored through the interrupting event, or not.

If the bits are kept someplace that isn't saved and restored by some automatic process, then when the interrupt turns the processor back on (which it must do, if the cpu is going to do anything) the cpu will then have to be explicitly turned back off, later on, by additional code. Which is the way I think you assumed it worked here.

If they are pushed and popped (saved and restored), as the MSP430 actually handles it, then the processor can wake up and shut back down without additional code being involved.

I'm not sure if there is a third way to handle the semantics and there is nothing intrinsically better about one way or the other, so I honestly don't think one is weirder. There are two ways, both within the bounds of 'reasonable.' Some go one way, some the other. I've used both kinds and don't find either of much preference. You just look it up on the sheet and do what they say to do.

Jon

Reply to
Jon Kirwan

Only seems weird 'cause I hadn't run into it before -- to date anything that I've put to sleep has a 'sleep' instruction (or several, to give you more than one level of 'sleep') that exits after an interrupt.

--

Tim Wescott
Wescott Design Services
http://www.wescottdesign.com

Do you need to implement control loops in software?
"Applied Control Theory for Embedded Systems" was written for you.
See details at http://www.wescottdesign.com/actfes/actfes.html
Reply to
Tim Wescott

I think, it would be better, if the processor would not go into sleep after reti.

If it keeps awake, you can simply make an endless loop to execute a new sleep command after reti.

But if you want it to stay awake after the reti, you have to manipulate the stack, which could cause some trouble. I don´t know, if this can be done in 'C'. I think, you would need some inline assembler to do the stack manipulation.

best regards

Stefan

Reply to
Stefan

That's the behaviour I'm used to with AVRs

Conversely, the MSP430 way avoids wasting some number of nanoJoules on every interrupt that would be spent in coding a loop around the sleep instruction. Low power is one of the stated goals ...

Mel.

Reply to
Mel

When I wrote, I was talking about fundamentals when saying "intrinsically better." I didn't mean that there might not be some technical argument.

If you imagine that your argument _is_ a fundamental one -- that it applies to ALL situations regardless -- then you are wrong. Another poster provided a sufficient example for you to know that much.

Jon

Reply to
Jon Kirwan

Yes, I understand. I made a similar system a few month ago with an avr processor. The avr was send into sleep and with external int, it should awake, do something and after this, it should go to sleep again.

In my application, the behaviour of the MSP430 would be perfect too, but the behaviour of the avr makes no problem. Only if i would not want the processor go to sleep after reti, it would be a problem.

But this discussion is obsolete. It is only necessary to know, what the processor really does. ;-)

Reply to
Stefan

In the _old_ days You did have to have a little bit of assembler to fiddle the stack - I still have a copy taken from a very old IAR application note and used with version 1.2x of the compiler. Since then the compiler vendors have all implemented intrinsic functions that put the processor into their low power mode or make the processor exit the interrupt handler and go into active mode ( for recent versions of the IAR tools it is __low_power_mode_off_on_exit( ) ).

Ian

Reply to
Ian

Say, the intel N10?

Reply to
mac

If you're not crazy before you start designing processors for Intel, you will be...

--

Tim Wescott
Wescott Design Services
http://www.wescottdesign.com

Do you need to implement control loops in software?
"Applied Control Theory for Embedded Systems" was written for you.
See details at http://www.wescottdesign.com/actfes/actfes.html
Reply to
Tim Wescott

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.