割り込みを用いた制御

割り込みとは

 割り込みとは、ハードウェアからの通知を受け取り、処理を走らせる仕組みです。割り込みが発生すると、現在処理されている内容を中断し、割り込みを処理する為の割込みコンテキストに遷移した上で、登録したコールバック関数が呼び出されます。

 多用される割り込みは、6.2 で説明したGPIOで、High/Lowの論理が切り替わった時等に通知を受けることが可能です。一つのデバイスをGPIOとI2Cの両方で接続し、GPIOで変更通知を受け、その後にI2Cでデバイスのレジスタを確認することで、何が変わったかを確認する事が可能なデバイスが存在します。

使い方

 照度センサデバイスドライバで割り込みに関する処理は、コメントアウトされてますが、以下に使用箇所があります。

kernel/mediatek/4.4/drivers/misc/mediatek/sensors-1.0/alsps/ltr578/ltr578.c

if (request_irq(ltr578_obj->irq, ltr578_eint_handler, IRQF_TRIGGER_NONE, "ALS-eint", NULL)) {

この関数は以下に定義があります。

kernel/mediatek/4.4/include/linux/interrupt.h

static inline int __must_check
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
	    const char *name, void *dev)
{
	return request_threaded_irq(irq, handler, NULL, flags, name, dev);
}

この関数はLinuxに割り込みを登録する関数になります。
第1引数であるirqは、割り込み番号を指定します。GPIOであればgpio_to_irq関数を使用してGPIOポートから割り込み番号を取得できる仕組みがあります。
第2引数であるhandlerは、呼び出されるコールバック関数になります。
第3引数であるflagsは、動作条件を指定するフラグです。GPIOにおいてIRQF_TRIGGER_RISINGであれば、LowからHighに論理が変わった時を表します。IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLINGと同時に指定することで、論理が変わった時という条件指定も可能です。
第4引数であるnameは、任意の文字列です。
第5引数はコールバック関数と共有するデータのポインタになります。

その他の割り込みの主要な関数には、以下のようなものがあります。

kernel/mediatek/4.4/kernel/irq/manage.c

/**
 *	enable_irq - enable handling of an irq
 *	@irq: Interrupt to enable
 *
 *	Undoes the effect of one call to disable_irq().  If this
 *	matches the last disable, processing of interrupts on this
 *	IRQ line is re-enabled.
 *
 *	This function may be called from IRQ context only when
 *	desc->irq_data.chip->bus_lock and desc->chip->bus_sync_unlock are NULL !
 */
void enable_irq(unsigned int irq)

登録した割り込みを実際に有効にします。

kernel/mediatek/4.4/include/linux/interrupt.h

static inline int enable_irq_wake(unsigned int irq)
{
	return irq_set_irq_wake(irq, 1);
}

5.8 で触れたCPUがsuspend状態に入っている時に、割り込み発生によってsuspend状態を解除させる設定を有効にします。

最後に

 Linuxにおける割り込み制御について説明しました。処理を中断して実行される為、割り込みに登録するコールバック関数は遅延処理等を活用し、短時間で終わらせるように注意して設計する必要があります。また、割り込みフラグが落とされる前にもう一回割込み条件を満たしても無視されるので、GPIOであれば実際の論理変化の回数と、コールバック関数の呼び出し回数が、必ずしも一致しないので、この点も注意して下さい。尚、enable_irq_wakeは、全ての割り込みが対応している訳でなく、ハード仕様上、suspend状態を解除できない割り込みもあるので確認が必要です。

Appendix. デバッグ関連

割り込みの登録状況や、発生回数は/proc/interruptsから確認可能です。

maverick:/ $ cat /proc/interrupts
           CPU0       CPU1       CPU2       CPU3       CPU4       CPU5       CPU6       CPU7
  1:          0          0          0          0          0          0          0          0     GICv3  29 Edge      arch_timer
  2:    1712290    1147572     941971     723560     175476     124051      99139      86640     GICv3  30 Edge      arch_timer
  5:     457366     377059     264948     162094      61456      37199      26078      23244  MT_SYSIRQ 176 Level     mt-gpt
  6:          1          0          1          0          0          0          0          0  MT_SYSIRQ 185 Level     pmic_wrap
  7:          0          0          0          0          0          0          0          0  MT_SYSIRQ 303 Level     CIRQ
 10:          0          0          0          0          0          0          0          0  MT_SYSIRQ 306 Edge      amms_irq
 13:     103881     103079      88706      71759      34879      27864      21432      18519  MT_SYSIRQ  77 Level     mtk-msdc
 14:          0          0          0          0          0          0          0          0  MT_SYSIRQ  78 Level     mtk-msdc
 20:         22         49         10          9          5          3          5          0  mtk-eint   1 Edge      gt9xx
 22:          0          0          0          0          0          0          0          0  mtk-eint   3 Edge      11240000.msdc cd
 24:          0          0          0          0          0          0          0          0  mtk-eint   5 Edge      hall_sensor_1
 29:        438        192        150         77         14         15         13         11  mtk-eint  10 Edge      mt6370_pmu_irq
 60:          0          1          3          2          0          0          1          0  mtk-eint  41 Edge      type_c_port0-IRQ
188:          0          0          0          0          0          0          0          0  mtk-eint 169 Edge      rt551x
198:          0          0          1          0          0          0          0          0  mtk-eint 179 Level     usbcd_eint
201:        285        786        854        517         35          7         84         26  mtk-eint 182 Level     pmic-eint
231:         88         79         59         48         18         10         13         15  MT_SYSIRQ  81 Level     mt-i2c

<省略>

380:          0          0          0          0          0          0          0          0  mt6370_pmu_irq 103 Edge      ldo_oc
389:          0          0          0          0          0          0          0          0  mt6370_pmu_irq 118 Edge      bled_ocp
IPI0:   3214709    2783965    2546969    2107078     832693     727117     647814     590297       Rescheduling interrupts
IPI1:       326      39449      35962      28533      47835      47823      48084      48169       Function call interrupts
IPI2:         0          0          0          0          0          0          0          0       CPU stop interrupts
IPI3:      6512       4902       4894       3797      10348      12823      11411       4568       Timer broadcast interrupts
IPI4:      8621       4537       3308       2332         94         68         44         33       IRQ work interrupts
IPI5:         0          0          0          0          0          0          0          0       CPU wake-up interrupts
Err:          0

主要な値の意味は以下になります。
CPU0-7: 各CPUで処理された割り込みの回数
右端: request_irqの引数で指定した任意の文字列

コメント

タイトルとURLをコピーしました