3

コードを書くとき、エラーが発生したかどうかをチェックすることがよくあります。例は次のとおりです。

char *x = malloc( some_bytes ); 
if( x == NULL ){
    fprintf( stderr, "Malloc failed.\n" ); 
    exit(EXIT_FAILURE); 
}

私もstrerror( errno )過去に利用したことがあります。

exit()私は、エラーが発生した場合にプログラムが ed であるかどうかが問題にならない小さなデスクトップ アプリケーションしか作成したことがありません。

しかし、今は組み込みシステム (Arduino) 用の C コードを書いていますが、エラーが発生した場合にシステムを終了させたくありません。システムの電源を落とし、エラー レポートを送信し、安全にアイドル状態にできる特定の状態/機能に移行したいと考えています。

単純に関数を呼び出すことerror_handler()もできますが、スタックが深くなり、メモリが非常に少なくなり、error_handler()操作不能になる可能性があります。

代わりに、スタックを効果的に折りたたんで大量のメモリを解放し、電源の切断とエラー報告の整理を開始するように実行したいと考えています。システムの電源を安全に落とさないと、深刻な火災の危険があります。

低メモリの組み込みシステムで安全なエラー処理を実装する標準的な方法はありますか?

編集 1:malloc()組み込みシステムでの使用を制限します。この特定のケースでは、ファイルの形式が正しくないと、ファイルの読み取り時にエラーが発生します。

4

5 に答える 5

1

低メモリの組み込みシステムで安全なエラー処理を実装する標準的な方法はありますか?

はい、それを処理する業界の事実上の方法があります。それはすべてかなり単純です:

  • プログラム内のすべてのモジュールに対して、そのモジュール内の関数で問題が発生する可能性のあるすべてのことを説明するカスタム列挙型などの結果の型が必要です。
  • エラー時にどのコードを返し、成功時にどのコードを返すかを記述して、すべての関数を適切に文書化します。
  • すべてのエラー処理を呼び出し元に任せます。
  • 呼び出し元が別のモジュールである場合、それもエラーを独自の呼び出し元に渡します。該当する場合、エラーの名前をより適切なものに変更する可能性があります。
  • エラー処理メカニズムは、コール スタックの一番下にある main() にあります。

これは、従来のステート マシンとうまく連携します。典型的なメインは次のとおりです。

void main (void)
{
  for(;;)
  {
    serve_watchdog();

    result = state_machine();

    if(result != good)
    {
      error_handler(result);
    }
  }
}

ベアボーンまたは RTOS マイクロコントローラ アプリケーションでは malloc を使用しないでください。安全上の理由からではありませんが、malloc を使用しても意味がないため単純です。プログラミングするときは、常識を適用してください。

于 2015-09-14T06:40:16.813 に答える
1

システムにウォッチドッグがある場合は、次を使用できます。

char *x = malloc( some_bytes ); 
assert(x != NULL);

の実装は次のassert()ようになります。

#define assert (condition) \
    if (!(condition)) while(true)

ウォッチドッグがトリガーする障害が発生した場合、システムはリセットを行います。再起動時に、システムはリセットの理由をチェックします。リセットの理由が「ウォッチドッグ リセット」の場合、システムは安全な状態に移行します。

アップデート

whileループに入る前に、 assertcold はエラー メッセージを出力したり、スタック トレースを出力したり、一部のデータを不揮発性メモリに保存したりします。

于 2015-09-12T09:43:48.283 に答える
0

スタックの使用を最小限に抑えるには:

関数呼び出しではなく、呼び出しが並列になるようにプログラムを作成してください。トップレベル関数は、次のサブ関数を呼び出します...など

プログラムアーキテクチャの(スタック制限には悪い)ネストされた方法:

top level function
    second level function
        third level function
            forth level function

組み込みシステムでは避けるべき

組み込みシステムのプログラム アーキテクチャの推奨される方法は次のとおりです。

top level function (the reset event handler)
    (variations in the following depending on if 'warm' or 'cold' start)
    initialize hardware
    initialize peripherals
    initialize communication I/O
    initialize interrupts
    initialize status info
    enable interrupts
    enter background  processing

interrupt handler
    re-enable the interrupt
    using 'scheduler' 
        select a foreground function 
        trigger dispatch for selected foreground function        
    return from interrupt

background processing 

(this can be, and often is implemented as a 'state' machine rather than a loop)
    loop:
        if status info indicates need to call second level function 1 
            second level function 1, which updates status info
        if status info indicates need to call second level function 2
            second level function 2, which updates status info
        etc
    end loop:

可能な限り、「第 3 レベル関数 x」は存在しないことに注意してください。

フォアグラウンド関数は、再度スケジュールされる前に完了する必要があることに注意してください。

注:上記で省略した詳細は他にもたくさんあります。

kicking the watchdog, 
the other interrupt events,
'critical' code sections and use of mutex(),
considerations between 'soft real-time' and 'hard real-time',
context switching
continuous BIT, commanded BIT, and error handling 
etc
于 2015-09-13T17:23:09.630 に答える