arm: Cortex-Mの割り込み
2024/09/05
ARM9系はあまり触っていなかったが、あちらは高速IRQというものがあった。
Cortex-M3はその系列からやり方が変わった。
どう変わったか説明できるほど詳しくないが、ARM9 や 11 を触っていた人は違うことに注意しようというだけだ。
説明しているサイトなどは多いので、個人的に印象深いところだけメモに残そう。
Vector Table
Cortex-M33 では Security Extension の有無でベクタテーブルが違う。
ncs だと “NS” の有無というやつだ。
“Exception Number” と “IRQ Number” があるが、CMSIS では IRQ Number だけを使う(シンプルにするため)と書いてあった(Exception typesのNote)。
Hard Fault
発生して一番困るのが Hard Fault だと思っている。
私もしばしば遭遇している。
hiro99ma blog: [nrf51]スケジューラを使ってGPIOハンドラからSPI転送するとHardFaultになった
何か間違っていることは分かるのだが、何かが足りなくて発生したのか、そもそもそういうことができないのか、みたいなところで悩んで時間がかかる。
上の私の例だと、割り込みハンドラから SPI 転送しようとしたら発生していた。
提供されている SPI 転送のドライバの中で割込禁止しようとしているが、ドライバを呼び出そうとしたのが割り込みハンドラの中だったので Hard Fault になったということらしい。
API の説明に「割り込みハンドラの中からは呼び出せません」とか書いてあれば気付いたのかもしれないが、たぶん記述はなかったのだろう。
割り込みハンドラの中であれこれやるのはよくないのだが、やれるけどよくないのか、そもそもやれないのかは結構違うと思う。 ボタンを押したら SPI 転送するだけのちょろっとしたプログラムだったらいいやん、と思ってしまう。 まあ、提供されたドライバではなく自分でレジスタをたたけばよいのだが。。。
ちなみに ncs の場合はこんな感じでログが出るようだ。
how to decipher HARD FAULT / MPU FAULT on zephyr running on nrf52832
ncs というよりも Zephyr kernel になるのかな。
SysTick
OS を載せるとだいたいなにがしかのタイマーがいるので、そういうときに SysTick を使うと思う。
が、Zephyr はタイミングのためのタイマーを使わないタイプ(tickless)だそうだ。 OS がスレッドのディスパッチなどのために tick を使わないというだけで、タイマーを持たないというわけではない。
では ncs では SysTick のところはどうなっているかというと、ここかな。
SysTick がないタイプもあるのでCONFIG_CPU_CORTEX_M_HAS_SYSTICK
と、システムクロックを使う気があり(CONFIG_SYS_CLOCK_EXISTS
)かつ SysTick 割込みも使う(CONFIG_CORTEX_M_SYSTICK_INSTALL_ISR
)場合とそうでない場合で仕込むハンドラが違う。
ということは、nRF53 はどうなってるんだ?
nRF Kconfig GUI だと出てこないので build/zephyr/.config
を見てみる。
CONFIG_CPU_CORTEX_M_HAS_SYSTICK=y
CONFIG_SYS_CLOCK_EXISTS=y
CONFIG_CORTEX_M_SYSTICK_INSTALL_ISR
は出てこなかったので、z_arm_exc_spurious
がテーブルには登録されているはず。
z_arm_exc_spurious
が何者かはわからんが、mapファイル上ではz_arm_usage_fault
やz_arm_hard_fault
と同じアドレスだったので、SysTick を有効にした途端に fatalエラー扱いになるんだろう。