¿Error en el compilador Keil ARM con controladores de interrupción y C++?

Tengo un problema al escribir controladores de interrupción en el compilador Keil ARM para LPC1114. Cuando escribo un programa en C ++ y especifico la opción del compilador --cpp, todo el código de los controladores de interrupción desaparece, se reemplaza con un bucle infinito. Escribí un programa simple que ilustra mi problema.

#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();
}

Cuando intento compilar este código con la opción del compilador --cpp, obtengo un bucle infinito en disasm:

SysTick_Handler PROC
            EXPORT  SysTick_Handler           [WEAK]
            B       .
            ENDP

Este es el lugar donde debe estar __NOP() del programa anterior. Y está ahí cuando estoy compilando código con la opción de compilador --c99 o sin opciones adicionales. La versión de Keil MDK es 4.12. ¿Alguien puede decirme si hay alguna solución o solución?

Como su ISR no hace nada, ¿solo está siendo optimizado? Tal vez podría intentar deshabilitar la optimización o declarar algo volatileen ella.
La optimización está establecida en -level0, Optimize for Time - deseleccionado. __NOP() no es nada. Pero también intenté cambiar las variables globales en el controlador de interrupciones o llamar a funciones. El código proporcionado anteriormente se simplificó para que fuera tan pequeño como para reproducir el problema.
Presenté una solicitud de soporte técnico a Keil, volveré a publicar aquí cualquier respuesta.
¿Por qué necesita un __NOP(); ¿llamada? ¿No puedes usar un simple punto y coma?

Respuestas (1)

La referencia "débil" solo significa que la rutina será reemplazada por una rutina en su código del mismo nombre. Cuando se usa C, esto es simple, los nombres siempre serán idénticos, pero el nombre de C ++ altera las funciones (para la sobrecarga de funciones, etc.), por lo que el nombre compilado probablemente no coincida con el nombre ISR predeterminado. Debe envolver la función (o al menos una referencia directa, no estoy seguro de los detalles que trabajo principalmente en C) en un envoltorio "C" externo para obligar al compilador a no alterar el nombre.

extern "C" {
  void SysTick_Handler(void)
  {
    // do whatever
  }
}
Gracias. Esto funciona exactamente como lo escribiste en el ejemplo. Y también puedo declarar la función en el archivo de encabezado como extern "C" void SysTick_Handler(void); y luego escribir mi controlador de interrupciones en forma clásica, es decir, sin "C" externa.
¡Oh Dios mío! ¡Gracias por esta gran respuesta! Se perdió mucho tiempo por no saber esto) ¡Gracias una vez más!