Последовательность сброса и загрузки¶
Устройство, работающее под управлением MicroPython, при запуске и инициализации после сброса проходит определённую последовательность загрузки.
Примечание
Последовательность _boot.py → boot.py → main.py → REPL, описанная ниже, выполняется прошивкой при каждом сбросе, независимо от способа подключения, поэтому применима всегда. Когда вы запускаете скрипт из OpenMV IDE, среда прерывает выполняемый в данный момент main.py и вместо него запускает скрипт, открытый в редакторе, используя собственный отладочный протокол. При этом она не использует REPL на устройстве, поэтому относящиеся к REPL упоминания на этой странице (интерактивное приглашение, Ctrl-D / Ctrl-C в последовательном терминале и т. д.) применимы к автономной работе и прямым сеансам последовательного терминала, тогда как сама последовательность загрузки применима во всех случаях.
Аппаратный сброс¶
Загрузка после аппаратного сброса происходит при первом включении платы — холодный старт. Это полный сброс аппаратных средств MCU.
Код порта MicroPython инициализирует все основные аппаратные средства (включая встроенные тактовые генераторы и регуляторы питания, внутренний последовательный UART и т. д.), а затем запускает среду MicroPython. Существующая конфигурация RTC может сохраняться после аппаратного сброса, но всё остальное состояние оборудования очищается.
Та же последовательность загрузки при аппаратном сбросе может быть запущена рядом событий, таких как:
Выполнение в коде Python функции
machine.reset().Нажатие пользователем физической кнопки Reset на плате (если применимо).
Выход из глубокого сна (на большинстве портов).
Сброс аппаратным сторожевым таймером (watchdog) MCU.
Срабатывание аппаратного детектора провала напряжения (brown out) MCU.
Подробности об аппаратно-зависимых причинах сброса зависят от порта и соответствующего оборудования. Для дальнейшего определения причины сброса можно использовать функцию machine.reset_cause().
Программный сброс¶
Когда MicroPython уже работает, можно вызвать программный сброс, набрав Ctrl-D в REPL или выполнив machine.soft_reset().
Программный сброс очищает интерпретатор Python, освобождает всю память Python и снова запускает среду MicroPython.
К состоянию, очищаемому программным сбросом, относится:
Все переменные, объекты, импортированные модули Python и т. д.
Большинство периферийных устройств, настроенных с помощью модуля machine. Есть очень ограниченные исключения, например режимы machine.Pin (т. е. является ли вывод входом или выходом, высоким или низким) на большинстве портов не сбрасываются. Более сложная конфигурация, такая как
Pin.irq(), сбрасывается всегда.Bluetooth.
Сетевые сокеты. Открытые сокеты TCP корректно закрываются по отношению к другой стороне.
Открытые файлы. Файловая система остаётся в корректном состоянии.
Некоторое системное состояние остаётся прежним после программного сброса, в том числе:
Любые существующие сетевые подключения (Ethernet, Wi-Fi и т. д.) остаются активными на уровне IP-сети. Запрос сетевого интерфейса из кода может показывать, что сетевой интерфейс по-прежнему активен с настроенным IP-адресом и т. д.
Активный REPL выглядит непрерывным до и после программного сброса, за исключением некоторых необычных случаев:
REPL через последовательный UART восстановит свою стандартную аппаратную конфигурацию (скорость передачи (бод) и т. д.).
Тактовая частота CPU обычно не изменяется программным сбросом.
Конфигурация RTC (т. е. установка текущего времени) не изменяется программным сбросом.
Последовательность загрузки¶
Когда MicroPython загружается после аппаратного или программного сброса, он выполняет эту последовательность загрузки по порядку:
_boot.py¶
Это внутренний скрипт, встроенный в прошивку MicroPython. Он предоставляется MicroPython на многих портах для выполнения основной инициализации.
Например, на большинстве портов _boot.py обнаруживает первую загрузку нового устройства и форматирует файловую систему внутренней флеш-памяти, подготавливая её к использованию.
Если только вы не создаёте собственную сборку MicroPython или не добавляете новый порт, вам, вероятно, не нужно беспокоиться о _boot.py. Лучше не изменять его содержимое, если вы по-настоящему не понимаете, что делаете.
boot.py¶
Файл с именем boot.py можно скопировать во внутреннюю файловую систему платы с помощью mpremote.
Если boot.py найден, он выполняется. Вы можете добавить в boot.py код для выполнения собственной разовой инициализации (например, для настройки оборудования платы).
Распространённая практика — настраивать сетевое подключение платы в boot.py, чтобы оно всегда было доступно после сброса для использования с REPL, mpremote и т. д.
Предупреждение
boot.py всегда должен завершаться и не выполняться бесконечно.
В зависимости от платы часть инициализации оборудования откладывается до завершения boot.py. Это включает инициализацию USB на камерах OpenMV Cam на базе STM32. На этих платах вывод, напечатанный из boot.py, может быть невиден на встроенном последовательном USB-порту до завершения выполнения boot.py.
Назначение этой отложенной инициализации в том, чтобы можно было предварительно настроить определённое оборудование в 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) # Following a normal Exception or main() exiting, reset the board. # Following a non-Exception error such as KeyboardInterrupt (Ctrl-C), # this code will drop to a REPL. Place machine.reset() in a finally # block to always reset, instead. machine.reset()
В противном случае MicroPython перейдёт в REPL после любого сбоя или если main завершится (см. ниже).
Любые глобальные переменные, заданные в
boot.py, по-прежнему будут установлены в глобальном контекстеmain.py.Чтобы полностью оптимизировать использование флеш-памяти и потребление памяти, вы можете скопировать предварительно скомпилированные файлы
main.mpyи/илиboot.mpyв файловую систему или даже встроить их в сборку прошивки.Выполнение
main.pyпропускается, когда программный сброс инициируется из сырого режима REPL (например, когда mpremote или другая программа взаимодействует напрямую с MicroPython).
Интерактивный интерпретатор (REPL)¶
Если main.py не найден или если main.py завершается, то Интерактивный режим интерпретатора MicroPython (он же REPL) запускается немедленно.
Примечание
Даже если main.py содержит бесконечный цикл, набор Ctrl-C на последовательном порту REPL вызовет KeyboardInterrupt. Если ни один обработчик исключений не перехватит его, то main.py завершится и запустится REPL.
Любые глобальные переменные, заданные в boot.py и main.py, по-прежнему будут установлены в глобальном контексте REPL.
REPL продолжает выполнение, пока код Python не вызовет аппаратный или программный сброс.
Программный кирпич (failure to boot)¶
Это редко, но возможно: MicroPython может перестать отвечать во время запуска — состояние, которое иногда называют «программным кирпичом» (soft bricked). Например:
Если выполнение
boot.pyзависает и встроенный последовательный USB-порт так и не инициализируется.Если код Python перенастраивает интерфейс REPL, делая его недоступным.
Будьте уверены, восстановление возможно!
Если вы используете OpenMV IDE, часто достаточно просто подключиться — среда останавливает выполняемый main.py и берёт управление на себя. Если камера вообще не подключается, используйте сброс к заводским настройкам (Factory Reset) ниже. Описанный далее метод с Ctrl-C предназначен для прямых сеансов последовательного терминала — он полагается на REPL на устройстве, который OpenMV IDE не использует.
KeyboardInterrupt¶
Во многих случаях открытие последовательного порта REPL и набор Ctrl-C вызовет KeyboardInterrupt и может привести к завершению выполняемого скрипта и запуску REPL. Из REPL вы можете использовать os.remove() для удаления некорректно работающего файла Python:
import os
os.remove('main.py')
Чтобы подтвердить, какие файлы по-прежнему присутствуют во внутренней файловой системе:
import os
os.listdir()
Сброс к заводским настройкам¶
Если вам не удаётся попасть в REPL описанным выше методом, остаётся вариант сброса к заводским настройкам: стирание всего содержимого файловой системы внутренней флеш-памяти. Это также решение, если внутренняя файловая система оказалась повреждена.
В OpenMV IDE есть несколько встроенных способов сделать это. Сначала переведите камеру в режим восстановления/загрузчика — метод различается в зависимости от платы, поэтому смотрите раздел Recovery and debug pins в кратком справочнике вашей платы о том, как в него войти. Затем нажмите кнопку подключения в OpenMV IDE и следуйте подсказкам, чтобы стереть файловую систему и перепрошить прошивку.
Предупреждение
Повторная прошивка прошивки без стирания файловой системы обычно не помогает восстановиться после программного кирпича, так как обычное обновление прошивки сохраняет содержимое файловой системы. Обязательно выберите вариант стирания, когда OpenMV IDE предложит это.
Если вы застряли, спросите на форумах OpenMV.