Utilizando o ULP do ESP32 para co-processamento

Este post faz parte da série Co-processador Ultra Low Power do ESP32. Leia também os outros posts da série:

Agora que já sabemos programá-lo, vamos colocá-lo para ajudar no co-processamento do sistema principal, onde reside os 2 núcleos principais do ESP32, cada um rodando a 240 MHz. A ideia deste post é tentar simular alguma tarefa pesada para o microcontrolador, em que qualquer desvio de código acarreta em uma visível falha que pode ser relevante ou não.

 

Um método bem simples de estressar o microcontrolador é um loop infinito sem delay efetuando alguma tarefa. Pensando nisso, faremos um PWM via software que é extremamente pior do que um PWM por hardware como Timers, que não são interferidos pelo código em si, como desvio por interrupções ou delays.

 

O PWM por software sofrerá com qualquer desvio de programação, inclusive interrupções externas, e é isso que será mostrado.

 

Vamos primeiramente entender a situação que nosso microcontrolador enfrentará:

  • O sistema principal irá gerar um PWM de 4 MHz continuamente, onde não pode haver flutuações na frequência;
  • Há um sensor conectado no microcontrolador para ativar um atuador sonoro em caso de pânico no sistema. Isso é feito através de uma interrupção externa, onde o código é desviado para uma rotina de interrupção (ISR) que ativa a buzina. Esse é um dos métodos mais eficazes e velozes para tratar eventos com microcontroladores, entretanto, vamos verificar como o sistema se comportou mais a frente...

 

Agora que já sabemos como o sistema precisa se comportar, vamos primeiramente testar o método de utilizar uma interrupção no mesmo núcleo que gera o PWM de 4 MHz. Veja o fluxograma que apenas idealiza como o processo é executado:

 

Fluxograma do código com interrupção.
Figura 1 - Fluxograma do código com interrupção.

 

Código C++:

 

Com um analisador lógico podemos visualizar os pinos do microcontrolador numa linha do tempo e ver como o sistema se comportou quando o botão de pânico foi pressionado.

 

Observações:

  • Canal 0: PWM de 4 MHz;
  • Canal 1: Atuador (buzina) ativo quando em nível lógico ALTO;
  • Canal 2: Botão de pânico pressionado quando em nível lógico BAIXO.

 

Analisador lógico no código com interrupção.
Figura 2 - Analisador lógico no código com interrupção.

 

É possível mais que claramente ver a ineficiência de tratamento da interrupção e gerência do PWM de alta frequência ao mesmo tempo. Mesmo o ESP32 trabalhando em 240 MHz, seu tratamento convencional de interrupções não é tão bom se comparado com outras arquiteturas de microcontroladores, como AVR, sendo possível ver que desde o botão ser pressionado e o atuador ligar, passaram-se aproximadamente 1,3 us, o que é relativamente lento. Todo o processo de desvio da interrupção até o retorno do PWM durou aproximadamente 3,5 us e isso não é tolerável no projeto. Apesar dos métodos convencionais serem lentos, é possível atribuir, via Assembly, interrupções de baixa latência diretamente na arquitetura da XTensa, mas não vamos tão a fundo por um problema que pode ser resolvido mais facilmente com algum dos outros 2 processadores.

 

Você pode estar se perguntando por que não atribuí a interrupção ao outro núcleo, já que o ESP32 conta com 2 núcleos principais e podemos deixar as tarefas separadas por núcleo, mas o outro núcleo também está ocupado com outra tarefa, então sobrou o ULP.

 

Vamos então programá-lo para ajudar o processamento do sistema principal. O ULP ficará encarregado de tratar todos sensores e atuadores do nosso sistema, que nesse caso é apenas um de cada, mas já é suficiente para analisar como é eficiente no co-processamento, visto que quanto mais sensores, mais o sistema principal seria prejudicado.

 

Fluxograma do código com ULP do ESP32 para co-processamento
Figura 3 - Fluxograma do código com ULP

 

Código C++:

 

Código ASM:

 

Vamos analisar novamente pelo analisador lógico, como o sistema se comportou quando o botão de pânico foi pressionado.

 

Observações:

  • Canal 0: PWM de 4 MHz;
  • Canal 1: Atuador (buzina) ativo quando em nível lógico ALTO;
  • Canal 2: Botão de pânico pressionado quando em nível lógico BAIXO.

 

Analisador lógico no código do ULP do ESP32 para co-processamento
Figura 4 - Analisador lógico no código do ULP.

 

 

Observe que mesmo durante o evento (pressionar do botão e atuador ativar) o PWM continuou perfeitamente como o esperado (4 MHz), mostrando a eficiência e importância de usar outro núcleo/microcontrolador para ajudar no processamento.

 

Os co-processadores têm uma trajetória relativamente importante para computação atual, sendo um dos mais famosos a Float Point Unit (FPU), que é um co-processador para efetuar cálculos de ponto flutuante presente na maioria dos dispositivos atuais, inclusive no ESP32. Os co-processadores livram o processador central de alguma tarefa, tornando o sistema, em geral, mais rápido.

 

O ULP pode ter poucos Mnemônicos (Instruction set limitado), mas se torna importantíssimo em projetos específicos, como nos 2 citados neste artigo. O simples fato de conseguir ler pinos digitais/analógicos e controlar pinos já o torna um aliado interessante para você aprender e utilizar.

 

 

Saiba mais

 

MSP430 - Modos de Low-Power

Idealização de um projeto IoT portátil

Embarcados interview: Jack Ganssle

Outros artigos da série

<< Usando o ULP do ESP32 em projetos Low Power
Este post faz da série Co-processador Ultra Low Power do ESP32. Leia também os outros posts da série:

NEWSLETTER

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Obrigado! Sua inscrição foi um sucesso.

Ops, algo deu errado. Por favor tente novamente.

José Morais
Estudante de Engenharia da Computação pela USC, pretende se aprimorar e fazer a diferença nesta imensa área da tecnologia. Apaixonado por IoT, sistemas embarcados, microcontroladores e integração da computação nos mais diversos fins práticos e didáticos.

Deixe um comentário

Seja o Primeiro a Comentar!

avatar
 
  Notificações  
Notificar