« PSoCのアナログref電圧 | メイン | 「テロとの戦い」 »
2007年11月07日
ARM7の割り込み
LPC2888とか、以前購入していたEZ-ARM7(LPC2214)の割り込みに関する調査。
けっこう複雑。http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/ などのサンプルを参考にする。(ちなみにオプティマイズのユーザ掲示板もあるようだ)
gcc向けのソースの書き方の手順は以下のとおり。
・VIC (Vectored Interrupt Controller)の設定
- VICIntSelect = 0x00; // すべての割り込みをとりあえずIRQとして使う
- VICIntEnable = 0x20; // 使いたい割り込みを許可(例えばTimer1なら、VIC Channelが#5なので、5ビット目を1(0x20)にする
- VICVectCntl0 = 0x25; // IRQ slotの0番目(優先度=最高)をEnableにして、割り当てるVIC Channelの番号(この例ではTimer1の5)を設定
- VICVectAddr0 = (unsigned long)Timer1_ISR; // IRQ slotの0番目の割り込み処理ルーチンのアドレス(関数名から逆算される)を設定
・割り込み処理ルーチンでするべきこと
- 割り込み関数自体を、IRQモードで実行する(つまり終わったらスーパーバイザ戻れ、ということか?)ため、__attribute__をつけて、次のように宣言する。
void __attribute__ ((interrupt("IRQ"))) Timer1_ISR(void)
- 割り込みフラグのクリア(Timer1なら、T1IR = 0x01;)
- VICVectAddr = 0xff; // VIC priority hardwareをクリアする、というおまじないらしい
・割り込みベクタの設定
IRQ割り込みがおこると、0x18番地にジャンプするので、ここに、以下の命令を書いておく。
---
LDR PC, [PC, #-0xff0]
---
これが0x18番地に書いてあるので、実行時のPCは0x20になっている(パイプライン処理の関係)。そのPCから0xff0をひいて0xffff f030番地の内容(実はVICVectAddrレジスタの内容)をPCにストア。VICVectAddrレジスタを読むと、いま起こった(中で優先度が最も高い)割り込みに対応するVICVectAddrx(x=0〜15)の値が読み出されるので、結果としていま起こった割り込みの処理ルーチンのアドレスがPCに入り、割り込み処理ルーチンへジャンプ。
・CPSR (Current Program Status Register)の設定
HRAさんのARM奮闘記からの情報で気づく。(よく読めば、アプリケーションノートAN10254のサンプルコードにもちゃんと書いてある。ちゃんと嫁>自分)
このレジスタで、FIQとIRQをそれぞれ許可・禁止を設定する(見落としがち)。CPSRは、アセンブラ命令を使わないといじれないので、以下のようなコードをスタートアップルーチン中に記述(あるいはasm()でもいいのか?いや、SPの初期化ができないからだめだな)。CPSRの7ビットめをクリアするとIRQが許可される(負論理)。ちなみにFIQは6ビット目をクリアすると許可。あわせて、スタックポインタ(SP)の初期化を、スーパーバイザモード、IRQモード(や、それ以外も使うならそれぞれ)に対して行う。(ARM7は、各モードで別々のSP(r13)を持っている)
----
ldr r3, ?? (__stack_end__などのアドレス) // スタック領域のお尻のアドレスをとりあえずr3に
msr cpsr_c, #0x13 // スーパーバイザモードに移行
mov sp, r3 // スーパーバイザモードのSPの設定(初期化)
sub r3, r3, #512 // 次に備えてSPを減らす(この512が、今のモードで使えるスタック領域のサイズ、ということになる)
mrs r0, cpsr // CPSRの値をr0に読み出し
bic r1, r0, #0x1f // まずはモード設定をクリア(bicは、即値で1のビットを0にする)
orr r1, r1, #0x12 // r1をIRQモードに移行するCPSRの値に設定
bic r1, r1, #0x80 // CPSRでIRQ割り込みを許可する値に設定
msr cpsr_c, r1 // r1をCPSRを(IRQモードに移行する)
mov sp, r3 // IRQモードのSPの設定(初期化)
msr cpsr_c, r0 // さっきのモード(スーパーバイザモード)に移行(戻る)
----
投稿者 akita : 2007年11月07日 09:27