Installing interrupts with KSDK 2.0?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Installing interrupts with KSDK 2.0?

Jump to solution
3,001 Views
robertbaruch
Contributor III

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?

Labels (1)
0 Kudos
Reply
1 Solution
1,453 Views
Jmart
NXP Employee
NXP Employee

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;

}

View solution in original post

4 Replies
1,453 Views
robertbaruch
Contributor III

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.

0 Kudos
Reply
1,454 Views
Jmart
NXP Employee
NXP Employee

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;

}

1,453 Views
robertbaruch
Contributor III

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.

0 Kudos
Reply
1,453 Views
Jmart
NXP Employee
NXP Employee

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. It probably was being optimized, since it never saw a need to re-read that variable.

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

0 Kudos
Reply