Muitas vezes quando usamos sistemas embarcados com suporte ao Linux, queremos usar apenas o mínimo de pacotes necessários para que o nosso sistema funcione. Por exemplo, se usarmos uma Raspberry Pi para criar um servidor, não precisamos de todas as funcionalidades incluídas em uma distro como a Raspbian, como por exemplo a interface gráfica.
É óbvio que existem distribuições já prontas (inclusive da própria Raspbian) que já vem com menos funcionalidades, porém ainda assim podemos querer customizar ainda mais. Para automatizar e facilitar a construção de uma distro customizada, existem algumas ferramentas de build para sistemas embarcados baseados em Linux. Entre elas estão incluídas, por exemplo, o Yocto e o Buildroot, que são projetos open-source.
Da mesma forma que existem diferentes ferramentas, existem diferentes placas que são capazes de rodar um sistema Linux Embarcado, como a BeagleBone e as placas ODROID. Neste post vamos falar um pouco sobre o uso do Buildroot para a criação de uma imagem para a Raspberry Pi, incluindo:
- Criar nosso próprio pacote (um programa simples em Python) e disponibilizá-lo para que possa ser incluído na nossa imagem;
- Escolher quais pacotes queremos adicionar à imagem final;
- Iniciar a execução do nosso programa assim que a raspberry fizer boot, evitando que seja necessário acessar a Raspberry (via ssh ou teclado) para começar a executar.
O sistema operacional no host (minha máquina) usado para construir esse tutorial é o Ubuntu 16.04 LTS. Porém, os conceitos se aplicam a qualquer distribuição, mudando apenas alguns pequenos detalhes como o gerenciador de pacotes (no caso deste tutorial, apt-get).
Buildroot
O que é?
Como dito anteriormente, o Buildroot é uma ferramenta que auxilia e automatiza a criação de distribuições Linux Embarcado. Ele faz a cross-compilação do código para a arquitetura da placa para a qual se quer construir a distribuição (mais sobre Cross-compilação neste artigo).
A documentação do Buildroot é bem completa (embora um pouco difícil de entender à primeira vista) e existe bastante referência online e na comunidade, como o site do Sérgio Prado e da Bootlin (antiga Free Electrons).
Instalação
Instalar o Buildroot é, basicamente, clonar ou baixar o repositório da ferramenta. Porém, para que possa ser usada, alguns pacotes são necessários, como explicado neste outro artigo. Para instalá-los, execute no terminal:
$sudo apt-get install build-essential libncurses5-dev bzr cvs git mercurial rsync subversion
Clone o repositório oficial ou o mirror no github:
$git clone https://git.buildroot.net/buildroot/ buildroot
ou:
$git clone https://github.com/buildroot/buildroot.git buildroot
Crie uma nova branch tendo como raiz a LTS (no momento, a LTS mais recente é a 2018.02):
$cd buildroot $git checkout 2018.02 -b simon_game_buildroot
Criando um pacote para o buildroot
Você pode desenvolver qualquer aplicação que desejar. Por simplicidade, recomendo o uso de Python caso você não tenha familiaridade com makefiles e cross-compilação de programas em C.
Para o Buildroot, importa que o código esteja em algum lugar acessível para que a ferramenta possa fazer o download e compilação (se necessário). Por exemplo, criando um repositório no seu Github.
Para este tutorial usarei um programa em Python que simula o comportamento de um jogo de GENIUS (SIMON, em inglês).
O jogo gera sequências crescentes aleatórias de quatro botões e o jogador deve repetir a sequência gerada para passar de nível. O código está disponível no github.
Na pasta do Buildroot, crie a pasta que terá as instruções de download e compilação do seu pacote. O manual do Buildroot recomenda a seguinte hierarquia quando criando novos pacotes:
Como só temos um novo pacote e não precisamos criar uma pasta para a empresa, a nossa estrutura ficará um pouco diferente:
O seu pacote pode ter qualquer nome, desde que o nome do diretório seja o mesmo do nome do arquivo com a extensão “.mk”.
Para isso, estando dentro do repositório do Buildroot que você clonou:
$mkdir package/simon-game $touch package/simon-game/simon-game.mk $touch package/simon-game/Config.in
Abra os arquivos criados com o seu editor de texto favorito, copie o conteúdo dos arquivos Config.in e simon-game.mk e salve.
Por fim, modifique o arquivo package/Config.in para incluir o seu pacote na ferramenta menuconfig. Neste arquivo, existe uma seção “menu Games”, e dentro dela iremos incluir o nosso jogo. Inclua a linha:
source "package/simon-game/Config.in"
Caso você deseje, é possível criar o seu próprio menu com os seus pacotes.
A partir desse momento, caso você queira pular para a seção Instalando o pacote criado e dependências via menuconfig, o seu sistema funcionará. Porém, o jogo simon não estará executando assim que a Raspberry Pi se iniciar. É preciso que você a acesse e execute diretamente o programa em /usr/local/bin/simon-game-master/simon_gpio.py.
Inicializando a aplicação no momento do boot
Iremos criar um script que será responsável por iniciar e parar o jogo. Esse script deve ser colocado em uma pasta específica, em que todos os scripts dentro dela são executados quando o sistema se inicia. A pasta em questão é /etc/init.d/.
Existem (pelo menos) duas formas de fazer com que o nosso script seja copiado para a Raspberry Pi no caminho desejado. Embora a primeira solução seja mais elegante (IMHO) e a recomendada no manual do buildroot, com a segunda solução fazemos com que o nosso pacote seja auto-contido, por isso eu segui com ela no meu desenvolvimento.
- Alterando rootfs_overlay: De acordo com o manual do buildroot: “A filesystem overlay is a tree of files that is copied directly over the target filesystem after it has been built.” Ou seja, após criado o sistema, os arquivos presentes na pasta de rootfs_overlay são copiados. É importante que a estrutura de diretórios dentro da rootfs_overlay seja mantida igual à estrutura de onde queremos adicionar os arquivos ou diretórios. Então deveríamos ter algo como /board/raspberrypi/rootfs_overlay/etc/init.d/S70simon.
- Criando o script na pasta do pacote e modificando o .mk: Dentro de package/simon-game, criamos um novo arquivo que será o script de execução do jogo, chamaremos o arquivo de S70simon (a nomeclatura deve obrigatoriamente começar com “S” seguido de um numeral). Modifique o arquivo simon-game.mk, adicionando o comando para copiar o script para a pasta desejada.
Instalando o pacote criado e dependências via menuconfig
Com todas as alterações salvas, na pasta raiz do buildroot, execute:
$make raspberrypi3_defconfig
Caso você esteja usando alguma outra versão da Raspberry Pi, modifique para o defconfig adequado (todos os arquivos de defconfig estão em /configs). Em seguida, vamos adicionar o nosso pacote:
$make menuconfig
Navegue para Target packages > Games e selecione simon-game. Volte para a tela inicial do menuconfig (esc-esc volta uma página), siga para Filesystem images > exact size e altere para 120M.
Salve as alterações e saia.
NOTA: O tamanho padrão da imagem que o buildroot gera é menor do que o que precisamos, o que causa um erro se não modificarmos este valor. Para descobrir o valor que precisamos, primeiro encontramos o tamanho da pasta target (após a primeira compilação sem sucesso), dividimos o valor por (1024)² e adicionamos mais 50M de padding (mais informações aqui e aqui).
$du -sb output/target
Compilação e criação do SD
Inicie a compilação e vá fazer alguma outra coisa, visto que este processo é bastante demorado (algumas horas, na minha máquina).
$make
Após finalizada a compilação, o seu diretório output/images deve ter a seguinte estrutura:
Copie o arquivo de imagem para o cartão de memória. Caso você não saiba onde o seu cartão foi montado, você pode usar o programa “disks” no seu Ubuntu para verificar. Substitua o valor após “of=” pelo caminho para o seu SD.
$sudo dd if=output/images/sdcard.img of=/dev/sdX
O seu cartão também pode ter sido montado em /dev/mmcblkX.
NOTA: O seu sistema operacional é comumente montado em /dev/sda. NÃO COLOQUE ESSA ROTA COMO SAÍDA DO COMANDO dd OU VOCÊ PERDERÁ TODOS OS SEUS ARQUIVOS.
Verificando o resultado
Ligue a Raspberry Pi à energia e verifique se o jogo inicia ao apertar o botão de start game.
As ligações de fios e conexões de entrada e saída estão descritas no readme do projeto.
|
Botão Start |
Botão Verde |
Botão Vermelho |
Botão Amarelo |
Botão Azul |
LED Verde |
LED Vermelho |
LED Amarelo |
LED Azul | |
|
Pino |
29 |
31 |
33 |
35 |
37 |
22 |
24 |
26 |
28 |
|
BCM |
5 |
6 |
13 |
19 |
26 |
25 |
8 |
7 |
1 |
Caso você queira ver se o processo está sendo executado no seu sistema, logue via ssh e execute:
$ps | grep simon*
Resumo
O buildroot facilita e automatiza o processo de criação de uma distribuição Linux customizada apenas com os pacotes que são do interesse do desenvolvedor. Neste artigo falamos sobre como usar o Buildroot para criar uma distribuição Linux contendo pacotes criados por nós e fazer com que esses programas sejam executados assim que a Raspberry Pi fizer o boot.
No github estão disponíveis os repositórios com o jogo em Python e com o buildroot modificado.
- Instale as dependências para o buildroot:
$sudo apt-get install build-essential libncurses5-dev bzr cvs git mercurial rsync subversion
- Baixe, fork ou clone o repositório pauloserrafh/buildroot e siga para a branch buildroot_simon_rpi:
$cd ~/Documents $git clone https://github.com/pauloserrafh/buildroot.git buildroot $cd buildroot $git branch origin/buildroot_simon_rpi -b buildroot_simon_rpi
- Inclua os pacotes necessários:
$make raspberrypi3_defconfig $make menuconfig
- Navegue para Target packages > Games e selecione simon-game. Volte para a tela inicial do menuconfig (esc-esc volta uma página), siga para Filesystem images > exact size e altere para 120M.
- Compile e grave no cartão de memória:
$make $sudo dd if=output/images/sdcard.img of=/dev/sdX
Saiba mais
Introdução a cross-compiling com a Raspberry Pi
Criando uma imagem customizada para a BeagleBone Black com Buildroot
Webinar Gravado: Desenvolvendo com Linux Embarcado
Referências











Olá Paulo, achei o local, fica no git, exatamente na sua conta.
Mas se eu não quiser deixar o meu código do git, é possível deixar local, e o arquivo .mk apontar para este novo local?
Abraço
Eduardo Scherrer
Olá Eduardo.
Primeiramente, perdão pela demora, não recebi (ou passei batido) a notificação de comentário aqui. Não sei se você ainda está com a dificuldade.
Você pode especificar um pacote local ao invés do git sem problemas. Na seção 17.5.2. generic-package reference do manual do buildroot são especificadas as possíveis formas de fazer build de diferentes formas, inclusive localmente.
https://buildroot.org/downloads/manual/manual.html#_infrastructure_for_packages_with_specific_build_systems
Provavelmente, o seu arquivo .mk ficará na forma:
LIBFOO_SITE = caminho/para/seu/pacote
LIBFOO_SITE_METHOD = local
Olá Paulo,
Onde deve estar salvo o arquivo .py? Não encontrei o lugar correto.
Abraço.