¿Error en el compilador ARM Keil con manejadores de interrupciones y C ++?

8

Tengo un problema con la escritura de controladores de interrupciones 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 caso de desastre:

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 del compilador --c99 o sin opciones adicionales. La versión Keil MDK es 4.12. ¿Alguien puede decirme si hay alguna solución o solución?

x4mer
fuente
Como su ISR no hace nada, ¿solo está siendo optimizado? Quizás podría intentar deshabilitar la optimización o declarar algo volatileen ella.
Nick T
La optimización se establece en -level0, Optimizar para tiempo - deseleccionado. __NOP () no es nada. Pero también intenté cambiar los vars globales en el controlador de interrupciones o llamar a funciones. El código proporcionado anteriormente se simplificó para ser tan pequeño como para reproducir el problema.
x4mer
1
Presentó una solicitud de soporte técnico a Keil, volverá a publicar aquí cualquier respuesta.
x4mer
¿Por qué necesitas un __NOP (); ¿llamada? ¿No puedes usar un simple punto y coma?
Kevin Vermeer

Respuestas:

14

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 ++ modifica las funciones (para la sobrecarga de funciones, etc.), por lo que el nombre compilado probablemente no coincida con el nombre ISR predeterminado. Debe ajustar la función (o al menos una referencia directa, no estoy seguro de los detalles que trabajo principalmente en C) en un contenedor externo "C" para forzar al compilador a no alterar el nombre.

extern "C" {
  void SysTick_Handler(void)
  {
    // do whatever
  }
}
timrorr
fuente
2
Gracias. Esto funciona exactamente como lo escribió 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 escribo mi controlador de interrupciones en forma clásica, es decir, sin "C" externa.
x4mer
¡Oh Dios mío! Gracias por esta gran respuesta! Se perdió mucho tiempo por no saber esto) ¡Gracias una vez más!