timer_avr.c

Go to the documentation of this file.
00001 
00045 #include <drv/timer_avr.h>
00046 #include <cfg/macros.h> // BV()
00047 
00048 #include <cpu/types.h>
00049 #include <cpu/irq.h>
00050 
00051 #include <avr/interrupt.h>
00052 #include <avr/io.h>
00053 
00054 #if CPU_AVR_ATMEGA1281 || CPU_AVR_ATMEGA168
00055     #define REG_TIFR0 TIFR0
00056     #define REG_TIFR2 TIFR2
00057 
00058     #define REG_TIMSK0 TIMSK0
00059     #define REG_TIMSK2 TIMSK2
00060 
00061     #define REG_TCCR2A TCCR2A
00062     #define REG_TCCR2B TCCR2B
00063 
00064     #define REG_OCR2A  OCR2A
00065 
00066     #define BIT_OCF0A  OCF0A
00067     #define BIT_OCF2A  OCF2A
00068 
00069     #define BIT_OCIE0A OCIE0A
00070     #define BIT_OCIE2A OCIE2A
00071 #else
00072     #define REG_TIFR0 TIFR
00073     #define REG_TIFR2 TIFR
00074 
00075     #define REG_TIMSK0 TIMSK
00076     #define REG_TIMSK2 TIMSK
00077 
00078     #define REG_TCCR2A TCCR2
00079     #define REG_TCCR2B TCCR2
00080 
00081     #define REG_OCR2A  OCR2
00082 
00083     #define BIT_OCF0A  OCF0
00084     #define BIT_OCF2A  OCF2
00085 
00086     #define BIT_OCIE0A OCIE0
00087     #define BIT_OCIE2A OCIE2
00088 #endif
00089 
00090 #if CPU_AVR_ATMEGA128 || CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA103
00091     /* These ATMega have different prescaler options. */
00092     #define TIMER0_PRESCALER_64 BV(CS02)
00093     #define TIMER2_PRESCALER_64 (BV(CS21) | BV(CS20))
00094 #else
00095     #define TIMER0_PRESCALER_64 (BV(CS01) | BV(CS00))
00096     #define TIMER2_PRESCALER_64 BV(CS22)
00097 #endif
00098 
00100 #if (CONFIG_TIMER == TIMER_ON_OUTPUT_COMPARE0)
00101 
00102     static void timer_hw_init(void)
00103     {
00104         cpu_flags_t flags;
00105         IRQ_SAVE_DISABLE(flags);
00106 
00107         /* Reset Timer flags */
00108         REG_TIFR0 = BV(BIT_OCF0A) | BV(TOV0);
00109 
00110         /* Setup Timer/Counter interrupt */
00111         ASSR = 0x00;                  /* Internal system clock */
00112         TCCR0 = BV(WGM01)             /* Clear on Compare match */
00113             #if TIMER_PRESCALER == 64
00114                 | TIMER0_PRESCALER_64
00115             #else
00116                 #error Unsupported value of TIMER_PRESCALER
00117             #endif
00118         ;
00119         TCNT0 = 0x00;                 /* Initialization of Timer/Counter */
00120         OCR0 = OCR_DIVISOR;           /* Timer/Counter Output Compare Register */
00121 
00122         /* Enable timer interrupts: Timer/Counter2 Output Compare (OCIE2) */
00123         REG_TIMSK0 &= ~BV(TOIE0);
00124         REG_TIMSK0 |= BV(OCIE0);
00125 
00126         IRQ_RESTORE(flags);
00127     }
00128 
00129     INLINE hptime_t timer_hw_hpread(void)
00130     {
00131         return TCNT0;
00132     }
00133 
00134 #elif (CONFIG_TIMER == TIMER_ON_OVERFLOW1)
00135 
00136     static void timer_hw_init(void)
00137     {
00138         cpu_flags_t flags;
00139         IRQ_SAVE_DISABLE(flags);
00140 
00141         /* Reset Timer overflow flag */
00142         TIFR |= BV(TOV1);
00143 
00144         /* Fast PWM mode, 9 bit, 24 kHz, no prescaling. */
00145         #if (TIMER_PRESCALER == 1) && (TIMER_HW_BITS == 9)
00146             TCCR1A |= BV(WGM11);
00147             TCCR1A &= ~BV(WGM10);
00148             TCCR1B |= BV(WGM12) | BV(CS10);
00149             TCCR1B &= ~(BV(WGM13) | BV(CS11) | BV(CS12));
00150         /* Fast PWM mode, 8 bit, 24 kHz, no prescaling. */
00151         #elif (TIMER_PRESCALER == 1) && (TIMER_HW_BITS == 8)
00152             TCCR1A |= BV(WGM10);
00153             TCCR1A &= ~BV(WGM11);
00154             TCCR1B |= BV(WGM12) | BV(CS10);
00155             TCCR1B &= ~(BV(WGM13) | BV(CS11) | BV(CS12));
00156         #else
00157             #error Unsupported value of TIMER_PRESCALER or TIMER_HW_BITS
00158         #endif
00159 
00160         TCNT1 = 0x00;         /* initialization of Timer/Counter */
00161 
00162         /* Enable timer interrupt: Timer/Counter1 Overflow */
00163         TIMSK |= BV(TOIE1);
00164 
00165         IRQ_RESTORE(flags);
00166     }
00167 
00168     INLINE hptime_t timer_hw_hpread(void)
00169     {
00170         return TCNT1;
00171     }
00172 
00173 #elif (CONFIG_TIMER == TIMER_ON_OUTPUT_COMPARE2)
00174     static void timer_hw_init(void)
00175     {
00176         cpu_flags_t flags;
00177         IRQ_SAVE_DISABLE(flags);
00178 
00179         /* Reset Timer flags */
00180         REG_TIFR2 = BV(BIT_OCF2A) | BV(TOV2);
00181 
00182         /* Setup Timer/Counter interrupt */
00183         REG_TCCR2A = 0; // TCCR2 reg could be separate or a unique register with both A & B values, this is needed to
00184         REG_TCCR2B = 0; // ensure correct initialization.
00185 
00186         REG_TCCR2A = BV(WGM21);
00187         #if TIMER_PRESCALER == 64
00188             REG_TCCR2B |= TIMER2_PRESCALER_64;
00189         #else
00190             #error Unsupported value of TIMER_PRESCALER
00191         #endif
00192 
00193         /* Clear on Compare match & prescaler = 64, internal sys clock.
00194            When changing prescaler change TIMER_HW_HPTICKS_PER_SEC too */
00195         TCNT2 = 0x00;         /* initialization of Timer/Counter */
00196         REG_OCR2A = OCR_DIVISOR;   /* Timer/Counter Output Compare Register */
00197 
00198         /* Enable timer interrupts: Timer/Counter2 Output Compare (OCIE2) */
00199         REG_TIMSK2 &= ~BV(TOIE2);
00200         REG_TIMSK2 |= BV(BIT_OCIE2A);
00201 
00202         IRQ_RESTORE(flags);
00203     }
00204 
00205     INLINE hptime_t timer_hw_hpread(void)
00206     {
00207         return TCNT2;
00208     }
00209 #elif (CONFIG_TIMER == TIMER_ON_OVERFLOW3)
00210 
00211     static void timer_hw_init(void)
00212     {
00213         cpu_flags_t flags;
00214         IRQ_SAVE_DISABLE(flags);
00215 
00216         /* Reset Timer overflow flag */
00217         TIFR |= BV(TOV3);
00218 
00219         /* Fast PWM mode, 9 bit, 24 kHz, no prescaling. */
00220         #if (TIMER_PRESCALER == 1) && (TIMER_HW_BITS == 9)
00221             TCCR3A |= BV(WGM31);
00222             TCCR3A &= ~BV(WGM30);
00223             TCCR3B |= BV(WGM32) | BV(CS30);
00224             TCCR3B &= ~(BV(WGM33) | BV(CS31) | BV(CS32));
00225         /* Fast PWM mode, 8 bit, 24 kHz, no prescaling. */
00226         #elif (TIMER_PRESCALER == 1) && (TIMER_HW_BITS == 8)
00227             TCCR3A |= BV(WGM30);
00228             TCCR3A &= ~BV(WGM31);
00229             TCCR3B |= BV(WGM32) | BV(CS30);
00230             TCCR3B &= ~(BV(WGM33) | BV(CS31) | BV(CS32));
00231         #else
00232             #error Unsupported value of TIMER_PRESCALER or TIMER_HW_BITS
00233         #endif
00234 
00235         TCNT3 = 0x00;         /* initialization of Timer/Counter */
00236 
00237         /* Enable timer interrupt: Timer/Counter3 Overflow */
00238         /* ATTENTION! TOIE3 is only on ETIMSK, not TIMSK */
00239         ETIMSK |= BV(TOIE3);
00240 
00241         IRQ_RESTORE(flags);
00242     }
00243 
00244     INLINE hptime_t timer_hw_hpread(void)
00245     {
00246         return TCNT3;
00247     }
00248 
00249 #else
00250     #error Unimplemented value for CONFIG_TIMER
00251 #endif /* CONFIG_TIMER */
00252