マルチコアの Raspberry Pi Pico でフラッシュを書き込む
フラッシュの書き込みではハマる人が減りますようにメモ
はじめに
Rasberry Pi Pico は中華マイコンと比べて値段が高いのであまり使っていなかったのですが、 1MB フラッシュの互換品が安く手に入ったので、PIO の練習がてら使っていました。
RP2040 には、CPU コアが 2個あり、pico-sdk からは以下のようにして、2個目の CPU を起動することができます。
multicore_launch_core1(main1)
今回ハマったのは、pico-sdk で LittleFS を使おうと思った時です。 LittleFS はマイコンのフラッシュの一部をファイルシステムとして扱うことのできるライブラリです。
pico でも使用例があるようなので、これを参考にしたのですが、
最初のフォーマットでマイコンが固まってしまいます。
いろいろ確認してみると、flash_range_program
などフラッシュの書き込みを行うところで固まっているようでした。
原因と対策
Pico では、プログラムの保存に SPI フラッシュを使っていて、XIP という仕組みで直接 SPI フラッシュ上のコードを実行できるようになっています。 したがって、SPI フラッシュの書き込み中に、プログラムコードを含めて一切フラッシュへのアクセスを行うことはできません。
上の使用例でも、save_and_disable_interrupts
を使用して割り込みコードが実行されないようにはなっていました。
今回試していたコードは、たまたまマルチコアを使用するようになっていたのですが、
LittleFS のフォーマットを、multicore_launch_core1
の前に行うとちゃんとフォーマットできるようになりました。
つまるところ、マルチコアで動作しているときは反対側のコアのフラッシュのアクセスも停止させる必要があるということでした。
pico-sdk の pico-multicore ライブラリには相手のコアの動作を一時停止させる方法があります。 https://www.raspberrypi.com/documentation/pico-sdk/group__multicore__lockout.html ちゃんと「フラッシュの書き込み時に使うといいよ」って書いてありますね… プロセッサ間の FIFO 割り込みを使って実装しているようです。
「動作を止めたい方のコア」においてあらかじめ以下のようにしておきます。
multicore_lockout_victim_init();
この状態で、「他方のコア」で以下のようにします。
multicore_lockout_start_blocking();
// フラッシュの書き込み
flash_range_program();
multicore_lockout_end_blocking();
これで、start_blocking から end_blocking までの間、「止めたい方のコア」の動作を一時停止できます。
というか、Arduino-pico の LittleFS ライブラリ見れば同様のコードが入ってるので、最初からこれを参考にすればよかった…