hands-on linux device drivers dwf 2013

67
Embedded Labworks Por Sergio Prado. São Paulo, Novembro de 2012 ® Copyright Embedded Labworks 2004-2013. All rights reserved. Crie seu próprio device driver para Linux com os processadores i.MX6 da Freescale.

Upload: sergio-prado

Post on 11-Jun-2015

808 views

Category:

Technology


1 download

DESCRIPTION

Slides do hands-on "Crie seu próprio device driver para Linux com os processadores i.MX6 da Freescale", apresentado no Design with Freescale 2013 em São Paulo/SP.

TRANSCRIPT

Page 1: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

Por Sergio Prado. São Paulo, Novembro de 2012® Copyright Embedded Labworks 2004-2013. All rights reserved.

Crie seu próprio device driver para Linux com os processadores i.MX6 da Freescale.

Page 2: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

SOBRE ESTE DOCUMENTO

✗ Este documento é disponibilizado sob a Licença Creative Commons BY-SA 3.0.http://creativecommons.org/licenses/by-sa/3.0/legalcode

✗ Os fontes deste documento estão disponíveis em:http://sergioprado.org/palestras/dwf2013/drivers

Page 3: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

SOBRE O PALESTRANTE

✗ Sergio Prado tem mais de 17 anos de experiência em desenvolvimento de software para sistemas embarcados, em diversas arquiteturas de CPU (ARM, PPC, MIPS, x86, 68K), atuando em projetos com Linux embarcado e sistemas operacionais de tempo real.

✗ É sócio da Embedded Labworks, onde atua com consultoria, treinamento e desenvolvimento de software para sistemas embarcados:http://e-labworks.com

✗ Mantém um blog pessoal sobre Linux e sistemas embarcados em:http://sergioprado.org

Page 4: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

WANDBOARD QUAD

✗ i.MX6 Quad (4 núcleos ARM Cortex-A9) rodando à 1GHz.

✗ 2G de RAM DDR3.

✗ Duas interfaces de cartão SD e uma interface SATA.

✗ Saídas de áudio (comum e S/PDIF) e vídeo HDMI.

✗ Ethernet Gigabit, USB host e OTG, WiFi, Bluetooth, serial, etc.

http://wandboard.org

Page 5: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

O PROJETO: DRIVER DE LED

Page 6: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

AMBIENTE DE LABORATÓRIO

/opt/labworks/drivers Ambiente de laboratório

docs Documentação do hands­on

driver Diretório de desenvolvimento do driver

images Ferramentas e imagens para gravar o cartão SD da Wandboard Quad

kernel Código­fonte do Linux

Page 7: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

LINUX, SIMPLES ASSIM... :)

Page 8: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

HISTÓRICO

✗ O kernel Linux é um dos componentes do sistema operacional, que requer bibliotecas e aplicações para prover funcionalidades aos usuários.

✗ Foi criado em 1991 por um estudante finlandês, Linus Torvalds, e começou a ser usado rapidamente como sistema operacional em projetos de software livre.

✗ Linus foi capaz de criar uma comunidade grande e dinâmica de desenvolvedores e usuários ao redor do projeto.

✗ Atualmente, centenas de pessoas e empresas contribuem com o Linux.

Page 9: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

Biblioteca C

Hardware

Biblioteca Biblioteca AplicaçãoUser space

Kernel Linux

AplicaçãoAplicação

Chamadas de sistema Notificação de eventosExportação de informações

Gerenciamento do hardware Notificação de eventos

ARQUITETURA GERAL

Page 10: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

FONTES DO KERNEL

✗ A versão oficial do código-fonte do kernel liberada por Linus Torvalds encontra-se em:http://www.kernel.org

✗ Baixando os fontes por http:$ wget http://www.kernel.org/pub/linux/kernel/v3.0/linux­3.6.tar.bz2$ tar xjfv linux­3.6.tar.bz2

✗ Baixando os fontes pelo git:$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git

Page 11: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

OUTROS REPOSITÓRIOS

✗ Muitas comunidades e fabricantes de hardware podem manter versões alternativas do kernel:

✗ Comunidades podem manter versões do kernel voltadas à arquiteturas específicas (ARM, MIPS, PPC), sub-sistemas (USB, PCI, network), sistemas de tempo-real, etc.

✗ Fabricantes de hardware podem manter versões específicas do kernel com suporte às suas plataformas de referência.

Page 12: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

LISTAGEM DOS FONTES$ lsarch            fs        MAINTAINERS      securityblock           include   Makefile         soundCOPYING         init      mm               toolsCREDITS         ipc       net              usrcrypto          Kbuild    README           virtDocumentation   Kconfig   REPORTING­BUGSdrivers         kernel    samplesfirmware        lib       scripts

Page 13: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

CONFIGURANDO O KERNEL

✗ O kernel possui centenas de drivers de dispositivo, diversos protocolos de rede e muitos outros itens de configuração.

✗ O kernel é bem modular, são muitas as opções disponíveis para serem habilitadas/desabilitadas.

✗ O processo de configuração serve para você configurar o kernel para ser compilado para sua CPU/plataforma.

✗ O conjunto de opções que você irá habilitar depende:✗ Do seu hardware (device drivers, etc).

✗ Das funcionalidades (protocolos de rede, sistemas de arquivo, etc).

Page 14: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

CONFIGURAÇÃO

✗ As configurações são salvas em um arquivo chamado .config no diretório principal dos fontes do kernel, e possuem o formato key=value. Exemplo:

CONFIG_ARM=y

✗ Dificilmente você vai precisar editar o arquivo .config manualmente. Existem ferramentas de interface gráfica para configurar o kernel e gerar o arquivo de configuração automaticamente:✗ make menuconfig

✗ make gconfig

✗ make xconfig

✗ make nconfig

Page 15: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

MENUCONFIG

Page 16: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

BUILT-IN OU MÓDULO

✗ O kernel permite que algumas das funcionalidades disponíveis possam ser habilitadas e compiladas de duas formas:

✗ Estática ou built-in: a funcionalidade selecionada é linkada estaticamente à imagem final do kernel.

✗ Dinâmica ou módulo: é gerado um módulo daquela funcionalidade (arquivo com extensão .ko). Este módulo não é incluído na imagem final do kernel. Ele é incluído no sistema de arquivos e pode ser carregado dinamicamente (em tempo de execução), conforme a necessidade.

Page 17: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

BUILT-IN OU MÓDULO (cont.)

✗ Opções booleanas (verdadeiro/falso)

[ ]   Opção desabilitada→

[*]   Opção habilitada (built­in)→

✗ Opções de 3 estados:

< >   Opção desabilitada→

<*>   Opção habilitada (built­in)→

<M>   Opção habilitada (módulo)→

Page 18: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

CONFIGURAÇÃO POR ARQUITETURA

✗ Toda a configuração do kernel é dependente da arquitetura.

✗ Por padrão, o kernel considera um build nativo, então irá usar a arquitetura da máquina de desenvolvimento (normalmente x86) no comando abaixo:$ make menuconfig

✗ Portanto, para configurar para ARM por exemplo, você precisa especificar a arquitetura:

$ make ARCH=arm menuconfig

✗ Ao invés de passar a variável ARCH na chamada do make, você pode também defini-la como variável de ambiente ou alterar o arquivo Makefile no diretório principal do kernel.

Page 19: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

CONFIGURAÇÕES PRÉ-DEFINIDAS

✗ Arquivos de configuração pré-definidos para diversas plataformas estão disponíveis em arch/<arch>/configs/.

✗ O uso de arquivos pré-configurados é a forma padrão de configurar um kernel para uma plataforma específica. Por exemplo, para carregar a configuração padrão da Wandboard:

$ make ARCH=arm wandboard_defconfig

Page 20: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

COMPILANDO O KERNEL

✗ Depois de configurado, para compilar nativamente basta executar:

$ make

✗ Não precisa de previlégios de root!

✗ Para cross-compilar, você precisa indicar a arquitetura e o prefixo do cross-compiler. Exemplo:

$ make ARCH=arm CROSS_COMPILE=arm­linux­

✗ O comando acima irá gerar uma imagem genérica para ARM. Se você quiser gerar uma imagem específica para determinado bootloader, deve adicionar ao fim do comando o nome da imagem. Exemplo para o U-Boot:

$ make ARCH=arm CROSS_COMPILE=arm­linux­ uImage

Page 21: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

COMPILANDO OS MÓDULOS

✗ Para compilar apenas os módulos, basta executar:

$ make modules

✗ Para cross-compilar os módulos, não esqueça de indicar a arquitetura e o prefixo do cross-compiler. Exemplo:

$ make ARCH=arm CROSS_COMPILE=arm­linux­ modules

Page 22: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

INSTALANDO O KERNEL

✗ Para instalar o kernel, basta executar o comando abaixo:$ make install

✗ Este comando irá instalar os seguintes arquivos no diretório /boot:✗ vmlinuz­<version> (imagem do kernel comprimida)

✗ System.map­<version> (endereços dos símbolos do kernel)

✗ config­<version> (arquivo de configuração do kernel)

✗ Normalmente não é usado em sistemas embarcados!

✗ Em sistemas embarcados, normalmente gravamos o kernel em um dispositivo de armazenamento (cartão SD, memória flash, etc).

Page 23: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

INSTALANDO OS MÓDULOS

✗ Para instalar os módulos, basta executar o comando abaixo:

$ make modules_install

✗ No caso de um ambiente de compilação cruzada, os módulos devem ser instalados no rootfs do target.

✗ Para isso, devemos passar o parâmetro INSTALL_MOD_PATH no comando de instalação:$ make ARCH=<arch> INSTALL_MOD_PATH=<dir> modules_install

Page 24: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

LABORATÓRIO

Compilando e testando o kernel

Page 25: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

MÓDULOS

✗ Internamente, o Linux é bem modular. Cada funcionalidade é abstraída em um módulo, com uma interface de comunicação bem definida. Por isso, permite um sistema de configuração onde você pode adicionar ou remover determinada funcionalidade.

✗ E o Linux permite que você compile separadamente determinada funcionalidade, e carregue o arquivo gerado em tempo de execução! Chamamos este arquivo compilado separadamente de módulo do kernel.

✗ Um device driver pode ser compilado de forma integrada ao kernel (built-in) ou como um módulo do kernel.

Page 26: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

VANTAGENS DOS MÓDULOS

✗ Módulos tornam fácil o desenvolvimento do kernel (ex: device drivers) sem precisar reiniciar o equipamento.

✗ Ajuda a manter a imagem do kernel bem pequena.

✗ Só ocupa memória enquanto estiver carregado.

✗ O tempo de boot do kernel fica menor.

✗ Cuidado: módulos rodam em kernel space. Uma vez carregados, eles tem total controle do sistema! Por isso só podem ser carregados como root.

Page 27: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

CARREGANDO UM MÓDULO

✗ Carregar apenas um módulo (é necessário passar o caminho completo do módulo):

$ insmod <module_path>.ko

✗ Carregar um módulo e todas as suas dependências (deve-se passar apenas o nome do módulo, sem a extensão .ko e sem seu caminho completo):

$ modprobe <module_name>

Page 28: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

DESCARREGANDO UM MÓDULO

✗ Descarregar apenas um módulo, desde que o módulo não esteja mais em uso (deve-se passar apenas o nome do módulo, sem a extensão .ko e sem seu caminho completo):

$ rmmod <module_name>

✗ Descarregar um módulo e todas as suas dependências, desde que não estejam mais em uso (deve-se passar apenas o nome do módulo, sem a extensão .ko e sem seu caminho completo):

$ modprobe ­r <module_name>

Page 29: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

LISTANDO INFORMAÇÕES DOS MÓDULOS

✗ Ler informações de um módulo, como sua descrição, parâmetros, licença e dependências (deve-se passar apenas o nome do módulo, sem a extensão .ko e sem seu caminho completo):

$ modinfo <module_name>

✗ Listar todos os módulos carregados:

$ lsmod

Page 30: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

__init é removido após a inicialização (built-in ou módulo)

__exit é descartado caso seja compilado estaticamente no kernel (built-in).

#include <linux/module.h>#include <linux/kernel.h>

/* module initialization */static int __init mymodule_init(void){    printk("My module initialized.\n");    return 0;}

/* module exit */static void __exit mymodule_exit(void){    printk("Exiting my module.\n");}

module_init(mymodule_init);module_exit(mymodule_exit);

MODULE_LICENSE("GPL");

Page 31: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

COMPILANDO UM MÓDULO

✗ Existem duas opções para compilar um módulo:✗ Fora da àrvore do kernel: fácil de gerenciar, mas não permite

compilar um módulo estaticamente (built-in).

✗ Dentro da árvore do kernel: permite compilar um módulo estaticamente ou dinamicamente.

Page 32: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

MAKEFILE

Obs: em caso de compilação cruzada, não esqueça de definir os parâmetros ARCH e CROSS_COMPILE.

KDIR := /linux/source/code/directory/

obj­m += mymodule.o

module:        $(MAKE) ­C $(KDIR) M=$(PWD) modules

clean:        $(MAKE) ­C $(KDIR) M=$(PWD) clean

Page 33: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

LABORATÓRIO

O primeiro módulo

Page 34: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

ACESSO AO HARDWARE

✗ No Linux, o acesso ao hardware é exportado para as aplicações através de 3 principais classes de dispositivos:

✗ Character device (dispositivo de caractere).

✗ Block device (dispositivo de bloco).

✗ Network device (dispositivo de rede).

Page 35: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

CLASSES DE DISPOSITIVOS

✗ Char device: pode ser acessado como um stream contínuo de dados (acesso sequencial), sem começo, meio e fim. É acessado através de um arquivo em /dev. Ex: porta serial, impressora, placa de som, etc.

✗ Block device: trabalha com blocos de dados, pode ser endereçável, tem começo, meio e fim. É acessado através de um arquivo em /dev. Ex: HD, CDROM, DVD, pendrive, etc.

✗ Network device: dispositivo totalmente diferente, que pode ser representado por uma interface de rede física ou por software (loopback), responsável por enviar e receber pacotes de dados através da camada de rede do kernel. Não possui um arquivo em /dev. A comunicação é feita através de uma API específica.

Page 36: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

ARQUIVOS DE DISPOSITIVO

✗ Os dispositivos de caractere e bloco são representados para as aplicações através de arquivos chamados arquivos de dispositivos e armazenados no diretório /dev por convenção.

✗ Cada arquivo de dispositivo possui 3 informações básicas, que identificam internamente o dispositivo ao qual o arquivo pertence:

✗ Tipo (caractere ou bloco).✗ Major number (categoria do dispositivo).✗ Minor number (identificador do dispositivo).

Page 37: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

ARQUIVOS DE DISPOSITIVO (cont.)

✗ Exemplos de arquivos de dispositivo:

brw­r­­­­­  1 root   root  31,   0 Feb  7  2012 /dev/mtdblock0brw­r­­­­­  1 root   root   8,   1 Feb  7  2012 /dev/sda1crw­rw­rw­  1 root   root   4,  64 Feb  7  2012 /dev/ttyS0crw­rw­rw­  1 root   root   4,  65 Feb  7  2012 /dev/ttyS1crw­rw­rw­  1 root   root  29,   0 Feb  7  2012 /dev/fb0crw­rw­rw­  1 root   root   1,   1 Feb  7  2012 /dev/memcrw­rw­rw­  1 root   root   1,   3 Feb  7  2012 /dev/null

Page 38: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

CONVERSANDO COM O HARDWARE

✗ Como os dispositivos de hardware são exportados através de arquivos de dispositivo para as aplicações, o acesso ao hardware é abstraído através de uma API comum de acesso à arquivos (open, read, write, close).

✗ Exemplo de escrita na porta serial:

int fd;

fd = open("/dev/ttyS0", O_RDWR);write(fd, "Hello world!", 12);close(fd);

Page 39: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

ACESSANDO UM ARQUIVO DE DISPOSITIVO

/dev/ttyS0

major/minor

Aplicação

Device driver

Leitura EscritaUser space

Kernel spaceTrata leitura Trata escrita

Page 40: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

DISPOSITIVOS DE CARACTERE

✗ A maioria dos drivers (com exceção de dispositivos de rede ou de bloco) são desenvolvidos como drivers de dispositivo de caractere.

✗ Um driver normalmente não implementa diretamente um driver de dispositivo de caractere.

✗ Ele utiliza um conjunto de APIs do kernel para esta tarefa, que chamamos de frameworks, disponíveis no modelo unificado de desenvolvimento de drivers do kernel (Unified Device Model).

Page 41: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

UNIFIED DEVICE MODEL

✗ Antes da versão 2.6, o kernel não possuía um padrão unificado de desenvolvimento de drivers que descrevesse os dispositivos conectados ao sistema e sua topologia.

✗ A partir do kernel 2.6 foi implementado o modelo de dispositivos unificado (unified device model), que é basicamente um framework para o desenvolvimento de drivers para os diferentes tipos de dispositivos suportados pelo Linux.

Page 42: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

ALGUMAS VANTAGENS

✗ Padrão para o desenvolvimento de drivers, evitando duplicação de código.

✗ Capacidade de identificar hierarquicamente todos os dispositivos e barramentos conectados ao sistema, facilitando por exemplo o gerenciamento de energia.

✗ Capacidade de separar e relacionar drivers e dispositivos de hardware.

✗ Capacidade de dividir os dispositivos por classes, sem se importar com sua topologia física.

Page 43: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

ARQUITETURA

Hardware

Infraestrutura de barramento

Driver

Framework

Interface de chamada de sistema

Bibliotecas/aplicações

Kernel space

User space

Page 44: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

FRAMEWORK

Aplicação Aplicação Aplicação

Interface de chamada de sistema

Char driver

Framebuffercore

Inputcore

TTY core

Block core

Framebufferdriver

Inputdriver

TTYdriver

Serialcore

IDEcore

SCSIcore

Serialdriver

IDEdriver

SCSIdriver

Page 45: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

BARRAMENTOS

DriverTeclado

USB core

DriverMouse

DriverTouchscreen

DriverRTC

I2C core Platform

Frameworks

Hardware

Driver USB Driver I2C

Page 46: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

MODELANDO O DRIVER

✗ No início do desenvolvimento de um driver, algumas decisões importantes precisam ser tomadas:

✗ Em qual framework o driver deverá se registrar?

✗ Que recursos do sistema o driver irá usar (IRQ, IOMEM, GPIO, etc)?

✗ Qual infraestrutura de barramento o driver irá usar?

✗ A partir destas informações, deve-se iniciar o estudos das APIs correspondentes ao framework, recursos do sistema e infraestrutura de barramento selecionadas.

✗ Cada tipo de driver é uma experiência totalmente diferente!

Page 47: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

DRIVER DE LED

CPU GPIO1.24

Driver GPIO

GPIO core

/sys/class/leds/

Leds Framework

Driver LedPlatform device

Page 48: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

DRIVER DE LED

✗ Quais as interfaces do kernel (API) que serão utilizadas pelo driver de led?

✗ Framework: leds framework.

✗ Recursos do sistema: GPIO 1.24.

✗ Infraestrutura de barramento: Platform device.

Page 49: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

LEDS FRAMEWORK

✗ Framework para dispositivos de led.

✗ Habilitado na opção do kernel CONFIG_NEW_LEDS.

✗ Fontes disponíveis em drivers/leds/ e definição da API em <linux/leds.h>.

✗ Documentação em Documentation/leds/leds­class.txt.

✗ Implementa um diretório em /sys/class/leds/ para cada led registrado, disponibilizando alguns arquivos para manipular estes leds.

Page 50: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

IMPLEMENTANDO

✗ Tudo o que um driver de led precisa fazer é:✗ Definir e inicializar uma estrutura do tipo led_classdev.

✗ Prover uma função de callback para mudar o status do led.

✗ Registrar o dispositivo de led com a função led_classdev_register().

✗ Muitos exemplos em drivers/leds/!

Page 51: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

LABORATÓRIO

Registrando no framework de leds

Page 52: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

RECURSOS

✗ Como o led esta conectado à um GPIO da placa, o único recurso que o driver irá acessar será o GPIO.

✗ Para acessar o GPIO, o driver irá trabalhar com a API de GPIO do kernel, também chamada de gpiolib.

✗ A definição da API da gpiolib esta disponível em <linux/gpio.h>.

✗ Uma documentação completa sobre esta API esta disponível nos fontes do kernel em Documentation/gpio.txt.

Page 53: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

USANDO A GPIOLIB

✗ O primeiro passo para usar a gpiolib é descobrir qual o número associado ao GPIO que deseja-se usar.

✗ A gpiolib atribui um número sequencial para cada GPIO registrado no GPIO core. Por exemplo (considerando-se que cada porta de I/O possui 32 GPIO's):✗ GPIO 1.10 = GPIO 10

✗ GPIO 2.5 = GPIO 37

✗ GPIO 3.1 = GPIO 65

✗ Com o número identificado, pode-se usar as funções da gpiolib para requisitar, configurar e usar o GPIO.

Page 54: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

ALGUMAS FUNÇÕES DA GPIOLIB

✗ gpio_request(): requisitar o uso de um GPIO.

✗ gpio_direction_input(): configurar o GPIO como entrada.

✗ gpio_direction_output(): configurar o GPIO como saída.

✗ gpio_get_value(): ler o GPIO.

✗ gpio_set_value(): escrever no GPIO.

✗ gpio_free(): liberar um GPIO requisitado.

Page 55: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

LABORATÓRIO

Acessando o GPIO

Page 56: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

INFRAESTRUTURA DE BARRAMENTO

✗ A infraestrutura de barramento tem alguns principais objetivos, dentre eles:✗ Padronizar e centralizar o acesso à determinado barramento.

✗ Separar os conceitos de driver e dispositivo de hardware, removendo do driver informações do hardware (IRQ, DMA, IOMEM, GPIO, etc).

✗ Possibilitar o gerenciamento de energia.

✗ Cada barramento (USB, I2C, SPI, etc) tem uma API específica, também chamada de bus core.

✗ Ambos o driver e o dispositivo de hardware devem se registrar no core do barramento.

Page 57: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

DEVICE PROBE

Bus Core

Driver

add_driver()

driver_probe()

Definição dodispositivoDriver

add_device()

Page 58: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

EXEMPLO: DRIVER MMA8450static struct i2c_driver mma8450_driver = {    .driver = {        .name  = "mma8450",        .owner = THIS_MODULE,    },    .probe    = mma8450_probe,    .remove   = __devexit_p(mma8450_remove),    .id_table = mma8450_id,};

Page 59: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

EXEMPLO: DRIVER MMA8450 (cont.)static int __init mma8450_init(void){    return i2c_add_driver(&mma8450_driver);}

static void __exit mma8450_exit(void){    i2c_del_driver(&mma8450_driver);}

module_init(mma8450_init);module_exit(mma8450_exit);

Page 60: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

EXEMPLO: REGISTRANDO MMA8450 /* implementado no arquivo de definição da placa */

static struct i2c_board_info mx53loco_i2c_devices[] = {    {        I2C_BOARD_INFO("mma8450", 0x1C),    },};

static void __init mx53_loco_board_init(void){    [...]    i2c_register_board_info(0, mx53loco_i2c_devices,                          ARRAY_SIZE(mx53loco_i2c_devices));    [...]}

Page 61: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

EXEMPLO: DRIVER MMA8450 PROBE()static int __devinit mma8450_probe(                       struct i2c_client *client,                       const struct i2c_device_id *id){    [...]    result = i2c_smbus_read_byte_data(client,                                    MMA8450_WHO_AM_I);    [...]    result = input_register_polled_device(idev);    [...]}

Page 62: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

PLATFORM DEVICES

✗ Alguns dispositivos podem não estar conectados em um barramento, como por exemplo uma UART, um RTC ou algum dispositivo conectado à um GPIO.

✗ Como então manter o mesmo padrão de infraestrutura de barramento?

✗ Implementando um platform driver através da infraestrutura de platform device!

Page 63: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

LABORATÓRIO

Platform driver

Page 64: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

PRÓXIMOS PASSOS

✗ Tornar o driver genérico para suportar múltiplos GPIOs.

✗ Usar o device tree para descrever o hardware (obrigatório nas últimas versões do kernel).

Page 65: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

E AGORA?

✗ Estude e conheça as APIs básicas do kernel (criação de drivers de dispositivo de caractere, acesso à I/O mapeado em memória, DMA, gerenciamento de processos, interrupção, mecanismos de sincronização, debugging, etc!)

✗ Não pare de estudar, acompanhe a evolução do kernel.

✗ Crie o hábito de ler muito código. Este hábito é essencial!

Page 66: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

PERGUNTAS?

Page 67: Hands-on Linux Device Drivers DwF 2013

Embedded Labworks

Por Sergio Prado. São Paulo, Novembro de 2012® Copyright Embedded Labworks 2004-2013. All rights reserved.

OBRIGADO!

E-mail [email protected] http://e-labworks.com