BeRTOS
timer_xmega.c
Go to the documentation of this file.
00001 
00047 #include <drv/timer_xmega.h>
00048 #include <cfg/macros.h> // BV()
00049 
00050 #include <cpu/types.h>
00051 #include <cpu/irq.h>
00052 
00053 #include <avr/io.h>
00054 
00055 /* Helper MACROS taken from the Atmel examples and altered
00056  *
00057  *  The AVR XMEGA has different structures for TC0 and TC1,
00058  *  however these only differ in the amount of compare/capture
00059  *  channels, so for this purpose they can be used exactly the same
00060   */
00061 
00062 //check if the bitvalues of the TC0 and TC1 Timer/Counters are really the same
00063 #if TC0_CLKSEL_gm != TC1_CLKSEL_gm || TC0_WGMODE_gm != TC1_WGMODE_gm || TC0_OVFINTLVL_gm != TC1_OVFINTLVL_gm
00064     #error TC0 and TC1 Timer/Counters cannot be configured with the same bitvalues
00065 #endif
00066 
00067 #define TIMER_CONFIG_CLOCK_SOURCE(_clkSel)\
00068     ((TIMERCOUNTER).CTRLA = ((TIMERCOUNTER).CTRLA & ~TC0_CLKSEL_gm) | _clkSel)
00069 
00070 #define TIMER_CLEAR_FLAGS() ((TIMERCOUNTER).INTFLAGS = 0xFF)
00071 
00072 #define TIMER_SET_PERIOD( _period ) ( (TIMERCOUNTER).PER = (_period) )
00073 
00074 #define TIMER_SET_OVERFLOW_INTERRUPT_LEVEL( _interruptLevel )\
00075     ((TIMERCOUNTER).INTCTRLA = ( (TIMERCOUNTER).INTCTRLA & ~TC0_OVFINTLVL_gm ) | _interruptLevel)
00076 
00077 #define TIMER_CONFIG_WGM(_wgm)\
00078     ((TIMERCOUNTER).CTRLB = ( (TIMERCOUNTER).CTRLB & ~TC0_WGMODE_gm ) | _wgm)
00079 
00080 #define TIMER_RESET() ( (TIMERCOUNTER).CTRLFSET = TC_CMD_RESET_gc )
00081 
00082 //Define TIMER_PRESCALE_REG_VALUE bases on the provided
00083 //TIMER_PRESCALER value
00084 #if TIMER_PRESCALER == 0
00085     #define TIMER_CLKSEL_gc             TC_CLKSEL_OFF_gc
00086 #elif TIMER_PRESCALER == 1
00087     #define TIMER_CLKSEL_gc             TC_CLKSEL_DIV1_gc
00088 #elif TIMER_PRESCALER == 2
00089     #define TIMER_CLKSEL_gc             TC_CLKSEL_DIV2_gc
00090 #elif TIMER_PRESCALER == 4
00091     #define TIMER_CLKSEL_gc             TC_CLKSEL_DIV4_gc
00092 #elif TIMER_PRESCALER == 16
00093     #define TIMER_CLKSEL_gc             TC_CLKSEL_DIV16_gc
00094 #elif TIMER_PRESCALER == 64
00095     #define TIMER_CLKSEL_gc             TC_CLKSEL_DIV64_gc
00096 #elif TIMER_PRESCALER == 256
00097     #define TIMER_CLKSEL_gc             TC_CLKSEL_DIV256_gc
00098 #elif TIMER_PRESCALER == 1024
00099     #define TIMER_CLKSEL_gc             TC_CLKSEL_DIV1024_gc
00100 #else
00101     #error Invalid value for TIMER_PRESCALER has been defined! Using default of 1
00102     #define TIMER_CLKSEL_gc             TC_CLKSEL_DIV1_gc
00103 #endif
00104 
00105 void timer_hw_init(void)
00106 {
00107     //Save and disable IRQ
00108     cpu_flags_t flags;
00109     IRQ_SAVE_DISABLE(flags);
00110     //disable the timer
00111     TIMER_CONFIG_CLOCK_SOURCE(TC_CLKSEL_OFF_gc);
00112     //clear all flags
00113     TIMER_CLEAR_FLAGS();
00114     //setup the Periode register value
00115     //CNT register will be reset to 0 when CNT == PER
00116     TIMER_SET_PERIOD(TIMER_PERIOD_VALUE);
00117     //set the Waveform Generation Mode to Normal
00118     TIMER_CONFIG_WGM(TC_WGMODE_NORMAL_gc);
00119     //enable the overflow interrupt
00120     //use the highest priority
00121     TIMER_SET_OVERFLOW_INTERRUPT_LEVEL(TC_OVFINTLVL_HI_gc);
00122     //enable timer by setting the correct prescaler/clock
00123     TIMER_CONFIG_CLOCK_SOURCE(TIMER_CLKSEL_gc);
00124     //Restore IRQ
00125     IRQ_RESTORE(flags);
00126 }