2 Comentários

As Novas Interfaces de GPIO do Kernel Linux v5.5

Kernel Linux V5.5

Quem nunca piscou um LED utilizando o /sys/class/gpio em Linux Embarcado? Mas essa interface, que externa acesso a GPIO via sysfs, está com os dias contados 💀, deve ser removida do Kernel Linux ainda esse ano.

Desde a versão 4.8 do Kernel Linux, lançado em outubro de 2016, que existem novas interfaces, baseadas em char device, para gerenciar GPIO em user space. Durante a Linux Developer Conference 2019 palestrei sobre o assunto, mostrando na prática o uso das novas interfaces com o libgpiod.

Nesse último domingo, 26/01/2020, foi lançada a primeira versão do Kernel Linux do ano de 2020, a v5.5. Nessa versão temos novidades no gpiolib, novas interfaces para configuração de pinos. Agora podemos configurar um pino como pull-up ou pull-down via user space 😍.

Interface de GPIO Kernel Linux v4.8 - gpiolib

Antes de demonstrar as novidades, vamos explorar primeiro o que já tínhamos desde o Kernel Linux v4.8. A gpiolib é uma API interna do Kernel Linux para gerenciamento e configuração de GPIO. Ela provê acesso às APIs tanto em Kernel Space, mantém drivers de dispositivos genéricos com relação à plataforma de hardware, como também em user space, através de chamadas ioctl em arquivos, char devices, em /dev/gpiochipX. Onde X é o número do banco de GPIO.

Vou usar a Raspberry Pi 3B para os exemplos práticos, assim podemos entender como se divide o stack do gpiolib, desde sua aplicação, no user space, até a funcionalidade ser aplicada ao hardware, controlador de GPIO, pelo kernel space.

Para demonstrar as funcionalidades vou usar os utilitários do projeto libgpiod. Essa biblioteca facilita as operações de chamadas ioctl, read e poll nos arquivos /dev/gpiochip, definindo uma API amigável para o uso, além de prover utilitários de linha de comando. Temos vários projetos que já implementam bindings do libgpiod para uso com diferentes linguagens de programação. Inclusive, eu já escrevi um artigo aqui no embarcados sobre o projeto da .NET Foundation que implementa essas interfaces, para a linguagem C# com .NET Core.

Utilitários Linha de Comando libgpiod - User Space

gpiodect

Primeiramente vamos utilizar o utilitário gpiodetect para saber quais bancos de GPIO e quantas linhas de GPIO temos disponíveis no nosso hardware:

GPIO do Kernel Linux

No caso da Raspberry Pi 3B temos dois char device, dois bancos de GPIO. Ele também lista o nome do driver controlador de cada banco. gpiochip0 é controlado pelo driver de pin control do processador ARM, enquanto o gpiochip1 é o expansor de GPIO, que é controlado pela VPU Broadcom. Podemos também verificar os bancos listando os gpiochip* em /dev:

GPIO do Kernel Linux

gpioinfo

Outra funcionalidade interessante que ganhamos com a nova interface é que os GPIOs podem ser representados por nomes. Por exemplo, executando o utilitário gpioinfo:

GPIO do Kernel Linux

Será listado a linha do banco de gpio, seu respectivo nome, uma descrição do uso do pino e a configuração do pino. Note acima os nomes das linhas 23 e 24 do gpiochip0. Editando o arquivo de device tree bcm2837-rpi-3-b.dts, propriedade gpio-lines-names do nó gpio, podemos nomear os pinos de acordo à sua função no circuito do projeto. Para o circuito de exemplo, figura abaixo, temos o pino 23 conectado a um push button e o pino 24 a um LED azul:

gpiofind

Os nomes facilitam na hora de consumir pinos. Não é necessário mais decorar, fazer cálculos do número do banco e linha, ou consultar datasheets para achar o pino. Em que pino está conectado o LED azul? Fácil, vamos perguntar para o utilitário gpiofind:

gpioset

Em conjunto com o gpiofind, podemos escrever estados de GPIO, facilmente pelos seus nomes com o utilitário gpioset. Por exemplo, vamos ligar o LED azul:

O gpioset espera o banco, gpiochip, linha de GPIO e o valor a ser setado, 1 para HIGH e 0 para LOW como padrão. O comando acima resolve o banco de GPIO e linha pelo seu nome, usando o gpiofind. Seria o mesmo que:

O argumento -m do comando é o mode, ele define o comportamento do comando depois de setar o GPIO. O -m wait diz para o comando esperar, o processo fica com o recurso do banco e linha do GPIO em uso, até que o usuário digite Enter no terminal. Podemos usar esse comportamento para explorar a informação de uso em outro terminal com o comando gpioinfo:

Podemos ver que a linha 24 está em uso. É aconselhado aos usuários da biblioteca libgpiod descrever o uso do pino. Aqui no caso os desenvolvedores dos utilitários, resolveram colocar na descrição de uso o próprio nome do utilitário: “gpioset”. Essa é uma informação preciosa para debug em desenvolvimento, para saber que processo, quem ou para que fim o recurso está sendo usado.

Exemplo Blink - libgpiod com Linguagem C 

O exemplo abaixo utiliza a API do libgpiod para criar um “blink” com nosso LED azul:

Note a linha 16 como instanciamos a estrutura gpiod_line procurando pelo nome da linha de GPIO.

Outra linha interessante de chamar a atenção é a 18. Quando executamos uma requisição para usar um pino, um dos argumentos é uma string com a descrição do uso do pino. Com o exemplo rodando, se abrirmos outro terminal e executar o gpioinfo, vamos notar a descrição:

Então o stack das chamadas ficam assim:

Você usa a API da biblioteca libpgiod, ou seus bindings para a linguagem de sua preferência, em user space. A libgpiod por sua vez irá executar as operações no char device. As system calls passam o controle para o Kernel que vai executar o código genérico da gpiolib.c. Essa por sua vez irá executar o código dependente da arquitetura da placa, que implementa a escrita dos registradores do controlador de GPIO. No caso da Raspberry Pi 3B, processador ARM Broadcom BCM2837, essa implementação fica por conta do pinctrl-bcm2835.c. Ele executa as escritas nos registradores do banco e linha de GPIO requeridos e enfim temos nosso LED piscando.

Novidades na gpiolib do Kernel Linux v5.5

Nos exemplos acima notem que não demonstrei “inputs” com os utilitários, apenas “outputs”. Porque vamos exemplificar os “inputs” em conjunto com as novidades que vieram no gpiolib do Kernel Linux v5.5.

Temos dois utilitários para ler GPIOs como entradas: gpioget e gpiomon. O gpioget tem um padrão parecido com o gpioset. Podemos utilizar ele em conjunto com o gpiofind para lermos o input do nosso botão pelo nome:

O gpiomon, GPIO monitor, através de chamadas poll fica monitorando as mudanças de estado no pino. Então, podemos usar ele em conjunto com o gpiofind, para monitorar eventos do nosso botão:

GPIO do Kernel Linux

Note que ao utilizar o comando, com o circuito do nosso exemplo, o estado do botão fica “louco”, está em um estado flutuante, não está mudando apenas quando pressionado:

GPIO do Kernel Linux

O circuito do botão do exemplo foi pensado sem um resistor de pull-down de propósito. Porque vamos usar a funcionalidade de pull-down do próprio controlador de GPIO do processador.

E é exatamente essa uma das novidades do gpiolib do Kernel v5.5. Anteriormente para configurar um pino como pull-up ou pull-down, você teria que descrever a configuração do pino via device tree. Agora temos uma nova interface que possibilita isso ser feito pelo char device da gpiolib, via user space 😮. 

Para usar essa funcionalidade você precisa estar rodando um Kernel Linux v5.5 ou superior, e ter o libgpiod v1.5 ou superior:

A libgpiod v1.5 já inclui o argumento -B, de bias, nos utilitários de linha de comando:

GPIO do Kernel Linux

Assim podemos usar o gpiomon configurando o pino do nosso botão com pull-down:

GPIO do Kernel Linux

Resolvendo o problema da flutuação do pino, agora só teremos mudança de estado quando pressionarmos o botão:

GPIO do Kernel Linux

Conclusões - As Novas Interfaces de GPIO do Kernel Linux V5.5

Configuração de bias via user space sempre foi uma funcionalidade que muitos pediam e ficavam em dúvida se era possível, configurar pull down ou pull up, via sysfs por exemplo. A comunidade de desenvolvedores do Kernel Linux ouviu os clamores dos makers e enfim implementou na gpiolib da v5.5. Ainda são novidades muito frescas, até chegar no Raspbian, por exemplo, pode levar um tempo. Então para usá-las por agora, provavelmente, você terá que compilar seu próprio Kernel v5.5 e libgpiod v1.5.

A libgpiod facilita muito o uso das interfaces, abstraindo as chamadas de ioctl, open e read nos /dev/gpiochip. Além de ter utilitários de linha de comando completos, que podem facilitar o uso em scripts bash por exemplo. É uma biblioteca mantida pela comunidade que tem contribuidores que também fazem parte dos desenvolvedores do Kernel Linux, aliás mantenedores dos sub sistemas de gpio e pin control. 

A gpiolib está bem completa. Agora podemos dar nosso adeus ao /sys/class/gpio e bibliotecas tipo wiringPi (escrevendo em /dev/mem que feio 😢) sem medo! As novas interfaces de gerenciamento de GPIO em user space, são a forma mais segura, confiável e recomendada de trabalhar com GPIOs. Elas foram pensadas para trabalhar em conjunto com o kernel space, para manter o controle dos estados do hardware e recursos da melhor forma.

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

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

Notícias » As Novas Interfaces de GPIO do Kernel Linux v5.5
Talvez você goste:
Comentários:

2
Deixe um comentário

avatar
2 Comentários
0 Respostas
0 Seguidores
 
Discussão de maior alcance
Discussão mais quente
2 Autores de comentários
Mr SparkFunCirineu C Fernandes Comentários recentes
  Notificações  
recentes antigos mais votados
Notificar
Mr SparkFun
Membro
Mr SparkFun

Olá! Parabéns pelo ótimo artigo. Gostaria de saber qual é a distro usada nesse exemplo. Tentei rodar no Raspbian Stretch 9.11 sem sucesso (ao tentar instalar a lib ocorre => configure: error: "libgpiod needs linux headers version >= v5.5.0").

Cirineu C Fernandes
Visitante
Cirineu C Fernandes

Muito útil a biblioteca, vamos fazer o uso dela com a GongoMESH, implementando em nosso script.

Séries

Menu