/* p6_8.c Demonstrate Nested Interrupts * * TC6 is setup to interrupt at about 1 Hz. In the interrupt handler, * PA16 is turned on and a delay function of 500 ms is called. * PA16 is turned off at the end of the delay. * * TC7 is setup to interrupt at about 10 Hz. In the interrupt handler, * PA17 and the LED0 is turned on and a delay function of 25 ms is called. * PA17 and the LED0 is turned off at the end of the delay. * * When TC6 has the higher priority (the way this code is), the TC7 * interrupts are blocked by TC6 interrupt handler and the LED stops * blinking intermittently. You can see their interactions better * with an oscilloscope on PA16 and PA17. * * When TC7 has the higher priority (you need to switch the priority of * the two timers at the #defines), the TC6 interrupt handler is * preempted by TC7 interrupts and the LED is blinking all the time. * * Tested with Atmel Studio 7 v7.0.1006 and Keil MDK-ARM v5.21a. */ #include "samd21.h" void delayMs(int n); /* priority of Timer1 and Timer2 should be between 0 and 3 */ #define PRIO_TC6 2 #define PRIO_TC7 3 int main (void) { __disable_irq(); REG_GCLK_CLKCTRL = 0x401D; /* GCLK0 -> TC6/TC7 */ REG_PM_APBCMASK |= 0x0000C000; /* enable TC7/6 Clock in PM */ REG_TC6_CTRLA = 1; /* reset TC6 before configuration */ while (REG_TC6_CTRLA & 1) {} /* wait till out of reset */ REG_TC6_CTRLA = 0x0520; /* prescaler /64, 16-bit mode, MFRQ */ REG_TC6_COUNT16_CC0 = 15500; /* set TOP count in MFRQ */ REG_TC6_CTRLA |= 2; /* enable TC6 */ REG_TC6_INTENSET = 0x10; /* enable match interrupt */ NVIC_SetPriority(TC6_IRQn, PRIO_TC6); NVIC_EnableIRQ(TC6_IRQn); /* enable TC6 interrupt in NVIC */ REG_TC7_CTRLA = 1; /* reset TC7 before configuration */ while (REG_TC7_CTRLA & 1) {} /* wait till out of reset */ REG_TC7_CTRLA = 0x0520; /* prescaler /64, 16-bit mode, MFRQ */ REG_TC7_COUNT16_CC0 = 1562; /* set TOP count in MFRQ */ REG_TC7_CTRLA |= 2; /* enable TC7 */ REG_TC7_INTENSET = 0x10; /* enable match interrupt */ NVIC_SetPriority(TC7_IRQn, PRIO_TC7); NVIC_EnableIRQ(TC7_IRQn); /* enable TC7 interrupt in NVIC */ __enable_irq(); /* enable interrupt globally */ REG_PORT_DIRSET0 = 0x00030000; /* make PA16/PA17 output */ REG_PORT_OUTCLR0 = 0x00030000; /* turn off PA16/PA17 */ REG_PORT_DIRSET1 = 0x40000000; /* make PB30 output */ while(1) { } } void TC6_Handler(void) { REG_PORT_OUTSET0 = 0x00010000; /* turn on PA16 */ delayMs(500); REG_PORT_OUTCLR0 = 0x00010000; /* turn off PA16 */ REG_TC6_INTFLAG = 0x10; /* clear MC0 flag */ } void TC7_Handler(void) { REG_PORT_OUTSET0 = 0x00020000; /* turn on PA17 */ REG_PORT_OUTCLR1 = 0x40000000; /* turn on LED0 */ delayMs(25); REG_PORT_OUTCLR0 = 0x00020000; /* turn off PA17 */ REG_PORT_OUTSET1 = 0x40000000; /* turn off LED0 */ REG_TC7_INTFLAG = 0x10; /* clear MC0 flag */ } /* millisecond delay based on 1 MHz system clock */ void delayMs(int n) { int i; for (; n > 0; n--) for (i = 0; i < 199; i++) __asm("nop"); }