Docsity
Docsity

Prepara tus exámenes
Prepara tus exámenes

Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity


Consigue puntos base para descargar
Consigue puntos base para descargar

Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium


Orientación Universidad
Orientación Universidad


Hadware material de estudio, Apuntes de Procesamiento de Señales Digitales

Material de estudio hadware comp

Tipo: Apuntes

2022/2023

Subido el 21/07/2023

usuario desconocido
usuario desconocido 🇪🇨

3 documentos

1 / 27

Toggle sidebar

Esta página no es visible en la vista previa

¡No te pierdas las partes importantes!

bg1
Interrupciones Hardware
LECCIÓN 3: INTERRUPCIONES HARDWARE
LECCIÓN 3: INTERRUPCIONES HARDWARE .......................................................... 1
3.1 Introducción ............................................................................................................. 2
3.2 Sistema de Interrupciones basados en Controladores de Interrupciones
Programables (arquitectura i386). ................................................................................ 2
3.3 Interrupciones hardware en Linux. .......................................................................... 5
3.3.1 Estructuras de datos para soportar el sistema de interrupciones hardware ............................... 5
.................................................................................................................................................................. 6
irqaction ................................................................................................................................................... 6
irq_desc .................................................................................................................................................... 8
Tabla descriptora de interrupciones idt_table ....................................................................................... 10
3.4 Procesado de interrupciones ................................................................................ 12
3.5 Procedimientos de Inicialización .......................................................................... 17
init_IRQ(). ............................................................................................................................................... 17
request_irq ............................................................................................................................................. 19
setup_irq ................................................................................................................................................ 22
free_irq ................................................................................................................................................... 25
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b

Vista previa parcial del texto

¡Descarga Hadware material de estudio y más Apuntes en PDF de Procesamiento de Señales Digitales solo en Docsity!

LECCIÓN 3: INTERRUPCIONES HARDWARE

  • LECCIÓN 3: INTERRUPCIONES HARDWARE
  • 3.1 Introducción.............................................................................................................
  • Programables (arquitectura i386). 3.2 Sistema de Interrupciones basados en Controladores de Interrupciones
  • 3.3 Interrupciones hardware en Linux...........................................................................
    • 3.3.1 Estructuras de datos para soportar el sistema de interrupciones hardware
    • irqaction
    • irq_desc....................................................................................................................................................
    • Tabla descriptora de interrupciones idt_table.......................................................................................
  • 3.4 Procesado de interrupciones
  • 3.5 Procedimientos de Inicialización
    • init_IRQ()................................................................................................................................................
    • request_irq.............................................................................................................................................
    • setup_irq................................................................................................................................................
    • free_irq...................................................................................................................................................

LECCIÓN 3: INTERRUPCIONES HARDWARE

3.1 Introducción

Las interrupciones hardware son producidas por varias fuentes, por ejemplo del

teclado, cada vez que se presiona una tecla y se suelta se genera una interrupción.

Otras interrupciones son originadas por el reloj, la impresora, el puerto serie, el

disco, etcétera.

Una interrupción de tipo hardware es una señal eléctrica producida por un dispositivo

físico del ordenador. Esta señal informa a la CPU que el dispositivo requiere su

atención. La CPU parará el proceso que está ejecutando para atender la

interrupción. Cuando la interrupción termina, la CPU reanuda la ejecución en donde

fue interrumpida, pudiendo ejecutar el proceso parado originalmente o bien otro

proceso.

Existe un hardware específico, para que los dispositivos puedan interrumpir lo que

está haciendo la CPU. La propia CPU, tiene entradas específicas para ser

interrumpida INT, cuando se activa esta entrada INT, la CPU para lo que está

haciendo y activa la salida para reconocer la interrupción INTA, y comienza a

ejecutar el código especial que maneja la interrupción. Algunas CPU´s disponen de

un conjunto especial de registros, que solo son utilizados en el modo de ejecución

de interrupciones, lo que facilita el trabajo de tratar las interrupciones.

La placa base del computador utiliza un controlador para decodificar las

interrupciones que no son mas que señales eléctricas producidas por los

dispositivos, coloca en el bus de datos información de que dispositivo interrumpió y

activa la entrada INT de interrupción de la CPU. Este chip controlador protege a la

CPU y la aísla de los dispositivos que interrumpen, además de proporcionar

flexibilidad al diseño del sistema. El controlador de interrupciones tiene un registro

de estado para permitir o inhibir las interrupciones en el sistema.

3.2 Sistema de Interrupciones basados en Controladores de

Interrupciones Programables (arquitectura i386).

Existe diverso hardware para implementar un controlador de interrupciones, los

computadores IBM PC o compatibles, utilizan el controlador de interrupciones

programable de Intel 82C59A-2 Cmos o sus chips compatibles. Este controlador ha

sido utilizado desde los comienzos del IBM PC, y es bien conocido el espacio de

direccionamiento de sus registros en la arquitectura ISA. Incluso en chips más

modernos se ha mantenido la misma localización.

Los IRQ o i nterrupt r e q uest (Pedido de Interrupción), son las notificaciones de las

interrupciones enviadas desde los dispositivos hardware a la CPU, en respuesta a la

IRQ, la CPU salta a una dirección – una r utina de s ervicio de i nterrupción (ISR),

comúnmente llamada Interrupt handler (Manejador de interrupciones) - Que se

encuentra como una función dentro del software manejador de ese dispositivo

formando parte del núcleo. Así, una función manejadora de interrupciones es una

función del núcleo que ejecuta el servicio de esa interrupción.

Los IRQ se encuentran numerados, y cada dispositivo hardware se encuentra

asociado a un número IRQ. En la arquitectura IBM PC y compatibles, por ejemplo,

IRQ 0 se encuentra asociado al reloj o temporizador, el cual genera 100

interrupciones por segundo, disquete el 6, los discos IDE la 14 y 15. Se puede

compartir un IRQ entre varios dispositivos.

La siguiente figura, muestra las interrupciones hardware y su correspondiente

puerto en el Controlador Programable de Interrupciones (PIC). No se deben

confundir los números IRQ entradas al controlador con los números de la

interrupción que son las entradas en la tabla de interrupciones. Los PIC se pueden

programar para generar diversos números de interrupción para cada IRQ.

Los Controladores también controlan la prioridad de las interrupciones. Por ejemplo,

el reloj (en IRQ 0) tiene una prioridad más alta que el teclado (IRQ 1). Si el

procesador está atendiendo una interrupción del reloj, el PIC no generará una

interrupción para el teclado hasta que ISR del reloj reajusta el PIC. Por otra parte, el

reloj puede interrumpir ISR del teclado. El PICs se puede programar para utilizar una

variedad de esquemas de la prioridad, pero no se suele hacer esto.

Se debe de tener en cuenta que el IRQ 2 del primer PIC, valida o invalida las

entradas del Segundo PIC (8 a 15).

Algunas interrupciones son fijadas por convenio en la configuración del PC, así es

que los manejadores de los dispositivos solicitan simplemente la interrupción cuando

se inicializan. Por ejemplo esto es lo que lo hace el manejador de disquete, solicita

siempre la IRQ 6.

Interrupción IRQ Descripción

00H - división por cero o desbordamiento

02H - NMI (interrupción no-enmascarable)

04H - desbordamiento (EN)

08H 0 Temporizador del sistema

09H 1 Teclado

0AH 2 Interrupción del segundo PIC

0BH 3 COM

0CH 4 COM

0DH 5 LPT

0EH 6 disquete

0FH 7 LPT

70H 8 Reloj

71H 9 I/o general

72H 10 I/o general

73H 11 I/o general

74H 12 I/o general

75H 13 Coprocesador

76H 14 Disco duro

77H 15 I/o general

3.3 Interrupciones hardware en Linux.

Una de las principales tareas del sistema de manejo de interrupciones es llevar las

diferentes interrupciones a los códigos de manejo de esas interrupciones.

Cuando se activa el contacto 6 del controlador de interrupciones, se debe reconocer

cual es la interrupción asociada a ese contacto, por ejemplo el controlador del

dispositivo disquete, por lo tanto el sistema de manejo de interrupciones debe

encaminar a la rutina que trata esta interrupción, para ello Linux proporciona un

conjunto de estructuras de datos y tablas, y un conjunto de funciones que las

inicializan y las manejan.

El sistema de interrupciones es muy dependiente de la arquitectura, Linux en la

medida de lo posible, tratará de que sea independiente de la máquina en la que

reside el sistema, para ello el sistema de interrupciones se va a implementar

mediante una serie de estructuras de datos y funciones en lenguaje C que

facilitarán la portabilidad. Veamos una presentación de las estructuras de datos

implicadas, resaltando las más importantes y describiendo los campos de cada una.

Posterior a eso se seguirá con la inicialización de estas estructuras que soportan las

interrupciones, esta parte es fuertemente dependiente de la arquitectura, nos

basaremos en i386. Finalmente se expondrá el flujo dentro del núcleo que sigue una

interrupción hardware, desde que se origina en el dispositivo hardware hasta que se

atiende por el manejador de la interrupción.

3.3.1 Estructuras de datos para soportar el sistema de interrupciones hardware

Estudiaremos las estructuras de datos del sistema de interrupciones:

irqaction almacena la dirección de la función de manejo de interrupciones.

irq_chip contiene las funciones que manejan un controlador de interrupciones

particular, es dependiente de la arquitectura.

irq_desc vector con una entrada para cada una de las interrupciones que pueden

ser atendidas.

Estructuras de datos para el sistema de interrupciones

SA_INTERRUPT Indica que esta interrupción puede ser interrumpida por

otra.

SA_SAMPLE_RANDOM Esta interrupción puede ser considerada de

naturaleza aleatoria, esto puede ser útil cuando se necesita una semilla de

aleatoriedad, etc.

SA_SHIRQ Esta IRQ puede ser compartida por diferentes struct irqaction

mask Este campo no se usa en la arquitectura i

name Un nombre asociado con el dispositivo que genera la interrupción. Como una

misma IRQ puede ser compartida por diferentes dispositivos, esto nos puede ayudar

a distinguir los dispositivos. Se puede leer en el fichero /proc/interrupts.

dev_id Todos y cada uno de los dispositivos implementados en Linux tiene un

número identificador único grabado por el fabricante. De esta forma, este campo

define qué dispositivo genera la interrupción. Estos identificadores se encuentran

definidos en ficheros cabeceras.

#define PCI_DEVICE_ID_S3_868 0x

#define PCI_DEVICE_ID_S3_928 0x88b

next Este campo contiene un puntero que apunta a la próxima struct irqaction en

la cola, esto sólo tiene sentido cuando la IRQ se encuentra compartida, así pues, en

la mayoría de los casos estará a NULL.

irq Numero de la línea IRQ.

dir Indica un puntero al descriptor del directorio /proc/irq/n asociado con la irq n.

irq_chip

Es una estructuras dependiente de la arquitectura, para Intel está definida en el

fichero include/linux/irq.h

su código es:

/* Describe el decodificador de interrupciones a bajo nivel y las funciones que lo

manejan */

98 struct irq_chip { 99 const char name; 100 unsigned int (startup)(unsigned int irq); 101 void (shutdown)(unsigned int irq); 102 void (enable)(unsigned int irq); 103 void (disable)(unsigned int irq); 104 105 void (ack)(unsigned int irq); 106 void (mask)(unsigned int irq); 107 void (mask_ack)(unsigned int irq); 108 void (unmask)(unsigned int irq); 109 void (eoi)(unsigned int irq); 110 111 void (end)(unsigned int irq); 112 void (set_affinity)(unsigned int irq, cpumask_t dest); 113 int (*retrigger)(unsigned int irq);

114 int (set_type)(unsigned int irq, unsigned int flow_type); 115 int (set_wake)(unsigned int irq, unsigned int on); 116 117 /* Currently used only by UML, might disappear one day./ 118 #ifdef CONFIG_IRQ_RELEASE_METHOD 119 void (release)(unsigned int irq, void dev_id); 120 #endif 121 / 122 * For compatibility, ->typename is copied into ->name. 123 * Will disappear. 124 */ 125 const char *typename; 126 };

Esta estructura contiene todas las operaciones específicas de un determinado

decodificador de interrupciones (8259) tales como el activado o desactivado de irqs,

etc. Los campos se detallan a continuación:

name Un nombre para /proc/interrupts

startup Activa una entrada irq para que pueda interrumpir.

shutdown Deshabilita una entrada irq.

enable y disable Igual que startup/shutdown respectivamente.

ack Comienzo de una nueva interrupción.

mask umask Pone quita una máscara para una interrupción.

eoi end Final de una interrupción.

set-affinity Para trabajar con varias CPUs (smp).

retrigger Vuelve a enviar una petición irq a la cpu.

set_type Define el modo de disparo (nivel, flanco) de la Irq.

set_wake Permite despertar a la unidad de alimentación al recibir una irq.

irq_desc

Es un vector de estructuras de tipo irq_desc_t , descriptor de interrupciones

dependiente de la arquitectura, para Intel está definido en el fichero

incluye/linux/irq.h. Por cada interrupción hardware del sistema habrá un elemento

en el array irq_desc[ ].

Su código es el siguiente:

struct irq_desc { 156 unsigned int irq; 157 irq_flow_handler_t handle_irq; 158 struct irq_chip *chip; 159 struct msi_desc *msi_desc; 160 void *handler_data; 161 void *chip_data; 162 struct irqaction action; / IRQ action list / 163 unsigned int status; / IRQ status / 164 165 unsigned int depth; / nested irq disables / 166 unsigned int wake_depth; / nested wake enables / 167 unsigned int irq_count; / For detecting broken IRQs */ 168 unsigned int irqs_unhandled;

#define IRQ_PENDING 4 /* IRQ pendiente, ha sido reconocida por el PIC

pero no ha sido atendida por el núcleo */

#define IRQ_REPLAY 8 /* IRQ reintenta pero todavía no atendida */

#define IRQ_AUTODETECT 16 /* IRQ esta siendo auto detectada */

#define IRQ_WAITING 32 /* IRQ no lista para auto detección */

Tabla descriptora de interrupciones idt_table

La tabla descriptora de las interrupciones IDT, es una tabla de 256 entradas que

junto con la tabla global de descriptores GDT, nos va a llevar dentro del núcleo a las

rutinas de manejo de interrupciones que se encuentran en el manejador del

dispositivo. Definida en arch/x86/kernel/traps.c, como gate_desc idt_table[256]. Y

cada entrada de la tabla es una estructura definida en,

arch/x86/include/asm/desc_defs.h

Como:

/* 16byte gate */ 45 struct gate_struct64 { 46 u16 offset_low; 47 u16 segment; 48 unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1; 49 u16 offset_middle; 50 u32 offset_high; 51 u32 zero1; 52 } attribute((packed));

hard

excepciones

syscall 0x

S D A

S D A

S D A

S D A

S D A

S D A

S D A

255 S D A

B L

IDTR

IDT

S: selector o índice D: desplazamiento A: atributos B: base L: límite

Las primeras entradas de la tabla están ocupadas por las excepciones.

Las interrupciones hardware, comienzan en la entrada 32 de la tabla, ocupan 16

entradas van desde 0x20 y hasta 0x2f.

La interrupción software ocupa la entrada 128, (0x80 en exadecimal).

IDTR es un registro dentro de la CPU que contiene la base y el límite de esta tabla

en memoria.

S con este campo seleccionamos una entrada dentro de la tabla GDT, que nos dará

la base y el límite del núcleo en memoria.

D es el desplazamiento que sumado a la base del núcleo no lleva a la función de

entrada para una determinada interrupción.

1. El decodificador de interrupciones recibe una interrupción (la patilla IRQ a nivel

alto), este interrumpe a la CPU, que automáticamente mediante la entrada que

corresponde a esta interrupción y con la ayuda de la IDT y la GDT nos lleva a

ENTRY (irq_entries_start) dentro de arch/i386/kernel/entry.S, que salta a

common_interrupt.

2. common_interrupt despues de guardar el estado del proceso SAVE_ALL llama

a do_irq pasándole el número de interrupción para ejecutar la función manejadora

ENTRY (irq_entries_start)

common_interrupt(n)

SAVE_ALL

do_IRQ(n) RESTORE_ALL

do_IRQ(n)

action->handler

manejador

handle_irq

IDT + GDT

interrupción (^) CPU

IDTR

GDTR

de la interrupción y posteriormente recupera el estado del proceso interrumpido

RESTART_ALL saltando a ret_from_intr.

3. do_IRQ llama a handle_IRQ.

4. handle_IRQ llama a las funciones necesarias para atender la interrupción action-

>handler dentro del manejador.

5. action->handler se ejecuta la función manejadora de la interrupción dentro del

manejador (driver) del dispositivo que interrumpió.

6. ret_from_intr restaura el estado del proceso interrumpido RESTORE_ALL y

continúa con la ejecución normal.

Flujo proceso a proceso

La función set_intr_gate inicializa la IDT, colocando el desplazamiento que nos lleva

al punto de entrada ENTRY (irq_entries_start) , dentro del fichero

Linux/arch/x86/kernel/entry_32.S.

irq_entries_start nos lleva a common_interrupt pasándole como parámetro el

número de interrupción en el stack cambiado de signo.

ENTRY( irq_entries_start ) 587 RING0_INT_FRAME 588 vector= 589 .rept NR_IRQS 590 ALIGN 591 .if vector 592 CFI_ADJUST_CFA_OFFSET - 593 .endif 594 1: pushl $~(vector) 595 CFI_ADJUST_CFA_OFFSET 4 596 jmp common_interrupt 597 .previous 598 .long 1b 599 .text 600 vector=vector+ 601 .endr 602 END(irq_entries_start)

Guarda el número de la interrupción en el stack, forma de pasar parámetros a una

función, y en negativo para que no exista conflicto con el número de señales

pushl $~(vector)

y salta a la función jmp common_interrupt

453 TRACE_IRQS_IRET

454 restore_nocheck_notrace: 455 RESTORE_REGS # recupera el estado de la máquina 456 addl $4, %esp # skip orig_eax/error_code 457 CFI_ADJUST_CFA_OFFSET -

restore_all:

RESTORE_REGS

do_IRQ , se encuentra en el fichero arch/x86/kernel/irq.c, maneja todas las interrupciones

normales de los dispositivos IRQ's (las interrupciones especiales producidas por tener varias CPU’s

(SMP), tienen un tratamiento especifico. Recibe el número de irq a través del registro eax y

un puntero a una estructura pt_regs donde se han guardado los registros. Llama a la

función handle_irq(irq, desc) , que contiene el manejador de esa interrupción.

199 unsigned int do_IRQ(struct pt_regs *regs) 200 { 201 struct pt_regs old_regs; 202 / high bit used in ret_from_ code */ 203 int overflow;

/* el numero de interrupción se encuentra en los bits más bajos de eax */

204 unsigned vector = ~regs->orig_ax; 205 struct irq_desc *desc; 206 unsigned irq; 207 208 209 old_regs = set_irq_regs(regs); 210 irq_enter(); 211 irq = __get_cpu_var(vector_irq)[vector]; 212 213 overflow = check_stack_overflow(); 214

/* accede a la posición del vector irq_desc para esta interrupción */

215 desc = irq_to_desc(irq); 216 if (unlikely(!desc)) { 217 printk(KERN_EMERG "%s: cannot handle IRQ %d vector %#x cpu %d\n", 218 func, irq, vector, smp_processor_id()); 219 BUG(); 220 } 221 222 if (!execute_on_irq_stack(overflow, desc, irq)) { 223 if (unlikely(overflow)) 224 print_stack_overflow();

/* llamada a la función

Llama a la función de alto nivel manejadora de la interrupción, con el número de irq

y un puntero a la entrada del vector de interrupciones irq_desc , la estructura

irq_desc mediante el campo action apunta al campo irqaction->handler que tiene

grabada la dirección de la función. Este campo ha sido previamente inicializado por

el driver del dispositivo.

225 desc->handle_irq(irq, desc);

228 irq_exit(); 229 set_irq_regs(old_regs); 230 return 1; 231 }

Por último la función que entra en juego es el manejador de la interrupción que es

una función que se encuentra dentro del código driver del dispositivo.

3.5 Procedimientos de Inicialización

Para que los dispositivos puedan utilizar el sistema de interrupciones, el sistema al

arrancar debe inicializar mediante unos procedimientos, que se encuentran en

/arch/x86/kernel/irqinit.c, las estructuras de datos relacionas con las interrupciones.

init_IRQ().

Esta función es llamada por el programa de inicio del sistema init start_kernel () , en

init/main.c. Esta función pone a punto la tabla de descriptores de interrupciones

(IDT). Se encuentra definida en el fichero arch/i386/kernel/i8259.c

Primeramente inicializa el vector de interrupciones hardware irq_desc[0..15].

Seguidamente inicializa la tabla IDT, llamando a la función set_intr_gate().

set_intr_gate

init_irq

IDT

INIT

pre_intr_init_hook

Irq_desq[]

319 BUG_ON((unsigned)n > 0xFF); 320 _set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS); 321 }

n va apuntando a las distintas entradas de la IDT.

DESCTYPE_INT tipo de descriptor interrupcion

addr es el desplazamiento que le va a llevar a la función irq_entries_start.

KERNEL_CS selector que apunta a la entrada de la GDT donde está la base del

código del núcleo.

llama a la macro _set_gate en Linux/arch/x86/asm/desc.h

static inline void _set_gate(int gate, unsigned type, void addr, 300 unsigned dpl, unsigned ist, unsigned seg) 301 { 302 gate_desc s; 303 pack_gate(&s, type, (unsigned long)addr, dpl, ist, seg); 304 / 305 * does not need to be atomic because it is only done once at 306 * setup time 307 */ 308 write_idt_entry(idt_table, gate, &s); 309 }

static inline void pack_gate(gate_desc *gate, unsigned char type, 66 unsigned long base, unsigned dpl, unsigned flags, 67 unsigned short seg) 68 { 69 gate->a = (seg << 16) | (base & 0xffff); 70 gate->b = (base & 0xffff0000) | 71 (((0x80 | type | (dpl << 5)) & 0xff) << 8); 72 }

static inline void native_write_idt_entry(gate_desc *idt, int entry, 116 const gate_desc gate) 117 { 118 memcpy(&idt[entry], gate, sizeof(gate)); 119 }

request_irq

Una vez que el sistema de interrupciones está inicializado, cuando se vayan

cargando los diferentes manejadores de dispositivos éstos harán uso de las

funciónes request_irq y setup_x86_irq para colocar la dirección de la función

manejadora de interrupción propia y activar la interrupción.

request_irq es llamado por los manejadores, en su inicio, para colocar la dirección

de la función manejadora de interrupción. Definida en kernel/irq/manage.c.

Crea un nuevo nodo en la lista irqaction y llena sus campos con los valores

suministrados para una IRQ.

request_irq – Asigna una línea de interrupción irq: Línea de interrupción a asignar handler: Función que se tiene que ejecutar cuando ocurre la IRQ irqflags: Flags del estado de la interrupción devname: Un nombre para el dispositivo asociado a esa interrupción dev_id: Identificador del dispositivo pasado a la función que trata la interrupción

  • Esta función asigna recursos a la interrupción y habilita la
  • línea de interrupción y el tratamiento de la IRQ. Una vez
  • ejecutada esta función el manejador ya puede ser invocado.
  • Ya que la función manejadora puede borrar cualquier
  • interrupción, se tiene que inicializar el hardware
  • y el manejador de interrupciones en el orden adecuado.
  • Dev_id debe ser un identificador único. Normalmente se toma
  • como identificador la dirección de la estructura device. Ya que
  • el manejador recibe este valor tiene sentido usar este valor.
  • Si la interrupción es compartida, el dev_id debe ser no NULL
  • esto se require cuando se libera la interrupción.
  • Flags:
  • IRQF_SHARED Interrupción compartida
  • IRQF_DISABLED Desactivar interrupción cuando se está procesando
  • IRQF_SAMPLE_RANDOM La interrupción se puede usar para random
  • IRQF_TRIGGER_* Especifica si se activa por flancos o por nivel

int request_irq(unsigned int irq, irq_handler_t handler, 670 unsigned long irqflags, const char *devname, void *dev_id) 671 { 672 struct irqaction *action;

irqaction

request_irq

setup_irq

MANEJADOR

función manejadora de la interrupción