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

8

Ich habe ein Problem beim Schreiben von Interrupt-Handlern im Keil ARM-Compiler für LPC1114. Wenn ich ein Programm in C ++ schreibe und die Compileroption --cpp spezifiziere, verschwindet der gesamte Code der Interrupt-Handler 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 Unordnung:

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. Keil MDK Version ist 4.12. Kann mir jemand sagen, ob es eine Lösung oder Problemumgehung gibt?

x4mer
quelle
Da Ihr ISR nichts tut, wird es nur weg optimiert? Vielleicht könnten Sie versuchen, die Optimierung zu deaktivieren oder etwas volatiledarin zu deklarieren .
Nick T
Die Optimierung ist auf -level0, Zeitoptimieren - deaktiviert. __NOP () ist nicht nichts. Ich habe aber auch versucht, globale Variablen im Interrupt-Handler zu ändern oder Funktionen aufzurufen. Der oben angegebene Code wurde vereinfacht, um das Problem zu reproduzieren.
x4mer
1
Wenn Sie eine technische Supportanfrage an Keil gesendet haben, wird hier jede Antwort erneut veröffentlicht.
x4mer
Warum brauchst du ein __NOP ()? Anruf? Können Sie nicht einfach ein einfaches Semikolon verwenden?
Kevin Vermeer

Antworten:

14

Die "schwache" Referenz bedeutet lediglich, dass die Routine durch eine Routine in Ihrem gleichnamigen Code ersetzt wird. Wenn Sie C verwenden, ist dies einfach. Die Namen sind immer identisch, aber der C ++ - Name beeinträchtigt 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 nicht sicher, welche Besonderheiten ich hauptsächlich in C arbeite) in einen externen "C" -Wrapper einschließen, um den Compiler zu zwingen, den Namen nicht zu entstellen.

extern "C" {
  void SysTick_Handler(void)
  {
    // do whatever
  }
}
timrorr
quelle
2
Vielen Dank. Dies funktioniert genau so, wie Sie es im Beispiel geschrieben haben. Außerdem kann ich 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 externes "C".
x4mer
Oh mein Gott! Vielen Dank für diese tolle Antwort! Es wurde so viel Zeit verschwendet, weil ich das nicht wusste. Nochmals vielen Dank!