約 604,265 件
https://w.atwiki.jp/kumikomi-yitjc/pages/40.html
何事も、やれば良いってものではない。ものには順番というものがある。 ...というわけで、割り込みにも順序というものがある。これまでも説明したように、H8/3052Fには、割り込みイベントを発生する複数のハードウエアがある。それぞれのハートウエアが「同時に割り込みイベントを発生する」などということも、世の中には有りえるのだが、CPUは同時には1つの処理しか実行できない。 この様な場合はどうするか..... 「面倒なので、無視する」 と言うのも一案である。 (冗談に聞こえるかもしれないが、本当である。その程度の緊急性しかない処理なら、放っておくというのは、正しい設計と言える。) しかし、世の中、そう簡単には行かない。「それぞれ」に「それぞれ」の事情があって、「それぞれ」は、その事情を満たしてほしいと願うものだ。(念仏の様であるが) では、どうするか。 同時に発生した割り込みは、発生したイベント毎に順位付け すれば良さそうである。ただし、順位付けが固定化すると、問題が生じる(場合がある)。例えば、 有名人のかすり傷と、瀕死のパンピーが119番した時に、有名人が優先されたのでは、たまったものではない... ※パンピー:一般people = 一般の人 のである。 この場合の優先順位(プライオリティ)は、有名/無名の差ではなく、症状の程度で左右されるべきである。従って、常にパンピーが優先されるわけでも無い。状況によって変化するということである。 この様な問題に対応するため、H8シリーズのCPUには、場合によって、割り込みの優先順位を切り替える機構が備わっている。 具体的には、 インタラプト・プライオリティ・レジスタ(IPRA、IPRB) を設定する。 事で、実現できる。 具体的には、 IPRAのビットを1に設定すると、そのビットに対応する割り込みイベントが優先されるようになる。 [IPRAのビットの定義] 割り込みイベントは沢山あるのでIPRAだけでは表現できないので、足りない分はIPRBを使っている。 [IPRBのビットの定義] 実際のプログラミングでは、以下のようになる。 #include monitor.h #define PB_DDR (*(volatile unsigned char *)0xFFFFD4) #define PB_DR (*(volatile unsigned char *)0xFFFFD6) #define PA_DDR (*(volatile unsigned char *)0xFFFFD1) #define PA_DR (*(volatile unsigned char *)0xFFFFD3) #define ISCR (*(volatile unsigned char *)0xFFFFF4) #define IER (*(volatile unsigned char *)0xFFFFF5) #define ISR (*(volatile unsigned char *)0xFFFFF6) #define IPRA (*(volatile unsigned char *)0xFFFFF8) #define IPRB (*(volatile unsigned char *)0xFFFFF9) #pragma interrupt(irq0_handler) // 以下に続く関数が、割り込みハンドラで // ある事を示す。 void irq0_handler() // 割り込みハンドラの定義 { static int cnt = 0; printf( irq0=%d\n , cnt++); } #pragma interrupt(irq1_handler) // 以下に続く関数が、割り込みハンドラで // ある事を示す。 void irq1_handler() // 割り込みハンドラの定義 { static int cnt = 0; printf( irq1=%d\n , cnt++); } int main() { long int w; PB_DDR = 0xFF; set_imask_ccr(1); // 全ての割り込みを不許可 IER |= 0x3; // IRQ0,1を有効にする。(CNX551の3,4ピン) ISCR = 0x3; // IRQ0,1をエッジトリガにする。 set_imask_ccr(0); // 全ての割り込みを許可 IPRA |= 0x80; // IRQ0 優先 while(1) { // 無限ループ printf( . ); } } 割り込みのマスク(有効化/無効化) また、H8を含む、ほとんど全てのCPUには、割り込みの発生自体を抑止する(これを割り込みマスクと呼ぶ)仕掛けも備わっている。例えば、 有名人がかすり傷を負った。(有名人) 119番に電話して救急車を呼ぼうとした。(有名人) 症状を聞いたら、かすり傷なので、「我慢しろ」と返事した。(消防署) この様な事例があった事を、ノートに記録した。(消防署) この例では、1,2は割り込みイベントの発生であるが、3で割り込みがマスクされ、割り込みハンドラ(救急車の出動)は抑止された。 しかし、事実そのものは、何らかの形で記録しておくことも必要なので、この様な処理を行った。(4の処理) 割り込みのマスクについては、複数の割り込みを一括してマスク(もしくはマスク解除)したい場合は、 CCRのIおよびUIビットを設定する。ただし、UIビットの動作条件は、CCRのUEビットの設定で変化する。 ※ set_imask_ccr()関数により行う。 であり、個別の割り込みマスクを制御したい場合は、各ハードウエアごとのレジスタを設定する。外部割り込み(IRQx)の例では、 IERの当該ビットを設定 である。 また、「4の記録する」という動作についても、、各ハードウエアごとに状態がレジスタに保存される。外部割り込み(IRQx)の例では、 ISRの当該ビットに、割り込み発生の有無が記録される。 ことになる。 ISRの各ビットの定義は、以下のようになっている。 bit 7 6 5 4 3 2 1 0 割り込みイベントが発生したIRQ - - IRQ5F IRQ4F IRQ3F IRQ2F IRQ1F IRQ0F 初期値 0 0 0 0 0 0 各ビットは、IRQ信号線による、割り込みイベントの発生によって1にセットされる。また、割り込みハンドラの呼び出しによって0にクリアされる。 IERの設定によって、割り込みハンドラがマスクされている状態で、割り込みイベントが発生した場合は、該当するビットは1にセットされたままで、プログラムによってクリアする必要がある場合もある。(でないと、割り込みマスクを解除した瞬間に、保留されていた割り込みイベントに該当する割り込みハンドラが起動されるため。) 具体的には、以下のようにする。 ISR = ~0x1; // IRQ0の割り込みイベントをクリア とする。 マスク不可能な割り込み(NMI) 話が前後するが、世の中には緊急事態と言う事もあって、どんな事があっても処理しなければならないということもある。 マイコンの世界では、この様な割り込みを、 NMI (Non Mascable Interrupt) ~ マスク不可能な割り込み と呼んでいる。 なお、言うまでも無いが、割り込みをマスクする = 割り込み禁止 であり、 割り込みマスクの解除=割り込み許可 である。 割り込み周辺回路のブロック図
https://w.atwiki.jp/hikipuro/pages/74.html
4000208h - IME - 16bit - 割り込みマスタ有効 (R/W) GBAと同じ使い方です。 4000210h - IE - 32bit - 割り込み有効 (R/W) 4000214h - IF - 32bit - 割り込み発生フラグ (R/W) ビット 説明 0~6 GBAと同じ 7 ARM7 のみ SIO/RCNT/RTC (Real Time Clock) 8~ GBAと同じ 16 IPC 同期 17 IPC 送信 FIFO Empty 18 IPC 受取 FIFO Not Empty 19 ゲームカード Data Transfer Completion 20 ゲームカード IREQ_MC 21 ARM9 のみ Geometry Command FIFO 22 ARM7 のみ Screens unfolding 23 ARM7 のみ SPI bus 24 ARM7 のみ Wifi 25~31 未使用 IE/IF flag bits (ARM9) bitPurposeSee also 31..22000000Cannot be set 21UnknownCan be written 20DS Card (IRQ pin)DS Card Port 19DS Card (controller)Card Registers 18UnknownCan be written 17UnknownCan be written 16UnknownCan be written 15..1400Cannot be set 13GBA Cart IRQ pinGBA Cartridge Port 12KeysKey Input 11DMA 3DMA 10DMA 2DMA 9DMA 1DMA 8DMA 0DMA 70Cannot be set 6Timer 3Timers 5Timer 2Timers 4Timer 1Timers 3Timer 0Timers 2Y-EqualsVideo 1H-BlankVideo 0V-BlankVideo ARM7 24Wireless hardwareMain? 23SPI completedSPI 22Hinge close magnetKeyInput 20DS Card (IRQ pin)DS Card Port 19DS Card (controller)Card Registers 13GBA Cart IRQ pinGBA Cartridge Port 12KeysKey Input 11DMA 3DMA 10DMA 2DMA 9DMA 1DMA 8DMA 0DMA 6Timer 3Timers 5Timer 2Timers 4Timer 1Timers 3Timer 0Timers 2Y-EqualsVideo 1H-BlankVideo 0V-BlankVideo IE 0x04000210 32 IF 0x04000214 32 IME 0x04000208 32 (8/16/32 accesses work, but only the LSB has any meaning, all others read 0, and ignore writes)
https://w.atwiki.jp/kumikomi-yitjc/pages/26.html
割り込みと聞いて、何を思い浮かべるか.... (1) サービスエリアでお手洗いの行列を無視する、おばちゃんとか... (2) コンビニのレジで、やっぱり順番を守らない、怖いおじさんとか... などであろうか。 いずれも、それまでの順番を無視して、自分の仕事を先行して処理させる事であり、コンピュータでは、この様な処理を「割り込み」(interrupt)という。 もう少し別の言い方をすると、 (1) 通常処理があって、順番に実行中に、 (2) 何らかの出来事(イベントと言う)が発生し、 (3) イベントに対応するため、通常処理を中断して、割り込みハンドラを起動し、こちらを実行する。 (4) 割り込みハンドラが終了したら、中断していていた通常処理を再開する。 という流れで処理が行われる。 割り込みの要因となるイベントには、キーボード、マウスの入力とか、待ち状態に入っていたハードウエアからの応答、タイマなどがある。 以上を図にすると、以下のようになる。 なお、割り込みと良く似た動作(用語と言った方が正確かもしれない)に「例外」と言うのがある。例外には、「ソフトウエア例外」、「ハードウエア例外」があるが、 ・「ソフトウエア例外」は、トラップ命令という特別な命令(一般的には、アセンブラで記述する)を使って、割り込みハンドラを呼び出す処理 ・「ハードウエア例外」は、イベントの発生によって割り込みハンドラを呼び出す処理(=割り込み) となる。「例外」と「割り込み」の用語の使いかたは、CPUによって若干の差があるが、「例外」は、「割り込み」を包含する概念として使われる事が多い。なお、「例外」は英語でexception(イクセプション)と表現する。 実際の動作 C言語で書かれたプログラムでは、割り込みの動作はイマイチ見え難い(そんなことないって?)。割り込みの動作は機械語(=アセンブラレベル)で行われているので、細かい事を言い出すと、アセンブラの知識がないと歯が立たない。そんなこと言っても、煙に巻かれるばかりなので、おおざっぱに動作を俯瞰すると、 通常の処理が動作している最中に、 割り込みイベントが発生すると、その割り込みを受け付けてよいか判断(割り込みを禁止する事を、割り込みをマスクすると言う)し、 現在実行中の命令のアドレス(プログラムカウンタと言うレジスタの値)とCCRレジスタを、スタックに記憶(これを、スタックに積むと言う)し、 割り込みベクタテーブルから、該当する割り込みハンドラのアドレスを読み取って、プログラムカウンタ(PC)に、その値を設定する.... これで、処理が割り込みハンドラに移る。 割り込みハンドラの処理が終了する時に、rte命令(割り込みハンドラからのリターン)を実行する。すると、3でスタックに積んだ、CCRとPCの値を取ってきて、それぞれのレジスタに設定する。(これで処理が1の通常の処理に戻る) と言うことになる。 AVRマイコンとC言語を用いたプログラミングの実際については、こちら。 H8マイコンとC言語を用いたプログラミングの実際については、こちら。 使用上の注意 割り込み処理を設計する際の注意事項として、割り込みイベントの発生頻度と、割り込みハンドラの処理時間の関係に留意する必要がある。例えば、 ①イベント発生の間隔 割り込みハンドラの処理時間 であれば、何の問題もないが、 ②イベント発生の間隔 ≧ 割り込みハンドラの処理時間 だったり、 ③イベント発生の間隔 割り込みハンドラの処理時間 だったりすると、不可解なバグに悩まされることになる。③の場合、割り込みハンドラの処理が終わらないうちに、次の割り込みが発生してしまうので、おかしなことになるのは自明である(あえて、この様に設計する場合もあり得るが)。②は一見すると、問題なさそうではあるが、割り込みハンドラの処理によっては、危険が生じる可能性がある(機械語レベルで実行時間=マシンサイクル.. を計算するスキルがあれば、別であるが、普通は、そんな面倒なことはやってられない)ので、慎重に設計する必要がある。 イベント発生の間隔 ≦ 割り込みハンドラの処理時間 については、言わずもがなである。
https://w.atwiki.jp/vvvvvvvvvvvvv/pages/34.html
《割(わ)り込(こ)み隊長(たいちょう)》 チューナー(効果モンスター) 星3/地属性/戦士族/攻1200/守 400 効果モンスターの効果が発動した時、 このカードは手札から特殊召喚する事ができる。 赤イカ白タコ寓話集で登場した地属性・戦士族の下級モンスターのチューナー。 (コメント募集中!) 関連カード 《切り込み隊長》 初出記事等 赤イカ白タコ寓話集 e76288(091220)-02 メモ欄 百合の間に割り込み隊長を洗脳─ブレインコントロール─
https://w.atwiki.jp/2messer14/pages/19.html
ゲートってなに?
https://w.atwiki.jp/kumikomi-yitjc/pages/127.html
AVRマイコンにはタイマ、AD変換、その他の複数の割り込みが存在する。ここでは、割り込みの基本的な動作・プログラミング手順と、外部割り込みへの適用について説明する。 AVRマイコン(他のマイコンでもほぼ同様であるが)での、割り込み処理の流れは、 ※ SERGはステータスレジスタ。 Iビットを操作する事で割り込み全体を禁止/許可する。 Iビットを1にする場合は sei() 0にする場合は cli() を実行する事 の様になる。 具体的には、タイマや外部割り込み信号線から割り込み信号が与えられると、 SREGレジスタのIビットをチェックして、内容が1にセットされていて、 個別の割り込みマスクが設定されていなければ、 CPUは割り込みを受け付け、 ベクタテーブルから割り込みハンドラのアドレスを参照し、 割り込みハンドラにジャンプする。【注意】 割り込みハンドラ内では、デフォルトでSREG I=0となっているため、他の割り込みは禁止される。 割り込みハンドラがリターンする時にSREG I=1となる。(多重割り込みの禁止) のように動作する。 AVRマイコンには、 5本の外部割り込み(INT0~3、INT6) INT0:4ピン、 INT1:5ピン、 INT2:6ピン、 INT3:7ピン、 INT6:30ピン 8本のピン変化割り込み(PCINT0~7) PCINT0:22ピン、 PCINT1:23ピン、 PCINT2:24ピン、 PCINT3:25ピン PCINT4:26ピン、 PCINT5:27ピン、 PCINT6:28ピン、 PCINT7:29ピン の外部割り込み信号線がある。いずれも他の機能と共用されているので、設定で割り当てを変える必要がある。外部割り込みとピン変化割り込みの違いは、割り込みイベントの発生条件の違いによる。(レベルトリガ、エッジトリガについては、こちら)外部割り込みでは、以下の様に、割り込みイベントの発生条件を4つの中から選択できるが、ピン変化割り込みでは信号レベルの変化(1→0とか)の1種類となる。 外部割り込み信号線による割り込みのプログラミングの手順 具体的なプログラミングの手順は以下の通りである。 割り込みハンドラの定義 割り込みイベントの発生条件を設定 割り込みマスクの設定 全ての割り込みを許可 以下、順に説明する。1.割り込みハンドラの定義 割り込みハンドラは、割り込み発生時に呼び出される関数の一種と考えればよい。 割り込みハンドラの名前(関数名)は、割り込み毎に事前に定義されていて、イベント名+_vectとなっている。(gccの場合) 従って、INT0の割り込みハンドラは、 INT0_vect となる。Cのソースで、割り込みハンドラを記述するには、 ISR(INT0_vect) // INT0_vectをベクタと呼ぶ { // 実行したい内容 } のように、記述する事。なお、イベント名と割り込みの対応は、下表「表:ベクタテーブル」を参照のこと。割り込みハンドラ実行中は、割り込み禁止状態になっている。割り込みハンドラも割り込まれる多重割り込みを使用したいなら、ハンドラ内でsei()を呼ぶ必要がある。2.割り込みイベントの発生条件を設定 以下の表から、各外部割り込み毎に、割り込みイベントの発生条件を選択する。 レベルトリガ、エッジトリガについては、こちらを参照表:外部割り込み(INT0~INT3、INT6)の割り込みイベント発生条件 ISCn1 ISCn0 機能 トリガ種別 0 0 INTピンのLレベルで割り込み レベルトリガ 0 1 INTピンの論理変化で割り込み エッジトリガ 1 0 INTピンの立ち下がりで割り込み エッジトリガ 1 1 INTピンの立ち上がりで割り込み エッジトリガ ※ISCn1などのnは外部割り込みの名前(INT0なら0)を表す。 具体的には、以下の通り、EICRAレジスタ及びEICRBレジスタの該当ビットに対して上の表の内容で、設定を行う。表:EICRAレジスタのビット配置 bitの位置 (ビットの名前) 7 (ISC31) 6 (ISC30) 5 (ISC21) 4 (ISC20) 3 (ISC11) 2 (ISC10) 1 (ISC01) 0 (ISC00) 機能 INT3のイベント発生条件 INT2のイベント発生条件 INT1のイベント発生条件 INT0のイベント発生条件 初期値 0 0 0 0 0 0 0 0 表:EICRBレジスタのビット配置 bitの位置 (ビットの名前) 7 (未使用) 6 (未使用) 5 (ISC61) 4 (ISC60) 3 (未使用) 2 (未使用) 1 (未使用) 0 (未使用) 機能 INT6のイベント発生条件 初期値 0 0 0 0 0 0 0 0 従って、INT2の割り込みイベント発生条件を、エッジトリガ(立ち下がり)としたいなら、 bitの位置 (ビットの名前) 7 (ISC31) 6 (ISC30) 5 (ISC21) 4 (ISC20) 3 (ISC11) 2 (ISC10) 1 (ISC01) 0 (ISC00) 機能 INT3のイベント発生条件 INT2のイベント発生条件 INT1のイベント発生条件 INT0のイベント発生条件 設定値 0 0 1 0 0 0 0 0 EICRA = 0x20; // INT2の割り込みイベント発生条件を、立ち下がりエッジに設定 以下のような簡潔な記述方法もあるが、ビット演算を学ぶため16進表記で記述する。 EICRA = _BV(ISC21); とする。3.割り込みマスクの設定 EIMSKレジスタの該当ビットを操作する事で、割り込みをマスク(禁止)、あるいは許可する事が出来る。表:EIMSKレジスタのビット配置 bitの位置 (ビットの名前) 7 (-) 6 (INT6) 5 (-) 4 (-) 3 (INT3) 2 (INT2) 1 (INT1) 0 (INT0) 機能 - 1:INT6割り込みを許可 0:INT6割り込みを禁止 - - 1:INT3割り込みを許可 0:INT3割り込みを禁止 1:INT2割り込みを許可 0:INT2割り込みを禁止 1:INT1割り込みを許可 0:INT1割り込みを禁止 1:INT0割り込みを許可 0:INT0割り込みを禁止 初期値 0 0 0 0 0 0 0 0 従って、INT6割り込みを許可したいなら、 bitの位置 (ビットの名前) 7 (-) 6 (INT6) 5 (-) 4 (-) 3 (INT3) 2 (INT2) 1 (INT1) 0 (INT0) 機能 - 1:INT6割り込みを許可 0:INT6割り込みを禁止 - - 1:INT3割り込みを許可 0:INT3割り込みを禁止 1:INT2割り込みを許可 0:INT2割り込みを禁止 1:INT1割り込みを許可 0:INT1割り込みを禁止 1:INT0割り込みを許可 0:INT0割り込みを禁止 設定値 0 0 0 0 0 0 0 0 EIMSK |= 0x40; // Enable INT6(割り込みを許可) 以下のような簡潔な記述方法もあるが、ビット演算を学ぶため16進表記で記述する。 EIMSK |= _BV(INT6); のように記述する。4.全ての割り込みを許可 3.の割り込みマスクの設定では、個別に割り込みの許可・禁止を切り替えていたが、これに加えて以下の様に、sei()関数とcli()関数を用いてSREGレジスタのIビットを設定する事で、割り込みの許可・禁止を切り替える。 sei(); // 設定済みの、全割り込みを許可(SREG I = 1) cli(); // 全ての割り込みを禁止(SREG I = 0) サンプルプログラム ...... /* * INTx 割り込みハンドラ * 割り込み発生時は、PC7を3回点滅させる。 */ //INTx 割り込みのベクタテーブルを指定 ISR(INT0_vect) // ピン割り込み(INT0 4ピン) //ISR(INT1_vect) //ピン割り込み(INT1 5ピン) //ISR(INT2_vect) //ピン割り込み(INT2 6ピン) //ISR(INT3_vect) //ピン割り込み(INT3 7ピン) //ISR(INT6_vect) //ピン割り込み(INT6 30ピン) { int i; for (i=0; i 3; i++) { PORTC = 0x80; // PC7(オンボードLED)をON _delay_ms(100); PORTC = 0x00; // PC7(オンボードLED)をOFF _delay_ms(100); } } int main() { CLKPR = 0x80; CLKPR = 0; // 16MHz動作のための設定 MCUCR = ~(1 PUD); // プルアップを有効にする /* ■外部割り込み(INT0~INT3)のマスクを設定する。各ビットが0の時、割り込みはマスク(禁止)される。(EIMSKレジスタ) 使用可能な外部割り込みは、INT0~INT3、INT6 */ EIMSK |= 0x01; // Enable INT0(割り込みマスクを解除) // EIMSK |= 0x02; // Enable INT1(割り込みマスクを解除) // EIMSK |= 0x04; // Enable INT2(割り込みマスクを解除) // EIMSK |= 0x08; // Enable INT3(割り込みマスクを解除) // EIMSK |= 0x40; // Enable INT6(割り込みマスクを解除) /* ■割り込みイベントの発生条件を選択する。(EICRAレジスタはINT0~INT3、EICRBレジスタはINT6) ISC?1 ISC?0 0 0 レベルトリガ(low active) 0 1 エッジトリガ(両エッジ) 1 0 エッジトリガ(立ち下がり) 1 1 エッジトリガ(立ち上がり) [EICRAレジスタ] 7(ISC31) 6(ISC30) 5(ISC21) 4(ISC20) 3(ISC11) 2(ISC10) 1(ISC01) 0(ISC00) INT3の発生条件 INT2の発生条件 INT1の発生条件 INT0の発生条件 [EICRBレジスタ] 7(未使用) 6(未使用) 5(ISC61) 4(ISC60) 3(未使用) 2(未使用) 1(未使用) 0(未使用) INT6の発生条件 */ EICRA |= 0x03; // INT0のトリガ選択(立ち上がりエッジで割り込み発生) // EICRA |= 0x0C; // INT1のトリガ選択(立ち上がりエッジで割り込み発生) // EICRB |= 0x30; // INT6のトリガ選択(立ち上がりエッジで割り込み発生) DDRC = 0x80; // PortCのbit7を出力に。ボード上のLEDへの出力 DDRD = 0x00; // PortDを入力に(INT0を使う場合) PORTD = 0x01; // PD0をプルアップ(INT0を使う場合) // DDRE = 0x00; // PortEを入力に(INT6を使う場合) // PORTE = 0x40; // PE6をプルアップ(INT6を使う場合) sei(); // 全割り込みを許可 while(1) { } } その他 割り込みが禁止(=マスク)された状態で割り込みイベントが発生すると、割り込みハンドラは呼び出されない。ただし割り込みイベントの発生は、EIFRレジスタに記録される。 また、EIFRレジスタに記録された割り込みイベントは、割り込みがsei()によって許可されるか、もしくはEIMSKレジスタにより割り込みが許可されると同時に処理(つまり割り込みハンドラの呼び出し)される。 割り込みが禁止された状態で、EIFRレジスタの割り込みイベントをクリアする事も出来る。(割り込みが許可されても、割り込みハンドラの呼び出しは行われなくなる) 表:EIFRレジスタのビット配置 bitの位置 (ビットの名前) 7 (-) 6 (INTF6) 5 (-) 4 (-) 3 (INTF3) 2 (INTF2) 1 (INTF1) 0 (INTF0) 機能 - INT6割込イベント発生:1 割込ハンドラ呼出:0 ※1、※2 - - INT3割込イベント発生:1 割込ハンドラ呼出:0 ※1、※2 INT2割込イベント発生:1 割込ハンドラ呼出:0 ※1、※2 INT1割込イベント発生:1 割込ハンドラ呼出:0 ※1、※2 INT0割込イベント発生:1 割込ハンドラ呼出:0 ※1、※2 初期値 0 0 0 0 0 0 0 0 ※1ビットに1を書くと、0に解除可能※2レベルトリガを選択すると、常に0 【注意】 EIFRレジスタは、割り込みイベントの有無を記録し、 該当するビットが1で、かつ、割り込みが許可されている場合は、割り込みハンドラを呼び出し、ビットは0にリセット 該当するビットが1で、かつ、割り込みが禁止されている場合は、割り込みハンドラは呼び出されず、ビットは1のまま。 該当ビットが1の状態で、割り込み禁止状態から、割り込み許可状態に移行すると、割り込みハンドラが呼び出される。 EIFRの各ビットはソフトウエアで書き換え可能。(従って、このビットの制御によって、ソフトウエアで割り込みハンドラを 呼び出したり、呼び出しをキャンセルすることが出来る。 のように使用することが出来る。 ピン変化割り込みのプログラミング手順 作成中... 多重割り込み 割り込みハンドラを実行中に、別の割り込みイベントが発生するとどうなるか.... 考えてみよう。予想される解答は、 割り込みイベントは無視される。 割り込みイベントは保留される。 実行中の割り込みハンドラが、別の割り込みハンドラに割り込まれる。 もう、訳分かんない。 その他 などであろうか。4と5は答えになって無いので無視するとして、1、2、3について考えてみる。 まず、1の「割り込みイベントは無視される。」であるが、割り込みイベントが無視されると、 時計が狂ったり 音が鳴らなかったり LEDが光らなかったり など、割り込みが関係する他の処理が動かない事になる。(あるいは正常に動作しない可能性が高い) これだと、色々、問題なので、実際には割り込みイベントが無視するという事は、一般には行わない。 (無視するようにプログラミングする事は出来る。) 2の「割り込みイベントは保留される」については、あり得る話である。なぜなら、割り込みにも色々な種類があるわけで、優先順位の高い割り込みを優先するというのは、必要な機能と考えられる。優先順位の高い割り込みイベントが処理されている間は、その他は、おとなしく待っている(=保留)という事だ。 3については、2の延長線上の話で、「優先順位の低い割り込みが、優先順位の高い割り込みによって、処理を割り込まれる」 ということである。 ただし、優先順位が低い割り込みであったとしても、プログラムの処理の都合で、どうしても割り込まれたくないという事もある。 (こういう部分を、クリティカルゾーンという)そのような場合は、割り込みをマスクする事で、割り込みが発生しないような配慮を行う必要がある。(クリティカルゾーンは、可能な限り、少なくするべき) 多重割り込みのイメージは以下の様な感じ。 AVRマイコンでは、デフォルトでは多重割り込みは発生しない設定になっている。なぜなら、割り込みハンドラの呼び出し時に、SREGレジスタのIビットが0に設定(つまりcli()が実行されるってこと)なので、他の割り込みが禁止されるからだ。 多重割り込みを実現したいなら、割り込みハンドラ内で、sei()を実行する必要がある。 以下に一覧(ベクタテーブル)を示す。 表:ベクタテーブル No Program Addres Source (割込イベント) Interrupt Definition(割り込みの詳細) 1 $0000 RESET External Pin, Power-on Reset, Brown-out Reset,Watchdog Reset, and JTAG AVR Reset (外部リセット入力、電源ONリセット、ウオッチドックリセット、JTAGリセット) 2 $0002 INT0 External Interrupt Request 0 (外部割り込み0:INT0ピン) 3 $0004 INT1 External Interrupt Request 1 (外部割り込み1:INT1ピン) 4 $0006 INT2 External Interrupt Request 2 (外部割り込み2:INT2ピン) 5 $0008 INT3 External Interrupt Request 3 (外部割り込み3:INT3ピン) 8 $000E INT6 External Interrupt Request 6 (外部割り込み4:INT6ピン) 10 $0012 PCINT0 Pin Change Interrupt Request 0 (ピン変化割り込み0:PCINT0) 11 $0014 USB General USB General Interrupt request (USB一般割り込み) 12 $0016 USB Endpoint USB Endpoint Interrupt request (USBエンドポイント割り込み) 13 $0018 WDT Watchdog Time-out Interrupt (ウオッチドック タイムアウト) 17 $0020 TIMER1 CAPT Timer/Counter1 Capture Event (タイマ/カウンタ1 キャプチャ) 18 $0022 TIMER1 COMPA Timer/Counter1 Compare Match A (タイマ/カウンタ1A 比較・一致) 19 $0024 TIMER1 COMPB Timer/Counter1 Compare Match B (タイマ/カウンタ1B 比較・一致) 20 $0026 TIMER1 COMPC Timer/Counter1 Compare Match C (タイマ/カウンタ1C 比較・一致) 21 $0028 TIMER1 OVF Timer/Counter1 Overflow (タイマ/カウンタ1 オーバフロー) 22 $002A TIMER0 COMPA Timer/Counter0 Compare Match A (タイマ/カウンタ0A 比較・一致) 23 $002C TIMER0 COMPB Timer/Counter0 Compare match B (タイマ/カウンタ0B 比較・一致) 24 $002E TIMER0 OVF Timer/Counter0 Overflow (タイマ/カウンタ0 オーバフロー) 25 $0030 SPI (STC) SPI Serial Transfer Complete (SPI 転送終了) 26 $0032 USART1 RX USART1 Rx Complete (USART1受信) 27 $0034 USART1 UDRE USART1 Data Register Empty (USART1データエンプティ) 28 $0036 USART1TX USART1 Tx Complete (USART1送信完了) 29 $0038 ANALOG COMP Analog Comparator (アナログ比較器) 30 $003A ADC ADC Conversion Complete (AD変換完了) 31 $003C EE READY EEPROM Ready (EEPROM操作可) 32 $003E TIMER3 CAPT Timer/Counter3 Capture Event (タイマ/カウンタ3 キャプチャ) 33 $0040 TIMER3 COMPA Timer/Counter3 Compare Match A (タイマ/カウンタ3A 比較・一致) 34 $0042 TIMER3 COMPB Timer/Counter3 Compare Match B (タイマ/カウンタ3B 比較・一致) 35 $0044 TIMER3 COMPC Timer/Counter3 Compare Match C (タイマ/カウンタ3C 比較・一致) 36 $0046 TIMER3 OVF Timer/Counter3 Overflow (タイマ/カウンタ3 オーバフロー) 37 $0048 TWI 2-wire Serial Interface (TWI) 38 $004A SPM READY Store Program Memory Ready (SPM操作可) 39 $004C TIMER4 COMPA Timer/Counter4 Compare Match A (タイマ/カウンタ4A 比較・一致) 40 $004E TIMER4 COMPB Timer/Counter4 Compare Match B (タイマ/カウンタ4B 比較・一致) 41 $0050 TIMER4 COMPD Timer/Counter4 Compare Match D (タイマ/カウンタ4C 比較・一致) 42 $0052 TIMER4 OVF Timer/Counter4 Overflow (タイマ/カウンタ4 オーバフロー) 43 $0054 TIMER4 FPF Timer/Counter4 Fault Protection Interrupt (タイマ/カウンタ4 誤り保護)
https://w.atwiki.jp/stevefox/pages/6.html
技名 ガード ヒット アッパーフェイントレフトフック 9 × バーチカル 15 12
https://w.atwiki.jp/msx-sdcc/pages/42.html
C言語でコードを記述している際にCPUの割り込みを停止したい事がある。 割り込み機能を停止する際はCPU命令のDI/EIを使う。 sdccではインラインアセンブラが可能なので、割り込みを停止したいところでは DI/EIなどをインラインして部分的に割り込みを停止させる。 //INLINE __asm di __endasm; //....... //INLINE __asm ei __endasm; このインラインを用いる方法以外に、関数自体をクリティカル指定 する方法もある。 これらはsdccの拡張で、関数名に修飾子__CRITICALを追加する。 void function(void) __critical { //Interrupt critical section } クリティカル指定された関数は、関数の実行時には必ず割り込みが禁止され、 終了時に割り込みが許可される。 クリティカル指定された関数は、実行されるタイミングで必ず割り込みが停止するので、 割り込みを利用した擬似スレッド処理なども必ず停止する。 そうした意味ではスレッド間のロック問題を扱うクリティカルセクションに 似ている。 sdccではこの他に__interrupt修飾がある。 __interruptは__criticalと組で用いる。 void function(void) __critical __interrupt { //Interrupt INT38h code } もしこのような関数名のコードを作成すると、関数のスタート時に 割り込みを停止し、同時に、全レジスタをスタックへ自動的に退避する。 処理が終わるとレジスタのデータを元に戻し、割り込み処理を再開する。 この一連の機能は割り込みを前提とした関数を作成する場合に必要となるものだ。 割り込みの停止はインラインアセンブラで書いて代替することも可能だが、 sdccでは関数名を修飾することでより判りやすいCコードを記述する事が出来るようになっている。 割り込み処理は、通常アセンブラで書くことが多いが、 関数名に__critical __interruptを指定し、割り込みベクタージャンプテーブル を書き換えれば、C言語の関数で割り込み処理を記述することが可能だ。 下手にアセンブラで割り込み処理を書く必要は無い。 割り込みベクトルの変更と割り込み関数 割り込みベクトルをBIOS(DOS)から自作関数へ書き換える場合はメモリーの書き換えを行なう。 特定のメモリーアドレスを書き換える場合はポインタアクセスとなるだろう。 例えばINT38hを書き換える場合は、該当箇所はJP 0xxxxhとなり3byteなので アドレスだけ変更する場合はアドレスの0x39,0x40を書き換える。 割り込み処理関数をInterrputVector38h()であると仮定すると以下のようになる。 //ポインタ型を定義 unsigned int *vector; //INT38hをセット vector=(unsigned int *)0x0039; //関数へのポインタを渡す *vector=(unsigned int)InterruptVector38h; これでINT38hの割り込みベクターエントリアドレスがInterruptVecto38h() への関数へのポインタとなった。 これでシステムタイマーの1/60Secの割り込みは、BIOSを経由せず、 必ず自前の関数InterruptVector38h()が呼ばれる。 ここにシステムファームウエアルーチンの全てを組み込めばBIOSは必要ではない。 割り込み処理をアセンブラではなくCで書くことも出来る。 元に戻す際は、DOS動作時のINT38hオリジナルの値に書き戻す。 //INT38h RECOVER *vector=(unsigned int)0xDD97;
https://w.atwiki.jp/msx-sdcc/pages/41.html
割り込みとはCPUが実行中に外部信号を受けて、実行中のプログラムから 一時的に割り込み処理プログラムを実行すること。 Z80の割り込み処理には大きく分けて2レベルの機能がある。 一つはソフトウエア的に割り込み処理を変更可能なINTと、 割り込みレベルが最も優先されるNMIである。 NMIは例えば電源が低下した時などあらゆる処理に優先されるような イベントをキャッチする際に用いられる。 通常の割り込み処理にはINTを使う。 2レベルの割り込みに加えてZ80のINT割り込みモードはさらに3つある。 モード0と呼ばれる割り込みは8080互換で、8080用の割り込みコントローラ 接続を前提としている。 このモードは複数の割り込みレベルを持ち、複数の割り込み信号をキャッチ できる。 割り込みされた場合、ジャンプ先は自動的にRST0h~RST38hなどのアドレスにジャンプする。 モード1は割り込みコントローラを使わずにソフトウエアで処理が可能なモードだ。 このモードは割り込み信号はたった一つのINTを使い、 複数のデバイスからの割り込みをキャッチし処理する。 特別な割り込みコントローラを必要としないので低コストで 異なるデバイスを接続可能だ。 どのデバイスから割り込み信号がスローされたかの判定はソフトウエアが 各デバイスをチェックして行なう。 モード1の割り込みは必ずRST38hだけが呼ばれる。 モード2はZ80周辺LSI専用の割り込みモード。 Z80周辺LSIは他のデバイスと異なり、各種LSIに割り込み処理機能を持っている。 多くのCPUは割り込みコントローラLSIを介して、割り込みレベルを デバイス毎にキャッチするが、Z80ファミリー周辺LSIはそれ自身に 割り込み処理機能を持っているので、特別な割り込みコントローラを持たない。 NMI割り込みの際は必ず0x0066が呼ばれる。 MSXでは割り込みモード1を使用している。このモードではハードウエア 割り込みはソフトウエアによりイベントが発生したデバイスを判別し、 ソフトウエア処理を行なっている。 そのために割り込みを使うハードウエアは、割り込みのイベントをソフトウエアで キャッチしなければならず、ソフトウエアのアップデートが必要となる。 BIOSはROMに記録されているので、書き換えが困難だ。 (通常はMSXではシステムワークエリアに書き換え可能なジャンプテーブル があり、フックと呼ばれている領域を書き換えているようだ) 割り込みが発生すると、CPUは通常のプログラム実行をやめて 特定の番地にジャンプする。 このジャンプ先はメモリーアドレスの0x0-0xff間の割り込みベクターと呼ばれる領域にジャンプする。 この領域はさらに割り込み処理ルーチンへのジャンプ命令が置かれている。 このルーチンに割り込み時の処理が記述されている。 割り込みベクターは、ハードウエア的に割り込みが発生した時にコール されるジャンプテーブルだが、ソフトウエア的にもジャンプする事が可能だ。 ジャンプテーブルや割り込みに関係するアドレスはゼロページ(0x0の先頭) 付近に存在することが多い。 割り込みベクトルへのジャンプアは以下のような命令でも可能だ。 JP 038h しかし他にも似た命令が存在する。 RST 38h RST38hなどの命令は直接コードに書くわけではなく割り込みコントローラが 8bitのデータバスに出力する際に利用する。ジャンプ命令としては重複している。 ソフトウエア的なジャンプ命令は、デバック用途やDOSのファンクションコール として利用される。 前者のJP命令が3byteであるのに対し、RST38hは1byte命令なので短い。 短い命令は割り込み処理へのジャンプコストを小さくする事が可能だ。 またソフトウエア的な割り込みはファンクションコールなどOS機能を提供する際にもよく用いられる。 NMI NMI割り込みはCPUのNMI端子がLレベルタイミングで割り込みが発生する。 このアドレスはソフトウエアにより変更できない(マスク不可)。 アドレスは必ず0x0066がコールされる。(このアドレスは別名でゼロページと呼ばれる事もある) NMI割り込み発生時のリターンはRET命令ではなくRETN命令を使う。 (INT割り込みはソフトウエアマスカブル---ソフトウエア変更可能---な割り込み端子。INT割り込みはモード0,1,2がある。各モードの切替はアセンブラのIM0,IM1,IM2命令で行なう。) MODE 0 モード0は8080互換性のため8080割り込みコントローラを接続する。 割り込みは8種類あり、8段階レベルの割り込みをキャッチすることができる。 この割り込みモードは外部に接続された割り込みコントローラが8レベルの割り込みシグナルを キャッチし、そのイベントによりCPUのINT端子にシグナルを送信する。 モード0のときの割り込みコントローラはINT端子を有効化すると同時にデータバスに8レベルの 割り込みデータを同時に出力する。このデータをCPUが受け取って適切なアドレスにジャンプ するわけである。 このときの8レベルの割り込みジャンプ先アドレスは以下となる。 Interrupt Level Address 0 0x0000 1 0x0008 2 0x0010 3 0x0018 4 0x0020 5 0x0028 6 0x0030 7 0x0038 モード0で割り込みが生じると、データバスに割り込みコントローラからデータが出力されるが、 この時のデータは、直接CPU命令のRST命令。 割り込みコントローラはCPUのRST命令をデータバスに出力していることになる。 割り込み発生時CPUはこのアドレス(命令)をデータバスから取り込んで割り込みアドレスへジャンプする。 プログラムカウンタのスタックへの退避は、モード0ではRST命令の実行のタイミングで行なわれる。 モード1では割り込みステート内でプログラムカウンタの値がスタックへ退避される。 MOOE 1 モード1は特別な割り込みコントローラやハードウエアを用いずにソフトウエアで割り込みを制御 するモード。割り込み端子はINTだけを使い特別なハードウエアは必要ない。 モード1割り込みシグナルが発生すると、キャッチしたイベントの区別に関わらずCPUは必ずアドレス 0x0038へジャンプする。 ハードウエア的には全ての割り込みイベントはINT端子で信号をキャッチする。 割り込みデバイスの判定と処理はソフトウエアによって判定し処理する。 モード1は割り込みレベルの詳細な設定はなく、ソフトウエアによって幾つもの割り込みレベルやイベントを 設定する事も可能。 ソフトウエアで割り込み処理を行なう場合は、割り込みシグナル発生後に対応するデバイスの割り込みフラグが 有効か無効かをソフトウエアでチェックする。 プログラムカウンタの退避は割り込みステート内で行なわれる。 割り込み処理から復帰する場合はRETではなくRETI命令を用いる。 モード1と同じような設計は現代でも受け継がれており、よく知られているMicrochip社のPICなどはハードウエア 割り込みレベルは一段階のみというシンプルさで、割り込みレベル処理はソフトウエア処理によって実装する。 PICマイクロコントローラはMODE1のようなソフトウエア割り込みでイベントや複数のデバイスを処理する。 MODE 2 モード2は割り込みベクターテーブル方式と呼ばれるもので、Z80周辺ペリフェラルに対応するモード。 予め決められた割り込みベクターテーブルを用いてアドレスを参照し処理ルーチンへとジャンプする。 モード2の動作は、割り込みベクターであるCPUのIレジスタと、割り込み時に割り込みコントローラからデータバスに出力されるデータを使う。 割り込みには予め定められた割り込みベクタージャンプテーブルを参照する。 ベクターテーブルにはジャンプ先のアドレスが記録されており、 モード2の割り込み発生時に、割り込みシグナルがキャッチされると、このアドレステーブルを参照して プログラムカウンタにセットし、割り込み処理ルーチンへジャンプする。 割り込みベクターのベースアドレスはIレジスタを利用し、残りの1byteは外部割り込み コントローラから出力される。 割り込みシグナルの発生は割り込みコントローラなど特別にハードウエアが必要となる。 モード2の割り込みコントローラは、割り込み発生時にINT端子にシグナルを発生させ、 同時にイベントごとに決められたベクターテーブル下位アドレスをデータバスに出力すればよい。 これらを実装したLSIはZ80周辺ペリフェラルの割り込みコントローラである。 割り込みベクターは256byteのアドレス範囲にテーブルが記録されるので最大で128レベルの割り込みを サポートすることができる。この割り込みベクターテーブルはベースアドレスを用いる事で、 任意のアドレス位置にテーブルを配置することができる。 モード2では割り込みステート内でプログラムカウンタがスタックへ保存される。 割り込みの有効化、無効化と内部ロジック 割り込み有効無効の切替を行なう場合は、DI/EI命令を使う。 CPUリセット直後は割り込みは無効に設定されているので、初期化時に割り込みを有効にセット する必要がある。 また割り込み発生後割り込みモードがDisable状態で戻るかEnable状態で戻るか注意が必要。 CPU内部では割り込みレベル切替えは割り込み用フリップフロップ(IFF1,IFF2)でスイッチしている。 Z80の割り込み処理は、NMIとINTではNMIが優先される。この仕組みのためにCPU内部では IFF1,IFF2というフリップフロップを用いた割り込みステート順序の制御が行なわれている。 NMIは割り込みとして優先レベルが高いので、NMI期間中にINTが発生するような場合、 割り込みを停止することができる。 IFF1は割り込み状態を保持するメモリ、IFF2はIFF1のバックアップとなる。 NMIが発生すると内部的には割り込み状態フラグはIFF2はIFF1へバックアップされ、 IFF1は割り込み禁止となる。 割り込みシグナルが発生すると自動的に割り込み停止となるのでIFF1は禁止状態となる。 RETN命令が実行されると、IFF2がIFF1に復帰されリターンする。 NMIとINTではIFF1,IFF2の動作に違いがある。この差で割り込みレベルを処理する。 INTではIFF1,IFF2の状態は変化せず割り込み禁止となるので、IFF1,IFF2でNMIとINTの割り込みレベルの 区別や制御が可能となる。 割り込み期間中、この内部の割り込み状態を示すIFF2の値は、LD A,I/LD A,R命令実行後、 パリティフラグに反映される。 割り込み内部ステートを表現するIFF1,IFF2というフリップフロップの状態はプログラムからは 見えないが、LD A,I/LD A,Rという命令を実行することで、フリップフロップの内部状態を フラグに反映させることができる。 VSYNC割り込みとディスクドライブ MSXディスク装置は当初から規格化内に存在するハードウエアではなく各社が設計製造し規格化された という経緯があるので互換性という意味で問題がある。 特に割り込み処理の部分に問題がある。 タイマー割り込みは1/60ごとに発生するが、ディスクドライブを搭載している機種では、 割り込みフックと呼ばれるジャンプテーブルにディスク装置の割り込みが追加されている。 ディスク装置がない機種では、割り込み発生時のフックと呼ばれるジャンプテーブルは 空いている。 割り込みフック自体はユーザーが使う事を考慮した空のジャンプテーブルで、通常は単に RETやJPが書かれている。ユーザーは必要であればこのジャンプテーブルに割り込みイベント 処理を追加し独自のルーチンをコールする。 ディスクドライブはシステムROM(例えばメインBIOS)内で割り込み処理を行なっておらず、 ユーザーに開放された割り込みフックジャンプテーブルを利用している。 この割り込みを消去すると、ディスクドライブは動作するが、ディスクのメディア交換などが 検出されなくなる。 (最善の設計は追加されたディスク装置のために割り込み処理ルーチンをメインBIOSに記述する ことだが、ROMBIOSを厳密に互換性を維持しようとするとAPIアドレスに変更が生じる。ディスク装置は 外付けで規格化内になかったためか奇妙な拡張方法となっている。それらは特に割り込み処理に無理があるように思われた)
https://w.atwiki.jp/denkara/pages/34.html
割り込みでLED点滅 割り込みで点滅させるプログラム。 これまたポート2に信号を出力させる。LEDをポート2に配線しよう。 main.c void main(void) { CINIT; SYSTEM.SCKCR.BIT.ICK=0; /*コアクロック96MHz*/ SYSTEM.SCKCR.BIT.PCK=1; /*周辺機器クロック PCLK=48MHz*/ PORT2.DDR.BYTE=0xff; /* PORT2の全端子を出力に設定 */ PORT2.DR.BYTE=0x00; /* PORT2のon/offを一応クリア */ /*CMT コンペアマッチタイマ*/ SYSTEM.MSTPCRA.BIT.MSTPA15=0;/* モジュールストップ解除CMT0,CMT1 */ /*クロック選択 0 PCLK/8 1 PCLK/32 2 PCLK/128 3 PCLK/512*/ CMT1.CMCR.BIT.CKS=3; /* 48MHz/512=93.75KHz 1周期=10.67μsec */ CMT1.CMCOR=46875; /*周期設定 46875x10.67=0.5sec */ CMT1.CMCNT=0; /*カウンタリセット*/ IEN(CMT1,CMI1)=1; /*割り込み要求許可*/ IPR(CMT1,CMI1)=1; /*割り込み優先レベル*/ CMT1.CMCR.BIT.CMIE=1; /*割り込み許可*/ CMT.CMSTR0.BIT.STR1=1; /*割り込み開始*/ while(1); } intprg.c 69行目~ // CMT0 CMI1 void Excep_CMT0_CMI1(void)~ { PORT2.DR.BYTE=~PORT2.DR.BYTE; /* ポートから読んできて反転してポートに戻す */ } }