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を登録したいのですが、どうしましょうかね…。

参考

docs.zephyrproject.org