Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Linux Device Drivers

Linux Device Drivers

Uma visão superficial de como funciona o acesso a dispositivos na parte interna do núcleo do sistema e um exemplo de device drivers.

Avatar for Tiago Martins

Tiago Martins

December 07, 2016
Tweet

More Decks by Tiago Martins

Other Decks in Programming

Transcript

  1. SEL630 - PROJETOS DE SISTEMAS DIGITAIS Linux Device Linux Device

    Drivers Drivers Tiago A. Martins Prof. Dr. Evandro Luís Linhari Rodrigues 1 . 1
  2. OBJETIVO import RPi.GPIO as gpio led_pin = 23 # Broadcom

    pin 23 (P1 pin 16) gpio.setmode(gpio.BCM) gpio.setup(led_pin, gpio.OUT) # Let there be light gpio.output(led_pin, gpio.HIGH) 2 . 1
  3. OBJETIVO import RPi.GPIO as gpio led_pin = 23 # Broadcom

    pin 23 (P1 pin 16) gpio.setmode(gpio.BCM) gpio.setup(led_pin, gpio.OUT) # Let there be light gpio.output(led_pin, gpio.HIGH) 2 . 1
  4. OBJETIVO import RPi.GPIO as gpio led_pin = 23 # Broadcom

    pin 23 (P1 pin 16) gpio.setmode(gpio.BCM) gpio.setup(led_pin, gpio.OUT) # Let there be light gpio.output(led_pin, gpio.HIGH) 2 . 1
  5. OBJETIVO import RPi.GPIO as gpio led_pin = 23 # Broadcom

    pin 23 (P1 pin 16) gpio.setmode(gpio.BCM) gpio.setup(led_pin, gpio.OUT) # Let there be light gpio.output(led_pin, gpio.HIGH) 2 . 1
  6. MICROCONTROLADORES #include <xc.h> int main(void) { TRISB0 = 0; /*

    RB0 as Output PIN */ while (1) { RB0 = 1; /* LED ON */ __delay_ms(1000); /* 1 Second Delay */ RB0 = 0; /* LED OFF */ __delay_ms(1000); /* 1 Second Delay */ } return 0; } 3 . 2
  7. MICROCONTROLADORES #include <xc.h> int main(void) { TRISB0 = 0; /*

    RB0 as Output PIN */ while (1) { RB0 = 1; /* LED ON */ __delay_ms(1000); /* 1 Second Delay */ RB0 = 0; /* LED OFF */ __delay_ms(1000); /* 1 Second Delay */ } return 0; } 3 . 2
  8. MICROCONTROLADORES #include <xc.h> int main(void) { TRISB0 = 0; /*

    RB0 as Output PIN */ while (1) { RB0 = 1; /* LED ON */ __delay_ms(1000); /* 1 Second Delay */ RB0 = 0; /* LED OFF */ __delay_ms(1000); /* 1 Second Delay */ } return 0; } 3 . 2
  9. MICROCONTROLADORES #include <xc.h> int main(void) { TRISB0 = 0; /*

    RB0 as Output PIN */ while (1) { RB0 = 1; /* LED ON */ __delay_ms(1000); /* 1 Second Delay */ RB0 = 0; /* LED OFF */ __delay_ms(1000); /* 1 Second Delay */ } return 0; } 3 . 2
  10. ARM CORTEX-M void gpio_init_pin(struct gpio_regs *port, unsigned char index, unsigned

    char pin, struct gpio_pin_config *cfg) { if (cfg->mode & GPIO_MODE_AF) write_reg_pin(&port->alt_func[pin >> GPIO_ALT_FUNC_PIN_SHIFT], pin, GPIO_ALT_FUNC_PIN_W, cfg->alt_func); /* Configure IO Direction mode (Input, Output, Alternate or Analog) */ write_reg_pin(&port->mode, pin, GPIO_MODE_PIN_W, cfg->mode & GPIO_MODE); /* Configure the IO Speed */ write_reg_pin(&port->out_speed, pin, GPIO_OUT_SPEED_PIN_W, cfg->speed); /* Configure the IO Output Type */ write_reg_pin(&port->out_type, pin, GPIO_OUT_TYPE_PIN_W, cfg->mode & GPIO_OUT_TYPE); /* Activate the Pull-up or Pull down resistor for the current IO */ write_reg_pin(&port->pup_pdown, pin, GPIO_PUP_PDOWN_PIN_W, cfg->pull); } 3 . 3
  11. ARM CORTEX-M void gpio_init_pin(struct gpio_regs *port, unsigned char index, unsigned

    char pin, struct gpio_pin_config *cfg) { if (cfg->mode & GPIO_MODE_AF) write_reg_pin(&port->alt_func[pin >> GPIO_ALT_FUNC_PIN_SHIFT], pin, GPIO_ALT_FUNC_PIN_W, cfg->alt_func); /* Configure IO Direction mode (Input, Output, Alternate or Analog) */ write_reg_pin(&port->mode, pin, GPIO_MODE_PIN_W, cfg->mode & GPIO_MODE); /* Configure the IO Speed */ write_reg_pin(&port->out_speed, pin, GPIO_OUT_SPEED_PIN_W, cfg->speed); /* Configure the IO Output Type */ write_reg_pin(&port->out_type, pin, GPIO_OUT_TYPE_PIN_W, cfg->mode & GPIO_OUT_TYPE); /* Activate the Pull-up or Pull down resistor for the current IO */ write_reg_pin(&port->pup_pdown, pin, GPIO_PUP_PDOWN_PIN_W, cfg->pull); } 3 . 3
  12. ARM CORTEX-M void gpio_init_pin(struct gpio_regs *port, unsigned char index, unsigned

    char pin, struct gpio_pin_config *cfg) { if (cfg->mode & GPIO_MODE_AF) write_reg_pin(&port->alt_func[pin >> GPIO_ALT_FUNC_PIN_SHIFT], pin, GPIO_ALT_FUNC_PIN_W, cfg->alt_func); /* Configure IO Direction mode (Input, Output, Alternate or Analog) */ write_reg_pin(&port->mode, pin, GPIO_MODE_PIN_W, cfg->mode & GPIO_MODE); /* Configure the IO Speed */ write_reg_pin(&port->out_speed, pin, GPIO_OUT_SPEED_PIN_W, cfg->speed); /* Configure the IO Output Type */ write_reg_pin(&port->out_type, pin, GPIO_OUT_TYPE_PIN_W, cfg->mode & GPIO_OUT_TYPE); /* Activate the Pull-up or Pull down resistor for the current IO */ write_reg_pin(&port->pup_pdown, pin, GPIO_PUP_PDOWN_PIN_W, cfg->pull); } 3 . 3
  13. ARM CORTEX-M void gpio_init_pin(struct gpio_regs *port, unsigned char index, unsigned

    char pin, struct gpio_pin_config *cfg) { if (cfg->mode & GPIO_MODE_AF) write_reg_pin(&port->alt_func[pin >> GPIO_ALT_FUNC_PIN_SHIFT], pin, GPIO_ALT_FUNC_PIN_W, cfg->alt_func); /* Configure IO Direction mode (Input, Output, Alternate or Analog) */ write_reg_pin(&port->mode, pin, GPIO_MODE_PIN_W, cfg->mode & GPIO_MODE); /* Configure the IO Speed */ write_reg_pin(&port->out_speed, pin, GPIO_OUT_SPEED_PIN_W, cfg->speed); /* Configure the IO Output Type */ write_reg_pin(&port->out_type, pin, GPIO_OUT_TYPE_PIN_W, cfg->mode & GPIO_OUT_TYPE); /* Activate the Pull-up or Pull down resistor for the current IO */ write_reg_pin(&port->pup_pdown, pin, GPIO_PUP_PDOWN_PIN_W, cfg->pull); } 3 . 3
  14. ARM CORTEX-M void gpio_init_pin(struct gpio_regs *port, unsigned char index, unsigned

    char pin, struct gpio_pin_config *cfg) { if (cfg->mode & GPIO_MODE_AF) write_reg_pin(&port->alt_func[pin >> GPIO_ALT_FUNC_PIN_SHIFT], pin, GPIO_ALT_FUNC_PIN_W, cfg->alt_func); /* Configure IO Direction mode (Input, Output, Alternate or Analog) */ write_reg_pin(&port->mode, pin, GPIO_MODE_PIN_W, cfg->mode & GPIO_MODE); /* Configure the IO Speed */ write_reg_pin(&port->out_speed, pin, GPIO_OUT_SPEED_PIN_W, cfg->speed); /* Configure the IO Output Type */ write_reg_pin(&port->out_type, pin, GPIO_OUT_TYPE_PIN_W, cfg->mode & GPIO_OUT_TYPE); /* Activate the Pull-up or Pull down resistor for the current IO */ write_reg_pin(&port->pup_pdown, pin, GPIO_PUP_PDOWN_PIN_W, cfg->pull); } 3 . 3
  15. ARM CORTEX-M void gpio_init_pin(struct gpio_regs *port, unsigned char index, unsigned

    char pin, struct gpio_pin_config *cfg) { if (cfg->mode & GPIO_MODE_AF) write_reg_pin(&port->alt_func[pin >> GPIO_ALT_FUNC_PIN_SHIFT], pin, GPIO_ALT_FUNC_PIN_W, cfg->alt_func); /* Configure IO Direction mode (Input, Output, Alternate or Analog) */ write_reg_pin(&port->mode, pin, GPIO_MODE_PIN_W, cfg->mode & GPIO_MODE); /* Configure the IO Speed */ write_reg_pin(&port->out_speed, pin, GPIO_OUT_SPEED_PIN_W, cfg->speed); /* Configure the IO Output Type */ write_reg_pin(&port->out_type, pin, GPIO_OUT_TYPE_PIN_W, cfg->mode & GPIO_OUT_TYPE); /* Activate the Pull-up or Pull down resistor for the current IO */ write_reg_pin(&port->pup_pdown, pin, GPIO_PUP_PDOWN_PIN_W, cfg->pull); } 3 . 3
  16. ARM CORTEX-M void gpio_init_pin(struct gpio_regs *port, unsigned char index, unsigned

    char pin, struct gpio_pin_config *cfg) { if (cfg->mode & GPIO_MODE_AF) write_reg_pin(&port->alt_func[pin >> GPIO_ALT_FUNC_PIN_SHIFT], pin, GPIO_ALT_FUNC_PIN_W, cfg->alt_func); /* Configure IO Direction mode (Input, Output, Alternate or Analog) */ write_reg_pin(&port->mode, pin, GPIO_MODE_PIN_W, cfg->mode & GPIO_MODE); /* Configure the IO Speed */ write_reg_pin(&port->out_speed, pin, GPIO_OUT_SPEED_PIN_W, cfg->speed); /* Configure the IO Output Type */ write_reg_pin(&port->out_type, pin, GPIO_OUT_TYPE_PIN_W, cfg->mode & GPIO_OUT_TYPE); /* Activate the Pull-up or Pull down resistor for the current IO */ write_reg_pin(&port->pup_pdown, pin, GPIO_PUP_PDOWN_PIN_W, cfg->pull); } void gpio_write_pin(struct gpio_regs *port, unsigned short pin_bit, unsigned char value) { if (value) port->bit_sr = pin_bit; /* set pin */ else port->bit_sr = pin_bit << GPIO_BIT_ST_W; /* reset pin */ } 3 . 3
  17. ARM CORTEX-M void gpio_init_pin(struct gpio_regs *port, unsigned char index, unsigned

    char pin, struct gpio_pin_config *cfg) { if (cfg->mode & GPIO_MODE_AF) write_reg_pin(&port->alt_func[pin >> GPIO_ALT_FUNC_PIN_SHIFT], pin, GPIO_ALT_FUNC_PIN_W, cfg->alt_func); /* Configure IO Direction mode (Input, Output, Alternate or Analog) */ write_reg_pin(&port->mode, pin, GPIO_MODE_PIN_W, cfg->mode & GPIO_MODE); /* Configure the IO Speed */ write_reg_pin(&port->out_speed, pin, GPIO_OUT_SPEED_PIN_W, cfg->speed); /* Configure the IO Output Type */ write_reg_pin(&port->out_type, pin, GPIO_OUT_TYPE_PIN_W, cfg->mode & GPIO_OUT_TYPE); /* Activate the Pull-up or Pull down resistor for the current IO */ write_reg_pin(&port->pup_pdown, pin, GPIO_PUP_PDOWN_PIN_W, cfg->pull); } void gpio_write_pin(struct gpio_regs *port, unsigned short pin_bit, unsigned char value) { if (value) port->bit_sr = pin_bit; /* set pin */ else port->bit_sr = pin_bit << GPIO_BIT_ST_W; /* reset pin */ } 3 . 3
  18. ARM CORTEX-M void gpio_init_pin(struct gpio_regs *port, unsigned char index, unsigned

    char pin, struct gpio_pin_config *cfg) { if (cfg->mode & GPIO_MODE_AF) write_reg_pin(&port->alt_func[pin >> GPIO_ALT_FUNC_PIN_SHIFT], pin, GPIO_ALT_FUNC_PIN_W, cfg->alt_func); /* Configure IO Direction mode (Input, Output, Alternate or Analog) */ write_reg_pin(&port->mode, pin, GPIO_MODE_PIN_W, cfg->mode & GPIO_MODE); /* Configure the IO Speed */ write_reg_pin(&port->out_speed, pin, GPIO_OUT_SPEED_PIN_W, cfg->speed); /* Configure the IO Output Type */ write_reg_pin(&port->out_type, pin, GPIO_OUT_TYPE_PIN_W, cfg->mode & GPIO_OUT_TYPE); /* Activate the Pull-up or Pull down resistor for the current IO */ write_reg_pin(&port->pup_pdown, pin, GPIO_PUP_PDOWN_PIN_W, cfg->pull); } void gpio_write_pin(struct gpio_regs *port, unsigned short pin_bit, unsigned char value) { if (value) port->bit_sr = pin_bit; /* set pin */ else port->bit_sr = pin_bit << GPIO_BIT_ST_W; /* reset pin */ } 3 . 3
  19. ESCREVENDO NO HARDWARE static ssize_t mydev_write(struct file *filp, const char

    __user *buf, size_t count, loff_t *f_pos) { int i; char *kbuf = kmalloc(count, GFP_KERNEL); if (!kbuf) return -ENOMEM; if (copy_from_user(kbuf, buf, count)) return -EFAULT; for (i = 0; i < count; i++) iowrite8((*buf)++, PORT_ADDRESS + (*f_pos)++); } 5 . 2
  20. ESCREVENDO NO HARDWARE static ssize_t mydev_write(struct file *filp, const char

    __user *buf, size_t count, loff_t *f_pos) { int i; char *kbuf = kmalloc(count, GFP_KERNEL); if (!kbuf) return -ENOMEM; if (copy_from_user(kbuf, buf, count)) return -EFAULT; for (i = 0; i < count; i++) iowrite8((*buf)++, PORT_ADDRESS + (*f_pos)++); } 5 . 2
  21. ESCREVENDO NO HARDWARE static ssize_t mydev_write(struct file *filp, const char

    __user *buf, size_t count, loff_t *f_pos) { int i; char *kbuf = kmalloc(count, GFP_KERNEL); if (!kbuf) return -ENOMEM; if (copy_from_user(kbuf, buf, count)) return -EFAULT; for (i = 0; i < count; i++) iowrite8((*buf)++, PORT_ADDRESS + (*f_pos)++); } 5 . 2
  22. ESCREVENDO NO HARDWARE static ssize_t mydev_write(struct file *filp, const char

    __user *buf, size_t count, loff_t *f_pos) { int i; char *kbuf = kmalloc(count, GFP_KERNEL); if (!kbuf) return -ENOMEM; if (copy_from_user(kbuf, buf, count)) return -EFAULT; for (i = 0; i < count; i++) iowrite8((*buf)++, PORT_ADDRESS + (*f_pos)++); } 5 . 2
  23. REGISTRANDO AS OPERAÇÕES DE ARQUIVOS #include <linux/fs.h> static struct file_operations

    mydev_fops = { .owner = THIS_MODULE, .open = mydev_open, .release = mydev_release, .write = mydev_write, .read = mydev_read }; 5 . 3
  24. REGISTRANDO AS OPERAÇÕES DE ARQUIVOS #include <linux/fs.h> static struct file_operations

    mydev_fops = { .owner = THIS_MODULE, .open = mydev_open, .release = mydev_release, .write = mydev_write, .read = mydev_read }; 5 . 3
  25. REGISTRANDO AS OPERAÇÕES DE ARQUIVOS #include <linux/fs.h> static struct file_operations

    mydev_fops = { .owner = THIS_MODULE, .open = mydev_open, .release = mydev_release, .write = mydev_write, .read = mydev_read }; 5 . 3
  26. ADICIONANDO O DISPOSITIVO #include <linux/init.h> #include <linux/module.h> static struct class

    *mydev_class; static int my_init(void) { ... mydev_class = class_create(THIS_MODULE, DRV_NAME); device = device_create(mydev_class, NULL, mydev->id, NULL, "mydev0"); ... } 5 . 4
  27. ADICIONANDO O DISPOSITIVO #include <linux/init.h> #include <linux/module.h> static struct class

    *mydev_class; static int my_init(void) { ... mydev_class = class_create(THIS_MODULE, DRV_NAME); device = device_create(mydev_class, NULL, mydev->id, NULL, "mydev0"); ... } 5 . 4
  28. ADICIONANDO O DISPOSITIVO #include <linux/init.h> #include <linux/module.h> static struct class

    *mydev_class; static int my_init(void) { ... mydev_class = class_create(THIS_MODULE, DRV_NAME); device = device_create(mydev_class, NULL, mydev->id, NULL, "mydev0"); ... } 5 . 4
  29. ADICIONANDO O DISPOSITIVO /DEV/MYDEV0 #include <linux/init.h> #include <linux/module.h> static struct

    class *mydev_class; static int my_init(void) { ... mydev_class = class_create(THIS_MODULE, DRV_NAME); device = device_create(mydev_class, NULL, mydev->id, NULL, "mydev0"); ... } 5 . 4
  30. ADICIONANDO O DISPOSITIVO /DEV/MYDEV0 #include <linux/init.h> #include <linux/module.h> static struct

    class *mydev_class; static int my_init(void) { ... mydev_class = class_create(THIS_MODULE, DRV_NAME); device = device_create(mydev_class, NULL, mydev->id, NULL, "mydev0"); ... } 5 . 4
  31. ADICIONANDO O DISPOSITIVO /DEV/MYDEV0 #include <linux/init.h> #include <linux/module.h> static struct

    class *mydev_class; static int my_init(void) { ... mydev_class = class_create(THIS_MODULE, DRV_NAME); device = device_create(mydev_class, NULL, mydev->id, NULL, "mydev0"); ... } static void my_exit(void) { ... device_destroy(mydev_class, mydev->id); class_destroy(mydev_class); ... } 5 . 4
  32. ADICIONANDO O DISPOSITIVO /DEV/MYDEV0 #include <linux/init.h> #include <linux/module.h> static struct

    class *mydev_class; static int my_init(void) { ... mydev_class = class_create(THIS_MODULE, DRV_NAME); device = device_create(mydev_class, NULL, mydev->id, NULL, "mydev0"); ... } static void my_exit(void) { ... device_destroy(mydev_class, mydev->id); class_destroy(mydev_class); ... } 5 . 4
  33. ADICIONANDO O DISPOSITIVO /DEV/MYDEV0 #include <linux/init.h> #include <linux/module.h> static struct

    class *mydev_class; static int my_init(void) { ... mydev_class = class_create(THIS_MODULE, DRV_NAME); device = device_create(mydev_class, NULL, mydev->id, NULL, "mydev0"); ... } static void my_exit(void) { ... device_destroy(mydev_class, mydev->id); class_destroy(mydev_class); ... } 5 . 4
  34. INICIALIZAÇÃO E REGISTRO DO DEVICE DRIVER #include <linux/init.h> #include <linux/module.h>

    #include <linux/fs.h> static int my_init(void) { ... ret = alloc_chrdev_region(&mydev->id, minor, num_devs, DRV_NAME); ... cdev_init(&mydev->cdev, &mydev_fops); mydev->cdev.owner = THIS_MODULE; mydev->cdev.ops = &mydev_fops; ... ret = cdev_add(&mydev->cdev, mydev->id, num_dev); ... } module_init(my_init); 5 . 5
  35. INICIALIZAÇÃO E REGISTRO DO DEVICE DRIVER #include <linux/init.h> #include <linux/module.h>

    #include <linux/fs.h> static int my_init(void) { ... ret = alloc_chrdev_region(&mydev->id, minor, num_devs, DRV_NAME); ... cdev_init(&mydev->cdev, &mydev_fops); mydev->cdev.owner = THIS_MODULE; mydev->cdev.ops = &mydev_fops; ... ret = cdev_add(&mydev->cdev, mydev->id, num_dev); ... } module_init(my_init); 5 . 5
  36. INICIALIZAÇÃO E REGISTRO DO DEVICE DRIVER #include <linux/init.h> #include <linux/module.h>

    #include <linux/fs.h> static int my_init(void) { ... ret = alloc_chrdev_region(&mydev->id, minor, num_devs, DRV_NAME); ... cdev_init(&mydev->cdev, &mydev_fops); mydev->cdev.owner = THIS_MODULE; mydev->cdev.ops = &mydev_fops; ... ret = cdev_add(&mydev->cdev, mydev->id, num_dev); ... } module_init(my_init); 5 . 5
  37. INICIALIZAÇÃO E REGISTRO DO DEVICE DRIVER #include <linux/init.h> #include <linux/module.h>

    #include <linux/fs.h> static int my_init(void) { ... ret = alloc_chrdev_region(&mydev->id, minor, num_devs, DRV_NAME); ... cdev_init(&mydev->cdev, &mydev_fops); mydev->cdev.owner = THIS_MODULE; mydev->cdev.ops = &mydev_fops; ... ret = cdev_add(&mydev->cdev, mydev->id, num_dev); ... } module_init(my_init); 5 . 5
  38. INICIALIZAÇÃO E REGISTRO DO DEVICE DRIVER #include <linux/init.h> #include <linux/module.h>

    #include <linux/fs.h> static int my_init(void) { ... ret = alloc_chrdev_region(&mydev->id, minor, num_devs, DRV_NAME); ... cdev_init(&mydev->cdev, &mydev_fops); mydev->cdev.owner = THIS_MODULE; mydev->cdev.ops = &mydev_fops; ... ret = cdev_add(&mydev->cdev, mydev->id, num_dev); ... } module_init(my_init); 5 . 5
  39. FINALIZAÇÃO E LIMPEZA #include <linux/init.h> #include <linux/module.h> static void my_exit(void)

    { ... cdev_del(&mydev->cdev); unregister_chrdev_region(mydev->id, num_devs); ... } module_exit(my_exit); 5 . 6
  40. FINALIZAÇÃO E LIMPEZA #include <linux/init.h> #include <linux/module.h> static void my_exit(void)

    { ... cdev_del(&mydev->cdev); unregister_chrdev_region(mydev->id, num_devs); ... } module_exit(my_exit); 5 . 6
  41. FINALIZAÇÃO E LIMPEZA #include <linux/init.h> #include <linux/module.h> static void my_exit(void)

    { ... cdev_del(&mydev->cdev); unregister_chrdev_region(mydev->id, num_devs); ... } module_exit(my_exit); 5 . 6
  42. UTILIZAÇÃO OU import RPi.GPIO as gpio gpio.output(led_pin, gpio.HIGH) if ((fd

    = fopen("/sys/class/gpio/gpio23/value", "w")) != NULL) { fwrite("1", sizeof(char), 2, fd); fclose(fd); } 6 . 2
  43. UTILIZAÇÃO OU import RPi.GPIO as gpio gpio.output(led_pin, gpio.HIGH) if ((fd

    = fopen("/sys/class/gpio/gpio23/value", "w")) != NULL) { fwrite("1", sizeof(char), 2, fd); fclose(fd); } 6 . 2
  44. UTILIZAÇÃO OU import RPi.GPIO as gpio gpio.output(led_pin, gpio.HIGH) if ((fd

    = fopen("/sys/class/gpio/gpio23/value", "w")) != NULL) { fwrite("1", sizeof(char), 2, fd); fclose(fd); } 6 . 2