割り込みハンドラとC ++を備えたKeil ARMコンパイラのバグ?


8

LPC1114用のKeil ARMコンパイラでの割り込みハンドラの記述に問題があります。C ++でプログラムを作成して--cppコンパイラオプションを指定すると、割り込みハンドラーからのすべてのコードが消え、無限ループに置き換えられます。私は自分の悩みを説明する簡単なプログラムを書きました。

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

--cppコンパイラオプションを使用してこのコードをコンパイルしようとすると、disasmで無限ループが発生します。

SysTick_Handler PROC
            EXPORT  SysTick_Handler           [WEAK]
            B       .
            ENDP

これは、上のプログラムの__NOP()が存在しなければならない場所です。--c99コンパイラオプションを使用して、または追加のオプションを使用せずにコードをコンパイルする場合にも、このオプションが表示されます。Keil MDKバージョンは4.12です。誰かが何か解決策や回避策があることを教えてもらえますか?


ISRは何もしないので、最適化されるだけではありませんか?おそらく、最適化を無効にするかvolatile、その中で何かを宣言してみることができます。
Nick T

最適化は-level0、時間の最適化-選択解除に設定されています。__NOP()は何もではありません。しかし、割り込みハンドラーまたは関数の呼び出しでグローバル変数を変更してみました。上記のコードは、問題を再現するために非常に小さいものに簡略化されています。
x4mer

1
Keilにテクニカルサポートリクエストを提出しました。回答はここに再投稿します。
x4mer 2010

__NOP();が必要な理由 コール?単純なセミコロンを使用できませんか?
ケビンフェルメール

回答:


14

「弱い」参照は、ルーチンが同じ名前のコード内のルーチンに置き換えられることを意味します。Cを使用する場合、これは単純です。名前は常に同じですが、C ++名は関数を破壊するため(関数のオーバーロードなど)、コンパイルされた名前はおそらくデフォルトのISR名と一致しません。関数を外部の「C」ラッパーでラップする必要があります(または、少なくとも前方参照、私がCで動作する詳細についてはわかりません)。

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

2
ありがとうございました。これは、例で書いたとおりに機能します。また、ヘッダーファイルで関数をextern "C"として宣言することもできます。void SysTick_Handler(void); 後で私の割り込みハンドラを古典的な形式で、つまりextern "C"なしで記述します。
x4mer

何てことだ!この素晴らしい答えをありがとう!これを知らなかったので、多くの時間が無駄になりました)もう一度ありがとう!
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.