1 / 57

Programación en Ingeniería Electrónica Tema 3: Acceso a dispositivos periféricos

Programación en Ingeniería Electrónica Tema 3: Acceso a dispositivos periféricos. Índice. Introducción Drivers (módulos) en Linux - Dispostivos de caracteres Drivers en Windows. INTRODUCCIÓN. S.O. Uso cómodo del sistema y eficiente del hardware. INTRODUCCIÓN. Programas .

adli
Télécharger la présentation

Programación en Ingeniería Electrónica Tema 3: Acceso a dispositivos periféricos

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Programación en Ingeniería ElectrónicaTema 3: Acceso a dispositivos periféricos

  2. Índice • Introducción • Drivers (módulos) en Linux - Dispostivos de caracteres • Drivers en Windows

  3. INTRODUCCIÓN S.O. Uso cómodo del sistema y eficiente del hardware

  4. INTRODUCCIÓN Programas Sistema operativo Hardware

  5. INTRODUCCIÓN Sistema Unix

  6. INTRODUCCIÓN Sistema Unix

  7. INTRODUCCIÓN Sistema Windows

  8. INTRODUCCIÓN • User space • Aplicaciones que utiliza el usuario (shell, ping…) • Interaccionan con el hardware, a través de funciones que soporta el kernel • Ejecución sin privilegios de procesador • User-mode drivers en Windows utilizan Win32 API • Kernel space • El kernel gestiona los recursos hardware del computador • Interfase entre las aplicaciones de usuario y el hardware • Módulos o drivers están dentro del espacio del kernel • Kernel-mode driver puede acceder a estructuras que un user-mode drivers no puede acceder

  9. INTRODUCCIÓN Estructura básica de un driver • Punto de entrada • Carga del driver (inicializa estructuras, asocia rutinas a las operaciones en dispositivos y se prepara para futuras invocaciones de las funciones) • Windows: DriverEntry (…) //Reiniciar sistema • Linux: init_module() ó module_init (rutina de inicio) • Descarga del driver (libera recursos) • Linux: cleanup_module() ó module_exit (rutina de salida) • Rutinas para el manejo del dispositivo • Abrir, cerrar, lectura, escritura,…

  10. INTRODUCCIÓN Requisitos previos • Programación • De forma general se utiliza el lenguaje C (punteros, manejo bits,…) • Sistemas Windows • C para kernel-mode drivers • C ó C++ para user-mode drivers • Excepciones: • Audio/Video streaming client minidrivers en C++ • WDM audio miniport drivers en C++ • Windows Image Acquisition drivers en C++ • Nociones de microprocesadores • Direccionamiento de memoria • Interrupciones

  11. INTRODUCCIÓN Bibliografía • Linux • Linux Device Driver (2nd Edition), Alessandro Rubini, Jonathan Cobert. Ed. O’Reilly (hasta kernel 2.4) • ftp://ftp.ora.com/pub/examples/linux/drivers2/book_pdf.rar • http://examples.oreilly.com/linuxdrive2/ldd2-samples-1.0.1.tar.gz • Linux Device Driver (3rd Edition) (kernel 2.6) • Disponible online en http://lwn.net/Kernel/LDD3/ • Windows • Microsoft Windows Driver Development Kit (DDK) • http://www.microsoft.com/whdc/devtools/ddk/default.mspx

  12. DRIVERS EN LINUX • Linux permite extender las funcionalidades del kernel en tiempo de ejecución • Cada funcionalidad (código) añadido al kernel (runtime) se denomina módulo • Un módulo, entre otros, puede ser un driver de dispositivo • Los módulos pueden ser cargados y descargados dinámicamente en el kernel: • Cargar: insmod nombre_del_modulo • Descargar: rmmod nombre_del_modulo • Ver módulos: lsmod

  13. DRIVERS EN LINUX Tipos de dispositivos • Character devices: • Dispositivo que puede ser accedido como un stream de bytes (consola, teclado, puerto serie) (normalmente un carácter) • Se acceden a través del sistema de ficheros como: /dev/tty1, /dev/lp0 • Implementan las llamadas al sistema: open, close, read y write • Block devices: • Se acceden a través del sistema de ficheros: directorio /dev • Un dispositivo de bloque es aquel que puede almacenar un sistema de fichero: disco • Sólo puede ser accedido como múltiplo de un bloque (1 Kb, 2Kb,…) • Utiliza llamadas al sistema como char-devices

  14. DRIVERS EN LINUX Tipos de dispositivos • Network interfaces: • Dispositivo que intercambia datos con otros hosts • No se utiliza el sistema de ficheros • Utiliza un nombre único (eth0) • Comunicación entre kernel y driver es diferente que las usadas con “char y block drivers” • Utiliza funciones relacionadas con la transmisión de paquetes • Otros dispositivos: • SCSI drivers • FireWire and USB drivers,

  15. DRIVERS EN LINUX Primer driver #define __KERNEL__ // necesario para construir módulos dinámicos #define MODULE #include <linux/module.h> #include <linux/kernel.h> int init_module(void) { printk("<1>Hola\n"); // printk está definida en el kernel // <1> indica la prioridad (alta) del mensaje return 0; } void cleanup_module(void) { printk("<1>Bye\n"); }

  16. DRIVERS EN LINUX Primer driver

  17. DRIVERS EN LINUX Contador de uso del módulo • Existe un contador por cada módulo • Un módulo no puede ser descargado si está ocupado • Kernels actuales gestionan el contador automáticamente • Puede ser necesario gestionarlo manualmente (kernel 2.4) • Hay tres macros definidas en <linux/module.h>: • MOD_INC_USE_COUNT • Incrementa el contador del actual módulo • MOD_DEC_USE_COUNT • Decrementa el contador • MOD_IN_USE • Evalúa si el contador es cero

  18. DRIVERS EN LINUX Contador de uso del módulo • El valor del contador viene dado en el tercer campo de cada entrada en /proc/modules • Los campos son: nombre, bytes usados en memoria y contador nls_iso8859-1 3516 1 nls_cp437 5148 1 vfat 13100 1 mousedev 5588 1 keybdev 2976 0 hid 22340 0 input 5920 0

  19. DRIVERS EN LINUX Utilizando recursos • Los drivers utilizan los recursos del sistema: • Memoria, I/O ports, I/O memory (memoria del dispositivo),… • Reservar memoria <linux/malloc.h> • void * kmalloc (unsigned int size, int priority) • GFP_KERNEL como prioridad • Liberar memoria <linux/malloc.h> • void kfree (void *obj)

  20. DRIVERS EN LINUX Utilizando recursos: I/O ports & I/O memory • /proc/ioports: Muestra una lista de las regiones de puertos registrados actualmente utilizados para la comunicación de entrada y salida con un dispositivo. 0000-001f : dma1 0020-003f : pic1 0040-005f : timer 0060-006f : keyboard 0070-007f : rtc 0080-008f : dma page reg 0170-0177 : ide1 01f0-01f7 : ide0 02f8-02ff : serial(auto) 0376-0376 : ide1 La primera columna indica el rango de direcciones de los puertos de entrada y salida reservado para el dispositivo listado en la segunda columna

  21. DRIVERS EN LINUX Utilizando recursos: I/O ports & I/O memory • I/O ports: • Evitar usar puertos utilizados por otros drivers • Tres funciones para gestionar los puertos: <linux/ioport.h> • int check_region (unsigned long start, unsigned long len) • Verifica si el rango indicado está reservado • Valores negativos (-EBUSY o -EINVAL) son devueltos si está ocupado • struct resource * request_region (unsigned long from, unsigned long • extent, const char *name) • Realiza la asignación • Éxito: devuelve un puntero non-NULL • void release_region (unsigned long from, unsigned long extend) • Libera la región

  22. DRIVERS EN LINUX Utilizando recursos: I/O ports & I/O memory • I/O ports: (reserva del puerto parelelo) En init_module port = check_region (0x378,1); if (port) { printk(“<1> puertopar: No puedo reservar 0x378\n”); cleanup_module(); return port; } request_region (0x378, 1, “puertopar”); En cleanup_module if (!port) release_region (0x378,1);

  23. DRIVERS EN LINUX Utilizando recursos: I/O ports & I/O memory • /proc/iomem: Muestra el mapa actual de la memoria del sistema para los diversos dispositivos 00000000-0009fbff : System RAM 0009fc00-0009ffff : reserved 000a0000-000bffff : Video RAM area 000c0000-000c7fff : Video ROM 000f0000-000fffff : System ROM 00100000-07ffffff : System RAM 00100000-00291ba8 : Kernel code 00291ba9-002e09cb : Kernel data e0000000-e3ffffff : VIA Technologies, Inc. VT82C597 [Apollo VP3] La primera columna muestra los registros de memoria utilizados por cada uno de los diferentes tipos de memoria.

  24. DRIVERS EN LINUX Utilizando recursos: I/O ports & I/O memory • I/O memory: • Tres funciones para gestionar la memoria: <linux/ioport.h> • int check_mem_region (unsigned long start, unsigned long len) • Verifica si el rango indicado está reservado • Valores negativos (-EBUSY o -EINVAL) son devueltos si está ocupado • struct resource * request_mem_region (unsigned long start, unsigned long extend, const char *name) • Realiza la asignación • Éxito: devuelve un puntero non-NULL • int release_mem_region (unsigned long start, unsigned long extend) • Libera la región

  25. DRIVERS EN LINUX Utilizando recursos: I/O ports & I/O memory • I/O memory: (reserva de espacio de memoria) if (check_mem_region (mem_addr, mem_size)) { printk(“<1> drivername: memoria usada\n”); return -EBUSY; } request_mem_region (mem_addr,mem_size, “drivername”);

  26. DRIVERS EN LINUX struct resource • Los rangos de los recursos utilizados son almacenados en una estructura del tipo resource • <linux/ioport.h> struct resource { const char *name; unsigned long start, end; unsigned long flags; struct resource *parent, *sibling, *child }; e800-e8ff : Adaptec AHA-2940U2/W / 7890 (PCI bus driver) e800-e8be : aic7xxx (driver , real ports on card)

  27. DRIVERS EN LINUX MACROS de Configuración: Asignando datos at load time • Dependiendo del sistema, algunos parámetros de un driver pueden cambiar (I/O address, …) • Ej: insmod mydriver param1=123 param2=“texto” • param1 y param2 son parámetros de tipo entero y cadena, respectivamente • Tienen que estar definidos en el módulo • Macro MODULE_PARM (nombre_parametro,”tipo”); • <linux/module.h> • Tipo  “b”: 1 byte, “h”: 2 bytes, “i”: entero, “l”: long, “s”: string • Las macros deben estar colocadas fuera de cualquier función • int param1=10; • char param2[10]=“hola”; • MODULE_PARM (param1, “i”); • MODULE_PARM (param2, “s”);

  28. DRIVERS EN LINUX MACROS de Configuración: Información adicional • MODULE_AUTHOR (name) • Nombre de autor • MODULE_DESCRIPTION (desc) • Descripción del módulo • MODULE_SUPPORTED_DEVICE (dev) • Dispositivo soportado por el módulo

  29. Drivers LINUX: Dispositivos de Caracteres • Se acceden a través del sistema de ficheros • Normalmente localizados en /dev • Identificados con una “c” en la primera columna de un “ls –l” crw-rw---- 1 root root 10, 62 2007-05-24 10:21 acpi • crw-rw---- 1 root audio 14, 12 2007-05-24 10:20 adsp • crw-rw---- 1 root video 10, 175 2007-05-24 10:20 agpgart • crw-rw---- 1 root audio 14, 4 2007-05-24 10:20 audio • crw------- 1 root root 5, 1 2007-05-24 10:22 console • brw-rw---- 1 root disk 3, 0 2007-05-24 11:19 hda • brw-rw---- 1 root disk 3, 1 2007-05-24 11:19 hda1 • brw-rw---- 1 root disk 3, 2 2007-05-24 11:19 hda2 • crw-rw-rw- 1 root root 5, 0 2007-05-24 11:20 tty • crw-rw---- 1 root root 4, 0 2007-05-24 11:20 tty0 • crw------- 1 root root 4, 1 2007-05-24 10:22 tty1 • crw-rw---- 1 root root 4, 10 2007-05-24 11:19 tty10

  30. Drivers LINUX: Dispositivos de Caracteres Major and minor numbers • Major number • Identifican el driver asociado con el dispositivo • El kernel utiliza el “major number” para ejecutar el driver apropiado • Minor number • Un driver puede controlar varios dispositivos • Utilizado para diferenciar entre diferentes dispositivos

  31. Drivers LINUX: Dispositivos de Caracteres Major and minor numbers • Asignar un major number a cada driver • Se realiza en la inicialización con la función: <linux/fs.h> • int register_chrdev (unsigned int major, const char *name, • struct file_operations *fops); • major: major number solicitado • name: nombre del dispositivo que aparecerá en /proc/devices • fops: puntero a un vector de punteros a funciones • se especifica las funciones que realizan las operaciones del driver • Valores devueltos: 0  Éxito en el registro • negativo  Fallo

  32. Drivers LINUX: Dispositivos de Caracteres Major and minor numbers • Kernel 2.4: major and minor numbers son de 8 bits (hasta 256 dispositivos) • Kernel 2.6: agrupado en dato de (32bits): Major (12 bits) minor (20 bits) • Asignación dinámica: major = 0 register_chrdev retorna el número • Major number reservados para uso local: 60-63, 120-127, 240-254 • Crear un dispositivo (root) • Permanece hasta que sea eliminado • mknod /dev/midispositivo c 200 0 • Eliminar dispositivo - rm /dev/midispositivo

  33. Drivers LINUX: Dispositivos de Caracteres Major and minor numbers • Eliminar el driver del sistema • int unregister_chrdev (unsigned int major, const char *name) • -EINVAL es retornado si: el nombre no coincide con los registrados • si major está fuera de rango

  34. Drivers LINUX: Dispositivos de Caracteres file_operations structure • El kernel la utiliza para acceder a las funciones del driver • Argumento en la función register_chrdev(…) • Todas las funciones devuelven 0 en caso de éxito, o un valor negativo en caso de error • El vector dispone de 15 entradas • Aquellas que no son inicializadas con una función, automáticamente se inicializan a NULL

  35. Drivers LINUX: Dispositivos de Caracteres file_operations structure • loff_t (*llseek) (struct file *, loff_t, int); • The llseek method is used to change the current read/write position in a file, and the new position is returned as a (positive) return value. The loff_t is a “long offset” and is at least 64 bits wide even on 32-bit platforms. • ssize_t (*read) (struct file *, char *, size_t, loff_t *); • Used to retrieve data from the device. A null pointer in this position causes the read system call to fail with -EINVAL (“Invalid argument”). A non-negative return value represents the number of bytes successfully read (the return value is a “signed size” type, usually the native integer type for the target platform). • ssize_t (*write) (struct file *, const char *, size_t,loff_t *); • Sends data to the device. If missing, -EINVAL is returned to the program calling the write system call. The return value, if non-negative, represents thenumber of bytes successfully written.

  36. Drivers LINUX: Dispositivos de Caracteres file_operations structure • int (*open) (struct inode *, struct file *); • Though this is always the first operation performed on the device file, the driver is not required to declare a corresponding method. If this entry is NULL, opening the device always succeeds, but your driver isn’t notified. Debe incrementarse el contador • int (*flush) (struct file *); • The flush operation is invoked when a process closes its copy of a file descriptor for a device; it should execute (and wait for) any outstanding operations on the device. Currently, flush is used only in the network file system (NFS) code. If flush is NULL, it is simply not invoked. • int (*release) (struct inode *, struct file *); • This operation is invoked when the file structure is being released. Like open, release can be missing. Debe decrementarse el contador

  37. Drivers LINUX: Dispositivos de Caracteres file_operations structure • int (*lock) (struct file *, int, struct file_lock *); • The lock method is used to implement file locking; locking is an indispensable feature for regular files, but is almost never implemented by device drivers. • ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *); • ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *); • These methods implement scatter/gather read and write operations. Applications occasionally need to do a single read or write operation involving multiple memory areas; these system calls allow them to do so without forcing extra copy operations on the data. • struct module *owner; • This field isn’t a method. Instead, it is a pointer to the module that “owns” this structure; it is usedby the kernel to maintain the module’s usage count.

  38. Drivers LINUX: Dispositivos de Caracteres file_operations structure struct file_operations midriver_fops={ read: mifuncion_read, write: mifuncion_write, open: mifuncion_open, release: mifuncion_release, };

  39. Drivers LINUX: Dispositivos de Caracteres file_operations structure int puerto_release (struct inode *inode, struct file *filp) { … } ssize_t puerto_read (struct file *filp, char *buf, size_t count, loff_t *f_pos) { … } ssize_t puerto_write (struct file *filp, char *buf, size_t count, loff_t *f_pos) { … }

  40. Drivers LINUX: Dispositivos de Caracteres file structure • Representa un fichero abierto en el kernel-space • Se comunica a cualquier función que opera con el fichero • Cuando se cierra el fichero, el kernel libera la estructura • Campos importantes • mode_t f_mode; • The file mode identifies the file as either readable or writable (or both), by • means of the bits FMODE_READ and FMODE_WRITE. You don’t need • to check permissions for read and write because the kernel checks before • invoking your method.

  41. Drivers LINUX: Dispositivos de Caracteres file structure • loff_t f_pos; • The current reading or writing position. loff_t is a 64-bit value (long • long in gcc ter minology). The driver can read this value if it needs to know • the current position in the file, but should never change it. • unsigned int f_flags; • These are the file flags, such as O_RDONLY, O_NONBLOCK, and O_SYNC. A • driver needs to check the flag for nonblocking operation, while the other flags • are seldom used. In particular, read/write permission should be checked using • f_mode instead of f_flags. All the flags are defined in the header <linux/fcntl.h>.

  42. Drivers LINUX: Dispositivos de Caracteres file structure • struct file_operations *f_op; • The operations associated with the file. The kernel assigns the pointer as part • of its implementation of open, and then reads it when it needs to dispatch any • operations. • void *private_data; • The open system call sets this pointer to NULL before calling the open method • for the driver. The driver is free to make its own use of the field or to ignore • it. The driver can use the field to point to allocated data, but then must free • memory in the release method before the file structure is destroyed by the • Kernel • struct dentry *f_dentry; The directory entry (dentry) structure associated with the file.

  43. Drivers LINUX: Dispositivos de Caracteres Copiando a/desde el espacio de usuario • Necesario copiar datos al/desde el espacio de usuario (read/write) • Funciones del kernel: • unsigned long copy_to_user (void *to, const void *from, • unsigned long count); //Read function • unsigned long copy_from_user(void *to, const void *from, • unsigned long count); //Write function

  44. Drivers LINUX: Dispositivos de Caracteres Funciones para acceder a I/O ports <asm/io.h> • unsigned inb(unsigned port); • void outb(unsigned char byte, unsigned port); Read or write byte ports (eight bits wide). The port argument is defined as unsigned long for some platforms and unsigned short for others. The return type of inb is also differ ent across architectures. • unsigned inw(unsigned port); • void outw(unsigned short word, unsigned port); These functions access 16-bit ports (word wide); they are not available when compiling for the M68k and S390 platforms, which support only byte I/O.

  45. Drivers LINUX: Dispositivos de Caracteres Funciones para acceder a I/O ports <asm/io.h> • unsigned inl(unsigned port); • void outl(unsigned longword, unsigned port); These functions access 32-bit ports. longword is either declared as unsigned long or unsigned int, according to the platform. Like word I/O, ‘‘long’’ I/O is not available on M68k and S390.

  46. Drivers LINUX: Dispositivos de Caracteres Funciones para acceder a I/O ports <asm/io.h> The prototypes for string functions are the following: • void insb(unsigned port, void *addr, unsigned long count); • void outsb(unsigned port, void *addr, unsigned long count); Read or write count bytes starting at the memory address addr. Data is read fr om or written to the single port port. • void insw(unsigned port, void *addr, unsigned long count); • void outsw(unsigned port, void *addr, unsigned long count); Read or write 16-bit values to a single 16-bit port. • void insl(unsigned port, void *addr, unsigned long count); • void outsl(unsigned port, void *addr, unsigned long count); Read or write 32-bit values to a single 32-bit port.

  47. Drivers en Windows CONCEPTOS • IRP (I/O Request Packets) • Es la estructura básica utilizada para comunicar con los drivers • Cada transacción de E/S viene descrita por una orden de trabajo (IRP) que le indica al driver lo que debe hacer. • La estructura consta de dos partes: • Cabecera. Se almacena información sobre la petición, tales como parámetros, dirección del objeto device • Entrada en la pila de E/S . Cada entrada contiene los parámetros y el código de las funciones a ejecutar en la petición de E/S

  48. Drivers en Windows CONCEPTOS • Objeto Driver • Por cada driver instalado y cargado, se crea un objeto driver • Almacena los punteros a las rutinas que implementa el driver (en la rutina DriverEntry) • Cuando se realiza una operación sobre dispositivo, se busca en el objeto la rutina a implementar

  49. Drivers en Windows CONCEPTOS • Objeto Device • Almacenan información acerca de las características y estado del dispositivo • Un objeto por cada dispositivo • La rutina DeviceEntry se encarga de crear el objeto • Almacena un puntero al objeto Driver

  50. Drivers en Windows Rutinas standards

More Related