2コアマイコン向け簡易OS設計のための下調べ編
Maix AmigoのK210とRaspberry Pi PicoのRP2040には意外な共通点があって、
- チップは2コアを提供している
- SDKはOSを提供していない
というポイントがある。というわけでこれら向けには他の環境と同様のコーディングはできず、まず適当なOSを用意してやる必要がある。
基本戦略
ESP32と同様の戦略、つまり:
- Core0: プロトコル処理等の通常のシステムにおけるOSカーネルに相当する処理
- Core1: ユーザアプリケーションを動作させる
という分割を前提とする。Core0側、つまりカーネルはチップベンダが提供するSDKで記述し、Core1側のアプリケーションは専用のSDKやlibcを別途用意する。Core1側のアプリケーションは将来的にWebAssemblyでの供給とチップを超えた共通化を目指す。
... もっとも、RP2040はメモリが少すぎるので一般的なアプリケーションを実現するのはほぼ不可能で、専用に構築したゲームが限界なのではないかと考えている。
調べること
簡易といっても、マルチプロセッサ対応のOSを作るにはそれなりのプリミティブが必要になる。
- プロセッサ間割り込みの方法 。Core0 → Core1 は最低でも必要になる。Core1 → Core0 は存在しなくてもポーリングで何とかできなくはないが、パフォーマンスのためには合った方が良い。
- キャッシュをフラッシュする方法 。 Core0 と Core1 でメモリを共有する可能性がある場合、例えば、Core0で行った変更がキャッシュだけに反映されていてCore1から見えないといった事故が発生する可能性がある。
- アトミックなメモリ更新方法 。Core0でカメラ画像を取り込んでCore1で使用するといったケースでは、Core1が画像を使用している間はCore0は更新しないように配慮する必要がある。このとき、 "カメラ画像使用中フラグ" はCore0とCore1で共有されるため、両者で矛盾なくフラグを更新できる仕組みが必要になる。
- プロセッサをスリープ/復帰させる方法 。流石に単純に消費電力倍は受け入れられないのでsleepさせる方法論が必要になる。
諸元、情報源
とりあえずどこを見れば良いのかを先に調べておく。
K210
K210のデータシートにリソース類は列挙されている。
関連するのは、
- RISC-V PLIC https://github.com/riscv/riscv-plic-spec/blob/master/riscv-plic.adoc
- CLINT "SiFive Interrupt Cookbook" が一番わかりやすい気がする
SDKは割り込みハンドラを抽象化しているので、それに乗るのが妥当な気がする。例えば、core1の起動コードは、
- Core1は
wfi
命令を実行して割り込みを待ち受ける: https://github.com/kendryte/kendryte-standalone-sdk/blob/02576ba67e8797444f3ee3f34c625b5ed048e707/lib/bsp/entry_user.c#L110-L113 - Core0からは
clint_ipi_send
APIでIPI(プロセッサ間割り込み)を掛ける: https://github.com/kendryte/kendryte-standalone-sdk/blob/02576ba67e8797444f3ee3f34c625b5ed048e707/lib/bsp/entry_user.c#L46-L58
というような実装になっている。一度Core1側でユーザコードの実行を始めたら、割り込みハンドラをオーバライドしてやらなければならない。
キャッシュ制御命令の類は提供されない 。つまり、DMAによってプロセッサ外部に出ていくデータは非キャッシュ領域に一旦手でコピーする必要がある。
Coreは独立したキャッシュを持つが、これらは(gccの)atomic拡張でカバーされる。 https://github.com/kendryte/kendryte-standalone-sdk/blob/06a2ea71f250e91d66fa156ff82ae1f5b9fc6e56/lib/bsp/include/atomic.h#L35-L51
RaspberryPi Pico
データシートにリソース類は列挙されている。
K210は割と素直なRISC-V SoCになっているが、RP2040の方は割と斬新な構成をしていて、例えば、"2.1.2. Atomic Register Access" で示されるようにバスレベルで周辺レジスタへのread-modify-writeをサポートしている。
また、(XIP -- 外部 NOR/NAND フラッシュからの直接実行用) を除いて 一切のCPUキャッシュが無い ので、K210と比べて気にするべきことは少ない。
ライブラリ pico_multicore
https://raspberrypi.github.io/pico-sdk-doxygen/group__pico__multicore.html がCore 1側の起動をサポートしている。