Cortex-M3の割り込み
出典: Wikimura
Cortex-M3コアにはRTOSで利用しやすいよう、割り込み周りで工夫があるらしい。
目次 |
動作モード
動作モードには、通常のプログラムを実行しているスレッドモードと、例外を実行しているハンドラモードという2つのモードがある。 アクセス権のモードには、特権モードとユーザモードがある。 これらの組み合わせの中で、ユーザモードのハンドラは存在しないので、以下の3種類のモードが存在する。
- 特権ハンドラ: 割り込みハンドラは常にこれ
- 特権スレッド
- ユーザスレッド
ユーザモードのアクセス権では、SCS(System Control Space)と呼ばれるメモリ空間へのアクセスが制限される。 NVICやMPUモード、デバッグ等の設定レジスタがこの空間に属している。
MPU起動時は特権スレッドモードで起動する。ユーザスレッドへの移行はCONTROL[1:0]の0番ビットのセットで行う。 一旦ユーザスレッドに移行してしまうと、自分から特権スレッドにはなれない。 戻る方法は、特権ハンドラ上でCONTROLの0番ビットをクリアすることに限られる。
スレッドのモードが特権・ユーザのどちらであれ、割り込みが入ると特権ハンドラモードになる。 そして、特権ハンドラから抜けると、CONTROLレジスタをいじらない限りは自動的に元に戻る。
[3.3動作モード参照]
スタック
MSPとPSP
Cortex-M3コアは2つのスタックポインタを持っている。Main Stack Pointer(MSP)とProcess Stack Pointer(PSP)のどちらかが使われる。
MSPはスレッドモード、ハンドラモードどちらでも使用できる。PSPはスレッドモードで使用できる。 どちらを使うかの設定は、CONTROL[1:0]レジスタの1番ビットで行う。
- 0: MSP
- 1: PSP
割り込みハンドラではMSPを使用し、その他のスレッドモードではPSPを使用するよう設定できる。 アプリケーションが自分のスタックを破壊しても、OSのスタックに影響を与えないなどの保護が実現できるらしい。
スタックポインタの設定はCONTROL[1]で行えると書いたが、MSPしか使わない場合は常にMSPが使われる。 PSPを使う場合は、ハンドラモードに切り替わると、自動的にMSPに切り替わる。 [3.6.3 Cortex-M3の二つのスタック・モデル 参照]
割り込み時のスタッキング
割り込みが起こると、自動的にいくつかのレジスタがスタックへ退避される。 この際に使用されるスタックは、スレッドモードで使用していたスタック(MSPまたはPSP)となる。 退避し終わると、ハンドラモードのスタック(MSP)になる。 [9.1.1 スタッキング 参照]
例外処理
SVC
OS上でプログラムを走らせると、ユーザプログラムが勝手にハードウェアへアクセスするのはよろしくないらしい。 ハードウェアへのアクセスはいわゆる特権が必要だから、OSにやってもらわなくてはならない。 これをお願いするための仕組みとして、システムコールがある。
Cortex-M3では、システムコールを実現するのに利用できるソフトウェア割り込みSVC(System Service Call)が提供されている。
SVC命令でSVCを発生させることができる。この命令は1つの8ビットイミディエイト(即値: 0x1などの値そのもの)を必要とする。 この値が機能を指定するのに使われる。
システムコールを呼び出すとき、引数をスタックに入れて渡したいときがある。 ここで、スタックにPSPを使用していると、SVCのハンドラに切り替わった時スタックもMSPに切り替わってしまう。 引数が入っている場所を割り出すための処理については、8章で取り扱われている。
[7.6 SVCとPendSV参照]
PendSV
時間がかかるシステムコールが、すでに実行されていた割り込みハンドラを妨げることは好ましくない。後で実行するためにPendSV(Pended System Call)というソフトウェア割り込みも提供されている。
例としてあげられていた、問題が起こるパターンは以下のようなものだった。
- SysTick例外でコンテキストスイッチを行う
- 割り込みハンドラ中にSysTick例外が発生する
- SysTick例外の優先度は割り込みに比べ高いため、横取りされる
- コンテキストスイッチは戻り先をタスクにする
- 全ての割り込みを処理し終える前に、ハンドラモードからスレッドモードへ切り替わるという現象が起こる
- 割り込みはすべて処理し終えない限りスレッドモードへは戻らない
- 良くある階段状の図でいうと、一番下がスレッド、それより上は全部ハンドラ
- この現象が発生すると用法フォルトが起きてしまう
こういった問題を避けるために、PendSVがあるらしい。
PendSVはSVCハンドラから発生させることのできる(保留させると書かれている)ソフトウェア割り込みらしい。
PendSVを最低優先度にセットすると良いらしいのだが?
これは使い方次第らしい。詳しく調べる。
[7.6 SVCとPendSV参照]

