12

STM32F107 チップを使用して C で開発を行っていますが、ある時点で、特定の関数を呼び出すとデバイスがリセットされ始めました。私はデバッガーを持っておらず、デバッグはシリアル ポート経由のプレーン テキストのみです。

レジスタにアクセスしてリセットの原因を確認できる他のマイクロコントローラをいくつか使用しましたが、このデバイスに相当するものが見つからないようです。Cortex-M3 のハードウェア例外は認識していますが、これらのハンドラー内にいるときは usart 経由でテキストを送信できないように見えるため (おそらく私の TX関数は割り込みを使用しますか?)。

そこで、このデバイスで私よりも経験豊富な人に尋ねることにしました: 通常、このような状況をデバッグするために何が行われますか?

編集

開発者の 1 人が WWDG ウォッチドッグをアクティブにし、障害ハンドラーから情報を取得する前にハードウェアをリセットしていました。間違った場所を指しているポインターによって関数を呼び出すことによるハード フォールトでした。ただし、ハード フォールト (@dwelch のアイデア) に保存されているレジスタから C コードを参照するための詳細 (またはそれに関する資料) を誰かが提供してくれることを期待して、この質問を続けます。

4

6 に答える 6

11

Cortex M3 には、作業を楽にする優れた障害処理機能があります。障害が発生すると、PC や LR などの複数のレジスタが自動的にスタックされ、障害ステータス レジスタがバス障害のアドレスなどを通知します。

適切なフォールト ハンドラーを実装する必要があります (たとえば、ここのハード フォールト ハンドラー: http://blog.frankvh.com/2011/12/07/cortex-m3-m4-hard-fault-handler/ )。スタック レジスタとデバッグ フォールト ステータス レジスタ。

印刷には UART を使用する必要があります。割り込みに依存しないフォールト ハンドラから使用する独自の単純なカスタム バージョンの printf を作成するだけです。uart Tx データ レジスタにバイトを直接書き込み、バイトの完了をポーリングするだけです。

于 2012-01-10T17:57:26.740 に答える
3

デバッグ用の割り込みハンドラーについて述べたこととは別に、一部の ST マイクロには、電源投入時 (つまりリセット後) に読み取ることができるリセット ソース レジスタもあります。Cortex M ファミリ (m0/m3/m4) の場合、レジスタは RCC_CSR です。http://www.st.com/web/en/resource/technical/document/reference_manual/DM00031020.pdf

残念ながら、ハード障害などの詳細を知ることはできませんが、ウォッチドッグ (ウィンドウまたは独立) がトリップしたかどうかはわかります。

于 2015-02-17T05:02:45.340 に答える
1

リセットと言うときは、割り込みやハンドラーの 1 つではなく、リセット ベクターをヒットするという意味で考えます。実際にチップをリセットしてソフトウェアを最初からやり直すと言っているのですか、それともどこかでハングしていると言っているのですか? または、ベクター テーブルがすべてリセット ベクターを指していますか?

続行する方法は、実際に見ているものによって異なります。より明確または具体的にする必要があるか、それを理解するための支援が必要な場合があります。

通常、未使用のベクトルを、それ自体に分岐する単純なハング コード行にマップします。後で、それらの一部を実際のコードに再マップする可能性があります。

Cortex-m は、C コードを指定できるという点で非常に優れています。例外が発生していると思われる場合は、現在のモードを把握するのに役立つ何かを取得するルーチンを指している場合、リンク レジスタにその情報または csr がどこかにある可能性があり、それを出力して無限ループに入ります。 . ベクタ テーブルの未使用部分に、この汎用デバッグ関数へのアドレスを入力します。

そこから、なぜその例外が発生したのかを理解する必要があります。たとえば、アラインされていないアクセスのようなものである可能性があります。ハンドラーを完全にセットアップする前にデバイスを初期化しようとしたときに割り込みを生成した可能性があります。

質問を編集して、回答や情報を増やしてください。

于 2012-01-10T18:48:50.790 に答える
1

デバッガーを持っていないことを考えると、マイクロコントローラーで役立つ周辺機器を見つけることをお勧めします。おそらく、切り替え可能な LED や、オシロスコープに接続できる使用されていない単純な GPIO ピンがあるでしょう。GPIO ピンを十分にゆっくりと (1 Hz より遅く、メーターによってはもっとゆっくり) 切り替える場合は、スコープの代わりに電圧計を使用できます。LED または GPIO ピンをトグルするコードを、追跡するまで一度に 1 つずつ各例外ハンドラーに配置します。使用可能な GPIO ピンが複数ある場合は、プロセスを高速化できます。リセットの原因となっている特定の関数のラッパーを作成することもできます。ラッパー関数は、ブレーク関数が実行される直前に有効になっている割り込みのリストを送信します。この方法ではありません'

この場合の GPIO ピンの利点の 1 つは、割り込みを必要としないことです。割り込みを必要とするもの (この場合の USART など) から離れることをお勧めします。優先度の高い例外によってリセットが発生している場合、デバッグ コードは実行されません。

初期化されていないポインターが原因でリセットが発生することもよくあります。関数ポインタをゼロに設定すると、実行がリセットのように見えます。この場合、USART が 1 バイトを完全に送信する前に USART 初期化コードが実行されている可能性があり、この場合、USART はデバッグ ツールとして役に立たなくなります。

于 2012-01-10T16:38:10.650 に答える
0

「正しい」ことは、残念ながらSTM32では実用的ではありません。それは、ソース コードの知識を持ち、スタックをアンワインドして、フォールトの原因となった完全な呼び出しスタックと行番号を提供できる大きな例外ハンドラーを配置することです。これには、アプリケーションからのすべてのデバッグ情報を STM32 のフラッシュ メモリに追加する必要があり、これは実用的ではありません。

IDE をだましてコール スタックを提供する方法があります。詳細をお伝えしたかったのですが、書き忘れていたので忘れてしまいました。スタック ポインターをあるシャドウ レジスターから別のレジスターに手動で変更する必要があると思います。

私が通常行うことは、ハード フォールトの例外ベクトルにブレークポイントを設定し、ブレーク ポイントがヒットしたときにすべてのレジスタを確認することです。プラスチック爆薬で行われた殺人の法医学的証拠と考えてください。レジスタの値からアイデアが得られます。0x20000000 で始まるレジスタ値は RAM アドレスです。0x08000000 で始まるレジスタ値はフラッシュ アドレスです。逆アセンブラを開き、それらのアドレスを入力します。おそらく、それらのメモリ位置にある変数または関数に直接移動します。それでも問題が解決しない場合は、スタック ポインターを調べます。スタック ポインターのメモリ位置を見て、同じトリックを行います。私は常に、例外が発生した関数を特定するのに十分な破片を見つけました。

于 2012-02-07T01:59:07.367 に答える