Sequência de Reset e Arranque¶
Um dispositivo a executar MicroPython segue uma sequência de arranque específica para iniciar e inicializar-se após um reset.
Nota
A sequência _boot.py → boot.py → main.py → REPL descrita abaixo é o que o firmware executa em cada reset, independentemente de como se liga — portanto aplica-se sempre. Quando executa um script a partir do OpenMV IDE, o IDE interrompe o main.py em execução e executa em seu lugar o script aberto no editor, através do seu próprio protocolo de depuração. Não utiliza o REPL do dispositivo, pelo que as referências específicas ao REPL nesta página (a linha de comandos interativa, Ctrl-D / Ctrl-C num terminal série, etc.) aplicam-se ao funcionamento autónomo e a sessões diretas de terminal série — mas a sequência de arranque em si aplica-se em todos os casos.
Reset forçado¶
O arranque após reset forçado é o que acontece quando uma placa é ligada pela primeira vez, um arranque a frio. Trata-se de um reset completo do hardware do MCU.
O código do port MicroPython inicializa todo o hardware essencial (incluindo relógios embebidos e reguladores de tensão, UART série interno, etc.) e depois inicia o ambiente MicroPython. A configuração existente do RTC pode ser mantida após um reset forçado, mas todos os outros estados de hardware são limpos.
A mesma sequência de arranque após reset forçado pode ser desencadeada por vários eventos, tais como:
Código Python a executar
machine.reset().O utilizador prime um botão físico de Reset na placa (quando aplicável).
Despertar do modo de sono profundo (na maioria dos ports).
Reset do watchdog de hardware do MCU.
Detetor de subtensão de hardware do MCU.
Os detalhes dos gatilhos de reset específicos do hardware dependem do port e do hardware associado. A função machine.reset_cause() pode ser utilizada para determinar melhor a causa de um reset.
Reset suave¶
Quando o MicroPython já está em execução, é possível desencadear um reset suave digitando Ctrl-D no REPL ou executando machine.soft_reset().
Um reset suave limpa o interpretador Python, liberta toda a memória Python e reinicia o ambiente MicroPython.
O estado que é limpo por um reset suave inclui:
Todas as variáveis Python, objetos, módulos importados, etc.
A maioria dos periféricos configurados com o módulo machine. Existem exceções muito limitadas; por exemplo, os modos de machine.Pin (ou seja, se um pino é entrada ou saída, alto ou baixo) não são repostos na maioria dos ports. Configurações mais avançadas como
Pin.irq()são sempre repostas.Bluetooth.
Sockets de rede. Os sockets TCP abertos são fechados de forma limpa em relação à outra parte.
Ficheiros abertos. O sistema de ficheiros é deixado num estado válido.
Algum estado do sistema permanece igual após um reset suave, incluindo:
Quaisquer ligações de rede existentes (Ethernet, Wi-Fi, etc.) permanecem ativas na camada de Rede IP. A consulta da interface de rede a partir do código pode indicar que a interface de rede ainda está ativa com um endereço IP configurado, etc.
Um REPL ativo aparece de forma contínua antes e depois do reset suave, exceto em alguns casos invulgares:
Um REPL de UART série irá restaurar a sua configuração de hardware predefinida (taxa de baud, etc.).
A velocidade do relógio da CPU normalmente não é alterada por um reset suave.
A configuração do RTC (ou seja, a definição da hora atual) não é alterada pelo reset suave.
Sequência de Arranque¶
Quando o MicroPython arranca após um reset forçado ou suave, segue esta sequência de arranque por ordem:
_boot.py¶
Este é um script interno incorporado no firmware MicroPython. É fornecido pelo MicroPython em muitos ports para realizar a inicialização essencial.
Por exemplo, na maioria dos ports, o _boot.py irá detetar o primeiro arranque de um novo dispositivo e formatar o sistema de ficheiros flash interno pronto para utilização.
A menos que esteja a criar uma compilação personalizada do MicroPython ou a adicionar um novo port, provavelmente não precisa de se preocupar com o _boot.py. É preferível não alterar o conteúdo a não ser que saiba mesmo o que está a fazer.
boot.py¶
Um ficheiro chamado boot.py pode ser copiado para o sistema de ficheiros interno da placa usando mpremote.
Se o boot.py for encontrado, então é executado. Pode adicionar código em boot.py para realizar inicialização personalizada única (por exemplo, para configurar o hardware da placa).
Uma prática comum é configurar a ligação de rede de uma placa em boot.py para que esteja sempre disponível após o reset para utilização com o REPL, mpremote, etc.
Aviso
O boot.py deve sempre terminar e não executar indefinidamente.
Dependendo da placa, alguma inicialização de hardware é adiada até após a saída do boot.py. Isto inclui a inicialização do USB nas OpenMV Cams baseadas em STM32. Nessas placas, a saída impressa a partir do boot.py pode não ser visível na porta série USB integrada até que o boot.py termine de executar.
O objetivo desta inicialização tardia é possibilitar a pré-configuração de hardware específico em boot.py e depois iniciá-lo com a configuração correta.
Nota
Por vezes é mais simples não ter um ficheiro boot.py e colocar qualquer código de inicialização no início do main.py.
main.py¶
De forma semelhante ao boot.py, um ficheiro chamado main.py pode ser copiado para o sistema de ficheiros interno da placa. Se for encontrado, é executado a seguir no processo de arranque.
O main.py destina-se a qualquer código Python que pretenda executar de cada vez que o seu dispositivo arrancar.
Algumas dicas para a utilização do main.py:
O
main.pynão tem de terminar; à vontade para colocar um ciclowhile Trueinfinito.Para aplicações Python complexas, não precisa de colocar todo o código em
main.py. Omain.pypode ser um ponto de entrada simples que importa a sua aplicação e inicia a execução:import my_app my_app.main()
Isto pode ajudar a manter clara a estrutura da sua aplicação. Também facilita a instalação de múltiplas aplicações numa placa e a alternância entre elas.
É boa prática, ao escrever aplicações robustas, envolver o código em
main.pycom um tratador de exceções para tomar a ação adequada se o código falhar. Por exemplo: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()
Caso contrário, o MicroPython passará para o REPL após qualquer falha ou se o main terminar (ver abaixo).
Quaisquer variáveis globais que tenham sido definidas em
boot.pyainda estarão definidas no contexto global demain.py.Para otimizar totalmente a utilização do flash e o consumo de memória, pode copiar ficheiros
main.mpye/ouboot.mpypré-compilados para o sistema de ficheiros, ou mesmo incorporá-los na compilação do firmware.A execução do
main.pyé ignorada quando um reset suave é iniciado a partir do modo REPL bruto (por exemplo, quando o mpremote ou outro programa está a interagir diretamente com o MicroPython).
Interpretador Interativo (REPL)¶
Se o main.py não for encontrado, ou se o main.py terminar, então o O Modo de Interpretador Interativo do MicroPython (também conhecido como REPL) iniciará imediatamente.
Nota
Mesmo que o main.py contenha um ciclo infinito, digitar Ctrl-C na porta série REPL irá injetar um KeyboardInterrupt. Se nenhum tratador de exceções o capturar, o main.py irá terminar e o REPL iniciará.
Quaisquer variáveis globais que tenham sido definidas em boot.py e main.py ainda estarão definidas no contexto global do REPL.
O REPL continua a executar até que o código Python desencadeie um reset forçado ou suave.
Bloqueio Suave (falha no arranque)¶
É raro mas possível que o MicroPython fique sem resposta durante o arranque, um estado por vezes chamado de «bloqueio suave». Por exemplo:
Se a execução do
boot.pyficar bloqueada e a porta série USB nativa nunca inicializar.Se o código Python reconfigurar a interface REPL, tornando-a inacessível.
Fique descansado, a recuperação é possível!
Se usar o OpenMV IDE, simplesmente ligar é frequentemente suficiente — o IDE para o main.py em execução e assume o controlo. Se a câmara não conseguir ligar de todo, use a opção Factory Reset abaixo. O método Ctrl-C descrito a seguir é para sessões diretas de terminal série — depende do REPL no dispositivo, que o OpenMV IDE não utiliza.
KeyboardInterrupt¶
Em muitos casos, abrir a porta série REPL e digitar Ctrl-C irá injetar KeyboardInterrupt e pode fazer com que o script em execução termine e um REPL inicie. A partir do REPL, pode usar os.remove() para remover o ficheiro Python com comportamento indevido:
import os
os.remove('main.py')
Para confirmar quais os ficheiros ainda presentes no sistema de ficheiros interno:
import os
os.listdir()
Factory Reset¶
Se não conseguir aceder a um REPL usando o método acima, a opção restante é uma reposição de fábrica: apagar todo o conteúdo do sistema de ficheiros flash interno. Esta é também a solução se o sistema de ficheiros interno ficar corrompido.
O OpenMV IDE tem várias formas integradas de o fazer. Primeiro coloque a câmara no modo de recuperação/bootloader — o método difere por placa, por isso consulte a secção Recovery and debug pins da referência rápida da sua placa para saber como entrar nesse modo. Depois clique no botão de ligação no OpenMV IDE e siga as instruções para apagar o sistema de ficheiros e re-instalar o firmware.
Aviso
Re-instalar o firmware sem apagar o sistema de ficheiros normalmente não recupera de um bloqueio suave, pois uma atualização normal de firmware preserva o conteúdo do sistema de ficheiros. Certifique-se de escolher a opção de apagar quando o OpenMV IDE solicitar.
Se ficar bloqueado, pergunte nos fóruns OpenMV.