8
\$\begingroup\$

I have a problem with writing interrupt handlers in Keil ARM compiler for LPC1114. When I write program in C++ and specify --cpp compiler option all code from interrupt handlers disappears, it is replaced with infinite loop. I wrote simple program that illustrates my trouble.

#include "LPC11xx.h"           // LPC11xx definitions
#define SYSTICK_DELAY 120000   // for 10 ms systick @ 12MHz osc

void SysTick_Handler(void)
{
  __NOP();
}

int main (void) 
{
  SystemInit();                   // from system_LPC11xx.c
  SysTick_Config(SYSTICK_DELAY);  // from core_cm0.h
  // Loop forever
  while (1) __NOP();
}

When trying to compile this code with --cpp compiler option I get infinite loop in disasm:

SysTick_Handler PROC
            EXPORT  SysTick_Handler           [WEAK]
            B       .
            ENDP

This is the place where __NOP() from above program must be. And it is there when I'm compiling code with --c99 compiler option or without additional options. Keil MDK version is 4.12. Can anyone tell me is there any solution or workaround ?

\$\endgroup\$
  • \$\begingroup\$ As your ISR does nothing is it just being optimized away? Perhaps you could try disabling optimization or declaring something volatile in it. \$\endgroup\$ – Nick T Dec 8 '10 at 14:44
  • \$\begingroup\$ Optimization is set to -level0, Optimize for Time - deselected. __NOP() is not nothing. But I also tried changing global vars in interrupt handler or calling for functions. The code provided above was simplified to be just so small to reproduce the problem. \$\endgroup\$ – x4mer Dec 8 '10 at 15:02
  • 1
    \$\begingroup\$ Filed a technical support request to Keil, will repost here any answer. \$\endgroup\$ – x4mer Dec 8 '10 at 15:06
  • \$\begingroup\$ Why do you need an __NOP(); call? Can't you just use a simple semicolon? \$\endgroup\$ – Kevin Vermeer Dec 8 '10 at 15:34
14
\$\begingroup\$

The "weak" reference just means that the routine will be replaced by a routine in your code of the same name. When using C this is simple, the names will always be identical but C++ name mangles the functions (for function overloading etc) so the compiled name will probably not match the default ISR name. You need to wrap the function (or at least a forward reference, I'm not sure of specifics I mostly work in C) in an extern "C" wrapper to force the compiler to not mangle the name.

extern "C" {
  void SysTick_Handler(void)
  {
    // do whatever
  }
}
\$\endgroup\$
  • 2
    \$\begingroup\$ Thank you. This works exactly as you wrote in example. And also I can declare function in header file as extern "C" void SysTick_Handler(void); and later write my interrupt handler in classical form i.e. without extern "C". \$\endgroup\$ – x4mer Dec 10 '10 at 14:22
  • \$\begingroup\$ Oh my god! Thank you for this great answer! So much time was wasted because of not knowing this ) Thank you once more! \$\endgroup\$ – user2977 Feb 12 '11 at 15:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.