Quem nunca escreveu um blink para o seu Arduino não é mesmo? E é realmente fácil programar o Arduino pelo IDE Arduino utilizando comunicação serial. Quando gravamos nosso Arduino um item muito importante entra em ação: o Bootloader. Nesse artigo vamos conhecer melhor as funcionalidades do Bootloader para o ATmega328 o microcontrolador, coração, do nosso querido Arduino.
Bootloader – Introdução
O Bootloader é um programa inicializador. Seu objetivo geralmente é de preparar o hardware para o funcionamento correto da nossa aplicação e/ou aplicar atualizações dessa aplicação. No caso do Arduino quando o ligamos a energia, ou pressionamos o botão de reset, o primeiro programa a ser executado é o Bootloader. O principal objetivo desse pequeno programa inicial no Arduino é de verificar e receber um novo Sketch do Arduino IDE desenvolvido no seu computador, e grava-lo na memória do microcontrolador. Isso ocorre facilmente pela porta serial USB do Arduino. Sem o Bootloader isso não seria possível, teríamos que recorrer a um hardware programador para o ATmega328. Nos tópicos abaixo vamos verificar as opções que temos para realizar um upload de sketch para nosso Arduino bem como as funcionalidades de dois Bootloaders utilizados para o ATmega328.
As formas de programar um Arduino
Há três formas de programar o ATmega328: utilizando o protocolo de alta voltagem Parallel Programming, utilizando ISP (In System Programmer) e o Self Programming. Nesse artigo vamos abordar um pouco dos dois últimos métodos que são os mais utilizados por nós Makers. O protocolo de alta voltagem Parallel Programming é mais aplicado na indústria quando se tem uma grande quantidade de microcontroladores a serem gravados simultaneamente.
ISP – In System Programmer
Para utilizar o ISP é preciso um programador, hardware dedicado ou microcontrolador programado para esse fim, esse programador vai se comunicar via SPI (Serial Peripheral Interface) com o ATmega328, enviar os dados do programa e o ATmega328 irá receber isso e gravar em sua memória flash. Esse processo já está implementado dentro do chip do ATmega328 então não é necessário ter um Bootloader gravado no chip de antemão. Na imagem abaixo um exemplo utilizando o programador USBasp com as conexões ISP conectadas ao socket do gravador:
Para enviar os dados do programa utilizando esse esquema ao programador com a IDE do Arduino você primeiro deve selecionar o tipo do programador: Tools -> Programmer -> USBasp
Feito isso agora pode-se utilizar a opção: Sketch -> Upload Using Programmer
Essa opção ira gravar seu sketch do Arduino IDE utilizando o USBasp, ou seu programador ISP selecionado na opção anterior. Você pode até mesmo utilizar um outro Arduino como programador ISP, mas isso é assunto para um outro artigo.
Self Programming – Bootloader
Self Programming como o próprio nome já diz é a forma em que o próprio microcontrolador se programa. Sem precisar de um hardware dedicado ele utiliza recursos e periféricos próprios para receber dados de uma nova programação e gravá-la. Mas pra isso o microcontrolador tem de saber que periféricos, recursos inicializar e implementar um protocolo para receber e gravar essa nova programação. Quem faz o Self Programming é o famoso Bootloader, que sabe e implementa como receber e gravar novos programas na memória flash de seu próprio ATmega328.
O ATmega328 possui 32Kbytes de memória flash no seu chip para armazenamento de programas e pode-se configurar essa memória em duas seções:
A seção de memória da Aplicação (Application Flash Section) é aonde será armazenada o sketch do seu Arduino, e a seção Boot Flash é aonde ficará armazenada a programação do Bootloader. Essa configuração em seções ainda possibilita que o ATmega328 ative a funcionalidade de RWW (Read While Write) na seção de aplicação, essa funcionalidade possibilita que o código do Bootloader grave a programação na memória flash de forma mais rápida. Por exemplo: sem essa funcionalidade a CPU do ATmega328 leria uma instrução de armazenamento em memória e a CPU teria que ficar em espera até que o processo de armazenamento terminasse, para assim poder ler e executar a próxima instrução, sendo que a memória estaria ocupada. Com o RWW a CPU consegue ler a instrução de armazenamento executa-la e ficar livre para ler e executar a próxima instrução na sessão de Boot Flash, porque foi definido que estamos executando código de outra sessão, que está livre, e não estamos necessariamente usando a mesma memória já que estão divididas em sessões.
Bootloader – Código Fonte
Se você ficou curioso para ver como é o código do Bootloader, saiba que ele está mais próximo do que você pensa. O código fonte e arquivos .hex para upload das diferentes versões do Bootloader vem junto com o Arduino IDE na pasta:
arduino-1.8.7/hardware/arduino/avr/bootloaders
Eu estou usando a versão 1.8.7, lembrando que se você estiver usando outra versão o nome da pasta vai estar diferente. Nesse artigo vamos dar destaque as pastas:
arduino-1.8.7/hardware/arduino/avr/bootloaders/atmega
arduino-1.8.7/hardware/arduino/avr/bootloaders/optiboot
Essas duas versões de Bootloader podem ser utilizadas no ATmega328 e são baseados no trabalho de Jason P. Kyle (stk500boot.c). Sendo assim implementam parte do protocolo STK500 da Atmell. O STK500 é um protocolo que consiste em uma serie de comandos e respostas, todas elas em ASCII padrão, para troca de dados e execução de tarefas, esse protocolo que é utilizado para que o Arduino IDE e o Bootloader se entendam e façam o upload corretamente do seu sketch.
bootloaders/atmega
Essa versão do Bootloader foi utilizada nas primeiras versões do Arduino:
Ele implementa parte do protocolo STK500, seguem algumas características:
- Utiliza baixa taxa de transmissão serial: 57600;
- Ao inicializar realiza o blink do led 13 somente uma vez;
- Lê e escreve da EEPROM;
- Ocupa 1950 bytes do Boot Flash Section;
Depois de compilado, gerando o arquivo ATmegaBOOT_168_atmega328.hex, o Arduino IDE ira realizar o upload e configurar as seções de Boot Flash para 2048 bytes, sobram ainda 98 bytes para eventuais melhorias e funcionalidades, e o Application Flash fica com 30720 bytes para armazenar seus sketches.
bootloaders/optiboot
Essa é a versão de Bootlaoder padrão, ela já vem embarcada de fábrica nos ATmega328P dos Arduino UNO. O Optiboot, como o próprio nome sugere, é uma versão otimizada do Bootloader, e foi baseada também na versão bootloaders/atmega que comentamos acima. Ela tem somente o necessário para realizar o upload do sketch, é uma versão bem enxugada do STK500. Seguem algumas características:
- Utiliza alta taxa de transmissão serial: 115200;
- Taxa de transmissão mais alta logo temos o upload do sketch mais rápido;
- Menor timeout entre entrada do Bootloader e salto para aplicação;
- Ao inicializar realiza o blink do led 13 três vezes;
- Ocupa míseros 502 bytes do Boot Flash Section;
- Com leitura e escrita da EEPROM habilitada ocupa 736 bytes;
Depois de compilado, gerando o arquivo optiboot_atmega328.hex, o Arduino IDE ira realizar o upload e configurar as seções de Boot Flash para 512 bytes, sobram ainda 10 bytes, e o Application Flash fica com 32256 bytes para armazenar seus skectches.
O Optiboot também implementa escrita e leitura da memória EEPROM, mas nesse caso ela ocupa mais espaço, assim tendo que configurar o Boot Flash section para 1024 bytes deixando livre 31744 bytes, mesmo assim gastando metade do armazenamento do bootloaders/atmega.
O Optiboot tem uma comunidade ativa de desenvolvimento e utiliza o Github como plataforma para sugestões de melhorias e relatos de erros: https://github.com/Optiboot/optiboo
Processo de Boot
Os dois bootloaders mencionados acima utilizam mais ou menos o mesmo fluxo, ou ideia de fluxo, para realizar o boot e verificar se há um novo programa a ser feito o upload:
Assim que o microcontrolador recebe energia, ou é resetado, executa-se o código no endereço do Boot Flash section. Esse código inicializa o output do pino 13, para dar aquele blink rápido quando ligamos a placa, a UART e verifica se está recebendo via serial algum comando do protocolo STK500, caso ele receba algum comando implementado ele executa o comando, transfere os dados e manda as respostas do protocolo. Caso ele não receba nenhum comando, e ele fica em loop lendo a serial por comandos por algum tempo, então ele salta para o endereço do Application Flash Section e executa nosso sketch.
Prós e Contras
Utilizar um Bootloader tem muitas vantagens, a primeira e um dos motivos ao qual eu costumo creditar o sucesso da plataforma Arduino é a facilidade de programação do microcontrolador sem necessidade de um hardware externo programador, o Arduino já vem com todos os recursos para realizar a programação, e o Bootloader é uma ferramenta de software essencial.
Em contra partida, como nem tudo são flores, perdemos aquele espaço que é do Boot Flash section que só servira para o Bootloader.
Conclusões
Não há dúvidas que o Bootloader é útil. E é importante ao Maker conhecer e estudar essa peça de software. Eu recomendo que comece seus estudos com o bootloaders/atmega. Na minha opinião ele é mais fácil de se entender e customizar. O Optiboot tem alguns truques para minimizar ao máximo seu tamanho e necessita de uma compreensão maior e estudo da arquitetura AVR.
Caso seu projeto precise de opções de boot customizadas. Você pode customizar seu Bootloader, por exemplo, para realizar atualizações da sua aplicação remotamente via WiFi utilizando o ESP32.
Caso seu projeto precise de mais espaço de armazenamento aqueles 512 bytes podem fazer a diferença. Em um caso desses você pode optar por embarcar sua solução sem Bootloader para ganhar espaço.
Tudo depende daquilo que se pretende alcançar com seu projeto. Conhecendo suas ferramentas fica fácil tomar a decisão e implementar sua solução.