Indice

PRESIONE AQUI PARA LLEVARSE LOS FUENTES

PRESIONE AQUI PARA LLEVARSE LOS EJECUTABLES


Problema a Resolver *

Objetivos *

Breve Introducción *

Desarrollo *

Direccionamiento de Dispositivos de E/S: *

Transferencia de Datos: *

Sincronización *

Manejo de Interrupciones *

Prioridades *

Resultados obtenidos. *

Conclusiones. *

Bibliografía. *

Apéndices. *

Enunciado

Diseñar un simulador de teclado.

Problema a Resolver

Realizar, los más claramente posible, un ejemplo de "una rutina de servicio de interrupción"; desde su organización hasta como interactúan los distintos componentes de la interfaz del dispositivo con la CPU.

Objetivos

  • Explicar un ejemplo de una rutina de servicio de interrupción.
  • Mostrar de forma secuencial ,a través de una aplicación hecha en Visual Basic, los pasos que se realizan durante el proceso de generación y atención de una interrupción generada por un dispositivo de entrada como lo es el teclado.
  • Que el programa de la aplicación se asemeje lo más posible al funcionamiento real de una rutina de servicio de interrupción.
  • Que el aplicativo tenga una interface agradable al usuario y sea de fácil instalación y uso.

 

Breve Introducción

Una de las características básicas de una computadora es su capacidad para enviar y recibir datos hacia y desde otros dispositivos.

Esta capacidad de comunicación permite a un operador, por ejemplo, introducir un programa y sus datos por medio del teclado de una terminal CRT y recibir resultados en una impresora, y realizar muchas otras operaciones de E/S que no vienen al caso.

Las funciones que necesita realizar una computadora para manejar operaciones de E/S son:

    1. Direccionamiento o selección de dispositivos individuales de E/S para una operación dada de transferencia.
    2. Transferencia de datos hacia y desde el dispositivo seleccionado.
    3. Sincronización o coordinación de la temporización de las operaciones de entrada y salida.

Se explicará como se implementan estos 3 aspectos en nuestro ejemplo de teclado, y veremos también las prestaciones y ventajas que nos brinda el lenguaje de programación elegido para presentar este caso.

Desarrollo

Direccionamiento de Dispositivos de E/S

Ya que por lo general una computadora tiene conectado más de un dispositivo, es necesario proporcionar algún medio para seleccionar uno de estos dispositivos para que participe de una operación de E/S.

En nuestro caso consideramos que sólo tenemos un dispositivo de E/S por lo que no tendremos demasiado problema para identificarlo. Vamos a suponer que estamos en el caso de una máquina de bus único, como lo es la PDP-11 y la mayoría de las microcomputadoras, donde el mismo bus sirve tanto como bus de memoria, como de bus de E/S. Entonces, es posible identificar los dispositivos de E/S asignándoles códigos únicos dentro del espacio de dirección de la memoria de la computadora. A esto se lo conoce como E/S por mapa de memoria. Nosotros asignaremos direcciones específicas a nuestro dispositivo, de la siguiente manera:

Registro de condición del teclado (KBSTATUS) KBSTATUS

Buffer de datos del teclado (TTYIN) TTYIN

Desde luego, aquellos usuarios que desean escribir su propio software del Sistema no tienen que emplear esta asignaciones.

Transferencia de Datos

Ahora se analizarán los medios por los cuales los datos pueden trasladarse, de los buffers de un dispositivo, a la memoria principal o a los registros de la CPU y viceversa. Por lo general esto se realiza mediante la ejecución de instrucciones de IN y OUT . Pero en aquellas máquinas en que los registros de datos de dispositivos externos se tratan como localizaciones de la memoria, puede usarse una instrucción de Mover para realizar operaciones de E/S, que es lo que emplearemos en nuestro caso, usando como pseudo-lenguaje el de la PDP-11. Por ejemplo:

MOVB @#TTYIN, LOC

Esta instrucción traslada el contenido del buffer de teclado a la dirección de memoria LOC.

El decodificador de dirección permite al dispositivo reconocer su dirección, al ser colocada en el bus de direcciones por la CPU. El registro de datos se utiliza para que contenga el los datos que se vayan a transferir a la CPU desde un dispositivo de entrada (que es nuestro caso), o para recibir datos provenientes de la CPU para que se transfieran a un dispositivo de salida.

El decodificador de dirección, los registros de datos y de condición, y los circuitos de control necesarios para coordinar transferencias de E/S constituyen la interfaz de nuestro dispositivo.

El método que utilizamos nosotros, de mover a direcciones de la memoria principal, se lo conoce como E/S controlada por programa. Con este método sólo podemos transferir una palabra de datos en cada instrucción de E/S.

Es por eso que la distribución de los "componentes" en la aplicación se asemeja a la figura 1

Líneas de direcciones

Líneas de datos

Líneas de control

 

 

 

Interfaz de E/S

 

Figura 1 Interfaz de E/S para un dispositivo de entrada

Sincronización

Una computadora debe disponer de medios para coordinar sus actividades con aquellas de los dispositivos externos que tenga conectados. La computadora necesita saber cuando se ha introducido en el teclado un nuevo carácter y está listo para la transferencia. En general, hay dos técnicas de uso común para lograr la coordinación: escrutinio, o verificación de condición (pooling), e interrupción.

En la técnica de escrutinio básicamente se cuenta de uno o más bits de información los cuales indican la condición de cada dispositivo de entrada o salida conectado a una computadora. El más importante se denomina bit de Ready "Listo". Cuando este bit esta en 1, puede emitirse una instrucción de E/S para realizar la transferencia requerida. Esto de inmediato borra el bit de Listo, el cual permanece en 0 hasta que el dispositivo este listo de nuevo. La cantidad de bits de información depende de la complejidad del dispositivo. Hay instrucciones especiales para leer esta información.

En la técnica de interrupciones, que fue la elegida en nuestro caso, en vez de ejecutar un ciclo de espera, como ocurre en la técnica de escrutinio, la CPU puede suspender temporalmente la ejecución de las instrucciones. El dispositivo alerta a la CPU al activar una de la líneas de control a la que se denomina línea de solicitud de interrupción (INTR: interrupt-request). Esto indica a la CPU que debe proceder a la ejecución de la transferencia de datos.

El uso de interrupciones se extiende mucho más allá del simple ejemplo aquí mostrado. Debido que ya no se requiere que la computadora verifique continuamente el estado de los dispositivos externos, el período de espera puede utilizarse para efectuar otras funciones útiles. Lo ideal es que tales períodos de espera puedan eliminarse.

La rutina que se ejecuta en respuesta a una solicitud de interrupción se conoce como rutina de servicio de interrupción. El dar servicio tiene mucha similitud con las llamadas a subrrutinas, donde la CPU debe realizar los siguientes pasos :

  • Completar la ejecución de la instrucción en curso.
  • Cargar el contador de programa (PC) con la dirección de la primera instrucción de la rutina de servicio de interrupción. Esta dirección puede estar unida por control fijo a la CPU.
  • Luego de la ejecución de la rutina de servicio de interrupción, la CPU debe regresar a la instrucción siguiente a la que había interrumpido.
  • Una instrucción de regreso-de-interrupción al final de la rutina de servicio provoca que la CPU vuelva a cargar desde una localización temporal de almacenamiento la dirección de la próxima instrucción, al PC, del programa que corría antes de ser interrumpido.

De este modo al momento de interrumpir un programa el contenido del PC, que apunta a la siguiente instrucción, debe ser almacenado temporalmente en memoria. En la mayoría de las computadoras lo hacen en la pila del procesador.

Como parte del manejo de interrupciones la CPU debe informar al dispositivo que su solicitud ha sido reconocida, de manera que este pueda eliminar su señal de solicitud de interrupción. En nuestro caso esto se logra mediante una señal de reconocimiento de interrupción (KNOWLEDGE), la cual se pone en 1 durante la ejecución de la instrucción, de la rutina de servicio, que lee del registro de datos TTYIN en la interfaz del mismo.

Debe observarse una diferencia importante con respecto a la similitud que existe con las llamadas a subrrutinas. El programa principal llama una subrrutina para que realice una función que él requiere. En cambio la rutina de servicio de interrupción puede no tener nada en común con el programa que se esté ejecutando cuando se recibe la interrupción.

Por lo tanto, antes de empezar la ejecución de la rutina de servicio de interrupción, la CPU debe guardar, junto con el contenido del PC, cualquier información que pueda afectar la ejecución cuando regrese al programa original, como ser la palabra de condición (PSW), lo registros de la CPU, y otros registros de uso interno. Este proceso de salvar y restaurar el contexto puede o no ser automático, dependiendo del mecanismo de manejo de interrupción que se este usando, involucrando varias transferencias de la memoria principal. A fin de minimizar el sobreuso por interrupción en algunas computadoras hay dos tipos de interrupción. Una guarda el contenido de todos los registros y la otra no. Un dispositivo de E/S puede utilizar cualquiera de las dos, dependiendo de sus necesidades de velocidad de respuesta. En el caso del teclado donde los tiempos no son tan críticos, y la cantidad de interrupciones es considerable, se guarda y restaura el contexto en antes y después de cada interrupción respectivamente.

Manejo de Interrupciones

Un característica importante que se encuentran en las computadoras es la capacidad de permitir o inhabilitar la ocurrencia de interrupciones de un programa, según se desee.

Existen muchas situaciones en que la CPU no debe tomar en cuenta las solicitudes de interrupción. Por ejemplo hasta que no se procese el carácter tipeado no deberán ocurrir otras interrupciones que interrumpan a esta ultima, ya que durante dicho proceso podrían modificarse algunos de los datos utilizados por las sucesivas instrucciones; lo cuales no se realizarían en el orden correcto que se esperaban que sucedan. Por estas razones, deben existir algunos medios a la disposición del programador para habilitar o inhabilitar las interrupciones. Una forma simple es proveer de instrucciones de máquina, tales como Habilitación-de-interrupción e Inhabilitación -de-interrupcion, o bien dejarle acceso, al programador, del registro de Habilitación-de-interrupción, de modo que bastaría mover el valor necesario para realizar estas funciones.

Para evitar que múltiples interrupciones de un mismo dispositivo sucedan a destiempo, con un mecanismo de manejo de interrupciones, solucionaría el problema. La secuencia de hechos que se involucran en el manejo de una solicitud de interrupción en nuestro caso sería:

  1. El teclado efectúa una solicitud de interrupción.
  2. La CPU interrumpe el programa que se estaba ejecutando en ese momento.
  3. Se inhabilitan las interrupciones.
  4. Se informa a su interfaz que su solicitud ha sido reconocida y, en respuesta, este desactiva la señal de solicitud de interrupción.
  5. Se realiza la acción solicitada por la interrupción. Es decir se ejecuta la rutina de servicio de interrupción.
  6. Se habilitan las interrupciones.
  7. Se reanuda la ejecución del programa interrumpido.

Prioridades

Como se mencionó anteriormente las interrupciones deberían inhabilitarse durante la ejecución de una rutina de servicio de interrupción. Esto nos asegura que la solicitud de interrupción de un dispositivo no provocará más de una interrupción. Este mismo concepto se utiliza cuando hay varios dispositivos, es decir, la que hasta que no se termine con la ejecución de la rutina de servicio, la CPU no aceptará una segunda solicitud de interrupción del mismo dispositivo.

Una solicitud de interrupción de algunos dispositivos de E/S no atendida a tiempo los puede llevar a operar de forma errónea (Por ejemplo un dispositivo condicionado por un reloj en tiempo real o un censor). Debido a esto es necesario que los dispositivos de E/S estén organizados con una estructura jerárquica de prioridades. En nuestro caso le asignamos al teclado una prioridad de 4. La prioridad de la CPU es la prioridad del programa que se encuentra ejecutando en cada momento, ya que cuando ocurra una solicitud, la CPU evaluará cual proceso tiene mayor importancia.

Un circuito de prioridades arbitra las solicitudes de interrupción recibidas por las líneas de control. La prioridad de la CPU se incorpora como parte de la Palabra de estado del procesador.

 

Enmascarado Selectivo de Interrupciones

La capacidad selectiva de habilitación e inhabilitación de interrupciones según la prioridad del dispositivo, se logra mediante el empleo de un flip-flop de habilitación-de-interrupción asociado con cada dispositivo, o incluso, grupo de dispositivos. Cuando la CPU lo pone en 1, este flip-flop permite que una solicitud emitida por el dispositivo llegue a la misma. De lo contrario la interrupción se enmascara y no permite que llegue a la CPU. En maquinas con esta organización, pueden tener un flip-flop de habilitación por cada dispositivo.

 

Resultados obtenidos

Como resultado vamos a seguir paso a paso un ejemplo simple de rutina de servicio de interrupción de una terminal de teclado. Los caracteres de entrada los almacenaremos en un buffer de la memoria principal, empezando por la localización LOC. Contamos con un bit de Listo que se encuentra en el registro de condición del teclado, llamado KBSTATUS, el cual no avisará cuando se encuentra disponible un carácter en el buffer de datos TTYIN. Se enciende cuando se oprime una tecla, y se borra cuando se leen los datos de TTYIN. Otro bit de Int se utiliza para habilitar o de habilitar interrupciones.

Entonces, será necesario cargar la localización, de memoria principal, que apunte al inicio de la rutina de servicio de interrupción, y también la palabra de condición del programa deseado. Esto puede hacerlo el Sistema Operativo antes de habilitar las interrupciones del dispositivo. La habilitación de interrupción se realiza mediante el uso de la Máscara de habilitación e inhabilitación de interrupción del teclado. Luego de una interrupción, este valor será cargado en la PS, y como resultado, la prioridad de la CPU quedará en 4 para que no ocurran interrupciones, durante la ejecución de la rutina de servicio. Inmediatamente antes de habilitar las interrupciones del teclado, el PS se borra, con lo que la prioridad de la CPU regresa a 0. De este modo podrán ser atendidas posteriores interrupciones. Siempre que se oprima una tecla, el Sistema Operativo será interrumpido y se ejecutará la rutina de servicio, que en nuestro caso la llamaremos LEER. El carácter de entrada se transferirá al un buffer circular en la memoria, incrementándose los apuntadores del mismo. Si los apuntadores apuntan a la misma ceda entonces se agotó la capacidad del mismo. Esto significa que el próximo carácter presionado no se tendrá en cuenta.

Si el carácter presionado es CR (Carriage Return), se inhabilitan las interrupciones y se ejecuta la rutina LINE para que se procese la línea de entrada que está en el buffer de datos. Al concluir la rutina de servicio, se ejecuta una instrucción de Regreso-de-interrupción, provocando que el PC y el PS se encuentren con lo que se guardó en la pila.

 

Conclusiones

En este trabajo practico abordamos una técnica simple del manejo de E/S, para dispositivos relativamente lentos, como lo fue el teclado en nuestro caso, llamada "E/S controlada por programa ", en donde la CPU realiza todas las funciones de control necesarias para llevarlas a cabo. Podemos notar que de tratarse de dispositivos de mayor velocidad, donde la cantidad de accesos es considerablemente más alta que la de dispositivos más lentos, la CPU se cargaría con una larga lista de procesos en espera de ser atendidos y otra, tal vez más larga, de procesos en ejecución. Como solución a esto se nos puede ocurrir la incorporación de otro dispositivo con el fin de aminorar el trabajo a la CPU. Como ser un controlador de Acceso Directo a Memoria (DMA), el cual le quita una gran carga a la CPU encargándose él mismo, controlado por la CPU, de las transferencias entre la memoria principal y los dispositivos de E/S. También podemos pensar en tener aún más CPUs, controladas por la CPU principal, para que se encarguen de realizar estas operaciones entre los dispositivos de E/S. A este arreglo de CPUs se lo conoce como Canales de E/S . Estas pueden realizar operaciones de E/S independientemente de la CPU principal, basta que la misma les cargue programas de canal, los cuales avisaran a la CPU cuando hallan terminado y estén listos para una nueva tarea.

Otro tema importante, que se trabajo, fue la forma de "avisarle" a la CPU, y viceversa, de la necesidad de procesar. Vimos dos formas de aviso. Una fue el escrutinio, donde la CPU censa constantemente un flag para saber si algún dispositivo necesita de ella, y vimos la gran demanda que esto requería. La segunda forma, y la más importante, fue la de las interrupciones. De este modo la CPU puede estar ejecutando otro proceso y cuando el dispositivo, o el proceso, lo requiera basta con encender un flag el cual le indica a la CPU que tiene que la requiere. Además las diferentes formas que existen de administrarlas, nos brindan la posibilidad de jerarquizar las prioridades de los dispositivos, así como también el manejo de un número mayor de los mismos. Podemos concluir finalmente que son de gran importancia en la mayoría de las computadoras, tanto como para las pequeñas, como para las grandes, variando la complejidad de los esquemas del manejo de las mismas, respectivamente.

 

Bibliografía

  • Andrew S. Tanenbaum. "Organización de Computadoras un Enfoque Estructurado". Tercera Edición. Ed. Prentice Hall.
  • U. Carl Hamacher, Zvonko G. Vranesic, Safwat G. Zaky. "Organización de Computadoras". Segunda Edición. Editorial Mc Graw Hill.
  • Boberg, R.W.: Proposed Microcomputer System 796 Bus Standard, Computer, vol 13, no. 10 · 89-105, Oct 1980
  • Kells, A.E., H. Fullmer, D.B. Gustavson y G. Morrow: Standard Specification For S-100 Bus Interface Device, Computer, vol 12 no. 7, · . 28-52, Julio 1979.
  • IEEE Standard Digital Interface For Programmable Instrumentation, ANSI/IEEE Standard 488, 1978.
  • Bruce McKinney. "Programación avanzada con Visual Basic 5.0". Mc Graw Hill. 1998


Apéndices

Explicación del Código Fuente

La idea de este apéndice es ver algunos de los beneficios que nos proporciona el lenguaje de programación elegido. Así como también ver, un poco, como fueron implementados algunos aspectos de nuestro simulador de teclado.

El lenguaje utilizado nos provee de eventos, los cuales son procedimientos o funciones, que se ejecutan en determinadas ocasiones particulares. Por ejemplo un evento puede ser cuando se presiona una vez un "botón de comando" con el botón derecho del mouse, entonces se ejecuta el evento "click", o bien cuando cambia el estado de algunos de los controles se ejecuta el evento "change". De este modo cada uno de los controles en pantalla digamos que cumple una "función" de acuerdo al resultado o a las acciones que efectúen los demás sobre él. Así es como se encadena el hilo de ejecución. Vamos a ver de que manera se ejecutan los eventos cuando se presiona una tecla:

    1. Se escribe un carácter en el cuadro de texto, que representa al teclado.
    2. Se ejecuta el evento Change en el cual intentará poner el carácter presionado en el registro de la interfaz TTYIN.
    3. Entonces se ejecuta el evento Change del TTYIN, el cual enciende el botón de Listo.
    4. Entonces el evento Timer del control Timer, el cual es ejecutado en cada lapso de tiempo, ejecutará una serie de rutinas las cuales chequean los distintos flags de condición, y de acuerdo a ello se ejecutan los procesos correspondientes. En este caso lo que hará es asignar al puntero de instrucción un numero de instrucción valido para que en el siguiente ciclo comience a ejecutarse la rutina de servicio de interrupción. Podríamos atrevernos a decir, con mucho cuidado, que cada lapso de tiempo "" estaría representando "" los ciclos de ejecución de la CPU, en un sentido amplio de los mismos, es decir, desde el punto en que en ambos se chequean flags de condición los cuales condicionan el hilo de ejecución de la CPU.
    5. Durante la ejecución de la rutina de servicio, la prioridad de la CPU se eleva para que no entren otras interrupciones del teclado.
    6. Si se presionó una Retorno de Carro, entonces se ejecuta la rutina Line, la cual imprime en pantalla los caracteres almacenados en el buffer de memoria. La ejecución de esta rutina excede el contenido de este trabajo práctico, es por ello que se ejecuta diríamos "instantáneamente".
    7. En el retorno de la rutina de servicio, se restituyen los flags de condición, y continúan ejecutándose por lapsos de tiempo los eventos del Timer, hasta que haya algo que hacer nuevamente.

Puede verse alguno de los beneficios que la programación orientada a eventos nos proporciona para realizar este tipo de trabajos de simulación.