リセットとブートシーケンス¶
MicroPython を実行しているデバイスは、リセット後の起動と初期化において特定のブートシーケンスにしたがいます。
ハードリセット¶
ハードリセットからの起動は、ボードに初めて電源が投入されたときに発生するコールドブートです。これは MCU ハードウェアの完全なリセットです。
MicroPython ポートのコードは、すべての主要なハードウェア(組込みのクロックと電源レギュレータ、内部シリアル UART などを含む)を初期化し、MicroPython 環境を起動します。既存の RTC 設定はハードリセット後も保持される場合がありますが、その他のハードウェア状態はすべてクリアされます。
同じハードリセットのブートシーケンスが、次のようなさまざまなイベントによってトリガーされる可能性があります。
Python コードが
machine.reset()
を実行する場合。ボード上に物理的なリセットボタンがあり、ユーザーがそれを押した場合
(ほとんどのポートで)ディープスリープから復帰した場合。
MCU のハードウェアウォッチドッグリセットがかかった場合。
MCU のハードウェアブラウンアウトが検出された場合。
ハードウェア固有のリセットトリガーの詳細は、ポートと関連するハードウェアによって異なります。 machine.reset_cause()
関数を使うと、リセットの原因をさらに特定できます。
ソフトリセット¶
MicroPython がすでに実行されている場合、 REPL で Ctrl-D を入力する か、 machine.soft_reset()
を実行することでソフトリセットをトリガーできます。
ソフトリセットは Python インタープリターをクリアし、すべての Python メモリを解放し、MicroPython 環境を再び起動します。
ソフトリセットによってクリアされる状態には次のものがあります:
すべての Python 変数、オブジェクト、インポートされたモジュールなど。
machine モジュール を使って有効化したペリフェラルのほとんど。非常に限られた例外はあります。たとえば machine.Pin のモード(ピンが入力か出力か、high か low か)は、ほとんどのポートではリセットされません。
Pin.irq()
などのような、より高度な設定は常にリセットされます。Bluetooth.
ネットワークソケット。開いている TCP ソケットは、相手側に対して正常に閉じられます。
開いているファイル。ファイルシステムは有効な状態のままです。
ソフトリセット後も、次のような一部のシステム状態は変わりません:
既存のネットワーク接続(イーサネット、Wi-Fi など)は、IP ネットワーク層でアクティブなままです。 コードからネットワークインタフェース を照会すると、構成された IP アドレスなどでネットワークインタフェースがまだアクティブであることがわかります。
アクティブな REPL は、いくつかの例外的な場合を除き、ソフトリセットの前後で継続して表示されます。
machine.USBDevice クラスを使ってカスタム USB インタフェースを作成した場合、リセット中にカスタム USB インターフェイスをクリアする必要があるため、内蔵の USB シリアルデバイスは切断されて再接続されるように見えます。
シリアル UART REPL は、デフォルトのハードウェア構成((ボーレートなど))を復元します。
CPU クロック速度は通常、ソフト リセットによって変更されません。
RTC 構成(つまり、現在の時刻の設定)はソフトリセットによって変更されません。
ブートシーケンス¶
MicroPython は、ハードリセットまたはソフトリセットの後のブートにおいて、次のブートシーケンスの順番にしたがいます。
_boot.py¶
これは MicroPython ファームウェアに凍結された 内部スクリプトです。これは、重要な初期化を行うために、多くのポートで MicroPython によって提供されます。
たとえば、ほとんどのポートで _boot.py
は新しいデバイスの最初のブートを検出し、 内部フラッシュのファイルシステム をフォーマットして使える状態にします。
カスタム MicroPython ビルドを作成したり、新しいポートを追加したりするのでなければ、おそらく _boot.py
について心配する必要はありません。何をしているのか本当にわかっているのでなければ、内容を変更しない方がよいでしょう。
boot.py¶
mpremote を使って、 boot.py
という名前のファイルをボード内部の ファイルシステム にコピーできます。
boot.py
が見つかると、それを実行します。 boot.py
には、カスタムの1回限りの初期化コードを追加できます(ボードのハードウェアを設定するなど)
一般的な方法は、ボードのネットワーク接続を boot.py
で設定して、 REPL や mpremote などで使えるように、リセット後に常に利用可能にしておくことです。
警告
boot.py は常に終了するようにすべきで、無期限に実行されるようにはしないでください。
ポートによっては、一部のハードウェアの初期化が boot.py
の終了後まで遅延されます。これには、stm32 ポートおよび machine.USBDevice をサポートするすべてのポートでの USB の初期化が含まれます。これらのポートで boot.py
から印字した出力は boot.py
の実行が終了するまで、内蔵 USB シリアル ポートに表示されない場合があります。
この遅い初期化の目的は、boot.py
で特定のハードウェアを事前に構成し、正しい構成で起動できるようにすることです。
注釈
boot.py
ファイルを作成せず、代わりに初期化コードを main.py
の先頭に配置する方が簡単な場合もあります。
main.py¶
boot.py
と同様に main.py
という名前のファイルをボードの内部 ファイルシステム にコピーできます。このファイルが見つかった場合は、起動プロセスの次の段階で実行されます。
main.py
はデバイスの起動時に毎回実行する Python コード用です。
main.py
使用上のヒント:
main.py
は終了する必要がないので、そこに無限ループwhile True
を入れてもかまいません。複雑な Python アプリケーションの場合、すべてのコードを
main.py
に配置する必要はありません。main.py
は、アプリケーションをインポートして実行を開始する単純なエントリ ポイントにきます。import my_app my_app.main()
これにより、アプリケーションの構造を明確に保つことができます。また、ボードに複数のアプリケーションをインストールし、それらのアプリケーションを切り替えることも簡単になります。
堅牢なアプリを作成するときは、コードがクラッシュした場合に適切なアクションを実行するために、例外ハンドラーで
main.py
の中のコードをラップすることをお勧めします。例:import machine, sys import my_app try: my_app.main() except Exception as e: print("Fatal error in main:") sys.print_exception(e) # 通常の例外や main() の終了後に、ボードをリセットします。 # KeyboardInterrupt(Ctrl-C)などの例外以外のエラーが発生した場合、このコードは # REPL (読み取り-評価-出力ループ)に移行します。常にリセットを行いたい場合は、 # finally ブロック内に machine.reset() を配置してください。 machine.reset()
さもなければ、クラッシュ後または main が終了した場合に MicroPython は REPL に戻ります(後の記載を参照)。
boot.py
で設定されたグローバル変数はmain.py
のグローバルコンテキストでも引き続き有効です。フラッシュの使用とメモリ消費を完全に最適化するには、 事前にコンパイルした
main.mpy
やboot.mpy
ファイルをファイルシステムにコピーするか、代わりにファームウェアビルドに 凍結 することもできます。raw REPL モード からソフトリセットが開始されると、
main.py
の実行はスキップされます(たとえば mpremote または別のプログラムが MicroPython と直接対話している場合など)。
対話型インタープリタ (REPL)¶
main.py
が見つからない場合、または main.py
が終了すると、 MicroPython 対話インタプリタモード (別名 REPL) が直ちに始動します。
注釈
main.py
の中に無限ループがある場合でも、REPL シリアルポートで Ctrl-C を入力すると、 KeyboardInterrupt
(キーボード割込み)が挿入されます。例外ハンドラがそれをキャッチしない場合は main.py
が終了し、REPL が始動します。
boot.py
と main.py
で設定したグローバル変数は、REPL のグローバルコンテキストでも引き続き有効です。
REPL は、Python コードがハードリセットまたはソフトリセットをトリガーするまで実行を続けます。
ソフトブリッキング(起動失敗)¶
まれではありますが、起動時に MicroPython が応答しなくなる可能性があります。この状態は「ソフトブリック」と呼ばれることもあります。例:
boot.py
の実行が立ち往生し、ネイティブ USB シリアル ポートが初期化されなくなる場合。Python コードが REPL インタフェースを再構成し、アクセスできなくなる場合。
安心してください、回復は可能です!
KeyboardInterrupt (キーボード割込み)¶
多くの場合、REPL シリアル ポートを開いて Ctrl-C
を入力すると、 KeyboardInterrupt
(キーボード割込み)が発生し、実行中のスクリプトを終了して、REPL が起動することがあります。REPL から os.remove()
を使って、動作がおかしい Python ファイルを削除できます。
import os
os.remove('main.py')
内部ファイルシステムにまだ存在するファイルを確認するには次のようにします:
import os
os.listdir()
セーフモードと工場出荷時設定へのリセット¶
REPL に簡単にアクセスできない場合は、次の2つの処理のいずれかを実行する必要があります。
「セーフ モード」ブートでは、
boot.py
とmain.py
をスキップして、直ちに REPL を始動し、クリーンアップを行えます。これは一部のポートでのみサポートされています。フラッシュファイルシステムの内容全体を消去するには、工場出荷時設定へのリセットを実行します。内部フラッシュ ファイルシステムが何らかの理由で破損した場合にも、この操作が必要になることがあります。
具体的な処理はポートごとに異なります:
上記にリンクされた特定の手順がないポートの場合、工場出荷時設定へのリセット プロセスでは、ボードのフラッシュ全体を消去し、MicroPython を最初から再度フラッシュする必要があります。通常、これには MicroPython のインストールに最初に使用したのと同じツールを使います。不明な場合は、ボードのインストールドキュメントを参照するか、 GitHub Discussions で質問してください。
警告
フラッシュ全体を消去せずにMicroPythonファームウェアを再フラッシュしても、通常はソフトブリックから回復できません。これは、ファームウェアを更新しても、ファイルシステムの内容がたいてい保持されるためです。