Wei Dongshanuboot_kernel_rootファイルシステムスタディノート5.8-レッスン005_キャラクターデバイスドライバー_セクション008_キャラクターデバイスドライバーの割り込みモードのキードライバー_コードの記述

drv_open関数分析

ピンを外部トリガー割り込みソースとして構成します。
(1)ピンラベル-void * dev_id
(2)高感度エッジ-符号なし長いirqflags
(3)割り込みラベル-符号なしint irq;
(4)割り込みタイプ-irq_handler_tハンドラー
(5))デバイス名-constchar * devname
上記のパラメーターは、Linuxカーネルのrequest_irq関数によって設定されます

[1]request_irq関数呼び出し

request_irq(IRQ_EINT0,  buttons_irq, IRQT_BOTHEDGE, "S2", &pins_desc[0]);

[2]request_irq関数内部処理:setup_irq関数を呼び出して割り込みを初期化します。
その中で、
irq =(3)割り込みラベル-unsigned int irq = IRQ_EINT0アクション-
>ハンドラー=(4)割り込み発生後に呼び出される関数-irq_handler_tハンドラー=ボタン_irqアクション-
>フラグ=(2)センシティブエッジ-符号なし長いirqflags = IRQT_BOTHEDGE
action-> name =(5)デバイス名-const char * devname = "S2"任意の値をとる
action-> next = NULL;
action-> dev_id =(1)ピンラベル-void * dev_id =&pins_desc [0]任意の値を選択できます。目的は、アンインストールするドライバーを決定することです。

int request_irq(unsigned int irq, irq_handler_t handler,unsigned long irqflags, const char *devname, void *dev_id)
{
	...
	retval = setup_irq(irq, action);
	...
}

[3]setup_irq関数内部処理:set_type関数処理を使用します

int setup_irq(unsigned int irq, struct irqaction *new)
{
	...
	if (desc->chip && desc->chip->set_type)
		desc->chip->set_type(irq,new->flags & IRQF_TRIGGER_MASK);
	...
}

その中で、desc->chipどこで定義されていますか?
arch\arm\plat-s3c24xx\irq.c\void __init s3c24xx_init_irq(void)、[1]IRQ_EINT0定義されているように、desc-> chipはs3c_irq_eint0t4に対応します。

void __init s3c24xx_init_irq(void)
{
	...
	/* external interrupts */
	
	for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
		irqdbf("registering irq %d (ext int)\n", irqno);
		set_irq_chip(irqno, &s3c_irq_eint0t4);
		set_irq_handler(irqno, handle_edge_irq);
		set_irq_flags(irqno, IRQF_VALID);
	}
	
	for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
		irqdbf("registering irq %d (extended s3c irq)\n", irqno);
		set_irq_chip(irqno, &s3c_irqext_chip);
		set_irq_handler(irqno, handle_edge_irq);
		set_irq_flags(irqno, IRQF_VALID);
	}
	...
}

ビューのs3c_irq_eint0t4定義:

static struct irq_chip s3c_irq_eint0t4 = {
	.name		= "s3c-ext0",
	.ack		= s3c_irq_ack,
	.mask		= s3c_irq_mask,
	.unmask		= s3c_irq_unmask,
	.set_wake	= s3c_irq_wake,
	.set_type	= s3c_irqext_type,
};

[4]set_type関数=s3c_irqext_type関数
前の呼び出しコードは次のとおりです。

new->flags=action->flags =	(2)敏感沿-unsigned long irqflags=IRQT_BOTHEDGE
desc->chip->set_type(irq,new->flags & IRQF_TRIGGER_MASK);

関数の定義は次のとおりです。

s3c_irqext_type(unsigned int irq, unsigned int type)
{
	...
	if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
	{
		gpcon_reg = S3C2410_GPFCON;
		extint_reg = S3C24XX_EXTINT0;
		gpcon_offset = (irq - IRQ_EINT0) * 2;
		extint_offset = (irq - IRQ_EINT0) * 4;
	}
	...
	/* Set the external interrupt to pointed trigger type */
	switch (type)
	{
		case IRQT_NOEDGE:
			printk(KERN_WARNING "No edge setting!\n");
			break;

		case IRQT_RISING:
			newvalue = S3C2410_EXTINT_RISEEDGE;
			break;

		case IRQT_FALLING:
			newvalue = S3C2410_EXTINT_FALLEDGE;
			break;
		//与前面request_irq函数调用一致
		case IRQT_BOTHEDGE:
			newvalue = S3C2410_EXTINT_BOTHEDGE;
			break;

		case IRQT_LOW:
			newvalue = S3C2410_EXTINT_LOWLEV;
			break;

		case IRQT_HIGH:
			newvalue = S3C2410_EXTINT_HILEV;
			break;

		default:
			printk(KERN_ERR "No such irq type %d", type);
			return -1;
	}
}

2つのdrv_close関数分析

機能目的:割り込みソースを解放する

  1. free_irq関数呼び出し
irq=(3)中断标号-unsigned int irq = IRQ_EINT0
dev_id = (1)引脚标号-void *dev_id = &pins_desc[0]

free_irq(IRQ_EINT0, &pins_desc[0]);

free_irq関数の定義:

void free_irq(unsigned int irq, void *dev_id)

3つのbuttons_irq割り込みサービス機能分析-ウェイクアップ機能

  1. 関数宣言の形式:static irqreturn_t buttons_irq(int irq, void *dev_id)
    注:ここでdev_id関数を確認できます:割り込みソースを決定します
  2. 戻り値:return IRQ_RETVAL(IRQ_HANDLED);
  3. ウェイクアップ機能:wake_up_interruptible(&button_waitq); /* 唤醒休眠的进程 */

4つのdrv_read関数分析-スリープ関数:

  1. スリープ関数呼び出し
/* 如果没有按键动作, 休眠 */
wait_event_interruptible(button_waitq, ev_press);
  1. 睡眠機能プロトタイプ
#define wait_event_interruptible(wq, condition)				\
({									\
	int __ret = 0;							\
	if (!(condition))						\								//condition数值为0的时候休眠
		__wait_event_interruptible(wq, condition, __ret);	\
	__ret;								\
})
  1. パラメータ宣言

[1] ev_pressパラメーター:

/* 中断事件标志, 中断服务程序将它置1:表示唤醒
third_drv_read将它清0:表示休眠 */
static volatile int ev_press = 0;

[2] button_waitqパラメーター:
キューにぶら下がっているプロセスを表します

static DECLARE_WAIT_QUEUE_HEAD(button_waitq);

5ドライブテスト1

アプリプログラムが読み取り機能を実行する場合:割り込み機能が発生しない場合はスリーププロセスが実行され
、割り込みが発生する場合はプロセスが起動されます

  1. 開発ボードがドライバーをロードした後にdrv_open関数を呼び出す方法は
    exec 5</dev/buttons意味:デバイスの電源を入れ、/dev/buttons5に配置します

    注:次の図に示されているシェルプロセス番号は770
    ここに画像の説明を挿入
    / proc / 770 / fdです。fd—これは、現在のプロセスによって開かれた各ファイルのファイル記述子を含むディレクトリです。これらのファイル記述子は、実際のファイルを指します。リンク;シェルプロセスによって開かれたドライバー/ dev / buttonsの
    ここに画像の説明を挿入
    実行効果:
    ここに画像の説明を挿入

  2. close関数を呼び出しますか?
    実施した:exec 5<&-
    ここに画像の説明を挿入
    ここに画像の説明を挿入

6ドライブテスト2

  1. テストプログラムの実行(バックグラウンドでの実行):./ app&
    ここに画像の説明を挿入
    図からわかるように、ドライバーとテストプログラムはバックグラウンドで実行されます。その中で、テストプログラムはスリープ状態(S)にあり
    ここに画像の説明を挿入
    、各プロセスによって占有されているCPUリソース表示します。topコマンド(終了するにはctrl + c)
    ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/xiaoaojianghu09/article/details/104303719