Esempio n. 1
0
void hwtimer_arch_enable_interrupt(void)
{
    timer_irq_enable(hw_timers[0]);
    timer_irq_enable(hw_timers[1]);
}
Esempio n. 2
0
/**
 * @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;
}
Esempio n. 3
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;
}