void hwtimer_arch_enable_interrupt(void) { timer_irq_enable(hw_timers[0]); timer_irq_enable(hw_timers[1]); }
/** * @brief Setup the given timer * * The SAM3X8E has 3 timers. Each timer has 3 independent channels. * RIOT uses the timers in WAVE mode with the following clock chaining: * * ---------- ---------- * | | | |-> IRQ-compareA * | TCx[2] | ---- TIOA2 --->| TCx[0] |-> IRQ-compareB * | | | | |-> IRQ-compareC * ---------- | ---------- * ^ | * | | ---------- * | | | |-> IRQ-compareA * TIMER_CLOCK1 ------->| TCx[1] |-> IRQ-compareB * | |-> IRQ-compareC * ---------- * * For each timer, channel 0 is used to implement a prescaler. Channel 0 is * driven by the MCK / 2 (42MHz) (TIMER_CLOCK1). */ int timer_init(tim_t dev, unsigned int ticks_per_us, void (*callback)(int)) { Tc *tim; /* select the timer and enable the timer specific peripheral clocks */ switch (dev) { #if TIMER_0_EN case TIMER_0: tim = TIMER_0_DEV; PMC->PMC_PCER0 = (1 << ID_TC0) | (1 << ID_TC1) | (1 << ID_TC2); break; #endif #if TIMER_1_EN case TIMER_1: tim = TIMER_1_DEV; PMC->PMC_PCER0 = (1 << ID_TC3) | (1 << ID_TC4); PMC->PMC_PCER1 = (1 << (ID_TC5 - 32)); break; #endif #if TIMER_2_EN case TIMER_2: tim = TIMER_2_DEV; PMC->PMC_PCER1 = (1 << (ID_TC6 - 32)) | (1 << (ID_TC7 - 32)) | (1 << (ID_TC8 - 32)); break; #endif case TIMER_UNDEFINED: default: return -1; } /* save callback */ timer_config[dev].cb = callback; /* configure the timer block by connecting TIOA2 to XC0 and XC1 */ tim->TC_BMR = TC_BMR_TC0XC0S_TIOA2 | TC_BMR_TC1XC1S_TIOA2; /* configure and enable channels 0 and 1 to use XC0 and XC1 as input */ tim->TC_CHANNEL[0].TC_CMR = TC_CMR_TCCLKS_XC0 | TC_CMR_WAVE | TC_CMR_EEVT_XC0; tim->TC_CHANNEL[1].TC_CMR = TC_CMR_TCCLKS_XC1 | TC_CMR_WAVE | TC_CMR_EEVT_XC0; tim->TC_CHANNEL[0].TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG; /* and start */ tim->TC_CHANNEL[1].TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG; /* and start */ /* configure channel 2: * - select wave mode * - set input clock to TIMER_CLOCK1 (MCK/2) * - reload on TC_CV == TC_RC * - let TIOA2 signal be toggled when TC_CV == TC_RC */ tim->TC_CHANNEL[2].TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 | TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_ACPC_TOGGLE; /* configure the frequency of channel 2 to 1us * ticks_per_us * * note: as channels 0 and 1 are only incremented on rising edges of TIOA2 line and * channel 2 toggles this line on each timer tick, the actual frequency driving ch0/1 * is f_ch2 / 2 --> f_ch0/1 = (MCK / 2 / 2 / 1000000) * ticks_per_us. */ tim->TC_CHANNEL[2].TC_RC = ((F_CPU / 1000000) / 4) * ticks_per_us; /* start channel 2 */ tim->TC_CHANNEL[2].TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG; /* enable interrupts for given timer */ timer_irq_enable(dev); return 0; }
int timer_set_absolute(tim_t dev, int channel, unsigned int value) { unsigned state = disableIRQ(); switch (dev) { #if TIMER_0_EN case TIMER_0: switch (channel) { case 0: TIMER0_COMP_A = (uint16_t) value; TIMER0_IRQ_FLAG_REG &= ~(1 << TIMER0_COMP_A_FLAG); TIMER0_IRQ_MASK_REG |= (1 << TIMER0_COMP_A_EN); break; case 1: TIMER0_COMP_B = (uint16_t) value; TIMER0_IRQ_FLAG_REG &= ~(1 << TIMER0_COMP_B_FLAG); TIMER0_IRQ_MASK_REG |= (1 << TIMER0_COMP_B_EN); break; case 2: TIMER0_COMP_C = (uint16_t) value; TIMER0_IRQ_FLAG_REG &= ~(1 << TIMER0_COMP_C_FLAG); TIMER0_IRQ_MASK_REG |= (1 << TIMER0_COMP_C_EN); break; default: restoreIRQ(state); return -1; } break; #endif #if TIMER_1_EN case TIMER_1: switch (channel) { case 0: TIMER1_COMP_A = (uint16_t) value; TIMER1_IRQ_FLAG_REG &= ~(1 << TIMER1_COMP_A_FLAG); TIMER1_IRQ_MASK_REG |= (1 << TIMER1_COMP_A_EN); break; case 1: TIMER1_COMP_B = (uint16_t) value; TIMER1_IRQ_FLAG_REG &= ~(1 << TIMER1_COMP_B_FLAG); TIMER1_IRQ_MASK_REG |= (1 << TIMER1_COMP_B_EN); break; case 2: TIMER1_COMP_C = (uint16_t) value; TIMER1_IRQ_FLAG_REG &= ~(1 << TIMER1_COMP_C_FLAG); TIMER1_IRQ_MASK_REG |= (1 << TIMER1_COMP_C_EN); break; default: restoreIRQ(state); return -1; } break; #endif #if TIMER_2_EN case TIMER_2: switch (channel) { case 0: TIMER2_COMP_A = (uint16_t) value; TIMER2_IRQ_FLAG_REG &= ~(1 << TIMER2_COMP_A_FLAG); TIMER2_IRQ_MASK_REG |= (1 << TIMER2_COMP_A_EN); break; case 1: TIMER2_COMP_B = (uint16_t) value; TIMER2_IRQ_FLAG_REG &= ~(1 << TIMER2_COMP_B_FLAG); TIMER2_IRQ_MASK_REG |= (1 << TIMER2_COMP_B_EN); break; case 2: TIMER2_COMP_C = (uint16_t) value; TIMER2_IRQ_FLAG_REG &= ~(1 << TIMER2_COMP_C_FLAG); TIMER2_IRQ_MASK_REG |= (1 << TIMER2_COMP_C_EN); break; default: restoreIRQ(state); return -1; } break; #endif case TIMER_UNDEFINED: default: restoreIRQ(state); return -1; } /* enable interrupts for given timer */ timer_irq_enable(dev); restoreIRQ(state); return 1; }