Bug nel compilatore ARM Keil con gestori di interrupt e C ++?


8

Ho un problema con la scrittura di gestori di interrupt nel compilatore ARM Keil per LPC1114. Quando scrivo un programma in C ++ e specifico l'opzione del compilatore --cpp, tutto il codice dei gestori di interrupt scompare, viene sostituito con un ciclo infinito. Ho scritto un semplice programma che illustra il mio 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();
}

Quando provo a compilare questo codice con l'opzione del compilatore --cpp ottengo un ciclo infinito nel disasma:

SysTick_Handler PROC
            EXPORT  SysTick_Handler           [WEAK]
            B       .
            ENDP

Questo è il posto dove deve essere __NOP () dal programma precedente. Ed è lì quando sto compilando il codice con l'opzione del compilatore --c99 o senza opzioni aggiuntive. La versione di Keil MDK è la 4.12. Qualcuno può dirmi che c'è qualche soluzione o soluzione?


Dato che il tuo ISR non fa nulla, viene semplicemente ottimizzato? Forse potresti provare a disabilitare l'ottimizzazione o dichiarare qualcosa volatileal suo interno.
Nick T,

L'ottimizzazione è impostata su -level0, Ottimizza per tempo - deselezionata. __NOP () non è niente. Ma ho anche provato a cambiare le variabili globali nel gestore di interrupt o a chiamare funzioni. Il codice fornito sopra è stato semplificato per essere così piccolo da riprodurre il problema.
x4mer,

1
Ha presentato una richiesta di supporto tecnico a Keil, ripubblicherà qui qualsiasi risposta.
x4mer,

Perché hai bisogno di un __NOP (); chiamata? Non puoi semplicemente usare un semplice punto e virgola?
Kevin Vermeer,

Risposte:


14

Il riferimento "debole" significa semplicemente che la routine verrà sostituita da una routine nel codice con lo stesso nome. Quando si usa C questo è semplice, i nomi saranno sempre identici ma il nome C ++ modifica le funzioni (per sovraccarico delle funzioni ecc.), Quindi il nome compilato probabilmente non corrisponderà al nome ISR predefinito. Devi racchiudere la funzione (o almeno un riferimento in avanti, non sono sicuro delle specifiche che lavoro principalmente in C) in un wrapper "C" esterno per forzare il compilatore a non alterare il nome.

extern "C" {
  void SysTick_Handler(void)
  {
    // do whatever
  }
}

2
Grazie. Funziona esattamente come hai scritto nell'esempio. E posso anche dichiarare la funzione nel file di intestazione come "C" void esterno SysTick_Handler (void); e successivamente scrivo il mio gestore di interrupt in forma classica, cioè senza "C" esterno.
x4mer,

Dio mio! Grazie per questa ottima risposta! È stato sprecato così tanto tempo perché non lo sapevo) Grazie ancora!
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.