Послідовність скидання та завантаження

Пристрій, що виконує MicroPython, дотримується певної послідовності завантаження для запуску та ініціалізації після скидання.

Примітка

Послідовність _boot.pyboot.pymain.py → REPL, описана нижче, виконується мікропрограмою при кожному скиданні, незалежно від способу підключення — вона застосовується завжди. Коли ви запускаєте скрипт з OpenMV IDE, IDE перериває виконання поточного main.py і запускає скрипт, відкритий у редакторі, замість нього через власний протокол налагодження. При цьому не використовується REPL на пристрої, тому специфічні для REPL посилання на цій сторінці (інтерактивний запит, Ctrl-D / Ctrl-C у послідовному терміналі тощо) стосуються автономної роботи та прямих сеансів через послідовний термінал — але сама послідовність завантаження застосовується у всіх випадках.

Апаратне скидання

Завантаження після апаратного скидання відбувається, коли плата вперше вмикається — це так зване холодне завантаження. Це повне скидання апаратного забезпечення мікроконтролера.

Портовий код MicroPython ініціалізує все необхідне апаратне забезпечення (включно з вбудованими тактовими генераторами та стабілізаторами живлення, внутрішнім послідовним UART тощо), а потім запускає середовище MicroPython. Після апаратного скидання може зберігатися конфігурація RTC, але всі інші стани апаратного забезпечення очищуються.

Таку ж послідовність апаратного завантаження може ініціювати низка подій, наприклад:

  • Виконання Python-коду machine.reset().

  • Користувач натискає фізичну кнопку скидання на платі (де це застосовно).

  • Вихід із глибокого сну (на більшості портів).

  • Скидання апаратного сторожового таймера мікроконтролера.

  • Детектор просідання напруги апаратного забезпечення мікроконтролера.

Деталі апаратно-залежних тригерів скидання залежать від порту та відповідного апаратного забезпечення. Функція 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 виглядає безперервним до та після програмного скидання, за винятком деяких незвичайних випадків:

    • Послідовний UART REPL відновлює свою стандартну апаратну конфігурацію (швидкість передачі (бод) тощо).

  • Тактова частота 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 Cams на базі 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-код не ініціює апаратне або програмне скидання.

Програмне «цеглування» (збій завантаження)

Рідко, але можливо, що MicroPython не реагує під час запуску — стан, який іноді називають «програмним цеглуванням». Наприклад:

  • Якщо виконання boot.py зависає і власний послідовний порт USB ніколи не ініціалізується.

  • Якщо Python-код перенастроює інтерфейс REPL, роблячи його недоступним.

Будьте спокійні — відновлення можливе!

Якщо ви використовуєте OpenMV IDE, просте підключення часто є достатнім — 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()

Factory Reset

Якщо ви не можете потрапити до REPL за допомогою описаного вище методу, залишається варіант factory reset: стирання всього вмісту внутрішньої флеш-файлової системи. Це також вирішення проблеми, якщо внутрішня файлова система пошкоджена.

OpenMV IDE має кілька вбудованих способів зробити це. Спочатку переведіть камеру в режим відновлення/завантажувача — метод відрізняється залежно від плати, тому дивіться розділ Recovery and debug pins у короткому довіднику вашої плати, щоб дізнатися, як увійти в нього. Потім натисніть кнопку підключення в OpenMV IDE і дотримуйтесь підказок для стирання файлової системи та перепрошивання мікропрограми.

Попередження

Перепрошивання мікропрограми без стирання файлової системи зазвичай не допоможе при програмному «цеглуванні», оскільки звичайне оновлення мікропрограми зберігає вміст файлової системи. Обов’язково виберіть параметр стирання, коли OpenMV IDE запропонує це.

Якщо виникнуть труднощі, запитайте на форумі OpenMV.