最近、今までとは少し違う仕事に入っている。
その中でARMのCortex-Rシリーズのマイコンを使うことになった。
Cortex-Mシリーズはこれまでも使ってきたのだが、これとは異なる点が多い。
使う上で一番違うと思ったのが割り込み関係である。
僕が今まで触ってきたマイコンと比べるとだいぶ面倒である。
ARMというマイコンアーキテクチャが知名度を上げたのが、ゲームボーイアドバンスで採用されたことだと言われている。
この当時使われていたのがARM7TDMIというコアだったらしい。
これがARM9E(ニンテンドーDSで採用)、ARM11(初代iPhoneで採用)と発展したが、
その次はARM12とならずのCortex-A, Cortex-R, Cortex-Mの3シリーズ展開になった。
この3シリーズ展開となったことがARMの活躍の場を広めたという。
3シリーズ展開になる前のARMは携帯電話のような用途がほとんどだった。
Cortex-Aシリーズの「A」はApplicationを表す。
従来からの携帯電話などの用途を継承し、リッチなOSも動くチップである。
WindowsがARM対応したとか、AppleがMacにARMベースのAppleシリコンを搭載したというので話題になっていたが。
Cortex-Mシリーズの「M」はMicrocontrollerを表す。
ワンチップマイコンを想定したもので、かなりコンパクトに作れるという。
ARMとしてはかなり異端な構成で、命令セットは従来のARM命令ではなくThumb2命令という可変長のものだけ対応している。
安価で使いやすいということで、Cortex-Mシリーズは多種多様な製品に組み込まれている。
そして、Cortex-Rシリーズ、「R」はReal-timeを表すがイマイチ知名度が低い。
ARMの組み込み向けで普及するCortex-Mと苦戦するCortex-R (ASCII.jp)
古い記事なんですけどね。
Cortex-RシリーズはCortex-Aシリーズと似ている点が多いのだが、
リアルタイム性の高い用途で使うためにメモリ周りの構成が異なる。
Cortex-AではMMU(Memory Management Unit)を搭載している。
仮想アドレスを物理アドレスに変換する機能を持っており、高級なOSを使うなら必須だが、
複雑な仕組みであるために処理時間の大きな変動を招きかねないと。
なのでこの部分はよりシンプルな仕組みにしている。
さらにTCM(密結合メモリ)というキャッシュと同じ速度でアクセスできるメモリがあり、
容量は限られるが、これを効果的に使うことで高速かつ一定時間で処理が実行できる。
このようにしてリアルタイム性の要求される処理に対応しようとした。
しかしCortex-Rシリーズはあまり流行らなかった。
Cortex-Mシリーズはキャッシュメモリを持たないコンパクトな構成だが、
これで十分な性能が得られるならば、リアルタイム性という点では申し分ない。
で、これで足りるケースが当初ARM社が目論んでいた以上に多かったと。
浮動小数点ユニットを搭載できるCortex-M4が登場してからはなおさら。
ARMとしては特異な構成だが、これが使いやすいんですよね。
当初はキャッシュメモリを搭載しないのが特色だったCortex-Mシリーズだが、
キャッシュを搭載できてより高性能化したCortex-M7なんてものも登場。
Cortex-Rシリーズでやりたかったことがだいたい入っちゃったのではと。
冒頭に書いたようにこのプロジェクトではCortex-R5Fを使うのは決まっている。
(Cortex-R5Fは浮動小数点演算に対応したCortex-R5のこと)
ただ、チームリーダーと話していたけど、実はCortex-M4あたりで対応できる処理なのではと。
確かにそんな気はするのだが、どうしてもCortex-R5Fになる理由がある。
それは様々な都合により、利用できるチップが限られることである。
検討の結果、使うことになりそうなチップにはCortex-A53とCortex-R5Fが複数個搭載されている。
このためCortex-R5Fを処理に使い、Cortex-A53は使わないという構成になると言っている。
正直無駄が多い構成だと思うのだが、現実に買えるチップがこれだから仕方ない。
うちとは逆にCortex-A53だけを使い、Cortex-R5Fは使わない構成も多いだろう。
思うところはあるが、Cortex-R5を使うと言うこと自体はそこまで変な話でもない。
ただ、割り込み処理が今まで触ってきたマイコンに比べると面倒である。
実はこの方式はARM11以前のARMで伝統的に使われていた方式らしい。
Cortex-Aも同じなのだが、Cortex-Mシリーズでは大きく2点異なる。
1つはNVIC(Nested Vectored. Interrupt Controller)の採用。
ベクタテーブルで割り込み要因ごとにジャンプするアドレスを指定できる。
もう1つがレジスタのスタックへの待避をハードウェア的に実行すること。
マイコンに割り込みが入ったら、割り込み処理が終わったら元の処理に戻れるように必要なレジスタを退避させる必要がある。
Cortex-Mシリーズでは割り込みが入れば必要なレジスタをスタックに自動的に格納する。
これにより割り込みハンドラではレジスタ退避のことを考えずに済む。
Cortex-Rシリーズではベクタテーブルには7種類しか格納できない。
リセットハンドラ、SVC, IRQ, FIQの3種類の割り込みと、未定義処理例外、プリフェッチアボート、データアボートの3種類の例外処理にそれぞれ1つ。
FIQは高速割り込み処理で、一般的な割り込みはIRQを使うとのこと。
SVC, IRQ, FIQに複数の要因がある場合は、割り込みハンドラで識別する必要がある。
Cortex-MのNVICはIRQ要因を識別して自動的に振り分けるが、他のマイコンでは一般的な構成である。
今まで触ってきたマイコンはどれもこの仕組みだったのでCortex-Rで戸惑ったと。
レジスタの待避も異なる。Cortex-RではUSR, FIQ, IRQ, SVC, ABT, SYS, UNDの7つのモードがある。
リセットとSVC割り込みがあるとSVCモードに、FIQ割り込みがあるとFIQモード、IRQ割り込みがあるとIRQモードに、未定義命令例外でUNDモード、アボート例外でABTモードに入る。
これらの5つのモードにはr13,r14,spsrレジスタが独立に存在する。
(r13は別名sp、スタックポインタとして使い、r14は別名lr、関数の復帰先を格納するリンクレジスタとして使う)
FIQモードではr8~r12の汎用レジスタ5つも独立に存在する。
割り込みが入るとレジスタバンクを切り替えて、割り込み前のプログラムカウンタをr14、プロセッサ状態を表すcpsrをspsrに格納する。
このようにレジスタバンクの切替とレジスタ間の転送で退避処理をすると。
ただ、これはこれでイマイチな仕組みである。
結局スタックへの格納処理は割り込みハンドラでやらないといけないから。
しかもこういう処理はアセンブラで書くしかないわけである。
r0~r3, r12をスタックに格納するのがお決まりだと。
(ARMではr4~r11の汎用レジスタは関数で使う時に退避させるのがお約束)
r14とspsrは多重割り込みを考える場合に退避が必要になる。
レジスタバンクの切替、レジスタ転送で退避できるのは1モード1回まで。
IRQ割り込み処理中にIRQ割り込みがあるなら、結局スタックに格納しないといけないと。
割り込み要因の識別もそうだけど、Cortex-Mではこれに相当する作業を自動的にやってくれるのにねって。
FIQ割り込みはうまくつかえば高速処理に適するのかもしれない。
FIQ割り込みの発生要因を1種類に限定しておけば識別処理はいらないし、
FIQモードで独立して持っているr8~r12レジスタは退避せず使えるわけだし。
ただ、r8~r12が退避不要という特徴を生かそうとすると、アセンブラで書かないと難しそう。
使い道が限られるので実際のところはあまり使われていないらしい。
識別不要にするというだけならばIRQ同様の使い方でもいいかもしれないけど。
なんてわけでとにかくCortex-Mより手間がかかって仕方ない。
ただ、この記事をゲームボーイアドバンスから話を始めた理由でもあるけど、こっちの方がARMの基本なんですよね。
Cortex-Mシリーズ以外ではこの考え方は共通している。
Cortex-R5に限ると実装例などの情報も少ないのだが、Cortex-Aシリーズの情報はけっこうある。
割り込み要因の識別方式など、チップにより異なる要素もあるので、
単純に同じコードでは済まないのが面倒ではあるのだけど。
Cortex-Mシリーズの情報はもっとあるのだが、これはまるで参考にならない。
Cortex-Rシリーズの特色としてMMUを搭載していないことと書いたが、
実はCortex-R82ではMMUを搭載して使うこともできるようになったという。
Arm、プロセッサ内でOSを動作可能にした「Cortex-R82」 (PC Watch)
MMUはリアルタイム処理に使わないとしてCortex-Rには搭載しなかったが、
Linuxのような高級なOSはMMUがないと動かない。
今回採用するかなと言っているチップはCortex-A53とCortex-R5Fを搭載しているが、
こういう構成にしているのはCortex-R5FではLinuxが動かないからかもしれない。
Cortex-R82ではMMUを搭載してコアごとに有効/無効を選べる。
一部のコアではMMUを使わずリアルタイム処理、一部のコアではMMUを使ってLinuxを動かす、なんてことができますよと言っている。
なるほどと思う部分もあるけど、それって流行るのかね?