Fehler im Keil ARM-Compiler mit Interrupt-Handlern und C++?

Ich habe ein Problem mit dem Schreiben von Interrupt-Handlern im Keil ARM-Compiler für LPC1114. Wenn ich ein Programm in C++ schreibe und die Compiler-Option --cpp angebe, verschwindet der gesamte Code von Interrupt-Handlern und wird durch eine Endlosschleife ersetzt. Ich habe ein einfaches Programm geschrieben, das meine Probleme veranschaulicht.

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

Beim Versuch, diesen Code mit der Compileroption --cpp zu kompilieren, erhalte ich eine Endlosschleife in Disasm:

SysTick_Handler PROC
            EXPORT  SysTick_Handler           [WEAK]
            B       .
            ENDP

Dies ist der Ort, an dem __NOP() aus dem obigen Programm sein muss. Und es ist da, wenn ich Code mit der Compileroption --c99 oder ohne zusätzliche Optionen kompiliere. Die Keil-MDK-Version ist 4.12. Kann mir jemand sagen, gibt es eine Lösung oder Problemumgehung?

Da Ihr ISR nichts tut, wird er nur wegoptimiert? Vielleicht könnten Sie versuchen, die Optimierung zu deaktivieren oder etwas volatiledarin zu deklarieren.
Die Optimierung ist auf -level0 eingestellt, Optimize for Time - deaktiviert. __NOP() ist nicht nichts. Aber ich habe auch versucht, globale Variablen im Interrupt-Handler zu ändern oder Funktionen aufzurufen. Der oben bereitgestellte Code wurde so vereinfacht, dass er nur so klein ist, dass er das Problem reproduzieren kann.
Eine technische Support-Anfrage an Keil eingereicht, wird hier jede Antwort erneut posten.
Warum brauchen Sie ein __NOP(); Anruf? Kannst du nicht einfach ein einfaches Semikolon verwenden?

Antworten (1)

Die "schwache" Referenz bedeutet nur, dass die Routine durch eine gleichnamige Routine in Ihrem Code ersetzt wird. Wenn Sie C verwenden, ist dies einfach, die Namen sind immer identisch, aber der C++-Name verstümmelt die Funktionen (zum Überladen von Funktionen usw.), sodass der kompilierte Name wahrscheinlich nicht mit dem Standard-ISR-Namen übereinstimmt. Sie müssen die Funktion (oder zumindest eine Vorwärtsreferenz, ich bin mir der Einzelheiten nicht sicher, da ich hauptsächlich in C arbeite) in einen externen "C"-Wrapper umschließen, um den Compiler zu zwingen, den Namen nicht zu manipulieren.

extern "C" {
  void SysTick_Handler(void)
  {
    // do whatever
  }
}
Danke dir. Das funktioniert genau so, wie du es im Beispiel geschrieben hast. Und ich kann auch die Funktion in der Header-Datei als extern "C" deklarieren void SysTick_Handler (void); und schreibe später meinen Interrupt-Handler in klassischer Form, dh ohne extern "C".
Ach du lieber Gott! Vielen Dank für diese tolle Antwort! Es wurde so viel Zeit verschwendet, weil ich das nicht wusste) Nochmals vielen Dank!