/* P6_7.c Testing nested interrupts * Timer1 is setup to interrupt at 1 Hz. * In timer interrupt handler, the red LED is turned on and a delay function of 350 ms is called. The LED is turned off at the end of the delay. * * Timer2 is setup to interrupt at 10 Hz. * In timer interrupt handler, the blue LED is turned on and a delay function of 20 ms is called. The LED is turned off at the end of the delay. * * When Timer1 has higher priority, the Timer2 interrupts are blocked by Timer1 interrupt handler. You can see that when the red LED is on, the blue LED stops blinking. * When Timer2 has higher priority, the Timer1 interrupt handler is preempted by Timer2 interrupts and the blue LED is blinking all the time. * Timer2 interrupt handler also turns PD2 low and high so that it may be probed by the scope. */ #include "MKL25Z4.h" void Timer1_init(void); void Timer2_init(void); void delayMs(int n); int main (void) { __disable_irq(); SIM->SCGC5 |= 0x400; /* enable clock to Port B */ SIM->SCGC5 |= 0x1000; /* enable clock to Port D */ PORTB->PCR[18] = 0x100; /* make PTB18 pin as GPIO */ PTB->PDDR |= 0x40000; /* make PTB18 as output pin */ PORTD->PCR[1] = 0x100; /* make PTD1 pin as GPIO */ PTD->PDDR |= 0x02; /* make PTD1 as output pin */ PORTD->PCR[2] = 0x100; /* make PTD2 pin as GPIO */ PTD->PDDR |= 0x04; /* make PTD2 as output pin */ Timer1_init(); Timer2_init(); __enable_irq(); while(1) /*wait here for interrupt */ { } } void TPM1_IRQHandler(void) { PTD->PCOR |= 0x02; /* turn on blue LED */ delayMs(350); PTD->PSOR |= 0x02; /* turn off blue LED */ TPM1->SC |= 0x80; /* clear TOF */ } void TPM2_IRQHandler(void) { PTB->PCOR |= 0x40000; /* turn on red LED */ PTD->PCOR |= 0x04; /* make PTD2 low */ delayMs(50); PTB->PSOR |= 0x40000; /* turn off red LED */ PTD->PSOR |= 0x04; /* make PTD2 high */ TPM2->SC |= 0x80; /* clear TOF */ } /* priority of TPM1 and TPM2 should be between 0 and 3 */ #define PRIOTPM1 2U #define PRIOTPM2 3U void Timer1_init(void) { SIM->SCGC6 |= 0x02000000; /* enable clock to TPM1 */ SIM->SOPT2 |= 0x03000000; /* use MCGIRCLK as timer counter clock */ TPM1->SC = 0; /* disable timer while configuring */ TPM1->SC = 0x02; /* prescaler /4 */ TPM1->MOD = 8192 - 1; //16384 - 1; /* modulo value */ TPM1->SC |= 0x80; /* clear TOF */ TPM1->SC |= 0x48; /* enable timer free-running mode and interrupt */ /* set interrupt priority for TPM1 */ /* NVIC->IP[TPM1_IRQn / 4] |= PRIOTPM1 << ((TPM1_IRQn % 4) * 8 + 6); */ /* NVIC->IP[4] |= PRIOTPM1 << 22; */ NVIC_SetPriority(TPM1_IRQn, PRIOTPM1); NVIC_EnableIRQ(TPM1_IRQn); /* enable Timer1 interrupt in NVIC */ } void Timer2_init(void) { SIM->SCGC6 |= 0x04000000; /* enable clock to TPM2 */ SIM->SOPT2 |= 0x03000000; /* use MCGIRCLK as timer counter clock */ TPM2->SC = 0; /* disable timer while configuring */ TPM2->SC = 0x02; /* prescaler /4 */ TPM2->MOD = 819 - 1; /* modulo value */ TPM2->SC |= 0x80; /* clear TOF */ TPM2->SC |= 0x48; /* enable timer free-running mode and interrupt */ /* set interrupt priority for TMP2 */ /* NVIC->IP[TPM2_IRQn / 4] |= PRIOTPM2 << ((TPM2_IRQn % 4) * 8 + 6); */ /* NVIC->IP[4] |= PRIOTPM2 << 30; */ NVIC_SetPriority(TPM2_IRQn, PRIOTPM2); NVIC_EnableIRQ(TPM2_IRQn); /* enable Timer2 interrupt in NVIC */ } // delay n milliseconds (16 MHz CPU clock) void delayMs(int n) { int32_t i, j; for(i = 0 ; i < n; i++) for(j = 0; j < 7000; j++) {} /* do nothing for 1 ms */ }