00001
00042 #include <timer/tc_timer_xmega.h>
00043 #include <assert.h>
00044 #include <interrupt.h>
00045 #include <intc.h>
00046 #include <regs/xmega_tc.h>
00047 #include <chip/tc.h>
00048 #include <pmic.h>
00049
00067 static void tc_timer_irq_handler(void *int_data)
00068 {
00069 struct timer *timer = (struct timer *)int_data;
00070
00071 assert(timer);
00072
00073 tc_write_reg8(timer->regs, INTCTRLB, TC_BF(INTCTRLB_CCAINTLVL,
00074 PMIC_INTLVL_OFF));
00075
00076 if (timer->callback)
00077 timer->callback(timer);
00078 }
00079
00080
00081 #if (defined(TC0_BASE) && defined(CONFIG_TIMER_0)) || defined(__DOXYGEN__)
00082 INTC_DEFINE_HANDLER(PMIC_TC0_CCA_IRQ, tc_timer_irq_handler,
00083 CONFIG_INTLVL_TC0_CCA);
00084 #endif
00085
00086 #if defined(TC1_BASE) && defined(CONFIG_TIMER_1)
00087 INTC_DEFINE_HANDLER(PMIC_TC1_CCA_IRQ, tc_timer_irq_handler,
00088 CONFIG_INTLVL_TC1_CCA);
00089 #endif
00090
00091 #if defined(TC2_BASE) && defined(CONFIG_TIMER_2)
00092 INTC_DEFINE_HANDLER(PMIC_TC2_CCA_IRQ, tc_timer_irq_handler,
00093 CONFIG_INTLVL_TC2_CCA);
00094 #endif
00095
00096 #if defined(TC3_BASE) && defined(CONFIG_TIMER_3)
00097 INTC_DEFINE_HANDLER(PMIC_TC3_CCA_IRQ, tc_timer_irq_handler,
00098 CONFIG_INTLVL_TC3_CCA);
00099 #endif
00100
00101 #if defined(TC4_BASE) && defined(CONFIG_TIMER_4)
00102 INTC_DEFINE_HANDLER(PMIC_TC4_CCA_IRQ, tc_timer_irq_handler,
00103 CONFIG_INTLVL_TC4_CCA);
00104 #endif
00105
00106 #if defined(TC5_BASE) && defined(CONFIG_TIMER_5)
00107 INTC_DEFINE_HANDLER(PMIC_TC5_CCA_IRQ, tc_timer_irq_handler,
00108 CONFIG_INTLVL_TC5_CCA);
00109 #endif
00110
00111 #if defined(TC6_BASE) && defined(CONFIG_TIMER_6)
00112 INTC_DEFINE_HANDLER(PMIC_TC6_CCA_IRQ, tc_timer_irq_handler,
00113 CONFIG_INTLVL_TC6_CCA);
00114 #endif
00115
00116 #if defined(TC7_BASE) && defined(CONFIG_TIMER_7)
00117 INTC_DEFINE_HANDLER(PMIC_TC7_CCA_IRQ, tc_timer_irq_handler,
00118 CONFIG_INTLVL_TC7_CCA);
00119 #endif
00120
00134 void tc_timer_init(uint8_t tc_id, void *regs, struct timer *timer,
00135 timer_callback_t callback)
00136 {
00137 assert(regs);
00138 assert(timer);
00139
00140 timer->regs = regs;
00141 timer->callback = callback;
00142 timer->clksel = tc_select_clock(tc_id,
00143 (uint32_t)CONFIG_TIMER_RESOLUTION);
00144
00145 tc_enable_pclk(tc_id);
00146 tc_write_reg8(regs, CTRLA, TC_CLKSEL_OFF);
00147 tc_write_reg8(regs, CTRLFSET, TC_BF(CMD, TC_CMD_RESET));
00148 tc_write_reg8(regs, CTRLB, TC_BIT(CTRLB_CCAEN));
00149 tc_disable_pclk(tc_id);
00150
00151 switch (tc_id) {
00152 #if (defined(TC0_BASE) && defined(CONFIG_TIMER_0)) || defined(__DOXYGEN__)
00153 case 0:
00154 intc_set_irq_data(PMIC_TC0_CCA_IRQ, timer);
00155 timer->intlvl = CONFIG_INTLVL_TC0_CCA;
00156 break;
00157 #endif
00158
00159 #if defined(TC1_BASE) && defined(CONFIG_TIMER_1)
00160 case 1:
00161 intc_set_irq_data(PMIC_TC1_CCA_IRQ, timer);
00162 timer->intlvl = CONFIG_INTLVL_TC1_CCA;
00163 break;
00164 #endif
00165
00166 #if defined(TC2_BASE) && defined(CONFIG_TIMER_2)
00167 case 2:
00168 intc_set_irq_data(PMIC_TC2_CCA_IRQ, timer);
00169 timer->intlvl = CONFIG_INTLVL_TC2_CCA;
00170 break;
00171 #endif
00172
00173 #if defined(TC3_BASE) && defined(CONFIG_TIMER_3)
00174 case 3:
00175 intc_set_irq_data(PMIC_TC3_CCA_IRQ, timer);
00176 timer->intlvl = CONFIG_INTLVL_TC3_CCA;
00177 break;
00178 #endif
00179
00180 #if defined(TC4_BASE) && defined(CONFIG_TIMER_4)
00181 case 4:
00182 intc_set_irq_data(PMIC_TC4_CCA_IRQ, timer);
00183 timer->intlvl = CONFIG_INTLVL_TC4_CCA;
00184 break;
00185 #endif
00186
00187 #if defined(TC5_BASE) && defined(CONFIG_TIMER_5)
00188 case 5:
00189 intc_set_irq_data(PMIC_TC5_CCA_IRQ, timer);
00190 timer->intlvl = CONFIG_INTLVL_TC5_CCA;
00191 break;
00192 #endif
00193
00194 #if defined(TC6_BASE) && defined(CONFIG_TIMER_6)
00195 case 6:
00196 intc_set_irq_data(PMIC_TC6_CCA_IRQ, timer);
00197 timer->intlvl = CONFIG_INTLVL_TC6_CCA;
00198 break;
00199 #endif
00200
00201 #if defined(TC7_BASE) && defined(CONFIG_TIMER_7)
00202 case 7:
00203 intc_set_irq_data(PMIC_TC7_CCA_IRQ, timer);
00204 timer->intlvl = CONFIG_INTLVL_TC7_CCA;
00205 break;
00206 #endif
00207
00208 default:
00209 unhandled_case(tc_id);
00210 }
00211 }
00212
00227 timer_res_t tc_timer_set_resolution(uint8_t tc_id, uint32_t resolution)
00228 {
00229 return tc_select_clock(tc_id, resolution);
00230 }
00231
00241 uint32_t tc_timer_get_resolution(uint8_t tc_id, timer_res_t timer_res)
00242 {
00243 return tc_get_resolution(tc_id, timer_res);
00244 }
00245
00257 void tc_timer_write_resolution(uint8_t tc_id, struct timer *timer,
00258 timer_res_t timer_res)
00259 {
00260 assert(timer);
00261 assert(timer->regs);
00262
00263 timer->clksel = timer_res;
00264 tc_write_reg8(timer->regs, CTRLA, timer_res);
00265 }
00266
00274 void tc_timer_start(uint8_t tc_id, struct timer *timer)
00275 {
00276 assert(timer->regs);
00277
00278 tc_enable_pclk(tc_id);
00279
00280
00281 tc_write_reg8(timer->regs, CTRLFSET, TC_BF(CMD, TC_CMD_RESTART));
00282 tc_write_reg8(timer->regs, CTRLA, timer->clksel);
00283 }
00284
00295 void tc_timer_set_alarm(uint8_t tc_id, struct timer *timer, uint16_t delay)
00296 {
00297 irqflags_t flags;
00298 bool enabled;
00299 uint16_t start;
00300
00301 assert(timer);
00302 assert(timer->regs);
00303
00304
00305 tc_write_reg8(timer->regs, INTCTRLB, TC_BF(INTCTRLB_CCAINTLVL,
00306 PMIC_INTLVL_OFF));
00307
00308
00309 enabled = tc_pclk_is_enabled(tc_id);
00310 if (!enabled)
00311 tc_enable_pclk(tc_id);
00312 else
00313 tc_write_reg8(timer->regs, CTRLA, TC_CLKSEL_OFF);
00314
00315
00316 flags = cpu_irq_save();
00317
00318 tc_write_reg8(timer->regs, INTFLAGS, TC_BIT(INTFLAGS_CCAIF));
00319
00320
00321
00322
00323 if (!enabled)
00324 tc_write_reg16(timer->regs, CCA, delay);
00325 else {
00326 start = tc_read_reg16(timer->regs, CNT);
00327 tc_write_reg16(timer->regs, CCA, start + delay);
00328 }
00329
00330 cpu_irq_restore(flags);
00331
00332 tc_write_reg8(timer->regs, INTCTRLB, TC_BF(INTCTRLB_CCAINTLVL,
00333 timer->intlvl));
00334
00335
00336 if (!enabled)
00337 tc_disable_pclk(tc_id);
00338 else
00339 tc_write_reg8(timer->regs, CTRLA, timer->clksel);
00340 }
00341
00349 void tc_timer_stop(uint8_t tc_id, struct timer *timer)
00350 {
00351 assert(timer);
00352 assert(timer->regs);
00353
00354
00355 tc_write_reg8(timer->regs, INTCTRLB, TC_BF(INTCTRLB_CCAINTLVL,
00356 PMIC_INTLVL_OFF));
00357 tc_write_reg8(timer->regs, CTRLA, TC_BF(CTRLA_CLKSEL, TC_CLKSEL_OFF));
00358 tc_disable_pclk(tc_id);
00359 }
00360
00372 uint16_t tc_timer_get_time(uint8_t tc_id, struct timer *timer)
00373 {
00374 bool enabled;
00375 irqflags_t flags;
00376 uint16_t time;
00377
00378 assert(timer);
00379 assert(timer->regs);
00380
00381 enabled = tc_pclk_is_enabled(tc_id);
00382
00383 if (enabled) {
00384
00385 flags = cpu_irq_save();
00386 time = tc_read_reg16(timer->regs, CNT);
00387 cpu_irq_restore(flags);
00388 } else {
00389 time = 0;
00390 }
00391
00392 return time;
00393 }
00394