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.

Is it necessary to stop TimerA during "timer overflow ISRs" ?

Hello Forum,

having used the timers on 8052, AVR and PIC, i find the 16bit timer on MSP430(F2013) different, normally in 8051/2, AVR etc we use timer Reload values to generate a particular delay and these reload values are loaded into 16bit Timer/counter register ( TH0 and TL0), but in msp 430 there are no reload values but only maximum count value that has to be loaded in TACCR0 register (timerA configured as up or up/down) and no reload values in TAR reg.

 

in 8052 when a Timer overflows and its ISR is entered, it is necessary to stop, reload and start the timer in the isr, do we need to do the same thing in msp430 or is it not needed ?

 

Regards,

nura

  • The TA or TB module with the associated CC channels in MSP430 have many different useful functions.

    If you just want a delay of certain number of clocks repeatedly, one of the simplest way is as follows:

    (a) Load that number-1 in CCR0

    (b) Set up TACTL in the "continuous mode"

    (c) Enable either CC0 interrupt or TA interrupt

    With this setup, TAR will count from 0 to number-1 and back to 0 and start over and over. And you will get that interrupt repeatedly.

  • Hello OCY,

    Thanks for your reply !

    i am using the TA in up mode to generate 50millisec( 49,999 is loaded into CCR0) with DCO set to calibrated 1Mhz, no clock division and MCLK=SMCLK=DCO, in the ISR i am using a variable to count 20 such interrupts (50mS intervals) to get 1 sec delay, after the 20 such iterations in the ISR i toggle an LED on P1.1.

    But i don't see the LED toggle after very sec but glows steadily. why is this happening? Also if i use Div by 4 or 8 ( ID_2 or 3)i see the LED toggling but at very large intervals ( 2 sec and 4 sec). can't we run the TA at direct DCO speed, should it be divided down ?

    here's the code i am using:

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

    #include  "msp430x20x3.h"

    LED EQU BIT1

                         ORG 0200H

    CNT: DS 1                   ; variable in RAM

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

                ORG   0F800h ;08000H ;                  ; Program Reset

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

    RESET:      MOV.W #0280h,SP              ; ; Initialize stackpointer TO THE END OF RAM                                                                                        

    SETCLK:   MOV.B &CALBC1_1MHZ,&BCSCTL1   ; Set range ; Set DCO to 1 MHz:

                      MOV.B &CALDCO_1MHZ,&DCOCTL   ; Set DCO step + modulation

    StopWDT:   mov.w #WDTPW+WDTHOLD,&WDTCTL  ; Stop WDT

    SetupP1:    bis.b #LED,&P1DIR            ; P1.1 output

                        bis.b #LED,&P1OUT            ; LED OFF

    SetupC0:    mov.w #CCIE,&CCTL0            ; CCR0 interrupt enabled

                       mov.w #49999d,&CCR0         ; LOAD VALUE TO BE COUNTED IN CCR0

    SetupTIMERA: mov.w #TASSEL_2+MC_1,&TACTL   ; SMCLK, upmode

                                                ;                                                                                  

    Mainloop:   MOV.B #20D,CNT

                        bis.w #CPUOFF+GIE,SR          ; CPU off, interrupts enabled

                       nop

                       JMP $                            

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

    ;                      TIMER_A_CCR0 ISR            

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

       TA0_ISR: MOV.W #00H,&CCR0         ; STOP TIMER

                MOV.W #49999D,&CCR0      ; START TIMER           

                DEC.B CNT

                JNZ  ; Set DCO to 1 MHz:EXIT

                MOV.B #20D,CNT    ; reload the counter for next round          

                xor.b  #00000010b,&P1OUT            ; Toggle P1.0,      

         EXIT:  reti                            ;                          

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

    ;           Interrupt Vectors

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

                ORG 0FFFEh                  ; MSP430 RESET Vector

                DW RESET                   ;

                ORG 0FFF2h                  ; Timer_A0 Vector

                DW TA0_ISR                 ;

                END

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

    on the bread board the LED glows steadily but in Proteus VSM the led toggles every 500mSec.

    old_cow_yellow said:
    With this setup, TAR will count from 0 to number-1 and back to 0 and start over and over. And you will get that interrupt repeatedly.

    i may be wrong but what you describe above is UP/Down mode but you are asking to setup the TA in "continuous mode" ( point (b) in last post)

    Regards,

    Nura

     

  • I am terribly sorry that I made a mistake in my previous reply. I said "continuous mode". It should have been "up mode".

    You correctly used "up mode" in your code. Offhand the only thing wrong that I can see is, you shouldn't ever load 0 to CCR0 while the Timer is in "up mode". You do not need to "stop" and "start" Timer in your ISR. Delete those first two MOV statements in your ISR and I think it will work. TAR will count as follows:

    0, 1, 2, 3, 4, 5, ..., 49997, 49998, 49999, 0, 1, 2, ..., 49998, 49999, 0, 1, 2, ..., 49998, 49999, 0, 1, 2, ..., (over and over again)

  • In "up mode", when TAR matches CCR0, TAR will clear itself and start from 0 again.

    Thus if CCR0 is 49999, it will count the way I described.

    Now, if you load a 0 to CCR0, you are giving the command for the TAR to clear itself whenever it matches 0. How is that going to work?

  • Thanks for your reply,

    i realized my "blunder" before reading your replies, i ran step by step debugging emulation session and found that the micro doesn't leave the TACCR0 ISR at all, after executing RETI instr the micro re-enters into the ISR, guess why ? because the CCIFG is raised again and again like in infinite loop.

    so much so for starting and stopping the TAR in ISR. i commented out those two instructions and Voila! the program ran smoothly.

    i developed this habit of  "stop, reload & start" for timers inside ISRs while working with 8052 family and AVRs. i guess what they say is correct - "old habits die hard".

    one more thing that bugs me is - when the count in TAR matches the value in CCR0, the CCIFG is raised and the program gets interrupted(CPU wakes up) and jumps to ISR, there is a  latency time when the ISR is executed. meanwhile when this keeps happening, the count in TAR register rolls over and keeps incrementing (from 0), so the next TA interrupt happens at CCR0 (minus) latency time and not at CCR0 value,  for example: the latency time taken to reach the ISR is 15 cycles and if the CCR0 value is 50,000d then the next ISR triggers at 50,000d -15 cycles,

    i want to avoid this inaccuracy and that's why i want to stop and start the timer in each ISR so that the next isr is triggered at exact interval.

    any comments on this ?


    Regards,

    Nura

     

     

  • You are partially correct. There is a delay between the interrupt and when the ISR takes the action you desired. But stopping the Timer is not the solution.

    Without stopping it, the Timer will generate an interrupt every 50000 cycles -- every time when TAR reaches 49999.

    There is a latency for the ISR to start executing, and there is an additional delay for ISR to reach the point to do your desired action. If the delays are constant, the action will still be repeated every 50000 cycles -- at a constant number of cycles after TAR reaches 49999. The interval between actions of the ISR is still 50000 cycles. If the delays vary from one round to the next, the interval between actions of the ISR will be 50000 plus or minus the variation of the delays, not the delays themselves. (For example: If the delay were 15 cycles like you said, the action will still take place every 50000 cycles exactly. If the delay were 15+-2 cycles, the action will be 50000+-2 cycles.)

    The Timer can be programmed to take certain simple actions at a certain cycle count. Interrupt latency and ISR execution time will not delay those actions. The CPU is used to tell the Timer ahead of time what to do at what cycle count.

  •  

    Thanks for your comments and insight.

     

    Regards,

    Nura

  • Some things to add:

    On the AVR ATMega128, the timers are working almost identically to the MSP. But I remember that the timers on PIC were a real mess.

    In addition to OCYs note about interrupt latency and code variation, there is another source of variation: if another ISR is active when the timer interrupt comes, the time until the other ISR is finished is added to the interrupt latency. In more complex systems this may add a huge variation (jitter) in the output signal. If possible, it is better to use the hardware support for timer-generated signals.

    If all you want to do is to toggle a port pin every 2 seconds (50ms*20 toggle time), you can get a precise output this way:

    set the timer clock to /16
    set TACCR0 to 62500
    configure TACCR0 to use the toggle outmode
    set the proper PxSEL bit for the TA0 output and you'll get a 0.5Hz output signal on this pin. Without any ISR and without any jitter other than what the clock base induces.

    In addition, the other TACCRx can give you several more outputs of 1Hz frequency and freely programmable duty cycle in this setup. Without any code other than the initialisation.
    Also, the timers offer the opposite functionality: they can 'capture' the current timer value if an external trigger is detected. There of yourse you need an ISR that reads the value and does something useful. It's even possible to clock thr timer from an external source (as event counter). And since some MSPs have up to 4 separate timers (plus maybe some basic timers such as an RTC/counter or the watchdog timer), there are many combinations possible, up to complex signal forms, frequency bursts etc.

    Any of these outputs are fixed to a certain port pin, unless the MSP you're using has a port mapping module (only few of the newest have)

    Personally, I normally use the CCR0 in a free-running mode (unless I need PWM outputs with very asymmetric duty cycles or a high PWM frequency).
    The TImer runs in continuous mode, overflowing at 65535. TACCR0 is set to  my wanted delay time (e.g. 1000 for 1ms interval @ 1MHz timer clock). When the ISR is called, I just add another 1000 to TACCR0, this means, the next TACCCR0 interrupt happens exactly 1ms after the last, no matter how long it took me to execute the ISR (as long as it happens in below 1ms, I use some safety code to detect this and correct at least the ms counter)
    It gives me as a side effect the option of using another CCRx register for exact microsecond delays. Just set TACCR1 to TAR+delay and wait until the interrupt flag is set. Works fine for intervals from 4 to 65535 microseconds (minimum depends a bit on the actual MCLK speed, 4 microseconds is for 16MHz)

    Timers are great :)

  •  

    Timers are Great , JMG but not on MSP430

    i think the some what "bugging" feature of MSP430 Timer is not being able to write to TAR ( though it can be read).

    In a 8051/2 or AVR we can actually write to the Timer register with any value to get precise delay. suppose i need 50mS delay so i load 65536 - 50000 = 15536d initially into the 16bit timer register and enable timer interrupt, when the timer overflows, a flag is raised and micro jumps to ISR vector, in the ISR we can reload the timer with same values or different values depending on use.

    8052 has 3 x 16 bit timers that can be individually configured in 4 modes.

    in MSP430, if the user is given access to write to TAR with initial values then we don't have to use CCR0 register,  CCR0 and CCR1 can be used for generating PWM on dedicated port pins.

    if  i have to generate 2 pwm signals on two port pins, i use CCR0 and CCR1 registers, but along with the 2 PWM signals if i have to generate a  time delay using hardware timer then i don't have an option, do i ? ( CCRO and CCR1 are already used up and don't want to use WDT as interval timer )

    i can play with 8052 and AVR timers as i like but timer/s on MSP430 handicap me. 

    One more feature of MSP430  that  handicaps me is the inability to set interrupt priorities, usually the interrupt priorities in MSP430 is fixed and priority is set as per the interrupt vector address.

    but in a 8052, user can set interrupt priorities as he likes


    Regards,

    Nura

  • Nura said:
    i think the some what "bugging" feature of MSP430 Timer is not being able to write to TAR ( though it can be read).

    ??? why says that? Of course you can. But if the timer clock is not synchronized with the MCLK, you should stop the timer first to avoid interferences. Btu of yourse you can write to TAR.
    Anyway, it makes not much sense writing a certain value into TAR.
    It may confuse you that there is a bit to reset the timer to 0. This bit will not only reset the timer but also reset the prescalers, which is the main purpose. To reset the tiemr to 0 (or any othe rvalue) jus twrite to it, whcih will happily alter TAR, bu tnot touch the prescalers (so the next tick may be shorter than expected)

    The difference is that TAR is a versatile counter which can count up to CCR0 and reset, up to overflow and up to CCR0 and back down. It has, however, no palin down mode. And why? It makes no difference if you use CCR0 to define the end value and let it count up or define a register (let's call it CCR0 :) ) where you define the start value and let the timer cound down. Except for the direction.

    Nura said:
    in MSP430, if the user is given access to write to TAR with initial values then we don't have to use CCR0 register,  CCR0 and CCR1 can be used for generating PWM on dedicated port pins.

    Well, just ignore that CCR0 is ther eand think of the timer as having one CCR register less. Let's call it TARLATCH or whatever. And well, all differences disappear. It's just the naming iand your imagination.

    Nura said:
    if  i have to generate 2 pwm signals on two port pins, i use CCR0 and CCR1 registers

    Well, you can't eat the cake and keep it. If you have an MSP with jsut CCR0 and CCR1 and you cannot use CCR0 as you want, it is jsut as having an MSP that does what you want but just has CCR0 and no CCR1. Do you feel better then?

    The 5438 has two TImerA and oen TiemrB mopdule with 3,5 and 7 CCR registers. You just picked the wrong processor for the application, that's all. it ha NOTHING to do with the way the timers work. Jsu tthat you want to do something where the hardware does not fit. Peel off the TA.0 pin and forget it was ever there and you're at the same level as before.

    CCR0 is there to serve a purpose. It might not be what you want but that's not the MSPs fault. It wasn't designed for USB transfers too. Nor for providing a PWM signal with programmable duty-cycle. If it doesn't fit your needs, well, buy a bigger gun.
    Take this advice for all your other complaints too. If it doesn't ft your needs, buy something that fits. If AVR and 8052 are so much better, why did you even bother buying an MSP?

    Nura said:
    i can play with 8052 and AVR timers as i like but timer/s on MSP430 handicap me. 

    No, it's just your pre-biased imagination that handicaps you. (no insult intended). Let got the idea how you did it there and you will see that there are equally good ways to do it here. if you don't want to go different ways, you shouldn't leave the path you already followed and stay with AVR and 8052.

     

     

  • Thanks for your replies and comments, you seem to be a die hard fan of MSP430!


    As a Programmer whose has worked with Z80,8052,PIC, AVR - i have a habit of comparing how things work in these MCUs, this fact holds true for majority of programmers.


    i moved ( well, not fully ) to MSP430 because of  "ultra low power" feature and my end application is battery operated equipment.


    your argument that i should select a bigger MSP instead of complaining is very much true, but the bigger part is not available in the same package as the original one.


     i chose this path ( of selecting MSP430) not because i was "unhappy"  with my 8052 or AVRs but the situation demands a very low power consumption.  other than this "sole" feature i don't feel MSP430 is any better than an AVR or 8052 variant.


    Everyone knows the huge popularity of AVRs and PICs is due to the availability  of simple, low cost development tools, an AVR or PIC can be easily programmed on a bread board using nothing more than a transistor, zener, 2 resistors and a DB9 connector.  But with MSP430........... you know the drill.


    Coming back to the Timers and interrupts;

    you are saying that i am allowed to write to TAR register?

    taking the above example  then i can write 15536d to TAR and set it in continuous mode, enable timer interrupt, allow TAR to overflow and then jump to Timer ISR, in the ISR i can stop the timer and reload again with 15536d and start timer ?


    Regards

    Nura

     

  • "you are saying that i am allowed to write to TAR register? "

    Yes, you can. Read the manual before you say you cannot do this or you have to do that.

    By the way, you can stop the Timer and restart it again too. But you cannot stop the time by doing that.

  • Nura said:
    Thanks for your replies and comments, you seem to be a die hard fan of MSP430!

    I now worked for some years with them, mostly 1x series and now 5x series. I also use the ATMega128 and I have some experience with the smaller pics (14 bit series) but while they are cheap, they are also a real mess to program and the hardware was quite limited. I guess there were better devices available, but I didn't pic(k) the device we used. Half of the code I inherited with the projects was workarounds for the PIC design limitations. Switching tio the MSP1232 was real fun. I also have some (but not so in-depth) experience with the 8032 (it's been a looong time since - wasn't the 8052 the one with mask programmed rom - usually a basic interpreter?) and the Z80/8080/8085 processors. The latter on larger machines rather than embedded systems.

    I cannot confirm that PICs have simple low-cost tools and breadboard programming - in-circuit programming, if necessary, was severely limiting the possible hardware you could attach to the PIC pins, and the programming process was slooooow. The advantage of the PICs was the very low price for mass production. But sicne our producs are not mass products, the ease of development and maintenance did count much more (in money as well) than the lower processor costs.

    Nura said:
    you are saying that i am allowed to write to TAR register?

    taking the above example  then i can write 15536d to TAR and set it in continuous mode, enable timer interrupt, allow TAR to overflow and then jump to Timer ISR, in the ISR i can stop the timer and reload again with 15536d and start timer ?

    Yes you can. You don't even need to stop the timer, if you don't mind getting a false first tick depending on when (in relation to the clock prescaler) you changed the TAR value manually (well, the change itself is unprecise enough so it souldn't count). But I don't know why you should. Writing (65536-15536) into CCR0 and letting TimerA run in up mode has the same result, but you first don't need to reload TAR each time and secondly you'll get an interrupt at equidistant intervals. Since the timer continues counting right after triggering the interrupt, the next interrupt comes after exact the same interval, no matter how long it takes for you to respond to the interrupt. Something that doesn't work on the PIC. But then, the PIC (at least the small one we had) did have only one single interrupt vector, so it was impossible that a different ISR was executing the moment the interrupt comes. as there was only one ISR.

     

**Attention** This is a public forum