Raspberry Pi pico 解析(core1 wait and wakeup...)

まだ少ししか触ってませんが、今まで使用してきたプロセッサはcore0で、core1は使ってないです。Raspberry Pi picoは Coretex-M0+ dual core なので片側(core1)を使っていないのはもったいない。そこでcore0とcore1がどのように共存しているのか、core1を使うにはどのようなことが必要かを調べてみました。core0とcore1の共存という事で、RP2040 Datasheetの Figure 6 に大まかなブロックが書かれています。Figure 7 ではSIOに注目してブロックが書かれています。

rpi_pico_rp2040_datasheet_fig6.png

rpi_pico_rp2040_datasheet_fig7.png


RP2040 Datasheet の 2.3.3. Event Signals に 「event信号はプロセッサ間で相互に接続されている」とあるので、core0でSEVするとcore1のWFEで受け、core1でSEVするとcore0のWFEで受けるという構成になっている様です。なので、自分自身(プロセッサ)にSEVを投げることはできないのですね。

プロセッサ間の通信ではSEV,WFEの構成をうまく利用しています(そのためにこの構成なのでしょうが)。もちろん、この通信方法は編集できないプログラム領域(ROM)で定義されている箇所にいるときだけです。後述しますが、core1が最初にROM内のプログラムによってWFE待ちの状態になってますが、これを解除した後は外部Flashや内臓SRAM上のプログラムになるので、プロセッサ間通信の方法は作り手しだいでいか様にも構成できます。


パワーオンリセット後にcore1が実行する場所はどこになるのでしょうか? RP2040 Datasheetの 2.4.8. List of Registers の M0PLUS: VTOR Register の内容より、VTOR.TBLOFFは初期値0x000000なのでcore0もcore1もリセットベクターは0x00000004に書かれているアドレスへジャンプするようです。bootromのソースコードを追っていくと、リセットベクター先に飛んで初っ端にcore0 or core1を判断しています。

rpi_pico_rp2040_datasheet_vtor.png

core0の場合はいろいろと複雑なことをした後、以前記載した様にROM→SRAMへ実行場所が移動しています。一方、core1の場合は最終的にWFEで待ちになってます。core1の処理内容を追ってみます。

core1はパワーオンリセットすると0x000004のリセットベクターが示す先(_start)に飛びます。_start でcoreのCPUIDを調査して0以外ならwait_for_vectorへ更に飛びます。wait_for_vectorへ飛んだ後は下図のようなシーケンスになるようです。図は流れがわかる範囲で簡素化しています。アセンブリ言語で書いてあるのと、エラー処理が入っているので実際はもっと複雑になってます。

rpi_pico_wait_core1.png

core0が何もしてこなかった場合、core1は以下の処理をします。

1. RX_FIFOを空にする
2. TX_FIFOに0を書き込む
3. core0に対してイベントを発生させる(SEV)
4. core1に対するイベント待ちにする(WFE) ← DEEPSLEEP

つまり、core1はcore0がイベント発生(SEV)するまでDEEPSLEEP状態で待ち続けているのです。DEEPSLEEP状態なので低消費。意図的にSEVしない限り悪さもしない。良いですね~。

では、眠り続けているcore1を起こして意図したプログラムを実行してもらうにはどうするかですが、core0からSEVでcore1を起こして、実行先を示してやるのです。上図では「val毎の処理」として端折ってますが、決まったシーケンスでcore0から指示を出してやる必要があります。また、1回の指示毎にWFEに遷移するので毎回core0からSEVを発行する必要があります。core0からの指示内容は以下の順です。

1. TX_FIFO(core0→core1)に'1'を書き込みSEVを発行する
2. TX_FIFO(core0→core1)にcore1のベクターアドレスを書き込みSEVを発行する
3. TX_FIFO(core0→core1)にcore1のスタックポインタ設定先を書き込みSEVを発行する
4. TX_FIFO(core0→core1)にcore1が実行するアドレスを書き込みSEVを発行する

C/C++ SDKでは途中、core1が予期しない位置にいる場合もあるので先頭へ戻す意味も含めて上記の1~4の前に'0'を書き込んでSEVを発行するを2回繰り返しています。

注目するべきは、core1がcore0に指示された先にジャンプするまでの処理は全てROM領域に書かれている内容であるという事です。なので、core1を起動させるにはこの手順を守らなければならないです。ただし、一旦飛び出すとそれからは自由です。再度core1をWFE(WFI)で寝させる場合、その後の起動方法はユーザーのプログラム次第なのです。プロセッサ間の通信も自由に設計できます。
スポンサーサイト



tag : RaspberryPi_pico

黒ねこ時計 くろック D02
プロフィール

jujurou

Author:jujurou
運営HP:チャコの部屋
Twitter:jujurou

カレンダー
01 | 2021/02 | 03
- 1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 - - - - - -
最新記事
最新コメント
カテゴリ
ユーザタグ

ぺるけ Linux RaspberryPi 全段差動プッシュプル 6P43P-E 三段化 トランジスタ式ミニワッター 6P43P TRminiWatterPart4 RaspberryPi_pico MPD FON2405E イーサネットコンバータ OpenOCD DAC buildroot windows Bluetooth BeagleBoneBlack FM3ペリフェラル map ODROID-U2 FM3評価ボード library mingw OpenGL シングル bitbake KiCad 計測 プリアンプ Edison VMware FM4 ミニワッター 6N6P TL-WR700N 

月別アーカイブ
ランキング

FC2 Blog Ranking

カウンター
検索フォーム
リンク
RSSリンクの表示
QRコード
QRコード
ライセンス
クリエイティブ・コモンズ・ライセンス
Twitter