12ステップで作る組込みOS自作入門
      7thステップ




                @sandai
【参考書籍】
12ステップで作る組込みOS自作入門
【内容】
1ステップずつ、実際に動かしながらプログラムを発展さ
せていく方式で無理なく学べる。OSやハードウェアに詳
しくない方にも理解できるよう
に十分な説明を提供

坂井 弘亮(著)
カットシステム(2010/5)

【税込価格】
4,410円

【サポートページ】
http://kozos.jp/books/makeos/
もくじ
1.割込みの概要
2.外部割込み、内部割込み
3.外部割込みの受け付け
4.組込みベクタと割込みハンドラ
5.割込み発生時のレジスタの扱い
6.H8/3069Fの割込み処理
7.ブートローダに割込みハンドラを実装
8.プログラムの実行
9.まとめ
1.割込みの概要
割込み
●   CPUは割込みを受け付けると、現在処理中のプ
    ログラムの実行を中断し、特定の処理に実行を
    移す
●   この割込み発生時に実行される処理を割込みハ
    ンドラと呼ぶ
    –   コールバックとも言われる
    –   割込みを受け付けることを割込みのハンドリングな
        どとも言う
●   割込みハンドラの処理が終わると中断していた
    処理に実行を移す
割込み処理の要点
●   割込み発生時に実行させたい処理を割込みハン
    ドラとしてあらかじめ登録しておく
●   割込みが発生した際には、現在実行中の処理を
    中断し登録しておいた割込みハンドラが実行さ
    れる
●   割込みハンドラの実行後に中断してた本来の処
    理に戻る
2.外部割込み、内部割込み
割込みの種類
●   割込みの種類は大きく分けて3つある
    –   外部割込み(ハードウェア割込み)
    –   例外
    –   内部割込み(ソフトウェア割込み)
●   これらの分け方はCPUによって違う
    –   例外と内部割込みを同じ「内部割り込み」として表
        現するケースもある
割込み要因の例
●   割込みを起こす原因となる現象を割込み要因と
    言う。割込み要因には様々な種類がある
●   割込み要因の例
    –   タイマ・コントローラに設定した時刻が満了した...タイマ割込み
    –   シリアルから文字を受信した...シリアル受信割込み
    –   リセット・ボタンがおされた...リセット割込み
    –   ゼロ除算が行われた...ゼロ除算例外
    –   不正なアドレスにアクセスした...不正アドレス・アクセス例外
    –   システム・コール命令が実行された...システム・コール割込み
    –   トラップ命令が実行された...トラップ割込み
外部割込み(ハードウェア割込み)
●   周辺I/Oに割込み要因が発生して、割込み線が
    アサートされることで発生する割込み
    –   アサートされたら割込みの処理に入る
●   アサートとは割込み入力ピンに、各種コント
    ローラから割込みの出力信号が送られたことを
    検出すること
    –   「キックされる」とも言う
CPUが出力信号を受ける仕組み
●   CPUには割込み受け付けのピン(割込み入力ピ
    ン)がある
●   このピンは各種コントローラが持つ出力線とい
    うピンから送られてくる割込み信号を受け付け
    るもの
    –   IRQ(Interrupt ReQuest:割り込み要求)という名前
        がついている事が多い
●   コントローラが信号を出力する方法ピンに電圧
    をかけるかどうかで行う
正論理と負論理
●   割込み出力線のピンの電圧がゼロの状態をLow
    レベル、電圧がかかった状態をHighレベルと言
    う
●   割込み出力線がLowからHighに変化したとき、
    コントローラが割込み出力線に信号を出力した
    ことになる
●   また、普段はHighで割込み発生時にLowに変化
    する回路もある
●   前者を正論理、後者を負論理と呼ぶ
    –   実際の割込み線は負論理が多い
    –   負論理はIRQやIRQ#と表現される
ポーリング
●   シリアル・ドライバのserial.cによってSCIの
    SSRレジスタのRDRFビットをwhileループで見張
    り文字の受信を検知している
    –   ビジーループで受信データが来るまで待っている
●   この場合、たとえば受信待ちしながら他の処理
    も同時に行う場合、別の処理を行いながら定期
    的にSSRレジスタのRDRFビットの状態をチェッ
    クする処理が必要となる
●   このように定期的に状態をチェックする処理を
    ポーリングと言う
シリアル受信割込み
●   ポーリングは良い手段ではない
    –   文字を受信した瞬間にチェックして処理するわけで
        はないので、反応が遅いから
●   ポーリングの改善策として割込みを利用する
●   シリアルからの文字受信時の処理を割込みハン
    ドラに登録しておけば、別の処理を行いながら
    文字を受信したときにその処理を行うことがで
    きる
●   このような割込みをシリアル受信割込みと呼ぶ
シリアル送信割込み
●   シリアル送信の場合、送信可能かどうかの判断
    をSCIのSSRレジスタのTDREビットを見ている
    –   これもビジーループで行なっている
●   これも割込みで処理できる。送信処理が完了し
    たら割込みによって通知してもらい、割込みハ
    ンドラの名かで次に送信すべき文字の送信処理
    を行う形にすれば良い
●   このような割込みをシリアル送信割込みと呼ぶ
割込みはコントローラで備えている
●   シリアル接続における送受信の割込みはコント
    ローラ側で発生し、CPUがそれを検知する
●   通信用コントローラの多くはこのような割込み
    機能を備えている
    –   LANコントローラも同じ
●   コントローラから割込みが発生したとき用に割
    込みハンドラを登録しておけば、ポーリングの
    ようにチェックする必要がない
CPU資源
●   割込みはCPU資源の有効活用という点でもメ
    リットがある
●   CPU資源とはCPUの処理時間のことで、CPUが実
    行できる一定時間内の命令数は決まっている
    –   よって、CPUが実行できる命令数は有限の資源と言
        える
内部割込み(ソフトウェア割込み)
●   内部割込みとはCPU内部での不正発生などに
    よって起きる割込み
    –   不正アドレス・アクセスやゼロ除算、アラインメン
        ト違反など
●   また、プログラム側でわざと発生させた割込み
    もある
    –   システム・コール命令、トラップ命令など
        ●   実はシステム・コール割込みがトラップ割込みに含まれ
            ており、トラップ割込みによってシステム・コールを実
            現するCPUもある(H8はこれ)
●   不正アドレス・アクセスやゼロ除算など不正な
    処理は「例外」と呼ぶ場合が多い
3.外部割り込みの受け付け
外部割込み入力ピン
●   外部割込みの受け付けにはCPUの入力ピンが必
    要
●   CPUによってはピンを複数持っている
●   この場合コントローラごとの割込みにそれぞれ
    割込みハンドラを登録することができる
割込み入力ピンが1本の場合
●   CPUによっては割込み入力ピンが1つしかない
●   その場合、各コントローラの割込み出力線をOR
    論理で集約して接続させる




     233頁 図7.3 複数の割込みをOR論理でまとめる より
OR論理での割込みハンドラ
●   OR論理でまとめた場合割込みハンドラは1つし
    か登録できない
●   CPUからはタイマ割込みかシリアル割込みか判
    断できないので、割込みハンドラ内でコント
    ローラのレジスタを参照して割込みが発生した
    かどうか調べて処理を行う
    –   このような処理を「ハンドラ内部で割込み要因を調
        べる」と言う
●   割込みハンドラのプログラミングは、本来なら
    回路図を読んで各コントローラの割込み出力線
    がどのように接続されているか確認してから行
    う必要がある
コントローラの数が多い場合
●   割込み入力よりもコントローラが多い場合、ひ
    とつの割込み入力にまとめる
●   この場合割込みコントローラというICを利用す
    る




      235頁 図7.4 割込みコントローラを利用する より
割込みコントローラ
●   複数の割込みをOR論理で結合し、さらに、各割
    込みの有効/無効化(割込みをCPUに通知するか
    しないか)や割込み優先度の制御が行える
●   割込みコントローラの制御は保持している制御
    用のレジスタによって行う
●   割込みコントローラを利用するメリット
    –   割込みの有効/無効が制御できる(割込みマスク)
    –   割込みコントローラのレジスタを見ることで、どの
        コントローラから割込みが発生したか分かる
●   割込みコントローラを利用することで、統一的
    な制御が可能となる
    –   各コントローラのレジスタの確認を割込みコント
        ローラだけで行えるから
4.組込みベクタと割込みハンドラ
組込み発生時の基本動作
●   CPUにおける組込み発生時の動作は2つに大別で
    きる
    –   ①特定のアドレスにジャンプ
    –   ②特定のアドレスからジャンプ先のアドレスを読み
        込んで、そこにジャンプ
●   ジャンプ先にある割込み処理を割込みハンドラ
    と呼ぶ
    –   ISR(Interrupt Service Routine:割込みサービス
        ルーチン)と呼ばれることもある
①特定のアドレスにジャンプ
●   割込み発生時に特定のアドレスに配置しておい
    た割込みハンドラが勝手に実行される、といっ
    たもの
●   特定のアドレスには決まった数の命令しか記述
    できないので自由なハンドラを置くことができ
    ない?っぽい
●   ので、だいたい②の方法が採用される
②特定のアドレスからジャンプ先の
  アドレスを読み込んで...
●   適当な場所に割込みハンドラを配置して、その
    ハンドラを配置したアドレスを特定のアドレス
    に書いておくというもの
●   いくつかある割込みハンドラのアドレス位置を
    配列でまとめたものを割込みベクタと呼ぶ
    –   この方法をベクタ割込み方式と言う
    –   割込みベクタはベクタ・テーブルなどとも言う
●   H8はベクタ割込み方式
    –   ハンドラの登録方法はvector.sと、ld.scrを読めば
        分かる
    –   つまり、割り込みベクタに割込みハンドラのアドレ
        スを書き込むってだけ
5.割込み発生時のレジスタの扱い
割込み復帰命令
●   多くのCPUには割込み復帰命令がある。これは
    割込み発生時に退避しておいた情報の復帰を行
    うためのもの
    –   割込みは現在の処理を中断して割込みハンドラを実
        行するわけだけど、割込みが発生する直前のデータ
        (レジスタの値)を中断していたときから始められる
        ように退避させている
    –   というわけで、割込み復帰命令は割込みハンドラの
        最後に実行される
●   ここで問題になることは
    –   どこに退避するのか?
    –   退避が必要な情報は何か?
どこに退避するのか?
●   CPU次第だが、大きく分けると2通り
    –   スタック
    –   退避先の専用のレジスタ
●   レジスタの退避はx86系だとアセンブリの命令
    で簡単に行えたはず
    –   具体的にどこに退避していたかは覚えてないけど、
        あまり気にすることじゃないと思う
何を退避するか?
●   多くのCPUでは以下の2つの値を退避させる
    –   プログラム・カウンタ(PC)
    –   モード・レジスタ(コントロールレジスタとも呼ぶ)
●   どちらも割り込み発生時にCPUが自動的に退避
    して保存している
    –   どこなのか具体的な場所は分からないが
プログラム・カウンタ(PC)の退避
●   割込みハンドラへのジャンプとはPCの強制的な
    書き換え
    –   割込みハンドラにジャンプした時点でPCの値は割込
        みハンドラのアドレスになっている
●   割込みハンドラにジャンプする前にPCを退避さ
    せておくことで、割込みハンドラの処理が終了
    したときに元のアドレス位置の処理に戻れるよ
    うにしている
モード・レジスタの退避
●   モード・レジスタは汎用レジスタとは違いCPU
    の動作モードを保存する役割の決まったレジス
    タ
●   動作モードには次のようなものがある
    –   割込み禁止
    –   特権モードとユーザモード
    –   メモリ保護の有効/無効の切替え
    –   仮想メモリによるアドレス変換の有効/無効の切替
        え
割込み発生時のモード・レジスタ
●   割込み発生時はモード・レジスタの設定が自動
    的に割込み無効になり、それから割込みハンド
    ラにジャンプする
    –   割込みハンドラの先頭で別の割込みを受け付けたと
        きにPCの保存先の値が書き換わって元の処理に戻れ
        なくなるから
    –   割込みのネスト、多重割込みなどと呼ばれる
●   CPUに特権モード割込みモードがあるなら割込
    みハンドラは特権モードで動作する必要がある
●   割込み発生時にモード・レジスタを退避させて
    おくことで、割込みハンドラが終了したときに
    元の状態に戻れるようにしている
アトミック
●   PCとモード・レジスタの保存処理はアトミック
    である必要がある
    –   アトミックは「分割してはいけない」という意味
●   分割して処理したときに処理の不整合が発生し
    てしまうような場合は、2つの処理を1命令で行
    えるような命令をCPUは持っている
    –   このような命令をアトミック命令と呼ぶ
●   割込み発生時にPCとモード・レジスタの値を退
    避させ、割込みハンドラの末尾にある割込み復
    帰命令でその2つの値を同時に復旧させる
    –   退避も復旧の処理もアトミックでなければならない
汎用レジスタの退避
●   PCとモード・レジスタ以外に、プログラム中で
    利用しているであろう汎用レジスタやフラグ・
    レジスタなどの値も割り込み発生時に保存して
    おく必要がある
●   これらはCPUの回路が複雑になるので自動で退
    避されることはない
●   つまり、何もしないままだと割込み復帰命令だ
    けでは元の処理に戻れない
●   そこで割込みハンドラの最初と最後で保存と復
    旧の処理を行う必要がある
    –   最初を割込みハンドラの入口、最後を割込みハンド
        ラの出口と呼ぶ
割込みハンドラの入口と出口
●   割込みハンドラの入口で行う処理
    –   汎用レジスタの値をどこかに保存
    –   その他プログラム中で利用しているレジスタ(フラ
        グ・レジスタなど)も保存
●   割込みハンドラの出口で行う処理
    –   汎用レジスタの値を保存先から復旧
    –   その他プログラム中で利用しているレジスタの値も
        復旧
●   割込みハンドラをC言語で記述した場合はこの
    ような処理が必須となる
    –   C言語のプログラムをコンパイラがアセンブラに変
        換する際に汎用レジスタを利用するから
保存・復旧するレジスタ
●   全ての汎用レジスタを保存する必要はなく、割
    込みハンドラ内部で利用する(値が書き換わる)
    レジスタのみが保存対象となる
    –   が、まあ、x86系は確か1つの命令で全て退避できる
        ようになっていたのでそれでいいんじゃないかな
●   処理の内容を把握しておけば退避するレジスタ
    の数を最小限に抑えることができるが、よくわ
    からないうちは割込みハンドラでは全ての汎用
    レジスタを保存・復旧するよう実装すれば問題
    ない
割込みのクリア
●   コントローラは割込み発生時にアサートし続け
    る
    –   コントローラは割込み出力をフリップ・フロップと
        して実装し、状態を維持している
●   アサートされたままだと、割込み復帰命令直後
    に割込み禁止が解除されることで再度割込みが
    かかってしまう(割込みが無限ループで発生)
    –   これを割込み要因のクリアし忘れと呼ぶ
●   そういった状態を回避するため、コントローラ
    の割込み関連レジスタを操作して割込みが発生
    したことを示すフラグを落とす必要がある
    –   これを割込みのクリアと呼ぶ
割込み処理のまとめ
●   CPUがPCとモード・レジスタは自動で保存・復
    旧がなされる
●   汎用レジスタやフラグレジスタは自力で保存・
    復旧する必要がある
    –   割込みハンドラの処理を軽くしたいなら退避させる
        レジスタを選ぶ必要があるが、よくわからないうち
        は全て退避させれば問題ない
●   割込みによって受信したデータなど参照した後
    は割込みのクリアを行う
    –   クリアしないと割込みの無限ループが起きるため
    –   なぜ無限ループが起きるかについては243pを読めば
        わかるんで、ここでは記述しない
●   以上が一般的なCPUにおける割込みの話
6.H8/3069Fの割込み処理
H8/3069Fの割り込みベクタ
●   主要な割り込みベクタ




     244頁 表7.1 H8/2069Fの割り込みベクタ(主要なもの) より
H8/3069Fの割り込みベクタの仕組み
●   H8はベクタ割込み方式なので、割込みが発生し
    たら割り込みベクタを参照し、設定された割込
    みハンドラにジャンプする
●   割り込みベクタの位置は0x000000~0x0000ffの
    256バイトで、1つの割込みベクタは4バイト
    –   64個登録できるってことかな
●   他の割り込みベクタについてはマニュアル参照
リセット(0x000000)
●   リセット・ベクタのことで、電源ON時に実行す
    る割込み
    –   具体的にはCPUのリセット割込み(RES)がLowから
        Highになったときにリセット割込みが発生
●   リセット・ボタンを押すとLowレベルになり、
    話すとHighレベルになる
●   ここらへんの回路図の仕組みは245pと、マニュ
    アル参照
トラップ命令(0x000020~0x00002c)
●   ソフトウェア割込みの一種で、割込みを明示的
    に発生させるもの
●   H8だとオペラントの値によって4種類の割込み
    が発生する
    –   なお、H8にはシステム・コールの割込みがないの
        で、トラップ命令で実装する
外部割込み(0x000030~0x000044)
●   外部割り込みの入力ピン(IRQ0~IRQ5)がアサー
    トされたときに発生する割込み
●   周辺I/Oの割込みはここで検知する
●   RXI0,RXI1,OXI2が受信完了、TXI0,TXI1,TXI2が
    送信データエンプティと呼ばれ、それぞれ
    SCI0,SCI1,SCI2のシリアルの受信/送信完了の
    割込みにあたる
●   H8ではシリアルコネクタに接続されているのは
    SCI1なんで、本書ではRXI1とTXI1だけ利用して
    いる
H8/3069Fのモード・レジスタ
●   H8はモード・レジスタはコンディションコード
    レジスタ(CCR)という1バイトのレジスタを持つ
●   一般的なCPUのモード・レジスタは様々なモー
    ド設定が可能だが、H8は単純なCPUなのでCCRの
    役割は「割込みの有効/無効」フラグしかもっ
    ていない
    –   CCRで設定できるのは組込みマスクのみ
●   CCRの他のビットはオーバーフロー・フラグ、
    キャリ・フラグなどのフラグ情報
    –   一般的にこれらの情報はフラグ・レジスタに集めら
        れるものだが、H8では全てCCRにまとめられている
H8/3069Fのレジスタの退避
●   H8のPCとCCRの退避先はスタック・ポインタで
    あるER7の指すメモリ上に自動的に保存される
    –   というかER7の位置。ここにPCが入る
    –   CCRが1バイト、PCが3バイトで積まれる
●   詳しいスタックへの保存動作については247pと
    H8/3069Fのマニュアルを参照
割り込みコントローラ
●   H8/3069Fにも割り込みコントローラが内蔵され
    ている、本書では特に利用しない
    –   割り込みコントローラはこのスライドでも扱ったけ
        ど、割込みの優先順位や有効/無効などの制御を各
        コントローラ全てに対して統一的に制御できるやつ
●   CPUでは割り込みコントローラを内蔵している
    ものが多く存在する
H8の割り込み禁止と復帰命令
●   割込み禁止はCCRの最上位ビットを1にすること
    で割込みが無効になる
    –   割込み禁止、割込みがマスクされると呼ぶ
    –   多重割込みしないようにできるってことだね
●   割込みの復帰命令はrteという命令を使う
    –   rteを実行するとスタックからPCとCCRを復旧される
H8の割り込み発生時の動作
●   ①スタック(スタック・ポインタの指す先)上
    に、PCとCCRの値を保存
●   その後割⑧込み要因に応じて割込みベクタを参
    照し、割込みハンドラにジャンプ(PCに割り込
    みベクタの値を代入する)
●   割込みハンドラが実行
●   割込みハンドラ終了時に割込み復帰命令を呼ぶ
    (PCとCCRが復旧され中断していた箇所から実行
    が再開される)
7.ブートローダに割込みハンドラを
        実装
これからの割込み処理
●   今まではビジーループを使ってコントローラの
    レジスタを監視しながら処理していたけれど、
    ここからはシリアル受信割込みを利用したもの
    に変更していく
●   それから割り込みベクタの設定を柔軟に行える
    ように「ソフトウェア・割り込みベクタ」とい
    うものを実装する
プログラムの追加
●   ブートローダ
    –    intr.h,intr.c...割込み処理の入口と出口
    –    interrupt.h,interrupt.c...ソフトウェア・割込み
         ベクタの処理
●   OS
    –    intr.h
    –    interrupt.h,interrupt.c
プログラムの修正
●   ブートローダ
    –    ld.scr...ソフトウェア・割り込みベクタを追加
    –    vector.c...ソフトウェア・割込みベクタを設定
    –    main.c...ソフトウェア・割り込みベクタの初期化
         追加
    –    Makefile
●   OS
    –    ld.scr...ソフトウェア・割込みベクタを追加
    –    serial.h,serial.c...組込み関連の関数追加
    –    main.c...シリアル受信割込みによる動作変更
    –    Makefile
割込みハンドラの問題
●   0x000000~0x0000ffが割り込みベクタの位置な
    のでフラッシュROMに割込みハンドラのアドレ
    スを配置することになる
●   ブートローダの書き込み時に固定で決まってし
    まうため、OS側から自由に操作できない
●   H8はベクタ割込み方式なので、アドレスが固定
    されOS側で用意した割込みハンドラの登録が面
    倒
●   さらに、仮に全て固定で割込みハンドラのアド
    レス位置を割り当てるとなると、サイズも大き
    くなってしまう
OSの割込みハンドラを扱う方法
●   OSに設定したアドレスを見るようにするわけ
    –   ①汎用レジスタを退避させる処理する割込みハンド
        ラをブートローダ側で用意して、組込みベクタには
        そのハンドラのアドレスを設定
    –   ②RAMの先頭にOS側の割込みハンドラのアドレスを
        書く
    –   ②ブートローダ側の割込みハンドラはRAMの先頭に
        書かれているアドレスにジャンプ
●   これでOS側で自由に割込みハンドラを設定可能
●   割込みの種類に応じて複数の割込みハンドラを
    利用できるようにして、CPUが行う割込みベク
    タの処理をソフトウェア的に行うようにした
ソフトウェア・割込みベクタ
●   本書では「RAMの先頭領域に設定する複数の割
    込みハンドラアドレス」をソフトウェア・割込
    みベクタと呼ぶ
    –   本書定義の用語
●   たいしてROM上の本来の割込みベクタは単に
    「割り込みベクタ」、「CPUの割り込みベク
    タ」と呼ぶ
●   今回はソフトウェア割込み(内部割り込み)は、
    ソフトウェアエラー、システム・コール、シリ
    アル割込みの3種類を定義
割込みハンドラの入口と出口
              (intr.S)
 ●   アセンブリで実装
     –   PCとモード・レジスタは自動で退避、復旧(rte命
         令)が行われているので汎用レジスタだけ処理する
        .global   _intr_serintr
_intr_serintr:
        mov.l     er6, @-er7
        mov.l     er5, @-er7
        mov.l     er4, @-er7
        mov.l     er3, @-er7
        mov.l     er2, @-er7
        mov.l     er1, @-er7
        mov.l     er0, @-er7
        mov.l     er7, er1
        mov.w     #SOFTVEC_TYPE_SERINTR, r0
        jsr       @_interrupt
        mov.l     @er7+, er0
        mov.l     @er7+, er1
        mov.l     @er7+, er2
        mov.l     @er7+, er3
        mov.l     @er7+, er4
        mov.l     @er7+, er5
        mov.l     @er7+, er6
        rte
interrupt.h
●   割込みハンドラの型の定義
    –   typedef void (*softvec_handler_t)(softvec_type_t
        type, unsigned long sp);

●   インラインアセンブラ
    –   #define INTR_ENABLE   asm volatile ("andc.b #0x3f,
        ccr")
    –   #define INTR_DISABLE asm volatile ("orc.b #0xc0,
        ccr")
vector.c
●   割込みの種類別に自動でそれぞれのハンドラが
    呼び出される
void (*vectors[])(void) = {
    start, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    intr_syscall, intr_softerr, intr_softerr, intr_softerr,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    intr_serintr, intr_serintr, intr_serintr, intr_serintr,
    intr_serintr, intr_serintr, intr_serintr, intr_serintr,
    intr_serintr, intr_serintr, intr_serintr, intr_serintr,
};
OSのmain.c
●   割込みハンドラの登録とシリアル受信割込みの
    有効化
●   intrはmain.cで定義している割込みハンドラ
    –   echoの後に続く文字を返すだけのやつ

    softvec_setintr(SOFTVEC_TYPE_SERINTR, intr);
    serial_intr_recv_enable(SERIAL_DEFAULT_DEVICE);
8.プログラムの実行
プログラムの実行
/Users/sandai/12step/src/07/os% sudo cu -l /dev/tty.usbserial-FTG6PQ4H
Connected.
kzload (kozos boot loader) started.
kzload> load
~+lsx kozos
Sending kozos, 15 blocks: Give your local XMODEM receive command now.
Bytes Sent:   2048   BPS:293

Transfer complete

XMODEM receive succeeded!
kzload> run
starting from entry point: ffc020
kozos boot succeed!
> echo test
 test
9.まとめ
まとめ
●   OSってのは割込みをきっかけに動作するもん
    で、こういう処理を割り込みドリブン、割込み
    駆動などと言う
    –   また、イベント・ドリブンやイベント駆動なども呼
        ばれることもある
●   とりあえず、割込みベクタの位置が決まってる
    から、そこに割込みハンドラ置いて、そのハン
    ドラからOSで用意したハンドラを実行すりゃい
    いわって話でした
●   今回は出てこなかったけど、タイマ割り込みと
    かないんかな

【学習メモ#7th】12ステップで作る組込みOS自作入門

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
    割込み ● CPUは割込みを受け付けると、現在処理中のプ ログラムの実行を中断し、特定の処理に実行を 移す ● この割込み発生時に実行される処理を割込みハ ンドラと呼ぶ – コールバックとも言われる – 割込みを受け付けることを割込みのハンドリングな どとも言う ● 割込みハンドラの処理が終わると中断していた 処理に実行を移す
  • 6.
    割込み処理の要点 ● 割込み発生時に実行させたい処理を割込みハン ドラとしてあらかじめ登録しておく ● 割込みが発生した際には、現在実行中の処理を 中断し登録しておいた割込みハンドラが実行さ れる ● 割込みハンドラの実行後に中断してた本来の処 理に戻る
  • 7.
  • 8.
    割込みの種類 ● 割込みの種類は大きく分けて3つある – 外部割込み(ハードウェア割込み) – 例外 – 内部割込み(ソフトウェア割込み) ● これらの分け方はCPUによって違う – 例外と内部割込みを同じ「内部割り込み」として表 現するケースもある
  • 9.
    割込み要因の例 ● 割込みを起こす原因となる現象を割込み要因と 言う。割込み要因には様々な種類がある ● 割込み要因の例 – タイマ・コントローラに設定した時刻が満了した...タイマ割込み – シリアルから文字を受信した...シリアル受信割込み – リセット・ボタンがおされた...リセット割込み – ゼロ除算が行われた...ゼロ除算例外 – 不正なアドレスにアクセスした...不正アドレス・アクセス例外 – システム・コール命令が実行された...システム・コール割込み – トラップ命令が実行された...トラップ割込み
  • 10.
    外部割込み(ハードウェア割込み) ● 周辺I/Oに割込み要因が発生して、割込み線が アサートされることで発生する割込み – アサートされたら割込みの処理に入る ● アサートとは割込み入力ピンに、各種コント ローラから割込みの出力信号が送られたことを 検出すること – 「キックされる」とも言う
  • 11.
    CPUが出力信号を受ける仕組み ● CPUには割込み受け付けのピン(割込み入力ピ ン)がある ● このピンは各種コントローラが持つ出力線とい うピンから送られてくる割込み信号を受け付け るもの – IRQ(Interrupt ReQuest:割り込み要求)という名前 がついている事が多い ● コントローラが信号を出力する方法ピンに電圧 をかけるかどうかで行う
  • 12.
    正論理と負論理 ● 割込み出力線のピンの電圧がゼロの状態をLow レベル、電圧がかかった状態をHighレベルと言 う ● 割込み出力線がLowからHighに変化したとき、 コントローラが割込み出力線に信号を出力した ことになる ● また、普段はHighで割込み発生時にLowに変化 する回路もある ● 前者を正論理、後者を負論理と呼ぶ – 実際の割込み線は負論理が多い – 負論理はIRQやIRQ#と表現される
  • 13.
    ポーリング ● シリアル・ドライバのserial.cによってSCIの SSRレジスタのRDRFビットをwhileループで見張 り文字の受信を検知している – ビジーループで受信データが来るまで待っている ● この場合、たとえば受信待ちしながら他の処理 も同時に行う場合、別の処理を行いながら定期 的にSSRレジスタのRDRFビットの状態をチェッ クする処理が必要となる ● このように定期的に状態をチェックする処理を ポーリングと言う
  • 14.
    シリアル受信割込み ● ポーリングは良い手段ではない – 文字を受信した瞬間にチェックして処理するわけで はないので、反応が遅いから ● ポーリングの改善策として割込みを利用する ● シリアルからの文字受信時の処理を割込みハン ドラに登録しておけば、別の処理を行いながら 文字を受信したときにその処理を行うことがで きる ● このような割込みをシリアル受信割込みと呼ぶ
  • 15.
    シリアル送信割込み ● シリアル送信の場合、送信可能かどうかの判断 をSCIのSSRレジスタのTDREビットを見ている – これもビジーループで行なっている ● これも割込みで処理できる。送信処理が完了し たら割込みによって通知してもらい、割込みハ ンドラの名かで次に送信すべき文字の送信処理 を行う形にすれば良い ● このような割込みをシリアル送信割込みと呼ぶ
  • 16.
    割込みはコントローラで備えている ● シリアル接続における送受信の割込みはコント ローラ側で発生し、CPUがそれを検知する ● 通信用コントローラの多くはこのような割込み 機能を備えている – LANコントローラも同じ ● コントローラから割込みが発生したとき用に割 込みハンドラを登録しておけば、ポーリングの ようにチェックする必要がない
  • 17.
    CPU資源 ● 割込みはCPU資源の有効活用という点でもメ リットがある ● CPU資源とはCPUの処理時間のことで、CPUが実 行できる一定時間内の命令数は決まっている – よって、CPUが実行できる命令数は有限の資源と言 える
  • 18.
    内部割込み(ソフトウェア割込み) ● 内部割込みとはCPU内部での不正発生などに よって起きる割込み – 不正アドレス・アクセスやゼロ除算、アラインメン ト違反など ● また、プログラム側でわざと発生させた割込み もある – システム・コール命令、トラップ命令など ● 実はシステム・コール割込みがトラップ割込みに含まれ ており、トラップ割込みによってシステム・コールを実 現するCPUもある(H8はこれ) ● 不正アドレス・アクセスやゼロ除算など不正な 処理は「例外」と呼ぶ場合が多い
  • 19.
  • 20.
    外部割込み入力ピン ● 外部割込みの受け付けにはCPUの入力ピンが必 要 ● CPUによってはピンを複数持っている ● この場合コントローラごとの割込みにそれぞれ 割込みハンドラを登録することができる
  • 21.
    割込み入力ピンが1本の場合 ● CPUによっては割込み入力ピンが1つしかない ● その場合、各コントローラの割込み出力線をOR 論理で集約して接続させる 233頁 図7.3 複数の割込みをOR論理でまとめる より
  • 22.
    OR論理での割込みハンドラ ● OR論理でまとめた場合割込みハンドラは1つし か登録できない ● CPUからはタイマ割込みかシリアル割込みか判 断できないので、割込みハンドラ内でコント ローラのレジスタを参照して割込みが発生した かどうか調べて処理を行う – このような処理を「ハンドラ内部で割込み要因を調 べる」と言う ● 割込みハンドラのプログラミングは、本来なら 回路図を読んで各コントローラの割込み出力線 がどのように接続されているか確認してから行 う必要がある
  • 23.
    コントローラの数が多い場合 ● 割込み入力よりもコントローラが多い場合、ひ とつの割込み入力にまとめる ● この場合割込みコントローラというICを利用す る 235頁 図7.4 割込みコントローラを利用する より
  • 24.
    割込みコントローラ ● 複数の割込みをOR論理で結合し、さらに、各割 込みの有効/無効化(割込みをCPUに通知するか しないか)や割込み優先度の制御が行える ● 割込みコントローラの制御は保持している制御 用のレジスタによって行う ● 割込みコントローラを利用するメリット – 割込みの有効/無効が制御できる(割込みマスク) – 割込みコントローラのレジスタを見ることで、どの コントローラから割込みが発生したか分かる ● 割込みコントローラを利用することで、統一的 な制御が可能となる – 各コントローラのレジスタの確認を割込みコント ローラだけで行えるから
  • 25.
  • 26.
    組込み発生時の基本動作 ● CPUにおける組込み発生時の動作は2つに大別で きる – ①特定のアドレスにジャンプ – ②特定のアドレスからジャンプ先のアドレスを読み 込んで、そこにジャンプ ● ジャンプ先にある割込み処理を割込みハンドラ と呼ぶ – ISR(Interrupt Service Routine:割込みサービス ルーチン)と呼ばれることもある
  • 27.
    ①特定のアドレスにジャンプ ● 割込み発生時に特定のアドレスに配置しておい た割込みハンドラが勝手に実行される、といっ たもの ● 特定のアドレスには決まった数の命令しか記述 できないので自由なハンドラを置くことができ ない?っぽい ● ので、だいたい②の方法が採用される
  • 28.
    ②特定のアドレスからジャンプ先の アドレスを読み込んで... ● 適当な場所に割込みハンドラを配置して、その ハンドラを配置したアドレスを特定のアドレス に書いておくというもの ● いくつかある割込みハンドラのアドレス位置を 配列でまとめたものを割込みベクタと呼ぶ – この方法をベクタ割込み方式と言う – 割込みベクタはベクタ・テーブルなどとも言う ● H8はベクタ割込み方式 – ハンドラの登録方法はvector.sと、ld.scrを読めば 分かる – つまり、割り込みベクタに割込みハンドラのアドレ スを書き込むってだけ
  • 29.
  • 30.
    割込み復帰命令 ● 多くのCPUには割込み復帰命令がある。これは 割込み発生時に退避しておいた情報の復帰を行 うためのもの – 割込みは現在の処理を中断して割込みハンドラを実 行するわけだけど、割込みが発生する直前のデータ (レジスタの値)を中断していたときから始められる ように退避させている – というわけで、割込み復帰命令は割込みハンドラの 最後に実行される ● ここで問題になることは – どこに退避するのか? – 退避が必要な情報は何か?
  • 31.
    どこに退避するのか? ● CPU次第だが、大きく分けると2通り – スタック – 退避先の専用のレジスタ ● レジスタの退避はx86系だとアセンブリの命令 で簡単に行えたはず – 具体的にどこに退避していたかは覚えてないけど、 あまり気にすることじゃないと思う
  • 32.
    何を退避するか? ● 多くのCPUでは以下の2つの値を退避させる – プログラム・カウンタ(PC) – モード・レジスタ(コントロールレジスタとも呼ぶ) ● どちらも割り込み発生時にCPUが自動的に退避 して保存している – どこなのか具体的な場所は分からないが
  • 33.
    プログラム・カウンタ(PC)の退避 ● 割込みハンドラへのジャンプとはPCの強制的な 書き換え – 割込みハンドラにジャンプした時点でPCの値は割込 みハンドラのアドレスになっている ● 割込みハンドラにジャンプする前にPCを退避さ せておくことで、割込みハンドラの処理が終了 したときに元のアドレス位置の処理に戻れるよ うにしている
  • 34.
    モード・レジスタの退避 ● モード・レジスタは汎用レジスタとは違いCPU の動作モードを保存する役割の決まったレジス タ ● 動作モードには次のようなものがある – 割込み禁止 – 特権モードとユーザモード – メモリ保護の有効/無効の切替え – 仮想メモリによるアドレス変換の有効/無効の切替 え
  • 35.
    割込み発生時のモード・レジスタ ● 割込み発生時はモード・レジスタの設定が自動 的に割込み無効になり、それから割込みハンド ラにジャンプする – 割込みハンドラの先頭で別の割込みを受け付けたと きにPCの保存先の値が書き換わって元の処理に戻れ なくなるから – 割込みのネスト、多重割込みなどと呼ばれる ● CPUに特権モード割込みモードがあるなら割込 みハンドラは特権モードで動作する必要がある ● 割込み発生時にモード・レジスタを退避させて おくことで、割込みハンドラが終了したときに 元の状態に戻れるようにしている
  • 36.
    アトミック ● PCとモード・レジスタの保存処理はアトミック である必要がある – アトミックは「分割してはいけない」という意味 ● 分割して処理したときに処理の不整合が発生し てしまうような場合は、2つの処理を1命令で行 えるような命令をCPUは持っている – このような命令をアトミック命令と呼ぶ ● 割込み発生時にPCとモード・レジスタの値を退 避させ、割込みハンドラの末尾にある割込み復 帰命令でその2つの値を同時に復旧させる – 退避も復旧の処理もアトミックでなければならない
  • 37.
    汎用レジスタの退避 ● PCとモード・レジスタ以外に、プログラム中で 利用しているであろう汎用レジスタやフラグ・ レジスタなどの値も割り込み発生時に保存して おく必要がある ● これらはCPUの回路が複雑になるので自動で退 避されることはない ● つまり、何もしないままだと割込み復帰命令だ けでは元の処理に戻れない ● そこで割込みハンドラの最初と最後で保存と復 旧の処理を行う必要がある – 最初を割込みハンドラの入口、最後を割込みハンド ラの出口と呼ぶ
  • 38.
    割込みハンドラの入口と出口 ● 割込みハンドラの入口で行う処理 – 汎用レジスタの値をどこかに保存 – その他プログラム中で利用しているレジスタ(フラ グ・レジスタなど)も保存 ● 割込みハンドラの出口で行う処理 – 汎用レジスタの値を保存先から復旧 – その他プログラム中で利用しているレジスタの値も 復旧 ● 割込みハンドラをC言語で記述した場合はこの ような処理が必須となる – C言語のプログラムをコンパイラがアセンブラに変 換する際に汎用レジスタを利用するから
  • 39.
    保存・復旧するレジスタ ● 全ての汎用レジスタを保存する必要はなく、割 込みハンドラ内部で利用する(値が書き換わる) レジスタのみが保存対象となる – が、まあ、x86系は確か1つの命令で全て退避できる ようになっていたのでそれでいいんじゃないかな ● 処理の内容を把握しておけば退避するレジスタ の数を最小限に抑えることができるが、よくわ からないうちは割込みハンドラでは全ての汎用 レジスタを保存・復旧するよう実装すれば問題 ない
  • 40.
    割込みのクリア ● コントローラは割込み発生時にアサートし続け る – コントローラは割込み出力をフリップ・フロップと して実装し、状態を維持している ● アサートされたままだと、割込み復帰命令直後 に割込み禁止が解除されることで再度割込みが かかってしまう(割込みが無限ループで発生) – これを割込み要因のクリアし忘れと呼ぶ ● そういった状態を回避するため、コントローラ の割込み関連レジスタを操作して割込みが発生 したことを示すフラグを落とす必要がある – これを割込みのクリアと呼ぶ
  • 41.
    割込み処理のまとめ ● CPUがPCとモード・レジスタは自動で保存・復 旧がなされる ● 汎用レジスタやフラグレジスタは自力で保存・ 復旧する必要がある – 割込みハンドラの処理を軽くしたいなら退避させる レジスタを選ぶ必要があるが、よくわからないうち は全て退避させれば問題ない ● 割込みによって受信したデータなど参照した後 は割込みのクリアを行う – クリアしないと割込みの無限ループが起きるため – なぜ無限ループが起きるかについては243pを読めば わかるんで、ここでは記述しない ● 以上が一般的なCPUにおける割込みの話
  • 42.
  • 43.
    H8/3069Fの割り込みベクタ ● 主要な割り込みベクタ 244頁 表7.1 H8/2069Fの割り込みベクタ(主要なもの) より
  • 44.
    H8/3069Fの割り込みベクタの仕組み ● H8はベクタ割込み方式なので、割込みが発生し たら割り込みベクタを参照し、設定された割込 みハンドラにジャンプする ● 割り込みベクタの位置は0x000000~0x0000ffの 256バイトで、1つの割込みベクタは4バイト – 64個登録できるってことかな ● 他の割り込みベクタについてはマニュアル参照
  • 45.
    リセット(0x000000) ● リセット・ベクタのことで、電源ON時に実行す る割込み – 具体的にはCPUのリセット割込み(RES)がLowから Highになったときにリセット割込みが発生 ● リセット・ボタンを押すとLowレベルになり、 話すとHighレベルになる ● ここらへんの回路図の仕組みは245pと、マニュ アル参照
  • 46.
    トラップ命令(0x000020~0x00002c) ● ソフトウェア割込みの一種で、割込みを明示的 に発生させるもの ● H8だとオペラントの値によって4種類の割込み が発生する – なお、H8にはシステム・コールの割込みがないの で、トラップ命令で実装する
  • 47.
    外部割込み(0x000030~0x000044) ● 外部割り込みの入力ピン(IRQ0~IRQ5)がアサー トされたときに発生する割込み ● 周辺I/Oの割込みはここで検知する ● RXI0,RXI1,OXI2が受信完了、TXI0,TXI1,TXI2が 送信データエンプティと呼ばれ、それぞれ SCI0,SCI1,SCI2のシリアルの受信/送信完了の 割込みにあたる ● H8ではシリアルコネクタに接続されているのは SCI1なんで、本書ではRXI1とTXI1だけ利用して いる
  • 48.
    H8/3069Fのモード・レジスタ ● H8はモード・レジスタはコンディションコード レジスタ(CCR)という1バイトのレジスタを持つ ● 一般的なCPUのモード・レジスタは様々なモー ド設定が可能だが、H8は単純なCPUなのでCCRの 役割は「割込みの有効/無効」フラグしかもっ ていない – CCRで設定できるのは組込みマスクのみ ● CCRの他のビットはオーバーフロー・フラグ、 キャリ・フラグなどのフラグ情報 – 一般的にこれらの情報はフラグ・レジスタに集めら れるものだが、H8では全てCCRにまとめられている
  • 49.
    H8/3069Fのレジスタの退避 ● H8のPCとCCRの退避先はスタック・ポインタで あるER7の指すメモリ上に自動的に保存される – というかER7の位置。ここにPCが入る – CCRが1バイト、PCが3バイトで積まれる ● 詳しいスタックへの保存動作については247pと H8/3069Fのマニュアルを参照
  • 50.
    割り込みコントローラ ● H8/3069Fにも割り込みコントローラが内蔵され ている、本書では特に利用しない – 割り込みコントローラはこのスライドでも扱ったけ ど、割込みの優先順位や有効/無効などの制御を各 コントローラ全てに対して統一的に制御できるやつ ● CPUでは割り込みコントローラを内蔵している ものが多く存在する
  • 51.
    H8の割り込み禁止と復帰命令 ● 割込み禁止はCCRの最上位ビットを1にすること で割込みが無効になる – 割込み禁止、割込みがマスクされると呼ぶ – 多重割込みしないようにできるってことだね ● 割込みの復帰命令はrteという命令を使う – rteを実行するとスタックからPCとCCRを復旧される
  • 52.
    H8の割り込み発生時の動作 ● ①スタック(スタック・ポインタの指す先)上 に、PCとCCRの値を保存 ● その後割⑧込み要因に応じて割込みベクタを参 照し、割込みハンドラにジャンプ(PCに割り込 みベクタの値を代入する) ● 割込みハンドラが実行 ● 割込みハンドラ終了時に割込み復帰命令を呼ぶ (PCとCCRが復旧され中断していた箇所から実行 が再開される)
  • 53.
  • 54.
    これからの割込み処理 ● 今まではビジーループを使ってコントローラの レジスタを監視しながら処理していたけれど、 ここからはシリアル受信割込みを利用したもの に変更していく ● それから割り込みベクタの設定を柔軟に行える ように「ソフトウェア・割り込みベクタ」とい うものを実装する
  • 55.
    プログラムの追加 ● ブートローダ – intr.h,intr.c...割込み処理の入口と出口 – interrupt.h,interrupt.c...ソフトウェア・割込み ベクタの処理 ● OS – intr.h – interrupt.h,interrupt.c
  • 56.
    プログラムの修正 ● ブートローダ – ld.scr...ソフトウェア・割り込みベクタを追加 – vector.c...ソフトウェア・割込みベクタを設定 – main.c...ソフトウェア・割り込みベクタの初期化 追加 – Makefile ● OS – ld.scr...ソフトウェア・割込みベクタを追加 – serial.h,serial.c...組込み関連の関数追加 – main.c...シリアル受信割込みによる動作変更 – Makefile
  • 57.
    割込みハンドラの問題 ● 0x000000~0x0000ffが割り込みベクタの位置な のでフラッシュROMに割込みハンドラのアドレ スを配置することになる ● ブートローダの書き込み時に固定で決まってし まうため、OS側から自由に操作できない ● H8はベクタ割込み方式なので、アドレスが固定 されOS側で用意した割込みハンドラの登録が面 倒 ● さらに、仮に全て固定で割込みハンドラのアド レス位置を割り当てるとなると、サイズも大き くなってしまう
  • 58.
    OSの割込みハンドラを扱う方法 ● OSに設定したアドレスを見るようにするわけ – ①汎用レジスタを退避させる処理する割込みハンド ラをブートローダ側で用意して、組込みベクタには そのハンドラのアドレスを設定 – ②RAMの先頭にOS側の割込みハンドラのアドレスを 書く – ②ブートローダ側の割込みハンドラはRAMの先頭に 書かれているアドレスにジャンプ ● これでOS側で自由に割込みハンドラを設定可能 ● 割込みの種類に応じて複数の割込みハンドラを 利用できるようにして、CPUが行う割込みベク タの処理をソフトウェア的に行うようにした
  • 59.
    ソフトウェア・割込みベクタ ● 本書では「RAMの先頭領域に設定する複数の割 込みハンドラアドレス」をソフトウェア・割込 みベクタと呼ぶ – 本書定義の用語 ● たいしてROM上の本来の割込みベクタは単に 「割り込みベクタ」、「CPUの割り込みベク タ」と呼ぶ ● 今回はソフトウェア割込み(内部割り込み)は、 ソフトウェアエラー、システム・コール、シリ アル割込みの3種類を定義
  • 60.
    割込みハンドラの入口と出口 (intr.S) ● アセンブリで実装 – PCとモード・レジスタは自動で退避、復旧(rte命 令)が行われているので汎用レジスタだけ処理する .global _intr_serintr _intr_serintr: mov.l er6, @-er7 mov.l er5, @-er7 mov.l er4, @-er7 mov.l er3, @-er7 mov.l er2, @-er7 mov.l er1, @-er7 mov.l er0, @-er7 mov.l er7, er1 mov.w #SOFTVEC_TYPE_SERINTR, r0 jsr @_interrupt mov.l @er7+, er0 mov.l @er7+, er1 mov.l @er7+, er2 mov.l @er7+, er3 mov.l @er7+, er4 mov.l @er7+, er5 mov.l @er7+, er6 rte
  • 61.
    interrupt.h ● 割込みハンドラの型の定義 – typedef void (*softvec_handler_t)(softvec_type_t type, unsigned long sp); ● インラインアセンブラ – #define INTR_ENABLE asm volatile ("andc.b #0x3f, ccr") – #define INTR_DISABLE asm volatile ("orc.b #0xc0, ccr")
  • 62.
    vector.c ● 割込みの種類別に自動でそれぞれのハンドラが 呼び出される void (*vectors[])(void) = { start, NULL, NULL, NULL, NULL, NULL, NULL, NULL, intr_syscall, intr_softerr, intr_softerr, intr_softerr, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, intr_serintr, intr_serintr, intr_serintr, intr_serintr, intr_serintr, intr_serintr, intr_serintr, intr_serintr, intr_serintr, intr_serintr, intr_serintr, intr_serintr, };
  • 63.
    OSのmain.c ● 割込みハンドラの登録とシリアル受信割込みの 有効化 ● intrはmain.cで定義している割込みハンドラ – echoの後に続く文字を返すだけのやつ softvec_setintr(SOFTVEC_TYPE_SERINTR, intr); serial_intr_recv_enable(SERIAL_DEFAULT_DEVICE);
  • 64.
  • 65.
    プログラムの実行 /Users/sandai/12step/src/07/os% sudo cu-l /dev/tty.usbserial-FTG6PQ4H Connected. kzload (kozos boot loader) started. kzload> load ~+lsx kozos Sending kozos, 15 blocks: Give your local XMODEM receive command now. Bytes Sent: 2048 BPS:293 Transfer complete XMODEM receive succeeded! kzload> run starting from entry point: ffc020 kozos boot succeed! > echo test test
  • 66.
  • 67.
    まとめ ● OSってのは割込みをきっかけに動作するもん で、こういう処理を割り込みドリブン、割込み 駆動などと言う – また、イベント・ドリブンやイベント駆動なども呼 ばれることもある ● とりあえず、割込みベクタの位置が決まってる から、そこに割込みハンドラ置いて、そのハン ドラからOSで用意したハンドラを実行すりゃい いわって話でした ● 今回は出てこなかったけど、タイマ割り込みと かないんかな