3

最近、組み込みソフトウェアで奇妙な動作に直面しています。

私が得たもの:ファイルサイズが大きすぎてマイクロコントローラーフラッシュから直接開始できないため、32ビットAVR32コントローラーを実行し、外部SDRAMからプログラムを開始します。物理メモリ マップにより、メモリ領域は次のように分割されます。

スタック (0x1000 から始まり、0xF000 の長さ) (< 0x1000 は MPU によって保護されます)

EBI SDRAM (0xD0000000 から始まり、0x00400000 の長さ)。


何が起こるか:残念ながら、再現できない例外が発生しました。与えられたスタック トレースを見ると、次のイベントが不規則に発生します。

名前: バス エラー データ フェッチ - イベント ソース: データ バス - ストアド リターン アドレス: 未完了の最初の命令

さらに、スタック ポインターには有効な値がありますが、例外が発生したアドレス (命令をフェッチするための最後のエントリ ポイント) はメモリ ニルヴァーナ (0x496e6372、0x5...、0x6.... 付近など) を指します。たぶん、これは「最初の未完了の指示」である必要があると思います。マニュアルが話しています。ただし、ソース コードの行は常に同じです。ポインターを介してデータ配列からメンバー関数にアクセスします。

      if(mSomeArray[i])
      {
         mSomeArray[i]->someFunction(); <-- Crash
      }

問題は、他のソース コードを追加または削除すると、イベントが消えて再び戻ることです。


考えたこと:何かが私の記憶 (マッピング) を壊しています。これにはどのような種類のエラーが考えられますか?

  • バッファオーバーフロー?
  • SDRAM コントローラがオフになる可能性があるため、一部のデータが失われます。それは不可能ではありませんが、むしろありそうもないことです
  • スタックは十分に大きく、透かしで確認済みです
  • データ バス レートと AVR クロックが正しく設定されている

これを解決する方法:もっと主張しますか? 残念ながら、これを AVRStudio でデバッグすることはできません。誰でもヒントやアイデアはありますか? それとも、明らかな何かが欠けていますか?


編集:

ユーザーからの言及されたアプローチ:

  • 関数ポインタと配列エントリのアドレスをチェック
  • スタック配列の上書き
  • 正しく書き込まれていない割り込み
  • 初期化されていないポインター
  • iクラッシュ ケース経由でアレイ アクセスを確認する
  • 不正なメモリアクセスには例外ハンドラアドレスを使用
  • snprintfの代わりに使用sprintf

スレッドへの後半の付録: 問題は、私のモジュールとは関係のない、古いソフトウェア モジュールでの間違った配列アクセス (間違ったインデックスが設定された) でした。これは偶然見つけたもので、以前は表示されなかったのが好奇心で、コード行を見つけるのにかなりの時間がかかりました。与えられた唯一の答えを正解としてマークします。

ご意見をお寄せいただきありがとうございます。

(あなたのソフトウェアの)世話をしてください;))

4

1 に答える 1

1

ここにいくつかのアイデアがあります:

  1. 'i' をチェックして、配列の境界内にあることを確認してください。
  2. これから呼び出される関数ポインタのアドレスを確認してください。SDRAM 内のアドレスを持つ必要があります。
  3. チップに、不正なメモリにアクセスしたときにジャンプする例外ハンドラ アドレスがあるかどうかを確認します。そこに着いたら、いくつかのデバッグデータを出力します
  4. デバッガーが許可する場合は、書き込み時に someFunction() にブレークポイントを設定します。これは、関数ポインターを上書きするときに他の関数をキャッチします。
于 2015-09-23T18:15:57.887 に答える