Sequência de Reset e Inicialização¶
Um dispositivo executando MicroPython segue uma sequência de inicialização específica para ligar e se inicializar após um reset.
Nota
A sequência _boot.py → boot.py → main.py → REPL descrita abaixo é o que o firmware executa a cada reset, independentemente de como você se conecta — portanto, ela sempre se aplica. Quando você executa um script a partir do OpenMV IDE, a IDE interrompe o main.py em execução e roda o script aberto no editor em seu lugar, usando seu próprio protocolo de depuração. Ela não usa o REPL no dispositivo, então as referências específicas do REPL nesta página (o prompt interativo, Ctrl-D / Ctrl-C em um terminal serial, etc.) se aplicam à operação autônoma e a sessões diretas de terminal serial — mas a sequência de inicialização em si se aplica em todos os casos.
Hard reset¶
Inicializar a partir de um hard reset é o que acontece quando uma placa é ligada pela primeira vez, uma partida a frio. Este é um reset completo do hardware do MCU.
O código de porte do MicroPython inicializa todo o hardware essencial (incluindo clocks embarcados e reguladores de energia, UART serial interna, etc.) e, em seguida, inicia o ambiente MicroPython. A configuração existente do RTC pode ser mantida após um hard reset, mas todo o restante do estado do hardware é apagado.
A mesma sequência de inicialização por hard reset pode ser disparada por uma série de eventos, tais como:
Código Python executando
machine.reset().O usuário pressiona um botão físico de Reset na placa (quando aplicável).
Acordar do sono profundo (na maioria dos portes).
Reset do watchdog de hardware do MCU.
Detector de queda de tensão (brown out) do hardware do MCU.
Os detalhes dos disparadores de reset específicos do hardware dependem do porte e do hardware associado. A função machine.reset_cause() pode ser usada para determinar com mais precisão a causa de um reset.
Soft Reset¶
Quando o MicroPython já está em execução, é possível disparar um soft reset digitando Ctrl-D no REPL ou executando machine.soft_reset().
Um soft reset limpa o interpretador Python, libera toda a memória do Python e inicia o ambiente MicroPython novamente.
O estado que é apagado por um soft reset inclui:
Todas as variáveis, objetos, módulos importados Python, etc.
A maioria dos periféricos configurados usando o módulo machine. Há exceções muito limitadas; por exemplo, os modos do machine.Pin (isto é, se um pino é entrada ou saída, alto ou baixo) não são resetados na maioria dos portes. Configurações mais avançadas, como
Pin.irq(), são sempre resetadas.Bluetooth.
Sockets de rede. Sockets TCP abertos são fechados de forma limpa em relação à outra parte.
Arquivos abertos. O sistema de arquivos é deixado em um estado válido.
Parte do estado do sistema permanece a mesma após um soft reset, incluindo:
Quaisquer conexões de rede existentes (Ethernet, Wi-Fi, etc.) permanecem ativas na camada de rede IP. Consultar a 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 parece contínuo antes e depois do soft reset, exceto em alguns casos incomuns:
Um REPL via UART serial restaurará sua configuração de hardware padrão (taxa de transmissão (baud rate), etc.).
A velocidade do clock da CPU normalmente não é alterada por um soft reset.
A configuração do RTC (isto é, o ajuste da hora atual) não é alterada pelo soft reset.
Sequência de Inicialização¶
Quando o MicroPython inicializa após um hard reset ou soft reset, ele segue esta sequência de inicialização em ordem:
_boot.py¶
Este é um script interno congelado no firmware do MicroPython. Ele é fornecido pelo MicroPython em muitos portes para realizar a inicialização essencial.
Por exemplo, na maioria dos portes o _boot.py detectará a primeira inicialização de um novo dispositivo e formatará o sistema de arquivos da flash interna, deixando-o pronto para uso.
A menos que você esteja criando um build personalizado do MicroPython ou adicionando um novo porte, provavelmente não precisa se preocupar com o _boot.py. É melhor não alterar seu conteúdo, a não ser que você realmente saiba o que está fazendo.
boot.py¶
Um arquivo chamado boot.py pode ser copiado para o sistema de arquivos interno da placa usando o mpremote.
Se o boot.py for encontrado, ele é executado. Você pode adicionar código no boot.py para realizar uma inicialização personalizada única (por exemplo, para configurar o hardware da placa).
Uma prática comum é configurar a conexão de rede da placa no boot.py para que ela esteja sempre disponível após o reset, para uso com o REPL, o mpremote, etc.
Aviso
o boot.py deve sempre encerrar e não rodar indefinidamente.
Dependendo da placa, parte da inicialização do hardware é adiada até depois que o boot.py encerra. Isso inclui a inicialização do USB nas OpenMV Cams baseadas em STM32. Nessas placas, a saída impressa pelo boot.py pode não ficar visível na porta serial USB embutida até que o boot.py termine de rodar.
O objetivo dessa inicialização tardia é tornar possível pré-configurar determinado hardware no boot.py e, então, fazê-lo iniciar com a configuração correta.
Nota
Às vezes é mais simples não ter um arquivo boot.py e colocar qualquer código de inicialização no topo do main.py em vez disso.
main.py¶
Semelhante ao boot.py, um arquivo chamado main.py pode ser copiado para o sistema de arquivos interno da placa. Se encontrado, ele é executado em seguida no processo de inicialização.
O main.py serve para qualquer código Python que você queira executar toda vez que o dispositivo iniciar.
Algumas dicas para o uso do main.py:
O
main.pynão precisa encerrar; fique à vontade para colocar um laço infinitowhile Truenele.Para aplicações Python complexas, você não precisa colocar todo o seu código no
main.py. Omain.pypode ser um ponto de entrada simples que importa sua aplicação e inicia a execução:import my_app my_app.main()
Isso pode ajudar a manter clara a estrutura da sua aplicação. Também facilita instalar várias aplicações em uma placa e alternar entre elas.
É uma boa prática, ao escrever aplicações robustas, envolver o código no
main.pycom um tratador de exceções para tomar a ação apropriada caso o código falhe. 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 cairá no REPL após qualquer falha ou se o main encerrar (veja abaixo).
Quaisquer variáveis globais que foram definidas no
boot.pyainda estarão definidas no contexto global domain.py.Para otimizar totalmente o uso da flash e o consumo de memória, você pode copiar arquivos
main.mpye/ouboot.mpypré-compilados para o sistema de arquivos, ou até mesmo congelá-los no build do firmware.A execução do
main.pyé ignorada quando um soft reset é iniciado a partir do modo raw REPL (por exemplo, quando o mpremote ou outro programa está interagindo diretamente com o MicroPython).
Interpretador Interativo (REPL)¶
Se o main.py não for encontrado, ou se o main.py encerrar, então o O Modo Interpretador Interativo do MicroPython (também conhecido como REPL) iniciará imediatamente.
Nota
Mesmo que o main.py contenha um laço infinito, digitar Ctrl-C na porta serial do REPL injetará um KeyboardInterrupt. Se nenhum tratador de exceções o capturar, então o main.py encerrará e o REPL iniciará.
Quaisquer variáveis globais que foram definidas no boot.py e no main.py ainda estarão definidas no contexto global do REPL.
O REPL continua executando até que o código Python dispare um hard ou soft reset.
Soft Bricking (falha ao inicializar)¶
É raro, mas é possível que o MicroPython fique sem resposta durante a inicialização, um estado às vezes chamado de “soft bricked”. Por exemplo:
Se a execução do
boot.pytravar e a porta serial USB nativa nunca for inicializada.Se o código Python reconfigurar a interface do REPL, tornando-a inacessível.
Fique tranquilo, a recuperação é possível!
Se você usa o OpenMV IDE, simplesmente conectar costuma ser suficiente — a IDE interrompe o main.py em execução e assume o controle. Se a câmera não conectar de jeito nenhum, use o Factory Reset abaixo. O método com Ctrl-C descrito a seguir é para sessões diretas de terminal serial — ele depende do REPL no dispositivo, que o OpenMV IDE não utiliza.
KeyboardInterrupt¶
Em muitos casos, abrir a porta serial do REPL e digitar Ctrl-C injetará um KeyboardInterrupt e pode fazer com que o script em execução encerre e um REPL inicie. A partir do REPL, você pode usar os.remove() para remover o arquivo Python problemático:
import os
os.remove('main.py')
Para confirmar quais arquivos ainda estão presentes no sistema de arquivos interno:
import os
os.listdir()
Factory Reset¶
Se você não conseguir acessar um REPL usando o método acima, a opção restante é um factory reset: apagar todo o conteúdo do sistema de arquivos da flash interna. Esta também é a solução caso o sistema de arquivos interno tenha ficado corrompido.
O OpenMV IDE possui várias formas embutidas de fazer isso. Primeiro coloque a câmera em seu modo de recuperação/bootloader — o método varia conforme a placa, então consulte a seção Recovery and debug pins da referência rápida da sua placa para saber como entrar nele. Em seguida, clique no botão de conectar no OpenMV IDE e siga as instruções para apagar o sistema de arquivos e regravar o firmware.
Aviso
Regravar o firmware sem apagar o sistema de arquivos geralmente não recupera o dispositivo de um soft bricking, pois uma atualização normal de firmware preserva o conteúdo do sistema de arquivos. Certifique-se de escolher a opção de apagar quando o OpenMV IDE solicitar.
Se você ficar travado, pergunte nos fóruns da OpenMV.