Encontrei um potencial problema essa semana. Ao tentar usar a minha placa “BSFrance LoRa32u4 II”, a qual, como diz no próprio nome é baseada no chip ATMega 32u4, vi que o mesmo tem apenas 28672 bytes disponíveis para programas. Isso porque o bootloader deste chip consome 4096 bytes (4K).
Eu planejo usar a biblioteca da MCCI, chamada LMIC, para conectar os meus projetos ao LoRaWAN da TTN/TTS (The Things Network/Stack). Esta é uma biblioteca massiva e sozinha consome uns 26Kb da memória de código. Isso e mais alguns recursos que uso, como I2C e EEPROM, eu acabarei atingindo o limite máximo de memória. Até o momento eu estava fazendo meus testes e desenvolvimento usando um Arduino UNO, e o bootloader nesse é de apenas 512 bytes e por isso não havia ainda atingido o teto máximo de memória.
O meu melhor plano então é o de conseguir usar o espaço de memória reservado ao bootloader e usar uma interface SPI de hardware para programar o processador, no meu caso, um dispositivo USBasp. Felizmente eu já tenho esse dispositivo, e após montar um circuito para conectar a placa (inicialmente estou testando com um clone do SparkFun Pro Micro (também baseado no chip 32u4), consegui fazer a programação direta. Também ao usar a programação através de SPI, o bootloader é automaticamente sobrescrito.
Um truque com a conexão do dispositivo USBasp na porta USB no Windows 10 é a necessidade de se instalar um driver. Para isso usei o driver instalado pelo utilitário zadig-2.7.exe que baixei através do site https://zadig.akeo.ie . Os passos para instalar o driver são:
- Conectar o dispositivo USB/SPI em uma porta USB
- Executar zadig-2.7.exe
- Selecionar menu Options -> List All Devices
- Selecionar USBasp
- Em driver, mudar para libusbK(v3.1.0.0)
Sketch uses 26186 bytes (91%) of program storage space. Maximum is 28672 bytes.
Global variables use 1364 bytes of dynamic memory.
Para resolver isso adicionei uma nova placa no arquivo de configuração do Arduino, ‘boards.txt’. A localização deste arquivo parece que depende se eu estou usando uma placa nativa Arduino (Arduino AVR Boards), ou se são definições instaladas depois, como por exemplo as definições da Adafruit ou da SparkFun. No meu caso eu verifiquei que para as placas nativas do Arduino o ‘boot.txt’ está localizado no diretório de instalação do IDE, ou seja: ‘C:\Program Files (x86)\Arduino\hardware\arduino\avr’. As demais definições eu encontrei na pasta ‘C:\Users\[usuario]\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.3’, o qual também corresponde ao local referido na página oficial do site arduino.cc.
Para eu poder usar toda a memória eu preciso então modificar a definição da minha placa para dizer ao compilador que agora tenho todos os 32Kb disponíveis. Além disso, é preciso programar um dos fuses do controlador para indicar que a área de memória normalmente dedicada ao bootloader está disponível para a execução do firmware. Os fuses que controlam isso estão no byte mais significativo, ou High Fuses, o que no arquivo ‘boards.txt’ corresponde à definição ‘bootloader.high_fuses’. O valor originalmente definido aqui éra de 0xD8 (ou em binário 11011000). De acordo com uma calculadora online dos bits de fuse para os microcontroladores AVR da Atmel, basta mudar este valor para 0xDF (ou em binário 11011111), mas aproveitando a oportunidade também quis desabilitar a função de resetar a memória EEPROM toda vez que um novo sketch é gravado no microcontrolador. Para isso configurei o High Fuse byte para 0xD7 (em binário 11010111).
É importante observar que na configuração dos fuses ‘1’ corresponde a desabilitado e ‘0’ a habilitado.
Visualmente ficou assim:
A modificação que fiz no ‘boards.txt’ foi de duplicar todas as entradas do [Pro Micro], mudar o prefixo de ‘promicro’ para ‘promicronbl’, mudar o título, a quantidade máxima de memória e o byte de High Fuse conforme indicado abaixo:
Não é muito intuitivo, mas para forçar a IDE Arduino a gravar a configuração de não usar o bootloader é necessário re-gravar o bootloader, isso irá forçar a alteração do novo valor para o High Fuse. Primeiro, fecho e rodo novamente a IDE Arduino, seleciono a definição de placa que adicionei, com a respectiva versão (voltagem e frequência). E seleciono gravar o bootloader: Para verificar que os fuses foram gravados conforme as especificações em ‘boards.txt’ eu usei um utilitário chamado AVRDUDESS, conectei usando a USBasp e li (read) os valores dos bytes dos fuses. Tudo certo! Finalmente, uma última verificação. Escrevi um sketch onde eu preencho todos os bytes iniciais com um vetor grande, forçando o código de piscar o led a ficar bem no final da memória flash:################################################################################ ########################### Pro Micro No Bootloader ############################ ################################################################################ promicronbl.name=SparkFun Pro Micro No Bootloader promicronbl.upload.tool=avrdude promicronbl.upload.protocol=avr109 promicronbl.upload.maximum_size=32672 promicronbl.upload.maximum_data_size=2560 promicronbl.upload.speed=57600 promicronbl.upload.disable_flushing=true promicronbl.upload.use_1200bps_touch=true promicronbl.upload.wait_for_upload_port=true promicronbl.bootloader.tool=avrdude promicronbl.bootloader.unlock_bits=0x3F promicronbl.bootloader.lock_bits=0x2F promicronbl.bootloader.low_fuses=0xFF promicronbl.bootloader.high_fuses=0xD7 promicronbl.build.board=AVR_PROMICRO promicronbl.build.core=arduino:arduino promicronbl.build.variant=promicro promicronbl.build.mcu=atmega32u4 promicronbl.build.usb_product="SparkFun Pro Micro No Bootloader" promicronbl.build.vid=0x1b4f promicronbl.build.extra_flags={build.usb_flags} ######################### Pro Micro 3.3V / 8MHz ################################ promicronbl.menu.cpu.8MHzatmega32U4=ATmega32U4 (3.3V, 8 MHz) promicronbl.menu.cpu.8MHzatmega32U4.build.pid.0=0x9203 promicronbl.menu.cpu.8MHzatmega32U4.build.pid.1=0x9204 promicronbl.menu.cpu.8MHzatmega32U4.build.pid=0x9204 promicronbl.menu.cpu.8MHzatmega32U4.build.f_cpu=8000000L promicronbl.menu.cpu.8MHzatmega32U4.bootloader.extended_fuses=0xFE promicronbl.menu.cpu.8MHzatmega32U4.bootloader.file=caterina/Caterina-promicro8.hex ############################# Pro Micro 5V / 16MHz ############################# promicronbl.menu.cpu.16MHzatmega32U4=ATmega32U4 (5V, 16 MHz) promicronbl.menu.cpu.16MHzatmega32U4.build.pid.0=0x9205 promicronbl.menu.cpu.16MHzatmega32U4.build.pid.1=0x9206 promicronbl.menu.cpu.16MHzatmega32U4.build.pid=0x9206 promicronbl.menu.cpu.16MHzatmega32U4.build.f_cpu=16000000L promicronbl.menu.cpu.16MHzatmega32U4.bootloader.extended_fuses=0xCB promicronbl.menu.cpu.16MHzatmega32U4.bootloader.file=caterina/Caterina-promicro16.hex
Usando a opção de fazer o upload do sketch usando o gravador USBasp, carrego o programa e verifico se o LED pisca: SUCESSO! Agora posso usar todos os 32Kb de memória flash disponíveis no meu clone do Arduino/SparkFun Pro Micro. Meu próximo passo será repetir o mesmo procedimento na minha placa “BSFrance LoRa32u4 II”.Sketch uses 32672 bytes (100%) of program storage space. Maximum is 32672 bytes. Global variables use 438 bytes (17%) of dynamic memory, leaving 2122 bytes for local variables. Maximum is 2560 bytes.