2

アプリケーションをより適切にデバッグするのに役立つデバッグツールを作成したいと思います。私は(OSなしで)必要最低限​​の作業をしています。AtmelのSAM3でIAR組み込みワークベンチを使用します。

タイムアウトの場合に特定のIRQを呼び出すウォッチドッグタイマーがあります(これはリリース時にソフトウェアリセットに置き換えられます)。IRQハンドラーで、ウォッチドッグタイムアウトが発生した正確な場所のスタックトレースを出力(UART)したいと思います。

Webを調べましたが、その機能の実装は見つかりませんでした。

誰もがこの種のものにアプローチする方法についての考えを持っていますか?

編集:OK、スタックからリターンアドレスを取得できたので、WDTタイムアウトが発生した場所を正確に把握できます。各関数が異なる量のローカル変数をスタックにプッシュするため、スタック全体の巻き戻しは最初に表示されるように単純ではありません。

私が最終的に得たコードはこれです(他の人にとっては、それが役に立つと思うかもしれません)

void WDT_IrqHandler( void )
{
    uint32_t * WDT_Address;
    Wdt *pWdt = WDT ;
    volatile uint32_t dummy ;
    WDT_Address = (uint32_t *) __get_MSP() + 16 ;
    LogFatal ("Watchdog Timer timeout,The Return Address is %#X", *WDT_Address);
    /* Clear status bit to acknowledge interrupt */
    dummy = pWdt->WDT_SR ;

}
4

5 に答える 5

6

ARM は、デバッグ シンボルなしでスタックをアンワインドするのに十分な情報を含むセクション .ARM.exidx と .ARM.extbl のペアを定義します。これらのセクションは例外処理のために存在しますが、これらを使用してバックトレースを実行することもできます。-funwind-tables を追加して、GCC にこれらのセクションを強制的に含めます。

于 2014-04-19T17:36:34.107 に答える
4

ARM でこれを行うには、コンパイラにスタック フレームを生成するように指示する必要があります。たとえば gcc では、オプションをチェックします-mapcs-frame。必要なものではないかもしれませんが、これが始まりです。

これがないと、関数ごとにパラメーターとローカル変数に応じて正確なスタック使用量が必要になるため、スタックを「展開」することはほぼ不可能になります。

サンプル コードを探している場合はdump_stack()、Linux カーネル ソースをチェックインして、ARM 用に実行された関連コードを見つけることができます。

于 2012-07-04T11:41:38.600 に答える
3

実行に従うのはかなり簡単なはずです。あなたのISRでプログラム的にではありません...

ARM ARM から、Cortex-M3 では xPSR、ReturnAddress、LR (R14)、R12、R3、R2、R1、および R0 をスタックにプッシュすることがわかっています。割り込みからの戻りを検出できるように lr をマングルし、ベクタ テーブルにリストされているエントリ ポイントを呼び出します。スタックを制御するために asm に isr を実装する場合、割り込みソースを無効にする (wdt をオフにするなど、これには時間がかかります) 単純なループを作成してから、ループに入ってその一部をダンプすることができます。スタック。

そのダンプから、lr/return アドレス、中断された関数/命令が表示されます。プログラムの逆アセンブリから、コンパイラが各関数のスタックに配置したものを確認し、各段階でそれを差し引いて進みます。好きなだけさかのぼるか、スタックの内容を印刷した限りさかのぼります。

isr でそのようなことを行うのではなく、ram でスタックのコピーを作成し、後で分析することもできます (コピーにはまだ時間がかかりすぎますが、uart で待機するよりも邪魔になりません)。

中断された命令のアドレスだけが必要な場合は、それが最も簡単なタスクです。スタックからそれを読み取るだけで、既知の場所にあり、出力されます。

于 2012-07-04T14:51:48.423 に答える
2

私の名前を聞きましたか?:)

おそらく、インラインアセンブリが少し必要になります。スタックフレームのフォーマットと、通常の1スタックポインタを保持するレジスタを把握し、関連する値をC変数に転送して、UARTに出力するための文字列をフォーマットできるようにします。

それほどトリッキーではないはずですが、もちろん(かなり低レベルなので)細部に注意を払う必要があります。

1「非例外」の場合と同様。実際、ARMが通常のコードと例外に対して異なるスタックを持っているかどうかはわかりません。

于 2012-07-04T09:11:55.787 に答える
0

ウォッチドッグ タイマーは、スタックにアンワインドするのに十分な情報が含まれていない場合でも、いつでも起動できます (たとえば、スタック スペースはレジスタ スピル用に割り当てられていますが、レジスタはまだコピーされていません)。

適切に最適化されたコードについては、デバッグ情報、ピリオドが必要です。ウォッチドッグ タイマーから実行できるのは、レジスタとスタック ダンプだけです。マシンが読み取り可能な形式で、.NET のコア ダンプに変換できgdbます。

于 2012-07-04T12:04:14.280 に答える