LABORATORIO DE SISTEMAS ELECTRÓNICOS
Controladores para GNU/Linux
Alvaro Araujo
Marzo ‘06 DEPARTAMENTO
DE INGENIERÍA ELECTRÓNICA
OBJETIVOS
• CONCEPTO DE CONTROLADOR
• CONTROLADORES EN GNU/LINUX
• EJEMPLO DE CONTROLADOR
• DESMITIFICAR LOS CONTROLADORES
LABORATORIO DE SISTEMAS ELECTRÓNICOS
•ARQUITECTURA
•“Módulo software que permite a otros módulos interactuar con los diferentes dispositivos hardware”
DEFINICIÓN
ESPACIO DE USUARIO Y KERNEL
Espacio de usuario (aplicaciones)
Espacio de kernel (módulos o controladores)
Hardware
Funciones de intercambio entre el espacio de usuario y el espacio del kernel (Ficheros)
Funciones de intercambio entre el espacio del kernel y el dispositivo hardware
LABORATORIO DE SISTEMAS ELECTRÓNICOS
FUNCIONES USUARIO-KERNEL
Quitar módulo Cerrar dispositivo Escribir dispositivo Leer dispositivo Abrir dispositivo Carga de módulo
Funciones de kernel
Funciones de usuarios Eventos
FUNCIONES KERNEL-HARDWARE
Escribir datos Leer datos
Funciones del kernel
Eventos
LABORATORIO DE SISTEMAS ELECTRÓNICOS
MI PRIMER CONTROLADOR
__KERNEL__
#define MODULE
#include <linux/module.h>
$ gcc –c nada.c
$ insmod nada.o
$ lsmod
$ rmmod nada nada.c
FUNCIONES USUARIO-KERNEL
rmmod Quitar módulo
Cerrar dispositivo Escribir dispositivo Leer dispositivo Abrir dispositivo
insmod Carga de
módulo
Funciones de kernel
Funciones de usuarios Eventos
LABORATORIO DE SISTEMAS ELECTRÓNICOS
MI PRIMER CONTROLADOR
__KERNEL__
#define MODULE
#include <linux/module.h>
int init_module(void){
printk(“<1>Hola mundo\n”);
return 0;
}
void cleanup_module(void) {
printk(“<1>Adios amigos\n”);
} algo.c
MI PRIMER CONTROLADOR
__KERNEL__
#define MODULE
#include <linux/module.h>
int init_module(void){
printk(“<1>Hola mundo\n”);
return 0;
}
void cleanup_module(void) {
printk(“<1>Adios amigos\n”);
} algo.c
LABORATORIO DE SISTEMAS ELECTRÓNICOS
MI PRIMER CONTROLADOR
__KERNEL__
#define MODULE
#include <linux/module.h>
#include <linux/init.h>
module_init(mi_inicio);
module_exit(mi_final);
algo.c
MI PRIMER CONTROLADOR
__KERNEL__
#define MODULE
#include <linux/module.h>
int init_module(void){
printk(“<1>Hola mundo\n”);
return 0;
}
void cleanup_module(void) {
printk(“<1>Adios amigos\n”);
} algo.c
LABORATORIO DE SISTEMAS ELECTRÓNICOS
FUNCIONES USUARIO-KERNEL
cleanup_module rmmod
Quitar módulo Cerrar dispositivo Escribir dispositivo Leer dispositivo Abrir dispositivo
init_module insmod
Carga de módulo
Funciones de kernel
Funciones de usuarios Eventos
CONTROLADOR PUERTO PARALELO
• OCUPA TRES BYTES DE MEMORIA
• DIRECCIÓN PRIMER BYTE 0x378
• ÚNICAMENTE PRIMER BYTE: SALIDAS
LABORATORIO DE SISTEMAS ELECTRÓNICOS
CONTROLADOR PUERTO PARALELO
__KERNEL__
#define MODULE
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/types.h>
#include <asm/io.h>
CONTROLADOR PUERTO PARALELO
/*Declaración de funciones*/
int paralelo_open(struct inode *inode, struct file *filp);
int paralelo_release(struct inode *inode, struct file *filep);
ssize_t paralelo_read(struct file *filep, char *buf, size_t count, loof_t *f_pos);
ssize_t paralelo_write(struct file *filep, const char *buf, size_t count, loof_t
*f_pos);
void cleanup_module(void);
LABORATORIO DE SISTEMAS ELECTRÓNICOS
CONTROLADOR PUERTO PARALELO
/*Funciones de acceso a fichero*/
Struct file_operations paralelo_fops = { read: paralelo_read,
write: paralelo_write, open: paralelo_open, release: paralelo_release };
/*Variables globales*/
Int paralelo_major =60;
CONTROLADOR PUERTO PARALELO
$ mknod /dev/paralelo c 60 0
DISPOSITIVOS == FICHEROS /dev
LABORATORIO DE SISTEMAS ELECTRÓNICOS
CONTROLADOR PUERTO PARALELO
/*Inicio de módulo*/
Int init_module(void){
int result;
//Registrando dispositivo
result = register_chrdev(paralelo_major,
“paralelo”, ¶lelo_fops);
if (result < 0){
printk(“<1>Fallo número mayor\n”);
return result;
}
CONTROLADOR PUERTO PARALELO
/* Disponibilidad de la región de memoria*/
port = check_region(0x378,1);
if (port){
printk(“<1>Fallo”);
result = port;
goto fallo;
}
printk(“<1>Insertando módulo”);
return 0;
fallo:
cleanup_module();
LABORATORIO DE SISTEMAS ELECTRÓNICOS
CONTROLADOR PUERTO PARALELO
/* Disponibilidad de la región de memoria*/
port = check_region(0x378,1);
if (port){
printk(“<1>Fallo”);
result = port;
goto fallo;
}
printk(“<1>Insertando módulo”);
return 0;
fallo:
cleanup_module();
CONTROLADOR PUERTO PARALELO
/* Disponibilidad de la región de memoria*/
port = check_region(0x378,1);
if (port){
printk(“<1>Fallo”);
result = port;
goto fallo;
}
printk(“<1>Insertando módulo”);
return 0;
fallo:
cleanup_module();
LABORATORIO DE SISTEMAS ELECTRÓNICOS
CONTROLADOR PUERTO PARALELO
/* Liberando el módulo*/
Void cleanup_module(void) {
//Liberamos el número mayor
unregister_chrdev(paralelo_major,
“paralelo”);
//Liberamos el puerto if (!port)
release_region(0x378,1);
printk(“<1>Quitando módulo”);
}
CONTROLADOR PUERTO PARALELO
/* Abriendo el dispositivo como fichero*/
int paralelo_open(………) { MOD_INC_USE_COUNT;
printk(“<1>Abriendo”);
return 1;
}
/* Abriendo el dispositivo como fichero*/
int paralelo_close(………) { MOD_DEC_USE_COUNT;
printk(“<1>Cerrando”);
return 0;
}
LABORATORIO DE SISTEMAS ELECTRÓNICOS
CONTROLADOR PUERTO PARALELO
/* Leyendo del dispositivo*/
int paralelo_read(………) { char par_buffer;
par_buffer = inb(0x378);
return 1;
}
/* Escribiendo en el dispositivo*/
int paralelo_write(………) { char par_buffer;
outb(par_buffer,0x378);
return 1;
}
FUNCIONES USUARIO-KERNEL
cleanup_module Rmmod
Quitar módulo
File op: release fclose
Cerrar dispositivo
File op: write fwrite
Escribir dispositivo
File op: read fread
Leer dispositivo
File op: open fopen
Abrir dispositivo
init_module insmod
Carga de módulo
Funciones de kernel
Funciones de usuarios Eventos
LABORATORIO DE SISTEMAS ELECTRÓNICOS
FUNCIONES KERNEL-HARDWARE
outb Escribir datos
inb Leer datos
Funciones del kernel
Eventos
APLICACIÓN FINAL
int main(void){
unsigned char byte;
FILE * puertopar;
puertopar = fopen(“/dev/puertopar”,”w”);
byte = 1;
while(1){
fwrite(&byte,1,1,puertopar);
sleep(1);
byte <<=1;
if (byte == 0) byte = 1;
}
fclose(puertopar);}
LABORATORIO DE SISTEMAS ELECTRÓNICOS
APLICACIÓN FINAL
CONSIDERACIONES ANTARES
__KERNEL__
#define MODULE
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/types.h>
#include <asm/io.h>
#include <asm/mcfsim.h> /* Registros internos del MCF5272 */
#define MCF_BAR 0x10000000
LABORATORIO DE SISTEMAS ELECTRÓNICOS
REFERENCIA OBLIGADA
LINUX DEVICE DRIVER A.Rubini Ed.O’Reilly
PREGUNTAS