デバイス ドライバーを QNX から Linux に移植しています。QNX では、古いドライバーは、真の割り込みハンドラーを登録するのではなく、無限ループを持つ pthread を使用して割り込みの発生を監視していました。専用のポーリング スレッドの代わりに register_irq() を使用することの有効性を実証するために、Linux で 2 つのドライバーを作成しました。それぞれに関連するコードを以下に示し、質問は下部にあります。
IRQ
ハンドラを書く
irqreturn_t timing_interrupt_handler(int irq, void *dev_id) {
u32 test;
/* read device interrupt command/status register */
test = ioread32(timing_card[3].base);
/* sanity check that the device reported the interrupt */
if ( test & (1 << 2) ) {
/* clear interrupt status */
iowrite32( 0x0d, timing_card[3].base);
/* toggle digital output line */
test = ioread32(timing_card[2].base);
if ( test & 0x01 )
iowrite32(test & ~0x1, timing_card[2].base);
else
iowrite32(test | 0x1, timing_card[2].base);
}
return IRQ_HANDLED;
}
ハンドラーを登録する
rc = request_irq(irq_line, timing_interrupt_handler,
IRQF_SHARED, "timing", timing_card);
if ( rc ) {
printk(KERN_ALERT "Failed to register irq %d\n", irq_line);
return rc;
}
ポーリングスレッド
スレッド関数を書く
int poll_irq(void *data) {
u32 test;
/* until module unload */
while ( !kthread_should_stop() ) {
/* read device interrupt command/status register */
test = ioread32(timing_card[3].base);
/* sanity check that the device reported the interrupt */
if ( test & (1 << 2) ) {
/* clear interrupt status */
iowrite32( 0x0d, timing_card[3].base);
/* toggle digital output line */
test = ioread32(timing_card[2].base);
if ( test & 0x01 )
iowrite32(test & ~0x1, timing_card[2].base);
else
iowrite32(test | 0x1, timing_card[2].base);
}
else
usleep_range(9, 11);
}
return 0;
}
スレッドを開始する
kthread = kthread_create(poll_irq, 0x0, "poll_IRQ_test");
wake_up_process(kthread);
質問
オシロスコープに 2 つのトレースを配置すると、1 つはカードのデジタル入力 (割り込みをトリガーする) を監視し、もう 1 つはカードのデジタル出力 (割り込みに反応する) を監視すると、イベントへの反応時間を測定できます。
最初の「適切な」方法である IRQ の登録には、約 80 マイクロ秒かかります。
無限スレッドを実行する 2 番目の方法では、約 15 ~ 30 マイクロ秒かかります。
何を与える?前者の利点は、処理能力をあまり消費しないことですが、なぜ応答時間がそれほど劇的に低下するのでしょうか? このポーリングスレッドを持つことは、実際にはどれほど悪いことでしょうか? ポーリング スレッドが CPU に与える余分な負荷を調査し、最終的に実証するにはどうすればよいでしょうか?
御時間ありがとうございます!
一番
スコット