Ok, I have a first draft of my own creation.
All the Kinetis documentation I have found says you don't have to do anything
special to write an ISR--that it can look just like a function. But this doesn't
tell me how the processor associates one of my functions with a particular
interrupt vector.
I found a student help file at the University of Texas that said the interrupt
vector table was in file Startup.s. My environment has a pre-defined assembly
language file called startup_MK10F12.s which contains such a table and the entry
for PIT channel 0 is named PIT0_IRQHandler, so that is the name I used for my
handler, below.
My board has an LED on bit 19 of Port E.
uint32_t lEDState, n;
/* ===================================================== */
/* */
/* Function: */
/* int main(void) */
/* */
/* Purpose: */
/* Initialize hardware & wait for interrupt. */
/* */
/* ===================================================== */
int main(void) {
uint32_t counterVal;
SystemCoreClockUpdate();
SIM->SCGC5 |= SIM_SCGC5_PORTE_MASK; /* Enable clock to PORTE */
SIM->SCGC6 |= 0x800000u; /* and PIT */
/* + + + + + + + + + + + */
/* Configure PORTE, bit */
/* 19 as output */
/* + + + + + + + + + + + */
PTE->PDDR = 0x000800000;
/* + + + + + + + + + + + + + + + + + + + + */
/* */
/* Configure PORTE, bit 19 PCR as: */
/* - Int stat flag to off (0) */
/* - Int config to disabled (000) */
/* - Lock reg to unlocked (0) */
/* - MUX to alt 001 (GPIO) */
/* - Drive strength enable to low (0) */
/* - Open drain enable to off (0) */
/* - Passive filter enable to off (0) */
/* - Slew rate enable to fast (0) */
/* - Pull enable to off (0) */
/* - Pull select to down (0) */
/* */
/* 3322 2222 2222 1111 1111 11 */
/* 1098 7654 3210 9876 5432 1098 7654 3210 */
/* ---- ---- ---- ---- ---- ---- ---- ---- */
/* ···· ···· ···· IIII ···· ···· ···· ···· */
/* ···· ···· ···· RRRR ···· ·MMM ···· ···· */
/* ···· ···I ···· QQQQ ···· ·UUU ·DOP ·S·· */
/* ···· ···S ···· CCCC L··· ·XXX ·SDF ·RPP */
/* ···· ···F ···· 3210 K··· ·210 ·EEE ·EES */
/* –––– –––– –––– –––– –––– –––– –––– –––– */
/* 0000 0000 0000 0000 0000 0001 0000 0000 */
/* */
/* = 0x0000 0100 */
/* + + + + + + + + + + + + + + + + + + + + */
PORTE->PCR[19] = 0x00000100;
n = 0;
lEDState = LED_OFF; /* Start with LED off */
PTE->PCOR = 0x000800000; /* Turn all LEDs off */
PIT->MCR = 0x1; /* Enable PIT timers */
/* Let PIT timers stop in debug mode */
/* + + + + + + + + + + + + + + + + + + + */
/* Assume clock frequency is 50 MHz. */
/* */
/* 1 msec = 50,000,000 x 0.1 = 5,000,000 */
/* LDVAL gets 1 less than this. (§35.2) */
/* + + + + + + + + + + + + + + + + + + + */
PIT->CHANNEL[0].LDVAL = 4999999; /* Set reload value to run 100 msec */
PIT->CHANNEL[0].TFLG = 0x1; /* Reset the timer interrupt flag (TIF) */
NVIC->ICPR[0] = 0x40000000; /* Clear pending PI timer, ch 0 interrupt */
NVIC->ISER[0] = 0x40000000; /* Enable PI timer, ch 0 interrupt */
PIT->CHANNEL[0].TCTRL = 0x03; /* Turn PIT timer 0 on, interrupts on */
for(;;) {
counterVal = PIT->CHANNEL[0].CVAL; /* Read out counter value */
if(counterVal < 100) {
n = n + 1; /* Address to set a breakpoint */
}
} /* END for(,,) */
return 0;
} /* END main() */
/* ===================================================== */
/* */
/* Function: */
/* void PIT0_IRQHandler(void) */
/* */
/* Purpose: */
/* Turns red LED on or off every 100 msec. */
/* */
/* ===================================================== */
void PIT0_IRQHandler(void) {
PIT->CHANNEL[0].TFLG = 0x1; /* Reset the timer interrupt flag (TIF) */
if(lEDState == LED_OFF) {
PTE->PSOR = 0x000800000; /* LED is on when output high */
lEDState = LED_ON; /* Indicate LED on */
} else {
PTE->PCOR = 0x000800000; /* LED is off when output low */
lEDState = LED_OFF; /* Indicate LED off */
}
return;
} /* END PIT0_IRQHandler() */
As before, the counter counts down to zero. When it re-loads bit 0 of the
PIT->CHANNEL[0].TFLG register gets set.
If I had programmed everything correctly, I would simultaneously see bit 30 of the
NVIC->ICPR[0] or NVIC->ISPR[0] registers get set, (the circuit from the PIT to the
NVIC is one of those paths that I can't find) but this doesn't happen, and my
handler never gets entered.
That's as much as I've been able to figure out on my own.