Arduino Dueで例外処理を有効にするにはどうすればよいですか?

Jan 07 2021

ここでの質問はいくつかのヒントを与えますが、そこで提供されるソリューションは、異なるコンパイラーとツールキットを使用するため、Dueでは直接機能しません。また、Dueにはほとんどのプロジェクトに十分なフラッシュがあるため、例外処理に必要な追加のコードは受け入れられます。ただし、AVRベースのボードと同様に、Arduino IDEを使用すると、コンパイラフラグに「-fno-exceptions」が自動的に追加され、コンパイルするスロー命令またはキャッチ命令が防止されます。

Dueで例外サポートを有効にするにはどうすればよいですか?

回答

5 PMF Jan 07 2021 at 15:04

まず、「-fno-exceptions」コンパイラフラグが「-fexceptions」で上書きされていることを確認する必要があります。さらに、スタック巻き戻し用のコンパイラサポート関数を含む別のライブラリをリンクする必要があります。

移動するC:\Users\<UserName>\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.12と、新しいファイルの作成platform.local.txtこのコンテンツでは:


compiler.cpp.extra_flags=-fexceptions
linker.elf.extralibs=-lsupc++

recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" -mcpu={build.mcu} -mthumb {compiler.c.elf.flags} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--start-group {compiler.combine.flags} {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.path}/{archive_file}" -Wl,--end-group -lm -lgcc {linker.elf.extralibs}

最後の行は、の対応する行と一致し、最後にplatform.txt余分な{linker.elf.extralibs}行が必要です(ツールキットをアップグレードすると、その行が更新される可能性があるため、他のパラメーターを比較する必要がある場合があります)。

これらの行は-fexceptions、コンパイラのコマンドラインにsupc++ライブラリを追加し、リンカの入力にライブラリを追加します(そうしないと、未解決の外部に関するエラーが発生します)。これらの変更後、プロジェクトを再構築して例外処理を使用できます。

いくつかの使用上のヒント

Dueの例外サポートには、約40kの追加フラッシュメモリが必要です。512kがあることを考えると、これは通常許容できます。少し余分なRAMも使用されますが、それも十分に小さいようです。

標準の例外クラスが定義されていないため(ArduinoSTLライブラリはすぐにコンパイルされないため)、独自の例外クラスを作成する必要があります。つまり、次のようになります。

class Exception
{
  private:
  const char* _msg;
  public:
  Exception(const char* msg)
  {
    _msg = msg;
  }

  const char* Message() const
  {
    return _msg;
  }
};

使用:


void ThrowExceptionFunc()
{
  throw Exception("Something bad happened");
}

void ValidateExceptionHandling()
{
  try
  {
    ThrowExceptionFunc();
    Serial.print("Exception was not thrown:");
  }
  catch(Exception& ex)
  {
    Serial.print("Exception happened:");
    Serial.println(ex.Message());
  }
}

未処理の例外はプログラムを終了することに注意してください。未処理の例外が原因で、対応するメッセージがシリアルコンソールに出力され、行き止まりの失敗状態になります。