サードパーティ ライブラリ経由で CAN コントローラーを使用しているときに、C アプリケーション (ベア トゥ ザ メタル、スーパーバイザー モードで実行) のある時点で、ISR でキャッチされる不正な命令エラーが発生していました。その時点までに、ISR で使用可能な例外スタック フレームのプログラム カウンター、フォールト、およびリターン アドレスは、すでに 0 でした。最初に遭遇したとき、スタックを少しバックアップすることができ、このようなスタック トレースを見ました。 :
Thread [1] <main> (Suspended : Step)
0x0
0x41f42200
...
timerInterrupt() at timer.c:1,175 0x2432ec
0x41902210
...
main() at main.c:1,433 0x211a44
0x40000000 は、このプロセッサの IPSBAR です。
この問題をすばやく再現できる既知の状態でアプリケーションを数回実行しました。通常は、0x0 へのジャンプ前の割り込み/例外時に、まったく同じスタック トレース/保存された命令まで実行しました。テストを通じて、割り込みが無効化された後に再度有効化された後の命令、または割り込みがマスクされていないコードのセクションでのみジャンプが発生することに気付きました。したがって、これは問題の原因となっているユーザー割り込みであるに違いないと考えましたが、マスクで割り込みが有効になっていないときに、設定されていないハンドラーを呼び出そうとするように見える理由はわかりませんでした。ISR が呼び出される前の IPSBAR 範囲内のアドレスの意味を 100% 確信しているわけではありませんが、それらはその ISR の各呼び出しで同じであるため、
そこで、通常のハンドラを追加する前に、割り込みコントローラ 0 のすべての割り込みベクトルにデフォルトの割り込みハンドラを追加して、アプリケーションを再度実行しました。 、スタックは次のようになります):
Thread [1] <main> (Suspended : Step)
__DefaultInterrupt() at interrupts.c
0x41f42200
...
timerInterrupt() at timer.c:1,175 0x2432ec
0x41902210
...
main() at main.c:1,433 0x211a44
その関数の SWIACK0 の値を観察すると、割り込みソースが 100 (ユーザー割り込み 36、PIT0 割り込み) であることがわかりました。まあ、それはすでにISR(上記のスタックにtimerInterrupt())を持っています。次に、ISR 関数ポインターが保存されている RAM の領域をチェックして、タイマー割り込みハンドラー関数ポインターが破損していないかどうかを確認しましたが、すべての割り込みハンドラーが設定された時点と、デフォルト ハンドラーのブレークポイントがヒットした時点との間に変化はありませんでした。
また、CAN コントローラーの割り込みハンドラーの割り込みレベルを 7 に設定すると (同じ割り込みが 18 の FlexCAN 割り込みソースすべてを処理する)、問題が発生しないことにも気付きました。まだどうすればいいのかわかりませんが、問題はCANライブラリまたはコントローラーのいずれかに問題があることを完全に示しています.
編集 - この時点では、どの ISR が割り込みを処理しているのか正確にはわかりませんでしたが、最初に疑われた割り込みソースに個々のハンドラーを追加しました。それは常に割り込みソース 63 です。ドキュメントによると、これは未使用の割り込みです。割り込みコントローラ0の最後のもの。
編集 2: SWIACK0 のアクティブな割り込みソースは実際には正しいと思いましたが、ベクター ベース アドレスが書き換えられているなど、別の問題がある可能性があります。残念ながら、書き込み専用の値であるため、読み戻す方法がわかりません。デフォルトの割り込みハンドラーがタイマー割り込みハンドラー内から呼び出されていたため、PIT0 の割り込みソースはそのレジスターにあると当初考えていましたが、タイマー割り込みがスタックにない場合にも示されます。リファレンス マニュアルには、オンチップ デバッグ デバイスを使用して制御レジスタ、つまり VBR を読み戻すことができることが示されていますが、デバッグ マニュアルにはこれを行うための情報がありません。
とりとめのない話を短くするために、ハイパースペースへのジャンプのソース、またはそれを取得するために使用できる情報を見つけたい.
IPSBAR 範囲内のアドレスがスタックにプッシュされることの意味は何ですか?
アドレス指定されたものはソースに完全に関連付けられているように見えるため、スタック内の値 (最初の例では 0x41f42200 など) を使用して
、スタックにプッシュされたこの割り込み/例外のソースを特定する方法はありますか?私はこれについて完全に間違っていますか?
私は、この考え方のすべてを放棄することを非常に嬉しく思います.
助けや洞察に感謝します.2つの脳細胞をこすり合わせてそれを行うことができたら、より多くの(簡潔な)情報でこれを更新します.