Trình Tự Khởi Động và Đặt Lại

Một thiết bị chạy MicroPython tuân theo một trình tự khởi động cụ thể để khởi động và tự khởi tạo sau khi đặt lại.

Ghi chú

Trình tự _boot.pyboot.pymain.py → REPL được mô tả bên dưới là những gì firmware chạy trong mỗi lần đặt lại, bất kể bạn kết nối như thế nào — vì vậy nó luôn được áp dụng. Khi bạn chạy một tập lệnh từ OpenMV IDE, IDE ngắt main.py đang chạy hiện tại và thay thế bằng tập lệnh đang mở trong trình soạn thảo, thông qua giao thức gỡ lỗi riêng của nó. Nó không sử dụng REPL trên thiết bị, vì vậy các tham chiếu dành riêng cho REPL trên trang này (dấu nhắc tương tác, Ctrl-D / Ctrl-C tại terminal nối tiếp, v.v.) áp dụng cho hoạt động độc lập và các phiên terminal nối tiếp trực tiếp — nhưng bản thân trình tự khởi động áp dụng trong tất cả các trường hợp.

Đặt lại cứng

Khởi động từ đặt lại cứng là những gì xảy ra khi một bo mạch được cấp nguồn lần đầu tiên, khởi động nguội. Đây là đặt lại hoàn toàn phần cứng MCU.

Mã cổng MicroPython khởi tạo tất cả phần cứng thiết yếu (bao gồm đồng hồ nhúng và bộ điều chỉnh điện, UART nối tiếp nội bộ, v.v.), sau đó khởi động môi trường MicroPython. Cấu hình RTC hiện có có thể được giữ lại sau khi đặt lại cứng, nhưng tất cả các trạng thái phần cứng khác đều bị xóa.

Cùng một trình tự khởi động đặt lại cứng có thể được kích hoạt bởi một số sự kiện như:

  • Mã Python thực thi machine.reset().

  • Người dùng nhấn nút Đặt lại vật lý trên bo mạch (nếu có).

  • Thức dậy từ chế độ ngủ sâu (trên hầu hết các cổng).

  • Đặt lại watchdog phần cứng MCU.

  • Bộ phát hiện điện áp thấp phần cứng MCU.

Chi tiết về các bộ kích hoạt đặt lại dành riêng cho phần cứng phụ thuộc vào cổng và phần cứng liên quan. Hàm machine.reset_cause() có thể được sử dụng để xác định thêm nguyên nhân của việc đặt lại.

Đặt lại mềm

Khi MicroPython đang chạy, có thể kích hoạt đặt lại mềm bằng cách gõ Ctrl-D trong REPL hoặc thực thi machine.soft_reset().

Đặt lại mềm xóa trình thông dịch Python, giải phóng tất cả bộ nhớ Python và khởi động lại môi trường MicroPython.

Các trạng thái bị xóa bởi đặt lại mềm bao gồm:

  • Tất cả các biến Python, đối tượng, các mô-đun đã nhập, v.v.

  • Hầu hết các ngoại vi được cấu hình bằng module machine. Có rất ít ngoại lệ, ví dụ: chế độ machine.Pin (tức là nếu một chân (pin) là đầu vào hay đầu ra, cao hay thấp) không được đặt lại trên hầu hết các cổng. Cấu hình nâng cao hơn như Pin.irq() luôn được đặt lại.

  • Bluetooth.

  • Socket mạng. Các socket TCP đang mở được đóng sạch sẽ đối với phía kia.

  • Các file đang mở. Hệ thống tệp được để lại ở trạng thái hợp lệ.

Một số trạng thái hệ thống vẫn giữ nguyên sau khi đặt lại mềm, bao gồm:

  • Bất kỳ kết nối mạng hiện có nào (Ethernet, Wi-Fi, v.v.) vẫn hoạt động ở lớp Mạng IP. Truy vấn giao diện mạng từ mã có thể cho biết giao diện mạng vẫn đang hoạt động với địa chỉ IP được cấu hình, v.v.

  • Một REPL đang hoạt động xuất hiện liên tục trước và sau khi đặt lại mềm, ngoại trừ một số trường hợp bất thường:

    • UART nối tiếp REPL sẽ khôi phục cấu hình phần cứng mặc định của nó (tốc độ baud, v.v.).

  • Tốc độ xung nhịp CPU thường không thay đổi bởi đặt lại mềm.

  • Cấu hình RTC (tức là cài đặt thời gian hiện tại) không thay đổi bởi đặt lại mềm.

Trình Tự Khởi Động

Khi MicroPython khởi động sau khi đặt lại cứng hoặc mềm, nó tuân theo trình tự khởi động này theo thứ tự:

_boot.py

Đây là tập lệnh nội bộ được đóng gói vào firmware MicroPython. Nó được MicroPython cung cấp trên nhiều cổng để thực hiện khởi tạo thiết yếu.

Ví dụ: trên hầu hết các cổng, _boot.py sẽ phát hiện lần khởi động đầu tiên của thiết bị mới và định dạng hệ thống tệp flash nội bộ sẵn sàng sử dụng.

Trừ khi bạn đang tạo bản build MicroPython tùy chỉnh hoặc thêm cổng mới, bạn có thể không cần lo lắng về _boot.py. Tốt nhất là không thay đổi nội dung trừ khi bạn thực sự biết mình đang làm gì.

boot.py

Một file có tên boot.py có thể được sao chép vào hệ thống tệp nội bộ của bo mạch bằng cách sử dụng mpremote.

Nếu boot.py được tìm thấy thì nó sẽ được thực thi. Bạn có thể thêm mã vào boot.py để thực hiện khởi tạo tùy chỉnh một lần (ví dụ: để cấu hình phần cứng của bo mạch).

Thông lệ phổ biến là cấu hình kết nối mạng của bo mạch trong boot.py để nó luôn có sẵn sau khi đặt lại để sử dụng với REPL, mpremote, v.v.

Cảnh báo

boot.py nên luôn thoát và không chạy vô thời hạn.

Tùy thuộc vào bo mạch, một số khởi tạo phần cứng bị trì hoãn cho đến sau khi boot.py thoát. Điều này bao gồm khởi tạo USB trên các OpenMV Cam dựa trên STM32. Trên các bo mạch này, đầu ra được in từ boot.py có thể không hiển thị trên cổng nối tiếp USB tích hợp cho đến sau khi boot.py chạy xong.

Mục đích của quá trình khởi tạo muộn này là để có thể cấu hình trước phần cứng cụ thể trong boot.py, rồi khởi động nó với cấu hình chính xác.

Ghi chú

Đôi khi đơn giản hơn là không có file boot.py và thay vào đó đặt bất kỳ mã khởi tạo nào ở đầu main.py.

main.py

Tương tự như boot.py, một file có tên main.py có thể được sao chép vào hệ thống tệp nội bộ của bo mạch. Nếu tìm thấy thì nó sẽ được thực thi tiếp theo trong quá trình khởi động.

main.py là dành cho bất kỳ mã Python nào bạn muốn chạy mỗi khi thiết bị của bạn khởi động.

Một số mẹo sử dụng main.py:

  • main.py không nhất thiết phải thoát, hãy tự nhiên đặt vòng lặp while True vô hạn trong đó.

  • Đối với các ứng dụng Python phức tạp, bạn không cần phải đặt tất cả mã của mình vào main.py. main.py có thể là điểm vào đơn giản để nhập ứng dụng và bắt đầu thực thi:

    import my_app
    my_app.main()
    

    Điều này có thể giúp giữ cho cấu trúc ứng dụng của bạn rõ ràng. Nó cũng giúp dễ dàng cài đặt nhiều ứng dụng trên bo mạch và chuyển đổi giữa chúng.

  • Thực hành tốt khi viết ứng dụng mạnh mẽ là bọc mã trong main.py với bộ xử lý ngoại lệ để thực hiện hành động thích hợp nếu mã bị lỗi. Ví dụ:

    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()
    

    Nếu không, MicroPython sẽ chuyển sang REPL sau bất kỳ sự cố nào hoặc nếu main thoát (xem bên dưới).

  • Bất kỳ biến toàn cục nào được đặt trong boot.py vẫn sẽ được đặt trong ngữ cảnh toàn cục của main.py.

  • Để tối ưu hóa hoàn toàn việc sử dụng bộ nhớ flash và tiêu thụ bộ nhớ, bạn có thể sao chép các file main.mpy và/hoặc boot.mpy đã được biên dịch trước vào hệ thống tệp, hoặc thậm chí đóng gói chúng vào bản build firmware thay thế.

  • Thực thi main.py bị bỏ qua khi đặt lại mềm được khởi tạo từ chế độ REPL thô (ví dụ: khi mpremote hoặc chương trình khác đang tương tác trực tiếp với MicroPython).

Trình Thông Dịch Tương Tác (REPL)

Nếu main.py không được tìm thấy, hoặc nếu main.py thoát, thì Chế độ Trình thông dịch Tương tác MicroPython (hay còn gọi là REPL) sẽ khởi động ngay lập tức.

Ghi chú

Ngay cả khi main.py chứa vòng lặp vô hạn, gõ Ctrl-C trên cổng nối tiếp REPL sẽ chèn một KeyboardInterrupt. Nếu không có bộ xử lý ngoại lệ nào bắt được nó thì main.py sẽ thoát và REPL sẽ khởi động.

Bất kỳ biến toàn cục nào được đặt trong boot.pymain.py vẫn sẽ được đặt trong ngữ cảnh toàn cục của REPL.

REPL tiếp tục thực thi cho đến khi mã Python kích hoạt đặt lại cứng hoặc mềm.

Soft Bricking (không thể khởi động)

Rất hiếm nhưng MicroPython có thể trở nên không phản hồi trong quá trình khởi động, một trạng thái đôi khi được gọi là "soft bricked". Ví dụ:

  • Nếu thực thi boot.py bị kẹt và cổng nối tiếp USB gốc không bao giờ được khởi tạo.

  • Nếu mã Python cấu hình lại giao diện REPL, làm cho nó không thể truy cập được.

Hãy yên tâm, việc khôi phục là có thể!

Nếu bạn sử dụng OpenMV IDE, chỉ cần kết nối thường là đủ — IDE dừng main.py đang chạy và tiếp quản. Nếu camera không kết nối được, hãy sử dụng Factory Reset bên dưới. Phương pháp Ctrl-C được mô tả tiếp theo dành cho các phiên terminal nối tiếp trực tiếp — nó dựa vào REPL trên thiết bị, mà OpenMV IDE không sử dụng.

KeyboardInterrupt

Trong nhiều trường hợp, mở cổng nối tiếp REPL và gõ Ctrl-C sẽ chèn KeyboardInterrupt và có thể khiến tập lệnh đang chạy thoát ra và REPL khởi động. Từ REPL, bạn có thể sử dụng os.remove() để xóa file Python có vấn đề:

import os
os.remove('main.py')

Để xác nhận những file nào vẫn còn trong hệ thống tệp nội bộ:

import os
os.listdir()

Factory Reset

Nếu bạn không thể truy cập REPL bằng phương pháp trên, tùy chọn còn lại là đặt lại nhà máy: xóa toàn bộ nội dung của hệ thống tệp flash nội bộ. Đây cũng là cách khắc phục nếu hệ thống tệp nội bộ bị hỏng.

OpenMV IDE có một số cách tích hợp để thực hiện điều này. Đầu tiên hãy đưa camera vào chế độ khôi phục/bootloader — phương pháp khác nhau tùy theo bo mạch, vì vậy hãy xem phần Recovery and debug pins trong quick reference của bo mạch để biết cách vào chế độ đó. Sau đó nhấp vào nút kết nối trong OpenMV IDE và làm theo hướng dẫn để xóa hệ thống tệp và nạp lại firmware.

Cảnh báo

Nạp lại firmware mà không xóa hệ thống tệp thường sẽ không khôi phục được từ trạng thái soft bricking, vì bản cập nhật firmware bình thường sẽ bảo toàn nội dung của hệ thống tệp. Hãy nhớ chọn tùy chọn xóa khi OpenMV IDE nhắc.

Nếu bạn bị mắc kẹt, hãy hỏi trên diễn đàn OpenMV.