timer_avr.c

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