Desenvolvimento bare metal para ARM Cortex-M com o GCC no Linux

- por Sergio Prado

Categorias: Microcontroladores Tags: ,

Um ambiente integrado de desenvolvimento (IDE) pode facilitar bastante a nossa vida, criando e gerenciando automaticamente projetos e aumentando a produtividade do desenvolvimento.

Mas tudo tem seu preço. E o preço que pagamos pelas facilidades de uma IDE é a falta de um controle maior sobre o projeto e o binário final gerado.

Criando um simples projeto de pisca-led para a Freedom Board FRDM-KL46Z no Kinetis Development Studio da Freescale, o código final consumiu aproximadamente 3K de RAM (dados) e quase 10K de flash (código)!

$ size led.elf 
   text	   data	    bss	    dec	    hex	filename
   9612	    720	   2272	  12604	   313c	led.elf

É claro que existe muito desperdício no código gerado, e poderíamos estudar algumas opções disponibilizadas pela IDE para otimizar o código e gerar um binário mais enxuto.

Mas trabalhando direto com o compilador podemos ter um controle muito maior sobre o código compilado. Resolvi então criar um projeto bare metal que consumisse o mínimo possível de espaço em RAM e flash para a aplicação de pisca-led.

Para testar, instalei o toolchain para desenvolvimento bare metal baseado no GCC mantido pelo pessoal da própria ARM:

$ mkdir ~/toolchain && cd ~/toolchain
$ wget https://launchpad.net/gcc-arm-embedded/4.9/4.9-2014-q4-major/+download/gcc-arm-none-eabi-4_9-2014q4-20141203-linux.tar.bz2
$ tar xjfv gcc-arm-none-eabi-4_9-2014q4-20141203-linux.tar.bz2

Após a instalação, você pode verificar se o toolchain está funcionando com o comando abaixo:

$ ./gcc-arm-none-eabi-4_9-2014q4/bin/arm-none-eabi-gcc -v

Criei um projeto simples para a FRDM-KL46Z e coloquei no GitHub:

$ cd ~
$ git clone https://github.com/sergioprado/bare-metal-arm.git
$ cd bare-metal-arm

O projeto é composto pelo linker script (link.ld) e dois arquivos .c. O arquivo startup.c contém a tabela de vetor de interrupção do microcontrolador e o ponto de entrada da aplicação, responsável por inicializar a memória (seções DATA e BSS) e executar a função main(), implementada no arquivo main.c e responsável por piscar o led.

$ ls
includes  LICENSE  link.ld  main.c  Makefile  startup.c

Para compilar o projeto, basta digitar make:

$ make
~/toolchain/gcc-arm-none-eabi-4_9-2014q4/bin/arm-none-eabi-gcc -c -mthumb -mcpu=cortex-m0plus -I./includes/ -o main.o main.c
~/toolchain/gcc-arm-none-eabi-4_9-2014q4/bin/arm-none-eabi-gcc -c -mthumb -mcpu=cortex-m0plus -I./includes/ -o startup.o startup.c
~/toolchain/gcc-arm-none-eabi-4_9-2014q4/bin/arm-none-eabi-gcc --specs=nano.specs -Wl,--gc-sections,-Map,main.map,-Tlink.ld -o main.elf  main.o  startup.o
~/toolchain/gcc-arm-none-eabi-4_9-2014q4/bin/arm-none-eabi-objcopy -O srec main.elf main.srec
~/toolchain/gcc-arm-none-eabi-4_9-2014q4/bin/arm-none-eabi-size main.elf
   text	   data	    bss	    dec	    hex	filename
    452	      0	   1024	   1476	    5c4	main.elf

Veja que o binário final do projeto de pisca-led ficou bem menor, ocupando apenas 452 bytes de flash e 1K de RAM (basicamente alocado para o stack).

Este projeto pode ser facilmente reutilizado em outras plataformas ARM Cortex-M, inclusive de outros fabricantes.

Para isso, basta alterar o linker script de acordo com a configuração de memória do microcontrolador, e implementar o pisca-led na função main().

Se necessário, altere o toolchain definido no Makefile.

Have fun!

Sergio Prado

Faça um Comentário

Navegue
Creative Commons Este trabalho de Sergio Prado é licenciado pelo
Creative Commons BY-NC-SA 3.0.