I've only found a document for KSDK 1.2, which refers to fsl_interrupt_manager.h, which doesn't seem to exist in SDK 2.0. I did find a function InstallIRQHandler in fsl_common.c, but I'm not sure I'm using it properly. Basically, I'm trying to write a delay function:
static bool timerWentOff = false;
void timerIRQHandler() {
PIT_StopTimer(PIT, 0);
timerWentOff = true;
}
void delayMsec(uint32_t msec) {
timerWentOff = false;
PIT_SetTimerPeriod(PIT, 0, (uint32_t) MSEC_TO_COUNT(msec, CLOCK_GetBusClkFreq()));
PIT_StartTimer(PIT, 0);
while (!timerWentOff);
}
void initTimerModule() {
CLOCK_EnableClock(kCLOCK_Pit0);
pit_config_t timerConfig = {
.enableRunInDebug = true,
};
PIT_Init(PIT, &timerConfig);
EnableIRQ(PIT0_IRQn);
InstallIRQHandler(PIT0_IRQn, (uint32_t) timerIRQHandler);
}
And then in main, something like:
for (;;) {
delayMsec(100);
LED_RED_TOGGLE();
}
However, when I hit InstallIRQHandler, I get a hard fault. What's the right procedure to install an interrupt?
Solved! Go to Solution.
Robert,
From your update 2 it looks like you're really close to solving your issue, you're only missing an interrupt clear inside of your timer interrupt handler. Adding this line:
PIT_ClearStatusFlags(PIT, 0, kPIT_TimerFlag);
You're seeing the CPU continually service the interrupt, since it's never cleared. It probably looks like it's running through the code properly because of the debugger delays, but it's really never able to go and do anything other than service the interrupt once it has been set by the PIT.
Now a little bit of background information on how you could have approached the use of interrupts in SDK 2.0 differently (hopefully a little easier as well).
Each of the interrupt functions in SDK 2.0 are defined with the 'weak' attribute. From gcc.gnu.org,
weak
The weak attribute causes the declaration to be emitted as a weak symbol rather than a global. This is primarily useful in defining library functions which can be overridden in user code, though it can also be used with non-function declarations. Weak symbols are supported for ELF targets, and also for a.out targets when using the GNU assembler and linker.
This means that in order to override the weak symbol, all you need to do is define the interrupt symbol in your own code. Interrupt symbols can be found in startup_<soc_name>.S. Choosing this route eliminates the need for the special linker directives as well as having to install the interrupt from application code; there's nothing to install when you're using the default symbol in the vector table. In my test, my interrupt handler looks like:
void PIT0_IRQHandler() {
PIT_StopTimer(PIT, 0);
PIT_ClearStatusFlags(PIT, 0, kPIT_TimerFlag);
timerWentOff = true;
}
Update: I changed the linker settings to include -Xlinker --defsym=__ram_vector_table__=1, and now I'm not getting the hard fault (it helps to make the vectors actually modifiable!) but now I'm not getting the interrupt. Anything wrong with the code?
Update 2: Added PIT_EnableInterrupts(PIT, 0, kPIT_TimerInterruptEnable); at the end of initTimerModule. Now it seems the interrupt is going off (a breakpoint in the interrupt handler is hit), but it's going off continuously -- the LED never gets toggled.
Robert,
From your update 2 it looks like you're really close to solving your issue, you're only missing an interrupt clear inside of your timer interrupt handler. Adding this line:
PIT_ClearStatusFlags(PIT, 0, kPIT_TimerFlag);
You're seeing the CPU continually service the interrupt, since it's never cleared. It probably looks like it's running through the code properly because of the debugger delays, but it's really never able to go and do anything other than service the interrupt once it has been set by the PIT.
Now a little bit of background information on how you could have approached the use of interrupts in SDK 2.0 differently (hopefully a little easier as well).
Each of the interrupt functions in SDK 2.0 are defined with the 'weak' attribute. From gcc.gnu.org,
weak
The weak attribute causes the declaration to be emitted as a weak symbol rather than a global. This is primarily useful in defining library functions which can be overridden in user code, though it can also be used with non-function declarations. Weak symbols are supported for ELF targets, and also for a.out targets when using the GNU assembler and linker.
This means that in order to override the weak symbol, all you need to do is define the interrupt symbol in your own code. Interrupt symbols can be found in startup_<soc_name>.S. Choosing this route eliminates the need for the special linker directives as well as having to install the interrupt from application code; there's nothing to install when you're using the default symbol in the vector table. In my test, my interrupt handler looks like:
void PIT0_IRQHandler() {
PIT_StopTimer(PIT, 0);
PIT_ClearStatusFlags(PIT, 0, kPIT_TimerFlag);
timerWentOff = true;
}
Thanks, Jason, that seems to work great! One other thing I neglected was to declare timerWentOff as volatile. Under Release, it was failing, and the only difference I could see is that Release uses -Os -g while Debug uses -O -g3. I made sure everything else was the same. I confirmed that it was -Os that caused the failure -- it was most likely optimizing the while (!timerWentOff) out, which would make sense for a nonvolatile timerWentOff.
Being able to see the disassembly would have helped :smileyhappy: Unfortunately (this is under KDS 3.1.0) pulling up the Disassembly window doesn't seem to do anything.
Robert,
You're right about the volatile on the timerWentOff variable, and I did have that in my code, just failed to mention that difference in my last post.
I'm surprised you're encountering issues with the disassembly view in KDS 3.1. I'm able to step through with the disassembly window open and it works fine, albeit slow.
If you're really wanting to put this question to rest (and this could be helpful in the future), the other option that you have is to use objdump. The following command will dump the assembly of a given executable or object file.
arm-none-eabi-objdump -D <filename> - here's a snippet of the output from my main.o delay function, which is based on your code from your original post.
58: f7ff fffe bl 0 <delay>
5c: bf00 nop
5e: 4b05 ldr r3, [pc, #20] ; (74 <delay+0x74>)
60: 781b ldrb r3, [r3, #0]
62: b2db uxtb r3, r3
64: f083 0301 eor.w r3, r3, #1
68: b2db uxtb r3, r3
6a: 2b00 cmp r3, #0
6c: d1f7 bne.n 5e <delay+0x5e>
Jason