Como é o fluxo de um programa para ESP32

O fluxo de um programa para ESP32 será explorado neste artigo desde o primeiro estágio de boot, abordando alguns pontos importantes, até a chamada do app_main(). De maneira básica sem se aprofundar, assim, sendo uma análise importante para àqueles que querem entender esse processo, bem como, àqueles que necessitam customizar o boot de segundo estágio, o qual veremos a seguir. Desta forma, este artigo será dividido da seguinte maneira:

Além do conteúdo que será abordado aqui, a seguir, algumas recomendações de leituras relacionadas, veja:

Artigos relacionados

1. Bootloader de primeiro estágio

Após o processo de reset do módulo ESP32 ou SoC (System on Chip), como é também conhecido, o bootloader de primeiro estágio será executado. O firmware desenvolvido para execução desta parte, foi elaborado pela Espressif e está armazenado em uma memória não volátil, ou seja, numa memória ROM (Read Only Memory).

Conforme citado acima, o PRO CPU é imediatamente inicializado executando o vector table, localizado na mesma ROM (0x40000400). Além disso, ele realiza algumas configurações pertinente ao funcionamento do módulo, enquanto o outro core, o APP CPU é mantido em estado de reset.

Após esta etapa, a imagem do bootloader de segundo estágio que está armazenado na Flash (endereço 0x1000) será transferida para a RAM. Na sequência, a callback call_start_cpu0() localizada no arquivo bootloader_start.c e no diretório components/bootloader/subproject/main, será chamada e o processo do bootloader de segundo estágio terá início.

2. Bootloader de segundo estágio

O segundo estágio tem início na chamada da callback call_start_cpu0(), esta invoca a função bootloader_init() que faz algumas configurações necessárias de hardware e software para suportar o funcionamento, dentre as configurações estão:

  • Inicialização do watchdog timer;
  • Proteção da memória;
  • Reset da região bss;
  • Reset da MMU (Manager Memory Unity);
  • Reconfiguração do clock;
  • Inicialização do console (UART ou USB);
  • Impressão da primeira mensagem no console: versão do ESP-IDF e indicação da inicialização do bootloader de segundo estágio (figura 1);
  • Validação da versão do chip comparado o valor armazenado no header da imagem do bootloader;
  • Configuração da Flash SPI se tudo estiver OK;
  • Verifica se houve reset no watchdog timer;
  • Habilita o hardware RNG (Random Number Generator) como fonte de entropia.

Em seguida, verifica-se qual tipo de partição sofrerá o boot (Single factory app, no OTA ou single factory app, two OTA definitions) mediante a consulta na tabela de partições localizada na memória Flash (0x8000), feito isto, carrega-se a imagem da aplicação.

Assim, finalizado o bootloader de segundo estágio, a callback call_start_cpu0() localizada em /esp-idf/components/esp_system/port/cpu_start.c é chamada, lembrando que até o presente momento o APP CPU está em reset.

Indicação no ESP-IDF monitor informações do bootloader
Figura 1 - informações do bootloader de segundo estágio.

As informações da figura 1 são oriundas do monitor de log do ESP-IDF executando uma aplicação hello_world. Este terminal pode ter acesso a partir da instalação do ESP-IDF no seu computador, a compilação do projeto hello_world e a execução do comando idf.py monitor, desta forma, obtem-se todas as informaçãoes pertinentes aos estágios de bootloader, bem como, da aplicação se esta estiver usando o printf(), por exemplo.

3. Início da aplicação do usuário

Já no ponto de entrada da aplicação, ou seja, na callback call_start_cpu0(), inicia o RTC, o carregamento do entry point do APP CPU (call_start_cpu1()), habilita o respectivo clock através da API start_other_core() e também faz a indicação de que o PRO CPU está ativo por meio do log no monitor (figura 2).

Identificação do entry point da aplicação no ESP-IDF monitor
Figura 2 - indicação do entry point da aplicação.

Deste modo, o PRO CPU aguarda o flag global de que o APP CPU foi inicializado e faz um jump para o endereço do start_cpu0() localizado em esp-idf/components/esp_system/startup.c. Já dentro desta função, começa-se a imprimir informações a respeito da aplicação, conforme a figura 3, somente então o PRO CPU faz alocação de heap, inicia o periférico de brownout, a área de uso da aplicação na memória Flash, o resumo de outros cores, desabilita o watchdog de boot e chama a função start_app() localizada em esp-idf/components/freertos/xtensa/port.c

Indicação do início da aplicação no monitor do ESP-IDF
Figura 3 - log de informações da aplicação no PRO CPU.

Em start_app(), o PRO CPU inicializa o watchdog timer, bem como o configura para 5 segundos e habilita a interrupção para esse mesmo core. Além disso, descobre-se que este core é o responsável por rodar a main_task() da aplicação do usuário por meio da API do FreeRTOS xTaskCreatePinnedToCore(). Logo, é impresso no monitor que scheduler do RTOS foi inicializado no PRO CPU, conforme a figura 4. Além disso, verifica-se o funcionamento core APP CPU.

Monitor indicando o funcioando dos cores
Figura 4 - cores em funcionamento.

A main_task() é a função que invoca a app_main() que está em todas as aplicação que faz as configurações iniciais e cria as task do seu projeto. Deste modo, conseguimos entender, de maneira simplória, como um fluxo de programa para ESP32 é dado.

Referências

confira mais artigos

compartilhe e comente

Compartilhar no linkedin
Compartilhar no whatsapp
Compartilhar no facebook
Compartilhar no telegram

O uso e reprodução deste conteúdo deve creditar o autor e está licenciado conforme a licença Creative Commons – Atribuição Compartilhada 4.0 Internacional (CC BY-SA 4.0). 

Olá, meu nome é Eder Andrade.