stm32で一つのベクタで複数の割り込みを処理するとき、など
ブログに時々、stm32とかのハマりポイントを
備忘録として書くことがあるのですが、最近書いてないのと、
身近で苦労しているような人がいるので、ヒントとして書きます。
これだけだと解決しないだろうけど...
------
自分がよく使っているstm32は、NVICをコアの
機能に持ち、ベクタ割り込みに対応しています。
ワンチップマイコンが、ハードウエアだけで動作する
割り込みコントローラーを持っているのは
今では当たり前になりすぎていて、だれも疑問に思いませんが
ついこないだ?例えば、arm7-TDMIのコアの頃には
ベクタ割り込みは、半自動でした。
※割り込み時に呼ばれるアドレスはすべて共通で、
割り込みハンドラ内で、どの割り込みの要求かを
自前のコードで判断、自力で処理ハンドラにジャンプしていました。
当然、アセンブラコード記述必須。
Cortexコアになって、ベクタ割り込みコントローラーがコアに
実装され、普通?に使えるようになりました。
割り込み、便利に使えるようになったので、幸せにはなったのですが
動作が分かりにくくなったのも確か。
クリティカルなタイミングで動かしていると、
一見不思議な動きをしているように見えたりします。
実体験から、2つTipsを選んで置いておきます。
------
①一つの割り込みベクタで、複数のイベントを管理
これに、個別に割り込み禁止/許可を組み合わせ、
かつ(ついつい)自分の都合のよいように
動作を解釈するときに、インシデント発生します。
※タイマー割り込みで、よくやりがちです。
例えば、TIM2には割り込み要因がいくつかありますが、
割り込みベクタはすべて共通で、どのイベントが発生しても
同じイベントハンドラ関数が呼ばれます。
ここで、割り込み分岐許可自体は、チャネルごとに設定できるので
割り込みは、TIM2のch1のコンペアマッチだけで発生させる、
という設定は出来て、これは正しく動作します。
この時、たとえばch1に加え、ch2もコンペアマッチ動作等で
初期化されていると、割り込みを使わないつもりでも
個別に割り込み禁止されていても、
SRレジスタのフラグは立ってしまいます。
(割り込みハンドラは呼ばれない:正しい動作)
この状態で、たまたまch1のイベントが発生して、
SRレジスタのフラグしかチェックしないと、
ch1とch2 両方の処理をしてしまうことになり、
ch2は割り込み禁止している(つもりな)のに、
なぜか処理が行われるように見えます。
割り込みハンドラの中で処理の
選択をする場合、SRだけでなく、
DIERも参照する必要があります。
※クリティカルパスが発生しない
ように、参照のタイミング自体も
よく吟味する必要があります。
------
②割り込みを動的に許可/禁止する場合
こちらは定番ですが、個別に割り込み許可する前に
要因となるSRをクリアしておく必要があります。
割り込み禁止期間の間に、イベント発生して
いると、割り込み許可した瞬間に、
ハンドラに分岐します。
※至極正しい動作ですが、大体の場合、
意図した動きではないでしょう。
通信などでは、一般的に割り込み禁止/許可を
動的に切り替えることは少なく、
考慮しなくても意図しない動作はしにくいですが。
フリーランタイマーのコンペアマッチなどでは
一定時間後にイベントが発生するので、
この動作を見落としがちです。
※こちらもクリティカルパス要注意
------
マイクロマウス系のソフトウエアでは、タイマーの
コンペアマッチ割り込みを、動的にON/OFF
することは少ないでしょうが、各種タイマーは
上手く使うと、色々なことが出来るようになります。
さらにDMAと組み合わせれば、相当複雑なことができますが、
上手く行かないときのデバッグの難易度も相当なものです。
まあ、ハードウエア設計時によく考えて、
個別に割り込み許可/禁止しなくても良いように、
構成すれば、あまり気にしなくても問題でないのですが。
何かの助けになれば、こそ
と取り急ぎ。
| 固定リンク | 0
コメント