리셋 및 부팅 시퀀스¶
MicroPython을 실행하는 장치는 리셋 후 시작 및 초기화를 위해 특정한 부팅 시퀀스를 따릅니다.
참고
아래에서 설명하는 _boot.py → boot.py → main.py → REPL 시퀀스는 연결 방식에 관계없이 펌웨어가 모든 리셋 시에 실행하는 과정이므로 항상 적용됩니다. OpenMV IDE에서 스크립트를 실행하면 IDE는 현재 실행 중인 main.py를 중단하고, 자체 디버그 프로토콜을 통해 에디터에 열려 있는 스크립트를 대신 실행합니다. 이때 장치의 REPL을 사용하지 않으므로, 이 페이지의 REPL 전용 참조 항목(대화형 프롬프트, 시리얼 터미널에서의 Ctrl-D / Ctrl-C 등)은 독립 실행 동작 및 직접 시리얼 터미널 세션에 적용됩니다. 다만 부팅 시퀀스 자체는 모든 경우에 적용됩니다.
하드 리셋¶
하드 리셋으로부터 부팅하는 것은 보드에 처음 전원이 들어올 때 발생하는 동작, 즉 콜드 부팅입니다. 이는 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 모드(즉, 핀이 입력인지 출력인지, 하이인지 로우인지)는 대부분의 포트에서 리셋되지 않습니다.
Pin.irq()와 같은 더 고급 구성은 항상 리셋됩니다.Bluetooth.
네트워크 소켓. 열려 있는 TCP 소켓은 상대방에 대해 정상적으로 닫힙니다.
열려 있는 파일. 파일 시스템은 유효한 상태로 유지됩니다.
소프트 리셋 후에도 동일하게 유지되는 일부 시스템 상태에는 다음이 포함됩니다:
기존의 모든 네트워크 연결(이더넷, 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가 종료된 후까지 지연됩니다. 여기에는 STM32 기반 OpenMV Cam에서의 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) # 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은 충돌이 발생하거나 main이 종료될 때(아래 참조) REPL로 떨어집니다.
boot.py에서 설정된 모든 전역 변수는main.py의 전역 컨텍스트에서도 여전히 설정되어 있습니다.플래시 사용량과 메모리 소비를 완전히 최적화하려면 사전 컴파일된
main.mpy및/또는boot.mpy파일을 파일 시스템에 복사하거나, 심지어 펌웨어 빌드에 프리즈할 수도 있습니다.main.py실행은 로 REPL 모드에서 소프트 리셋이 시작될 때(예: 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 인터페이스를 재구성하여 접근할 수 없게 만드는 경우.
안심하세요, 복구는 가능합니다!
OpenMV IDE를 사용하는 경우 단순히 연결하는 것만으로 충분한 경우가 많습니다. IDE가 실행 중인 main.py를 멈추고 제어를 넘겨받습니다. 카메라가 전혀 연결되지 않는다면 아래의 공장 초기화를 사용하세요. 다음에 설명하는 Ctrl-C 방법은 직접 시리얼 터미널 세션을 위한 것으로, OpenMV IDE가 사용하지 않는 장치의 REPL에 의존합니다.
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 포럼에서 문의하세요.