8

コードに奇妙なバグがあり、デバッグしようとすると消えてしまいます。

私のタイマー割り込み(常にシステムティッカーを実行している)には、次のようなものがあります:

 if (a && lot && of && conditions)
 {
     some_global_flag = 1;                   // breakpoint 2
 }

私のメインループには

 if (some_global_flag)
 {
     some_global_flag = 0;
     do_something_very_important();   // breakpoint 1
 }

メインループのこの条件は、タイマーの条件が(私が思うに)満たされているときに呼び出されることはありません。条件は外部です(ポートピン、ADCの結果など)。まず、位置1にブレークポイントを設定しましたが、トリガーされることはありません。

それを確認するために、ブレークポイントnrを設定します。2行目some_global_flag = 1;で、この場合、コードは機能します。条件が真の場合、両方のブレークポイントがトリガーされます。

アップデート1:

あるタイミング条件が原因であるかどうかを調査するためifに、デバッグなしで実行している場合はタイマーに入力されないため、タイマーに次を追加しました。

 if (a && lot && of && conditions)
 {
     some_global_flag = 1;                   // breakpoint 2
 }


 if (some_global_flag)
 {
     #asm("NOP");    // breakpoint 3
 }

フラグは、コード内の他の場所では使用されません。それはRAMにあり、RAMは最初にゼロにクリアされます。

現在、すべてのブレークポイントが無効になっている場合(または、メインのブレークポイント1のみが有効になっている場合)、コードは正しく機能せず、関数は実行されません。ただし、NOPでブレークポイント3のみを有効にすると、コードは機能します。ブレークポイントがトリガーされ、続行した後、関数が実行されます。(それは目に見える出力と聞こえる出力を持っているので、それが実行されるかどうかは明らかです)

アップデート2:

タイマー割り込みは、最初の「SEI」によって割り込み可能でした。その行を削除しましたが、動作は目立った方法で変更されていません。

アップデート3:

外部メモリを使用していません。フラッシュの制限に非常に近いので、コンパイラで最大でサイズを最適化します。

コンパイラ(CodeVision)が責任を負うことができますか、それとも私は何か非常に間違ったことをしましたか?

4

5 に答える 5

6

デバッガーは、プロセッサーの実行方法とコードの実行方法を変更できる/変更できるため、これは驚くべきことではありません。

分割統治。それが機能するまで物事を削除し始めます。それと並行して、何もせずに開始し、タイマー割り込みとメインループの数行のコードのみを追加します。do_something_very_important()は、LEDを点滅させたり、UARTを吐き出したりするような単純なものです。それが機能しない場合は、より大きなアプリを機能させることはできません。それが機能する場合は、割り込みにinitコードと条件を追加し始めますが、説明されている数行を超えてメインループを複雑にしないでください。失敗するまでコードを追加して戻すことにより、割り込みハンドラーの条件を増やします。

1つのものを追加して失敗し、それを削除して失敗しないという境界に達したら、逆アセンブルを実行して、それがコンパイラーのものであるかどうかを確認します。「追加したときにavr割り込みハンドラーが壊れてしまうのはなぜですか...」ということが明らかでない場合、これは別のSOチケットを保証する可能性があります。

これを数十行程度のメインと数行の割り込み行にまで減らすことができる場合は、他の人が自分のハードウェアで試して、おそらく並行して理解できるように投稿してください。

于 2012-02-08T16:22:49.610 に答える
5

これはおそらく典型的な最適化/デバッグのバグです。some_global_flag揮発性としてマークされていることを確認してください。これは、intuint8uint64でもかまいません...

volatile int some_global_flag

このようにして、some_global_flagの値がどうなるかについて何も仮定しないようにコンパイラーに指示します。コンパイラ/オプティマイザは割り込みルーチンへの呼び出しを認識できないため、これを行う必要があります。そのため、some_global_flagは常に0(初期状態)であり、変更されないと想定されます。

すでに試した部分を読み間違えてごめんなさい...

avr-gccを使用してコードをコンパイルし、同じ動作をするかどうかを確認できます...

于 2012-02-08T08:04:12.627 に答える
4

奇妙に思えるかもしれませんが、最終的には、入力ラインの1つでの強い過渡現象が原因であることが判明しました(システムに電力を供給しますが、ADC測定も条件として使用されます)。

システムは短時間定期的に電源障害が発生する可能性があり、重要な一時データは内部SRAMの一部に保持されます。これは起動後にクリーニングされず、使用時にデータを(10分以上)保持するように設計されています。 CPUが電圧低下している間の小さなコンデンサの。

システムのこの部分をテストして完全に機能したため、質問にこれを投稿しませんでした。そのため、コースから外れたくありませんでした。

最後に私が見つけたのは、非常に強い過渡現象を生成する環境で新しい機能が使用されたことです。私の質問の条件の1つは、「永続RAM」内の変数の1つに依存する状態に依存していました。そして最後にブレークポイントを使用することで、その一時的な影響から私を救いました。

最後に、タイミングを調整することで問題を解決しました。

編集:問題の場所を見つけるのに役立ったのは、最も重要な変数の値を「永続RAM」領域に記録し、それらのいくつかが破損していることを確認できたことです。

于 2012-02-08T17:57:07.513 に答える
1

私はここで間違っているかもしれませんが、問題のボードにアタッチし、それが実行されるはずのハードウェアでプログラムをデバッグするためにデバッガーを使用している場合、アタッチを実行するときのマイクロコントローラーの動作を変更できると思います... 。それ以外に、上記で提案されたvolatileキーワードには手がかりがありません。

于 2012-02-08T08:00:37.697 に答える
1

これは、ARMプロセッサを想定して記述されています。

ブレークポイント(RAMまたはROM bkpoint)を使用すると、プロセッサはブレークポイントで実行モードからデバッグモードに強制的に切り替えられ(停止モードまたは監視モードのいずれか)、デバッグ速度で実行されるか、アボートハンドラーが実行されるため、JTAGベースのデバッグが実行されます。基本的に煩わしいデバッグです。

特にARM(または他のタイプのバス計装)のETM(組み込みTrace Macrocell)は、邪魔にならないように設計されており、命令とデータをリアルタイムでログに記録できるため、実際に何が起こったのかを調べることができます。

于 2014-09-09T15:15:15.863 に答える