🧱

操作不能になった Raspberry Pi Pico W を救出する

2025/03/03に公開

何を思ったかメインのソースコードにこんなコードを仕込んでいました。ラズピコで WiFi 系の機能を使うとリセットが必須なので開発のしやすさのために書いてたコードです。

try:
    ip = connect_to_wifi()
    app.run(port=80)
except KeyboardInterrupt:
    machine.reset()

もちろん開発中は何の問題になりませんでした。

ある程度動作も安定してきたので、このファイルの名前を main.py にリネームして自動起動するようにしました。これがすべての始まりです。

ちょっとコードを修正しようと Stop/Restart をクリックすると何かがおかしいことに気づきました。Thonny がずっとエラーを吐きます。USB を抜き差ししても変わりません。

PROBLEM IN THONNY'S BACK-END: Internal error (serial.serialutil.SerialException: WriteFile failed (PermissionError(13, 'デバイスがコマンドを認識できません。', None, 22))).
See Thonny's backend.log for more info.
You may need to press "Stop/Restart" or hard-reset your MicroPython device and try again.


Process ended with exit code 0.

rshell から操作しようにも同じエラーで無理です。REPLにもファイルにもアクセス不可。完全に詰みました。

さらに最悪だったのは、最新のソースコードのバックアップを取っていなかったことです。ソースコードは Pico の中にしか残ってません。

だいたいこういうときは、Pico のフラッシュを初期化できる flash_nuke.uf2 を使うのが定番ですが、これでは努力がすべて無駄になってしまうので何とかソースコードを救出する方法を探しました。

方法1: レスキューファームウェアを使う

この手のミスは割と初心者にはありがちらしく、main.py をリネームして自動起動しないようにしてくれるレスキューファームウェアを作ってくれている方がいました。まずはそれを試してみます。
https://forums.raspberrypi.com/viewtopic.php?t=305432

結果

なんと、効果なし。よくよく調べるとこのファームウェア、無印 Pico 用に作られているみたいで Pico W では使えませんでした。
もちろん無印 Pico では使えるみたいです。

方法2: バイナリを直接弄る

かなりの荒業。フラッシュをダンプして直接編集しちゃって main.py の自動起動を阻止しようっていう話です。picotool を使います。

Windows で picotool を使うには

picotool のリポジトリにはバイナリが無いのですが、ここにビルド済みバイナリが公開されてます。
https://github.com/raspberrypi/pico-sdk-tools

これをDLして使っていくのですが、使おうとすると次のようなエラーが出ます。

No accessible RP-series devices in BOOTSEL mode were found.

but:

RP2040 device at bus 1, address 3 appears to be in BOOTSEL mode, but picotool was unable to connect. You may need to install a driver via Zadig. See
    "Getting started with Raspberry Pi Pico" for more information

Windows で picotool を使うにはドライバのインストールが必要みたいです。
ここで Zadig というソフトを使います。いろんなデバイスに汎用 USB ドライバをインストールできるソフトみたいです。
起動したら、RP Boot を選択して、Install Driver をクリックします。

これで Windows でも picotool が使えます👍

まず、フラッシュをダンプします。

$ picotool save -a -t bin flashdump.bin

ダンプしたファイルをバイナリエディタで開いて、main.py を検索します。
一番最初に出てくるのが、MicroPython 本体のソースで main.py を起動する処理が書かれているところだと思います(多分)。なので、ここを書き換えちゃえば起動時に自動実行されるファイル名が変わって、main.py は起動しなくなるっていうことです!

今回は適当に nain.py に書き換えてみました。

書き換えられたら、Pico に戻してあげます。

$ picotool load -u -t bin flashdump.bin

これで無事ソースコードの救出に成功しました🛟


教訓: main.py を使うときは慎重になろう

参考

https://forums.raspberrypi.com/viewtopic.php?t=341573
https://forums.raspberrypi.com/viewtopic.php?t=377909

Discussion