割り込みとは
割り込みとは、ハードウェアからの通知を受け取り、処理を走らせる仕組みです。割り込みが発生すると、現在処理されている内容を中断し、割り込みを処理する為の割込みコンテキストに遷移した上で、登録したコールバック関数が呼び出されます。
多用される割り込みは、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の引数で指定した任意の文字列
コメント