athrill(アスリル) を使用してベアメタル・プログラミング(2回目：割り込みがソフトウェアに通知されるまで) 

#概要
[前回](https://qiita.com/kanetugu2018/items/7d2ce8def53cb9bda06b)は，普段当たり前のように使っている main 関数が動き出すまでの流れを解説しました．今回から割り込み処理の実装方法について解説したいと思います．ただ，割り込み処理を実装するためには，最低でも以下の知識が必要となります．

 * ハードウェア周りの知識
 * アセンブラの知識

そのため，少なくとも３回にわけて解説を進めたいと思います(もしかするともっと伸びるかも…)．

* 第１回：ハードウェア側で発生した割り込みがソフトウェア側に通知されるまで
* 第２回：ソフトウェア側に通知された割り込み処理をアセンブラで実装
* 第３回：アセンブラからC言語の世界へ

第１回となる今回は，割り込みコントローラを起点にして，ハードウェアで発生した割り込みがソフトウェア側に通知されるまでの流れを解説していきます．

#割り込みコントローラ
割り込み処理をプログラミングする上で，前提知識として割り込みコントローラの役割/動作内容についておさえておく必要があります．

割り込みコントローラはハードウェアデバイスであり，マイコン毎にそのハードウェア仕様は様々ですが，その役割は，
　**「様々な周辺デバイス(タイマ，CAN等)からの割り込み要求を受けて，CPUに割り込み要求を行う」**
と言えます．

athrill は，その割り込みコントローラをエミュレーションしており(V850ES/Fx3)，V850ES/Fx3を前提に解説を進めます．

本割り込みコントローラは，先述のとおり，様々な周辺デバイスからの割り込み要求を受け付けます．
そのため，ハードウェアマニュアルを紐解くと，下表(詳細はハードウェアマニュアル参照ください)に示すような仕様が必ずあります．


|     種類     | 名称          | 発生要因  | 例外コード | ハンドラ・アドレス |
|-------------|--------------|----------|-----------|----------------|
|リセット|リセット|内部要因からのリセット入力|0x0000|0x00000000|
|ノンマスカブル|NMI|NMI端子有効エッジ入力|0x0010|0x00000010|
|：|：|：|：|：|
|ソフトウェ例外|TRAP0n|TRAP命令|0x0040|0x00000040|
|：|：|：|：|：|
|マスカブル|INTLVIL|低電圧検出|0x01E0|0x000001E0|
|：|：|：|：|：|
|マスカブル|INTTAA2CC0|TAA2キャプチャ0/コンペア0一致|0x0080|0x00000080|
|：|：|：|：|：|

この仕様の読み方は以下のとおりです．

* 「種類/名称」
 * 割り込みコントローラに対して割り込みを発生させる周辺デバイス等を指しています．
* 「発生要因」
 * 文字通り割り込みの発生要因です．
 * たとえば，INTTAA2CC0の場合は，タイマデバイスのカウンタ値がコンペア値と一致した場合に割り込み要求を発生させると読めます(周期的な割り込みを発生させる場合によく使用します)．

ここまでがハードウェア側の世界であり，この割り込み要求が発生し，CPUがその割り込みを受け付けた場合の仕様が
**「例外コード」**と**「ハンドラ・アドレス」**になります．

CPUは，割り込み要求を受け付けると，以下のレジスタの値を変更します．
※マスカブル割り込み前提で話を進めます．また，割り込みが発生するまでの流れの解説に焦点をあてていますので，
※細かなレジスタの話は思い切って省略しました．詳細を確認されてたい方は，ハードウェアマニュアルを参照ください．

* システムレジスタ(PSW)
 * CPUに対する割り込みを禁止状態にします(PSWのIDビットをセット)
* システムレジスタ(EIPC)
 * 現在実行中のプログラムのアドレス(CPUのPCレジスタの値)を本レジスタに退避します
* システムレジスタ(EIPSW)
 * 現在のPSWを本レジスタに退避します
* システムレジスタ(ECR)
 * **「例外コード」**を本レジスタに設定します
* PC(プログラムカウンタ)
 * **「ハンドラ・アドレス」**を本レジスタに設定します

上記の通り，プログラムカウンタは割り込み前後で切り替わってしまいますから，ソフトウェア側では通常処理を実行しているにもかかわらず，唐突に割り込みの「ハンドラ・アドレス」に
処理が移ってしまうことになります．

#デモ

この様子をathrillでデバッグして，確かめてみましょう．

下図は，main関数が処理実行中に割り込み番号22の割り込みが発生したため，
プログラムの処理が割り込み処理部分に切り替わった様子を示しています．

|before|=>|after|
|------|-----|-----|
|![main.png](https://qiita-image-store.s3.amazonaws.com/0/244147/0ebf8482-af5d-a2a7-cea0-269eaa3c332d.png)|=>|![interrupt.png](https://qiita-image-store.s3.amazonaws.com/0/244147/b56f9999-6502-a059-6dc8-4208d0a78b46.png)|

割り込みが発生することで，プログラムの処理が全く違う見知らぬ世界に変化してしまうことがわかります．
さらに，このときのCPUレジスタの値の変化を見てみましょう．

![cpu_diff.png](https://qiita-image-store.s3.amazonaws.com/0/244147/f7eb050d-1fc6-d84f-957c-f976720c097a.png)

上図の通り，プログラムカウンタはmain関数から，割り込み番号22の「ハンドラ・アドレス」である0x1e0に切り替わっていることがわかりますよね．これが，プログラムの処理がまったく違う世界に切り替わってしまった原因と言えます．

さらに，EIPC, ECR, PSWのシステムレジスタ値も前述の通り変化しています．これらのレジスタ値は，割り込みから復帰するためにとても大切な情報ですが，今日のところはこのへんで終わりにします．

次回は，「ソフトウェア側に通知された割り込み処理をアセンブラで実装」について解説したいと思います．
お楽しみに！

#関連記事
* [マルチコア対応仮想環境(athrill)を使用して TOPPERS/ATK2 を実行する](https://qiita.com/kanetugu2018/items/b43c5715124f42a0393d)
* [メモリ保護対応版 athrill(アスリル) のご紹介](https://qiita.com/kanetugu2018/items/f2205475c4a4eae699c0)
* [今さらなぜCPUエミュレータを自作しようとおもったのか？](https://qiita.com/kanetugu2018/items/d692e612c3d4d715c0ad)
* [athrill(アスリル)を使用してC言語ポインタ変数を理解する](https://qiita.com/kanetugu2018/items/b9ad84c2f74324174864)
* [athrill(アスリル)機能マニュアル](https://qiita.com/kanetugu2018/items/cf3dea16710a3f0737e8)
* [athrill(アスリル) を使用してベアメタル・プログラミング(１回目：main関数が動き出すまで)](https://qiita.com/kanetugu2018/items/7d2ce8def53cb9bda06b)
* [TOPPERS/ATK2カーネル向け実機レス環境(athrill2)](https://qiita.com/kanetugu2018/items/75dadc340f3db2a344ab)