Bootloader, no ambiente dos microcontroladores, é um programa residente em parte específica da memória que permite ao chip se “auto programar”, seja recebendo o programa via serial ou USB, não irei entrar no mérito aqui dos mais raros via WiFi ou rede Ethernet.
O Arduino foi o grande precursor tanto de placa de prototipagem rápida como de uso de um bootloader, quando foi lançado o comum era usarmos um Programador/Gravador dedicado pra gravação dos chips, incluindo os Atmel usados no Arduino.
E também uso de um software de gravação separado da IDE onde se editava o código durante o desenvolvimento. Com a baixa de preços e consequente popularização dos Debugers dedicados isso começou a mudar um pouco:
Figura 1 – Pickit da Microchip conectado a uma placa de desenvolvimento
Figura 2 – Atmel ICE Debuger / Programador
Mas voltando ao nosso Bootloader, e mais especificamente do Arduino que usa o microcontrolador Atmega328 de 32Kbytes de memória de programa organizados em 16K x 16bits. Esses dados da memória são especialmente importantes pois
- O Bootloader ocupa um espaço na memória, ficando sempre lá “residente”
- Por motivos óbvios, ele fica alocado sempre no começo ou no final da memória
Então daí extraímos algumas coisas como:
- quanto maior o Bootloader (mais espaço ocupa) pior será, ocupando mais memória que não pode ser utilizada para o programa
- outra coisa é que, na prática, o compilador gera o programa por padrão, sempre começando do endereço 0x00, e nesse começo da memória também temos os chamados Vetores de Interrupção, então se o bootloader for alocado nesse começo teremos que realocar de alguma maneira esses pontos.
Sabendo desses fatos podemos entender da melhor maneira que o bootloader pode ser aplicado, no caso do projeto Arduino foi escolhido o OptiBoot que une várias qualidades, como ser de código fonte aberto/ uso livre, ocupa um mínimo de espaço que no Atmega328 é de 512bytes somente e também fica alocado no endereço final da memória, sendo assim compatível com os AVRs (que reservam esse espaço pro Bootloader) e é o menos intrusivo possível dentro dessa arquitetura de microcontroladores.
-Esquema de Memória/ endereçamento do Bootloader
Na figura 3, podemos ver a organização de memória e o espaço no final que a Atmel reserva para o Bootloader (mas que também pode ser utilizada pelo programa se disponível).
Mas e como funciona isso ?
O processo de funcionamento é relativamente simples:
- Ao ser resetado o microcontrolador “desvia” o endereço normal que programa iniciaria (0x00) para o início do programa de Bootloader no caso do OptiBoot no Atmega328, esse endereço é o 0x3DFF, que é: 0x3FFF – 0x3DFF = 512bytes
- Nesse ponto sob controle do programa de bootloader, esse espera alguns momentos por um ‘caracter de início’ vindo pela serial, caso não receba até o tempo estipulado ele aborta e retorna ao endereço logo
- Recebendo o ‘caracter de início’, que é a variável STK_READ_SIGN cujo valor é definido em 0x75, o OptiBoot envia o Device Signature pro software que dá início ao processo de auto gravação: Recebe o endereço, dado a ser gravado e grava na memória seguindo um protocolo específico.Figura 4- Fluxograma do OptiBoot
Alguns detalhes bem importantes:
- Para que ao resetar ocorra o desvio para o (endereço do) Bootloader é necessário que isso seja habilitado o Boot fuse bit BootRST
- O tamanho pré definido pro Bootloader (Boot Size), e consequentemente o endereço para o qual ocorrerá esse salto, é também gravado nos fuse bits BootSZ1 e BootSZ0.
Ambas configurações acima se encontram no “High Fuse” do Atmega328, que devem ser configurados no software gravador inicial que irá fazer a 1a gravação do chip com o próprio Bootloader.
Referências:
Github do OptiBoot: https://github.com/Optiboot/optiboot
Instruções do Atmega: http://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf
Datasheet do Atmega328: https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf