1

c++ コードを stm32f4 マイクロチップにコンパイルする際に問題が発生しています。

標的

ここでいくつかのことを達成しようとしています:

  1. C++ コードを stm32f4-discovery にコンパイルします (これは、必要最小限のプログラムで [コンストラクターとその他の c++ 固有の機能を実装して] 正常に実行されています)。
  2. ST が提供するペリフェラル ライブラリを使用してコードを記述します (この場合、USART 機能を使用しています)。
  3. GNU ツールを使用して、商用 IDE を使用せずにコードをコンパイルします (これは学習タスクです)。

問題

私は 2 つのプロジェクトをセットアップしています。1 つは ac プロジェクトで、正しくコンパイルされます。このプロジェクトの出力で stm32f4 もフラッシュしましたが、正しく実行されました。2 番目のプロジェクトでは、C++ コンパイラの make ファイルとファイル名に小さな変更を加えた同じコードを使用します (コードに違いはありません)。C プロジェクトは正常にコンパイルされ、C++ プロジェクトはエラーをスローします。

両方のプロジェクトとターミナルでの出力は、https : //dl.dropboxusercontent.com/u/32204435/USART.tar.gz にあります。

設定

Ubuntu 12.04.3 LTS 64 ビットを使用しています。この Web サイトの指示に従って arm-none-eabi ツールチェーンをインストールしました: vedder.se/2012/07/get-started-with-stm32f4-on-ubuntu-linux/

情報と分析

私ができることから、arm-none-eabi-g++ コンパイラでの newlib のサポートにエラーがあります。2 つのプロジェクトにコードの違いがないため、エラーが発生する理由がわかりません。printf などの newlib の関数を使用すると、同様のエラーが発生します。USART の例では、newlib を使用するプロジェクトの可能性を制限しました (唯一の例外はデータ型です)。このエラーは、newlib が原因ではなく、欠落しているハードウェア ヘッダー (または newlib スタブとして知られている) が原因のようです (syscalls.h)。syscalls.h を適用しようとしても失敗しました。

C++ サポートを使用してこのプロジェクトを構築するのを手伝ってくれる人はいますか? エラーなしで newlib のコードを使用するための解決策を提供してくれませんか?

私はまだ学んでいます。私は 17 歳で、教師がいない (自己主導型) ので、経験が浅いように見えるかもしれませんが、私は :) 知識のギャップが予想されます。

メリークリスマス!

4

2 に答える 2

2

Makefile の te CFLAGS に -fno-rtti と -fno-exceptions を追加します。

または、このハックをコンパイル ファイルに追加することもできます。

extern "C" int __aeabi_atexit(void *obj, void (*dtr)(void *), void *dso_h) {
    (void) obj;
    (void) dtr;
    (void) dso_h;
    return 0;
}

void *__dso_handle = 0;

/**
 * This is an error handler that is invoked by the C++ runtime when a pure virtual function is called.
 * If anywhere in the runtime of your program an object is created with a virtual function pointer not
 * filled in, and when the corresponding function is called, you will be calling a 'pure virtual function'.
 * The handler you describe should be defined in the default libraries that come with your development environment.
 */
extern "C" void __cxa_pure_virtual() {
        while (1)
                ;
}

namespace __gnu_cxx {

void __verbose_terminate_handler() {
        while(1)
                ;
}

}

これにより、例外チェックに対するシグナル トラップが無効になります。

グッドハック!

于 2013-12-24T18:01:31.233 に答える
0

rtti と例外を使用するには、いくつかの syscalls 実装を定義する必要があります。

私のコンパイラ (gcc arm embedded 4.8 + newlib nano) では、この回避策は正常に動作します (src/hack.cpp という名前の新しいファイルに追加します):

extern "C" int __aeabi_atexit(void *obj, void (*dtr)(void *), void *dso_h) {
    return 0;
}

/* Enable if your stub don't provide dso handle symbol */
#if 0
void *__dso_handle = 0;
#endif

extern "C" void __cxa_pure_virtual() {
    while (1)
        ;
}

namespace __gnu_cxx {
  void __verbose_terminate_handler() { while(1) ; }
}

extern "C" int _getpid(void) {
  return 1;
}

extern "C" void _kill(int pid) { while(1) ; }

extern "C" int _end;

static char *end_of_data = (char *) &_end;

/*
 * WARNING: No stack/heap colition check.
 * For check colition and stack growing overflow use SP register value
 * or RAM end limit depeding of processor architecture
 */
extern "C" char *_sbrk (int delta) {
        char *ptr = end_of_data;
        end_of_data += delta;
        return ptr;
}

_write または _isatty などの未定義のシンボルで引き続き問題が発生する場合は、リンカー フラグに -lnosys を追加します。

結果の実行可能ファイルは、例外のないバージョンよりもわずかに太くなっています。(約 8K) ただし、例外が必要で、1M のフラッシュを搭載した Cortex-M4 で rtti メカニズムがわずかなオーバーヘッドである場合

于 2013-12-25T15:08:22.043 に答える