Interagindo com o Device Tree da PocketBeagle Board

Introdução

O Kernel Linux passou a suportar os device trees a partir de sua versão 3.7. Um device tree pode ser definido, em poucas palavras, como um arquivo descritor de hardware, o qual permite ao Kernel carregar os device drivers em função dos dispositivos declarados/descritos. Assim, o Kernel é capaz de associar as corretas interfaces de comunicação com os respectivos dispositivos de hardware descrito no sistema. Ou seja, os device trees formam o elo entre o hardware (dispositivo físico) e device drivers. Este elo permite o correto funcionamento de acesso/leitura/escrita de dispositivos externos com drivers executados em Kernel space.

Porém, você sabe como manipular um Device Tree? Sabe como encontrá-lo dentre os disponíveis, fazer modificações e colocar o Device Tree editado em ação? Este artigo vai te ajudar nisso, considerando como hardware-alvo a PocketBeagle Board.

Hardware utilizado

Neste artigo, utilizaremos como hardware alvo a PocketBeagle Board. Trata-se de uma placa com pequenas dimensões, sendo uma das mais novas da linha das placas Beaglebone. Esta placa é voltada a aplicações portáteis como em robótica e que exijam o uso de um sistema operacional como um Linux embarcado. Mais informações sobre a PocketBeagle podem ser encontradas neste artigo aqui: https://www.embarcados.com.br/PocketBeagle-nova-placa-da-beagleboard/

Figura 1 – PocketBeagle board (fonte: https://www.filipeflop.com/produto/PocketBeagle-board/)

Esta placa utiliza como sistema operacional uma distribuição Debian cross-compilada para o SoC da placa, sendo as imagens oficiais oferecidas no site http://beagleboard.org/latest-images. Este artigo considera que a PocketBeagle que você vai trabalhar já esteja com o sistema operacional instalado e que seja possível acessá-la via SSH.

O que será mostrado no artigo?

Neste artigo, será mostrado:

  1. Como um Device Tree Blob (não sabe do que se trata? Leia este artigo: https://sergioprado.org/linux-e-o-suporte-a-device-tree-parte-2/) é carregado na PocketBeagle Board
  2. Como descobrir o Device Tree Blob utilizado na PocketBeagle Board
  3. Como decompilar o Device Tree Blob (transformá-lo em um Device Tree Source editável)
  4. Como adicionar um LED externo no Device Tree Source original da PocketBeagle Board
  5. Como compilar o Device Tree Source editado em um novo Device Tree Blob para a PocketBeagle Board
  6. Como testar o Device Tree Blob novo na PocketBeagle Board

Primeiro passo: como um Device Tree Blob é carregado na PocketBeagle Board?

Antes de tudo, é preciso saber que o bootloader alto nível (ou seja, o bootloader chamado pelo bootloader de segundo estágio – SPL / MLO) usado na PocketBeagle é o U-Boot (site oficial: https://www.denx.de/wiki/U-Boot). O U-Boot tem como principal tarefa preparar o hardware básico (interfaces de comunicação, por exemplo) para o Kernel Linux e fazê-lo ser inicializado.

Porém, o U-Boot faz uma série de outras tarefas. Uma delas é passar ao Kernel, via parâmetro, qual arquivo de Device Tree Blob deve ser usado para o hardware em que o Kernel está sendo executado (hardware alvo). Um Device Tree Blob é uma versão compilada do Device Tree Source, ou seja, um “binário” com o Device Tree do hardware-alvo. A partir do momento que o Kernel possui tal DTB, este poderá controlar todos os dispositivos físicos do hardware-alvo através de seus device drivers.

De forma sucinta, o Device Tree Blob diz ao Kernel quais dispositivos estão ligados e onde eles estão ligados. Ele permite que o Kernel tenha controle do hardware (e também exporta este controle ao User space via sysfs).

Os Device Tree Blobs suportados pelo Kernel no hardware-alvo são normalmente compilados junto com o próprio Kernel. Estes estão disponíveis, no hardware-alvo, em /boot/dtbs/VERSAO_DO_KERNEL, sendo no meu caso a versão do Kernel igual a 4.9.147-ti-r117. Observe a figura 1.

Figura 2 – Device Tree Blobs suportados pelo Kernel da placa alvo

E como descobrir o Device Tree Blob utilizado pela PocketBeagle Board?

Como mencionado anteriormente, é função do segundo estágio de bootloader (no caso da PocketBeagle Board, o U-Boot) informar ao Kernel Linux qual Device Tree Blob utilizar para o hardware-alvo em questão. Mas como descobrir qual Device Tree Blob o hardware-alvo usa?

Bom, há algumas maneiras. Uma delas, por associação, consiste em ler o arquivo /proc/device-tree/model e obter o modelo do Device Tree que o hardware-alvo utiliza de fato. No caso da PocketBeagle Board, o modelo é TI AM335x PocketBeagle, conforme mostra a figura 3.

Figura 3 – Device Tree model utilizado pela PocketBeagle Board

Pesquisando em /boot/dtbs/VERSAO_DO_KERNEL (no meu caso, /boot/dtbs/4.9.147-ti-r117) por arquivos de Device Tree Blobs com nomes que contenham a string “PocketBeagle”, são encontradas duas ocorrências: am335x-PocketBeagle-simplegaming.dtb e am335x-PocketBeagle.dtb. Das ocorrências encontradas, a que parece mais genérica para a PocketBeagle Board é a am335x-PocketBeagle.dtb, logo este é o Device Tree Blob original da placa.

Já de forma mais exata, pode-se fazer uma busca mais minuciosa pelo Device Tree Blob usado pela placa. Na PocketBeagle Board, o U-Boot cria, na partição rootfs, um arquivo chamado bbb-uEnv.txt. Este arquivo contém toda a parte mais baixo nível do segundo estágio de bootloader (endereços de memória dos loaders, parâmetros a serem passados ao Kernel, etc.). Neste arquivo, há a seguinte linha:

Esta linha informa que o Device Tree Blob passado ao Kernel é o localizado em /boot/dtbs/${uname_r}/${fdtfile}, sendo as variáveis de ambiente uname_r a versão do Kernel e fdtfile o almejado nome do Device Tree Blob. Logo, o nome do arquivo de Device Tree Blob usado pela PocketBeagle Board é o exato conteúdo da variável de ambiente fdtfile. Mas onde encontrar o valor dessa variável de ambiente?

Como essa variável de ambiente é do U-Boot, ela só pode ter seu valor lido de duas formas:

  1. Utilizar a UART da placa (tty0) para pegar as mensagens seriais enviadas pelo U-Boot e descobrir qual Device Tree Blob é utilizado. Infelizmente, por ser uma etapa prévia ao Kernel em si, as mensagens do U-Boot não aparecem dentre as mensagens exibidas pelo dmesg.
  2. Procurar no código-fonte do U-Boot por esta variável de ambiente.

Como nem sempre dispomos de um um conversor USB-Serial para ligar na UART da placa e capturar as referidas mensagens, vai ser seguido o caminho 2.

O código-fonte do U-Boot é encontrado neste repositório: https://github.com/u-boot/u-boot . Explorando o repositório e seus códigos-fonte, é possível encontrar o arquivo include/configs/am335x_evm.h (https://github.com/u-boot/u-boot/blob/master/include/configs/am335x_evm.h), o qual contém definições comuns aos SoCs da série am335x (série na qual o SoC da PocketBeagle Board pertence). Nele, o seguinte fragmento de código-fonte se destaca:

Logo, por meio do fragmento de código-fonte acima, é possível afirmar que a variável de ambiente fdtfile é definida de acordo com outra variável de ambiente: board_name.

Resta, portanto, descobrir qual o board_name da PocketBeagle Board. Na página oficinal que instrui a compilação do U-Boot para a PocketBeagle Board (https://www.digikey.com/eewiki/display/linuxonarm/PocketBeagle), há instruções para que dois pacthes sejam aplicados no código-fonte do U-Boot antes de sua compilação:

Explorando o patch 0001-am335x_evm-uEnv.txt-bootz-n-fixes.patch, é possível observar que há uma função para cada placa da linha Beaglebone para retornar o respectivo board_name. Por eliminação, o seguinte código-fonte é o relacionado a PocketBeagle Board:

Isso significa que, quando a placa for uma PocketBeagle Board (identificado pelo acrônimo pb em board_is_pb() ), o board_name retornado é A335PBGL. Portanto, voltanto ao trecho de código-fonte do arquivo https://github.com/u-boot/u-boot/blob/master/include/configs/am335x_evm.h, confirma-se que o Device Tree Blob da placa é o am335x-PocketBeagle.dtb.

Decompilando o Device Tree Blob da placa

Uma vez conhecido o Device Tree Blob utilizado pela PocketBeagle Board, o próximo passo é fazer sua decompilação, ou seja, extrair o Device Tree Source que deu origem ao Device Tree Blob. No Linux embarcado, todo Device Tree Blob pode ser decompilado com a ferramenta dtc. Ainda, a mesma ferramenta é capaz de compilar Device Tree Sources e gerar respectivos Device Tree Blobs.

Ao decompilar o am335x-PocketBeagle.dtb, chegaremos ao Device Tree Source (dts) exato utilizado na placa. Dessa forma, obtem-se o dts exato referente ao dtb original da placa, deixando sua edição segura, uma vez que, originalmente, ele estava 100% correto. Logo, uma vez estando no diretório /boot/dtbs/VERSAO_DO_KERNEL (no meu caso, /boot/dtbs/4.9.147-ti-r117), a decompilação do am335x-PocketBeagle.dtb é feita com o seguinte comando:

Após este comando, o arquivo am335x-PocketBeagle.dts estará disponível, e conterá todo o código do Device Tree Source original da placa.

Adicionando um LED externo no Device Tree Source

Agora, é hora de adicionar um LED externo no Device Tree Source (am335x-PocketBeagle.dts), de modo que esse LED possa ser controlado pelos Device Driver de LEDs do Kernel. Dessa forma, tem-se um LED totalmente suportado pelo framework de LEDs do Kernel, ficando livre a uma aplicação qualquer e/ou usuário simplesmente configurar como o LED deve funcionar (se deve piscar, acender, apagar, etc.) e o Kernel cuida do resto. Como comportamento default, este LED deve ter como Trigger o Heartbeat (https://elixir.bootlin.com/linux/v4.8/source/drivers/leds/trigger/ledtrig-heartbeat.c).

Se você olhar atentamente, perceberá que a PocketBeagle Board já possui 4 LEDs, identificados como USR0, USR1, USR2 e USR3, conforme mostra a figura 4.

Figura 4 – User LEDs (fonte: https://github.com/beagleboard/PocketBeagle/wiki/System-Reference-Manual#Figure_14_User_LEDs)

Buscando pela string “leds” no Device Tree Source da placa (am335x-PocketBeagle.dts), são encontrados os nós dos User LEDS, conforme mostrado abaixo:

Logo, o nó do Device Tree Source correspondente ao LED externo deverá ser adicionado no mesmo nível dos demais LEDs (User LEDs). Neste artigo, o LED será acionado pelo GPIO 57 da PocketBeagle Board, o que significa que é preciso saber como este GPIO é identificável no Device Tree Source (equivalente ao parâmetro gpios nos nós dos LEDs no trecho acima).

Considere o pinout da placa, mostrado na figura 5.

Figura 5 – pinout da PocketBeagle Board

Pelo pinout, GPIO 57 corresponde ao pino 6 do header P2, ou na notação comumente vista nas Beaglebone, P2_06. Pesquisando por “P2_06” no Device Tree Source da placa (am335x-PocketBeagle.dts), é encontrado o seguinte nó:

Portanto, o GPIO 57 é identificável no Device Tree Source (parâmetro gpios) por <0x196 0x19 0x0>. Sendo assim, o LED externo terá um nó conforme a seguir:

O campo label (beaglebone:green:extLed) corresponde a forma com que ele aparecerá nos arquivos exportados via sysfs.

Por fim, o nó de LEDs completo fica conforme mostrado abaixo:

Após inserir o nó com LED externo, salve Device Tree Source.
Não se esqueça de ligar fisicamente o LED externo ao GPIO 57. Utilize para isso um resistor de 470 Ohm / 0.25W.

Recompilação do Device Tree Blob (com o LED externo)

Para recompilar o Device Tree Blob atualizado (já com o LED externo adicionado), utilize novamente a ferramenta dtc, conforme comando abaixo estando no diretório /boot/dtbs/VERSAO_DO_KERNEL (no meu caso, /boot/dtbs/4.9.147-ti-r117).

Teste do novo Device Tree Blob na PocketBeagle Board

Para testar o novo Device Tree Blob na PocketBeagle Board, a forma mais simples é reiniciar a placa. Após o reboot, você perceberá o LED externo piscando, conforme Trigger configurado (Heartbeat).

Ainda, é possível ver o controle do LED externo exportado via sysfs conforme o label informado no nó do Device Tree do LED externo. Este controle pode ser visto em /sys/class/leds/beaglebone:green:extLed, conforme mostra a figura 6.

Figura 6 – controle do LED externo (/sys/class/leds/beaglebone:green:extLed) exportado via sysfs

Veja no vídeo abaixo o LED externo funcionando conforme mostrou este artigo:

Sem licença Creative Commons

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Linux Embarcado » Interagindo com o Device Tree da PocketBeagle Board
Comentários:
Notificações
Notificar
guest
2 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Josemar Alves de Carvalho
Membro
20/08/2020 09:17

Ola Pedro.
Imagino o trabalho que deve ter dado para encontrar todos os passos a serem feitos.
Obrigado por compartilhar e parabens pelo artigo.

Talvez você goste:

Nenhum resultado encontrado.

Séries

Menu