Mini210S 開発キット詳細URL
第XV章S5PV210中断システム
第一節 S5PV210中断システム構造
S5PV210中断コントローラは4のベクタ中断コントローラ(VIC)、ARM PrimeCell PL192 と 4つのTrustZone Interrupt Controller (TZIC)で構成されます。
S5PV210 93個の中断ソースをサポートし、次の章ではその一を使用して、説明します。
第二節 プラグラム説明
完全なコードは、ディレクトリ15.intご参照ください。
1. start.S
手順は4つあります,中に ステップ2、4は中断機能で:
ステップ 1 bssをクリアします;
ステップ 2 中断を開き、 CPSR レジスタを設置,中断を有効にします,
コードは:
mov r0、 #0x53
msr CPSR_cxsf、 r0
ステップ 3 mainにジャンプ;
ステップ 4 中断処理;プログラムが正常に作動すると、実行すると、プログラムがステップ 3まで実行し直接メインにジャンプします、当部分のコードは実行しません。中断が発生する場合では、当部分のコードにジャンプし、中断実行します。
2. main.c
手順は4つあります,中に ステップ2、3、4 は中断機能で:
ステップ 1 シリアルポート初期化;
ステップ 2 中断機能初期化, system_initexception()呼び出し;
コードは:
void system_initexception( void)
{
// 中断ベクタテーブル
pExceptionUNDEF = (unsigned long)exceptionundef;
pExceptionSWI = (unsigned long)exceptionswi;
pExceptionPABORT = (unsigned long)exceptionpabort;
pExceptionDABORT = (unsigned long)exceptiondabort;
pExceptionIRQ = (unsigned long)IRQ_handle;
pExceptionFIQ = (unsigned long)IRQ_handle;
// 中断コントローラを初期化
intc_init();
}
上記のコードの主要機能は2つです:
ステップ 1 中断ベクタテーブルを設定
各例外、異常が発生した場合、PCが自動的に対応の例外ベクタにジャンプします。S5PV210の例外ベクタの開始アドレスは0xD0037400で、原因は下図のように:
IRQ中断例外が発生したときには、対応する処理関数はIRQ_handle()、すなわちstart.Sのステップ 4コードので、コードは:
IRQ_handle:
// 中断モード•スタックを設定
ldr sp、 =0xD0037F80
// シーンを保存
sub lr、 lr、 #4
stmfd sp!、 {r0-r12、 lr}
// 中断ハンドラ関数にジャンプ
bl irq_handler
// サイト復旧
ldmfd sp!、 {r0-r12、 PC}^
IRQ中断例外が発生したときに 、プログラムは中断ベクタテーブルの設定に従って、コードの部分にジャンプして、中断モード•スタックを設定する、シーンを保存し、最後中断ハンドラ関数irq_handler()を呼び出し、処理完了後サイト復旧します。irq_handler()方法については、次で説明します。
ステップ 2 中断コントローラを初期化
関数 intc_init()を呼び出し、コードは:
void intc_init(void)
{
// すべての中断を禁止する
VIC0INTENCLEAR = 0xffffffff;
VIC1INTENCLEAR = 0xffffffff;
VIC2INTENCLEAR = 0xffffffff;
VIC3INTENCLEAR = 0xffffffff;
// 中断タイプをIRQに選択
VIC0INTSELECT = 0x0;
VIC1INTSELECT = 0x0;
VIC2INTSELECT = 0x0;
VIC3INTSELECT = 0x0;
// VICxADDRをクリア
intc_clearvectaddr();
}
先ずはすべての中断を無効にしてから、中断タイプをIRQを選択し、最後にレジスタVICxARRD VICxADDrをクリアします。VICxADDrには発生した中断のハンドラ関数を保存します。相関のレジスタは:
ステップ 3 外部中断レジスタ設定
コード:
// 1111 = EXT_INT[16]
GPH2CON |= 0xF;
// 010 = Falling edge triggered
EXT_INT_2_CON |= 1<<1;
// unmasked
EXT_INT_2_MASK &= ~(1<<0);
先ず GPH2_0ピンを中断機能に設定し、次に外部中断EINT16_31を立ち下がりエッジトリガします;
最後に中断を中止しません;
ステップ 4 VIC 相関レジスタ設定
コード:
// 中断 EINT16_31 ハンドラ関数コンフィグ
intc_setvectaddr(NUM_EINT16_31、 isr_key);
// 中断 EINT16_31をonにする
intc_enable(NUM_EINT16_31);
ここでは2つ関数を使用します:
1) intc_setvectaddr()
機能はレジスタ VICVECTADDRのコンフィグ 、各中断ハンドラ関数の保存です。ここの外部中断EINT16_31のハンドラ関数は isr_key()。
関数 irq_handler()、コード:
void irq_handler(void)
{
unsigned long vicaddr[4] = {VIC0ADDR、VIC1ADDR、VIC2ADDR、VIC3ADDR};
int i=0;
void (*isr)(void);
for(; i<4; i++)
{
if(intc_getvicirqstatus(i) != 0)
{
isr = vicaddr[i];
break;
}
}
(*isr)();
}
中断発生な場合、ハードウェアげ現在の中断ハンドラ関数をレジスタVICVECTADDRからレジスタVICDDRにコピーします、irq_handler()関数でレジスタVICDDRのハンドラ関数を呼び出せます。
再来看看外部中断 EINT16_31 的处理関数 isr_key(),代码如下:
void isr_key(void)
{
printf("we get company\r\n");
beep();
// clear VIC0ADDR
intc_clearvectaddr();
// clear pending bit
EXT_INT_2_PEND |= 1<<0;
}
先ず"we get company"をプリントアウトし、ブザーが1回鳴き、最後に然后蜂鸣器会响一下,最后是清 VIC 相関レジスタ VIC0ADDRと外部中断レジスタEXT_INT_2_PENDをクリアします。
2) intc_enable()
VIC でレジスタVICINTENABLEを設定し、外部中断 EINT16_31をonにします。
ステップ 5 無限ループ
数字 1、2、3、4…,をプリントアウトして、外部中断 EINT16_31 を待ちます。
第三節 コードコンパイルとプログラミングの実行
コードをコンパイルし、Fedora端末で下記のコマンドを実行します:
# cd 15.int
# make
15.intのディレクトリ下にint.binを生成し、それを開発ボードにプログラムします。
第四節 実験現象
先ずは数字 1、2、3、4...、をプリントアウトし続き、 KEY1 を押すと外部中断 EINT16_31 は発生し、IRQ_handlerにジャンプします。最後にirq_handler()と中断ハンドラ関数isr_key()を呼び出します。当関数は先ず゜we get company:EINT16_31゜をプリントアウトします、そして中断をクリアします。テスト結果は次のとおりです:
---続く