Desenvolvimento de driver de dispositivo Linux:O subsistema de controle de pin
Nota do Editor:O kernel Linux embarcado já desempenha um papel vital em sistemas embarcados e tem cada vez mais importância no atendimento aos diversos requisitos da Internet das Coisas (IoT). Por sua vez, os drivers de dispositivo fornecem o link crítico entre os aplicativos e os próprios dispositivos IoT. Em Linux Device Drivers Development, o autor John Madieu oferece uma visão abrangente do desenvolvimento desses drivers, combinando uma explicação detalhada com muitos exemplos de código.
Este trecho, Capítulo 14 do livro, enfoca o controle de pinos e GPIOs - uma área de particular importância para desenvolvedores de sistemas embarcados que procuram interagir com dispositivos de hardware personalizados. Esta primeira parte deste trecho apresenta o subsistema de controle de pinos.
Adaptado de Linux Device Drivers Development, por John Madieu.
Capítulo 14. Controle de pinos e subsistema GPIO
Por John Madieu
A maioria dos drivers Linux embarcados e engenheiros de kernel escrevem usando GPIOs ou brincam com a multiplexação de pinos. Por pinos, quero dizer linha de componente de saída. O SoC multiplexa os pinos, o que significa que um pino pode ter várias funções, por exemplo, MX6QDL_PAD_SD3_DAT1 em arch / arm / boot / dts / imx6dl-pinfunc.h pode ser uma linha de dados SD3 1, cts / rts do UART1, Rx do Flexcan2 ou GPIO normal.
O mecanismo pelo qual se escolhe o modo em que um alfinete deve funcionar é chamado de multiplexação de alfinetes. O sistema responsável é denominado controlador de pinos. Na segunda parte do capítulo, discutiremos o Resultado de entrada para fins gerais ( GPIO ), que é uma função especial (modo) em que um pino pode operar.
Neste capítulo, iremos:
-
Percorra o subsistema de controle de pinos e veja como alguém pode declarar seus nós na DT
-
Explore as interfaces GPIO baseadas em inteiros legadas, bem como a nova API de interface baseada em descritor
-
Lide com GPIO mapeado para IRQ
-
Lidar com interfaces sysfs dedicadas a GPIOs
Subsistema de controle de pinos
O controle Pin ( pinctrl ) o subsistema permite o gerenciamento de multiplexação de pinos. No DT, os dispositivos que precisam de pinos para serem multiplexados de uma certa maneira devem declarar a configuração de controle de pinos de que precisam.
O subsistema pinctrl fornece:
-
Multiplexação de pinos, que permite reutilizar o mesmo pino para finalidades diferentes, como um pino sendo um pino UART TX, linha GPIO ou Linha de dados HSI. A multiplexação pode afetar grupos de pinos ou pinos individuais.
-
Configuração de pinos, aplicando propriedades eletrônicas de pinos como pull-up, pull-down, força do driver, período de debounce e assim por diante.
O objetivo deste livro é limitado ao uso de funções exportadas pelo driver do controlador de pino e não como escrever um driver do controlador de pino.
Pinctrl e a árvore do dispositivo
O pinctrl nada mais é que uma forma de reunir pinos (não apenas GPIO) e passá-los para o driver. O driver do controlador de pinos é responsável por analisar as descrições dos pinos no DT e aplicar sua configuração no chip. O driver geralmente precisa de um conjunto de dois nós aninhados para descrever o grupo de configurações de pinos. O primeiro nó descreve a função do grupo (para que propósito o grupo será usado), o segundo contém a configuração dos pinos.
Como os grupos de pinos são atribuídos no DT depende muito da plataforma e, portanto, do driver do controlador de pinos. Cada estado de controle de pino recebe um ID inteiro começando em 0 e contíguo. Pode-se usar uma propriedade de nome, que será mapeada no topo dos IDs, de forma que o mesmo nome sempre aponte para o mesmo ID.
A própria vinculação de cada dispositivo cliente determina o conjunto de estados que deve ser definido em seu nó DT e se deve definir o conjunto de IDs de estado que deve ser fornecido ou se deve definir o conjunto de nomes de estado que deve ser fornecido. Em qualquer caso, um nó de configuração de pino pode ser atribuído a um dispositivo por meio de duas propriedades:
-
pinctrl-
:Isso permite fornecer a lista de configurações de pinctrl necessárias para um determinado estado do dispositivo. É uma lista de phandles, cada um dos quais aponta para um nó de configuração de pino. Esses nós de configuração de pino referenciados devem ser nós filho do controlador de pino que eles configuram. Podem existir várias entradas nesta lista para que vários controladores de pino possam ser configurados, ou para que um estado possa ser construído a partir de vários nós para um único controlador de pino, cada um contribuindo com a configuração geral.
-
nome-pinctrl:Isso permite dar um nome para cada estado em uma lista. A entrada de lista 0 define o nome para o ID de estado inteiro 0, a entrada de lista 1 para o ID de estado 1 e assim por diante. O ID de estado 0 geralmente recebe o nome padrão . A lista de estados padronizados pode ser encontrada em include / linux / pinctrl / pinctrl-state.h.
A seguir está um trecho da TD, mostrando alguns nós de dispositivo, junto com seus nós de controle de pinos:
No exemplo anterior, uma configuração de pino é fornecida no formato
MX6QDL_PAD_DISP0_DAT15__GPIO5_IO09 0x80000000
MX6QDL_PAD_DISP0_DAT15__GPIO5_IO09 representa a função de pino, que é GPIO neste caso, e 0x80000000 representa as configurações de pino. Para esta linha,
MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
MX6QDL_PAD_EIM_D25__UART3_RX_DATA representa a função de pino, que é a linha RX de UART3, e 0x1b0b1 representa suas configurações.
A função pin é uma macro cujo valor é significativo apenas para o driver do controlador de pin. Eles são geralmente definidos em arquivos de cabeçalho localizados em arch // boot / dts /. Se alguém usar um UDOO quad, por exemplo, que tem um i.MX6 quad core (ARM), o cabeçalho da função do pino seria arch / arm / boot / dts / imx6q-pinfunc.h. A seguir está a macro correspondente à quinta linha do controlador GPIO5:
#define MX6QDL_PAD_DISP0_DAT11__GPIO5_IO05 0x19c 0x4b0 0x000 0x5 0x0
Esses nós anteriores são chamados a partir do nó específico do driver correspondente. Além disso, esses pinos são configurados durante a inicialização do driver correspondente. Antes de selecionar um estado de grupo de pinos, deve-se obter o controle de pino primeiro usando a função pinctrl_get (), chamar pinctrl_lookup_state () para verificar se o estado solicitado existe ou não e, finalmente, pinctrl_select_state () para aplicar o estado.
A seguir está um exemplo que mostra como obter um pincontrol e aplicar sua configuração padrão:
Geralmente, essas etapas são executadas durante a inicialização do driver. O local adequado para esse código pode ser na função probe ().
pinctrl_select_state () chama internamente pinmux_enable_setting (), que por sua vez chama pin_request () em cada pino no nó de controle do pino.
Um controle de pino pode ser liberado com a função pinctrl_put (). Pode-se usar a versão gerenciada por recursos da API. Dito isso, pode-se usar pinctrl_get_select (), dado o nome do estado a ser selecionado, para configurar o pinmux. A função é definida em include / linux / pinctrl / consumer.h da seguinte maneira:
static struct pinctrl * pinctrl_get_select (struct device * dev,
const char * name)
onde * name é o nome do estado conforme escrito na propriedade pinctrl-name. Se o nome do estado for padrão, pode-se apenas chamar a função pinctr_get_select_default (), que é um invólucro em torno de pinctl_get_select ():
static struct pinctrl * pinctrl_get_select_default (
dispositivo de struct * dev)
{
return pinctrl_get_select (dev, PINCTRL_STATE_DEFAULT);
}
Vejamos um exemplo real em um arquivo dts específico da placa (am335x-evm.dts):
dcan1:d_can @ 481d0000 {
status =“ok”;
nomes-pinctrl =“padrão”;
pinctrl-0 =<&d_can1_pins>;
};
E no driver correspondente:
pinctrl =devm_pinctrl_get_select_default (&pdev-> dev);
if (IS_ERR (pinctrl))
dev_warn (&pdev-> dev, ”os pinos não são configurados a partir do driver”);
O núcleo de controle de pinos reivindicará automaticamente o estado de pinça padrão para nós quando o dispositivo for testado. Se alguém definir um estado de inicialização, o núcleo pinctrl irá definir automaticamente o pinctrl para este estado antes da função probe (), e então muda para o estado padrão após probe () (a menos que o driver já tenha mudado explicitamente os estados).
A próxima edição discutirá o subsistema GPIO.
Reimpresso com permissão da Packt Publishing. Copyright © 2017 Packt Publishing
John Madieu é um engenheiro de Linux embarcado e kernel que mora na França, em Paris. Suas principais atividades consistem no desenvolvimento de drivers e Board Support Packages (BSP) para empresas em áreas como automação, transporte, saúde, energia e militar. John trabalha na EXPEMB, uma empresa francesa pioneira em design de placas eletrônicas com base em computador em módulo e em soluções Linux embarcadas. Ele é um entusiasta de código aberto e sistemas embarcados, convencido de que é apenas compartilhando conhecimento que se aprende mais.
Tecnologia da Internet das Coisas
- Lidando com as vulnerabilidades de segurança da IoT industrial
- O Desenvolvimento de Plásticos Modernos
- Perspectivas para o desenvolvimento de IoT Industrial
- Quem está encarregado do carro conectado? Pergunte ao motorista no loop
- Seis etapas para proteger sistemas embarcados na IoT
- O ponto de inflexão para SaaS no desenvolvimento de produtos (Parte 2)
- O ponto de inflexão para SaaS no desenvolvimento de produtos:Parte 1
- Desafios na seleção do fornecedor certo de desenvolvimento de IoT
- Os requisitos IPC de controle complexo
- Quais são os principais motivadores para o desenvolvimento de IoT empresarial bem-sucedido?