[Armadillo:05586] Armadillo-9 の割り込みのフリップフロップ

Yasuhisa Nakamura email@hidden
2010年 8月 6日 (金) 03:15:29 JST


MLの皆様、お世話になってます。
中村です。

Armadillo-9の割り込みについての質問(疑問)です。
ちょっと長いメールです。

ハードウェアマニュアルの最後に「PC/104の割り込みコントローラの仕組み」
という図解があります。

・ここに記載されているFFは、どのようなFFでしょうか?
・このFFは説明のとおりに動いているのでしょうか?

arch/arm/mach-ep93xx/irq.cにprintk()をいくつか挿入して挙動を
調べてみたのですが、どうも、説明通りには動いていないような
気がしてなりません。


調査は次のような方法で行いました。


■ハードウェア:
  ・Armadillo-9 単体
  ・PC/104バスのIRQ3(B25)とGND(B32)からリード線を引き出す。
  ・このリード線を短絡してIRQ3をLowに落とす。


■arch/arm/mach-ep93xx/irq.c に次のパッチ

--- irq.c-orig  2008-06-17 17:33:48.000000000 +0900
+++ irq.c       2010-08-06 02:02:44.000000000 +0900
@@ -134,25 +134,35 @@

 static void mask_irq_intisa3 (unsigned int irq)
 {
+       printk("mask_irq_intisa3: irq=%d\n", irq);
+       printk("mask_irq_intisa3: now:    MISCREG_INTSR3=0x%x\n", MISCREG_INTSR3 & 0xf);
        miscreg_intmr3 |= 1 << (irq - IRQ_ISA_BASE);
        MISCREG_INTMR3 = miscreg_intmr3;
+       printk("mask_irq_intisa3: masked: MISCREG_INTSR3=0x%x\n", MISCREG_INTSR3 & 0xf);
 }

 static void mask_ack_irq_intisa3 (unsigned int irq)
 {
        u8 mask;

+       printk("mask_ack_irq_intisa3: irq=%d\n", irq);
+       printk("mask_ack_irq_intisa3: now:     MISCREG_INTSR3=0x%x\n", MISCREG_INTSR3 &
0xf);
        mask = 1 << (irq - IRQ_ISA_BASE);
        miscreg_intmr3 |= mask;
        MISCREG_INTMR3 = miscreg_intmr3;
+       printk("mask_ack_irq_intisa3: masked:  MISCREG_INTSR3=0x%x\n", MISCREG_INTSR3 &
0xf);

        MISCREG_INTCR3 = mask;
+       printk("mask_ack_irq_intisa3: cleared: MISCREG_INTSR3=0x%x\n", MISCREG_INTSR3 &
0xf);
 }

 static void unmask_irq_intisa3 (unsigned int irq)
 {
+       printk("unmask_irq_intisa3: irq=%d\n", irq);
+       printk("unmask_irq_intisa3: now:      MISCREG_INTSR3=0x%x\n", MISCREG_INTSR3 &
0xf);
        miscreg_intmr3 &= ~(1 << (irq - IRQ_ISA_BASE));
        MISCREG_INTMR3 = miscreg_intmr3;
+       printk("unmask_irq_intisa3: unmasked: MISCREG_INTSR3=0x%x\n", MISCREG_INTSR3 &
0xf);
 }

 static struct irqaction irq_isa = {


■テスト用のドライバ
  [Armadillo:00993] のものを流用させていただきました。
  主要部分は次の通りです。

static irqreturn_t ep93xx_isa3_isr(int irq, void *dev_id, struct pt_regs *regs)
{
    printk("isa3_isr: irq=%d, dev_id=%s\n", irq, (char *)dev_id);
    printk("isa3_isr:  end\n");
    return IRQ_HANDLED;
}

int __init pc104port_init(void)
{
    int ret;

    printk("pc104port init:\n");
    ret = request_irq(IRQ_ISA3, ep93xx_isa3_isr, 0 /*SA_INTERRUPT*/, "isa3_isr", 0);
    printk("pc104port request_irq ret = %d\n", ret);
    printk("pc104port init: end\n");
    return 0;
}

void __exit pc104port_exit(void)
{
    free_irq(IRQ_ISA3,0);
}

module_init(pc104port_init);
module_exit(pc104port_exit);


■実行結果

insmodしたときのメッセージ

pc104port init:
unmask_irq_intisa3: irq=64
unmask_irq_intisa3: now:      MISCREG_INTSR3=0x0
unmask_irq_intisa3: unmasked: MISCREG_INTSR3=0x0
pc104port request_irq ret = 0
pc104port init: end


次にPC/104バスのIRQ3から引き出して、IRQ3をGNDに落としている
リード線を解放する(IRQ3=Highになる)と、割り込みが連続的に発生。

大量にメッセージがでますが、そのうちの一部(チャタリングが
なさそうなところ)は次のようになります。

....
....
mask_ack_irq_intisa3: irq=64
mask_ack_irq_intisa3: now:     MISCREG_INTSR3=0x1
mask_ack_irq_intisa3: masked:  MISCREG_INTSR3=0x0
mask_ack_irq_intisa3: cleared: MISCREG_INTSR3=0x0
isa3_isr: irq=64, dev_id=<NULL>
isa3_isr:  end
unmask_irq_intisa3: irq=64
unmask_irq_intisa3: now:      MISCREG_INTSR3=0x0
unmask_irq_intisa3: unmasked: MISCREG_INTSR3=0x1
mask_ack_irq_intisa3: irq=64
mask_ack_irq_intisa3: now:     MISCREG_INTSR3=0x1
mask_ack_irq_intisa3: masked:  MISCREG_INTSR3=0x0
mask_ack_irq_intisa3: cleared: MISCREG_INTSR3=0x0
isa3_isr: irq=64, dev_id=<NULL>
isa3_isr:  end
unmask_irq_intisa3: irq=64
unmask_irq_intisa3: now:      MISCREG_INTSR3=0x0
unmask_irq_intisa3: unmasked: MISCREG_INTSR3=0x1
mask_ack_irq_intisa3: irq=64
mask_ack_irq_intisa3: now:     MISCREG_INTSR3=0x1
mask_ack_irq_intisa3: masked:  MISCREG_INTSR3=0x0
mask_ack_irq_intisa3: cleared: MISCREG_INTSR3=0x0
isa3_isr: irq=64, dev_id=<NULL>
isa3_isr:  end
unmask_irq_intisa3: irq=64
unmask_irq_intisa3: now:      MISCREG_INTSR3=0x0
unmask_irq_intisa3: unmasked: MISCREG_INTSR3=0x1
....
....

何がおかしいか(気になっているか)というと、まず
割り込み要因が発生した直後の
  mask_ack_irq_intisa3: now:     MISCREG_INTSR3=0x1
  mask_ack_irq_intisa3: masked:  MISCREG_INTSR3=0x0
が「あれ?」なのです。

図では、ISRはFFそのもの(FFの出力?)で、IMRはISRの前にあります。
そうするとFFが値をラッチしているならば、IMRでFFの入力を
マスクしてもFFをクリアしていないのですから、ISRの値は変化
しないはずです。

ところが、上のようにマスクをかけただけでISRがクリアされてます。

mask_ack_irq_intisa3 の出口でFFをクリアしたときは
  mask_ack_irq_intisa3: cleared: MISCREG_INTSR3=0x0
まぁ、そのとおりでしょう。(これだけでは、FFのクリア機能が
正しく動いているかどうかは判断できませんが・・・)

で、その次のマスクの解除です。
unmask_irq_intisa3: now:      MISCREG_INTSR3=0x0
unmask_irq_intisa3: unmasked: MISCREG_INTSR3=0x1

PC/104バスの割り込み入力IRQ3(B25端子)はオープンのまま、つまり
HIGHレベルのままですが、マスクを解除するとISRが1になります。

ここでこのメール冒頭の質問になります。
このフリップフロップはどのようなフリップフロップなのでしょう?

割り込み入力のエッジを記憶して、割り込みをレベルトリガで
ハンドリングできるようにするためのものなのではないでしょうか?
そして割り込みが処理されたところでICRでFFをクリア、つまり
割り込み要因の解除です。
(エッジの検出と保持でないならば、ここにFFを入れる必要は
ないよう思います。マスクレジスタだけで十分。)


こちらの都合でちょっと古いカーネルソースを使っています。
linux-2.6.12.3-a9-14 です。
念のためこの arch/arm/mach-ep93xx/irq.c を 2.6.12.3-a9-17 の
ものと比較をしてみましたが、この部分の違いはないようです。


以上、よろしくお願いいたします。

-- 
なかむら




armadillo メーリングリストの案内