ZephyrのIRQ_CONNECTメモ
はじめに
Zephyrのdriverを書いています。IRQハンドラ登録の処理を調査したので、メモを残しておきます。
IRQ_CONNECT
Zephyrで割り込みハンドラを登録する場合、IRQ_CONNECT
というマクロを使用します。
まず、Zephyrのドキュメントに掲載されている利用例です。
#define MY_DEV_IRQ 24 /* device uses IRQ 24 */ #define MY_DEV_PRIO 2 /* device uses interrupt priority 2 */ /* argument passed to my_isr(), in this case a pointer to the device */ #define MY_ISR_ARG DEVICE_GET(my_device) #define MY_IRQ_FLAGS 0 /* IRQ flags. Unused on non-x86 */ void my_isr(void *arg) { ... /* ISR code */ } void my_isr_installer(void) { ... IRQ_CONNECT(MY_DEV_IRQ, MY_DEV_PRIO, my_isr, MY_ISR_ARG, MY_IRQ_FLAGS); irq_enable(MY_DEV_IRQ); ... }
素直な作りで、IRQ番号、プライオリティ、IRQハンドラといった情報を指定します。 このマクロは次のように定義されています。
|> zephyr/include/irq.h
#define IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \ _ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p)
ターゲットアーキテクチャごとに実装が変わります。ここでは、Cortex-Mの実装を見ていきます。
#define _ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \ ({ \ _ISR_DECLARE(irq_p, 0, isr_p, isr_param_p); \ _irq_priority_set(irq_p, priority_p, flags_p); \ irq_p; \ })
コメントで次のように書かれている通り、Cortex-Mでは、静的に割り込みが設定できます。
/** * Configure a static interrupt. * * All arguments must be computable by the compiler at build time. * ... */
Zephyrで面白いのは、ここからです。
* _ISR_DECLARE will populate the .intList section with the interrupt's * parameters, which will then be used by gen_irq_tables.py to create * the vector table and the software ISR table. This is all done at * build-time.
_ISR_DECLARE
マクロは、.intList
セクションに割り込みパラメータを置きます。これを、pythonスクリプトで解析して、ISRテーブルを作ります。
_ISR_DECLARE
マクロは、次のように定義されています。
|> zephyr/include/sw_isr_table.h
/* Create an instance of struct _isr_list which gets put in the .intList * section. This gets consumed by gen_isr_tables.py which creates the vector * and/or SW ISR tables. */ #define _ISR_DECLARE(irq, flags, func, param) \ static struct _isr_list _GENERIC_SECTION(.intList) __used \ _MK_ISR_NAME(func, __COUNTER__) = \ {irq, flags, &func, (void *)param}
さて、別言語から、静的にIRQを登録したいのですが、どうしましょうかね…。