PRÁCTICA 9: “Introducción a los Sistemas de Entrada/Salida” Arquitectura de Computadores 2º Curso de Ingeniería en Informática Curso 2006/2007 ENUNCIADO OBJETIVOS • • • • Consolidar los conocimientos adquiridos sobre los mecanismos de Entrada/Salida Aprender a programar dispositivos de E/S a bajo nivel Conocer la gestión de E/S en Linux Adquirir soltura a la hora de manejar datasheets DESCRIPCIÓN El alumno debe realizar un programa que simule el comportamiento de un reloj despertador. Se debe mostrar en todo momento la fecha y hora actual y, en caso de activarse la alarma programada, hacer sonar alguna “melodía” por el altavoz. Para conocer la fecha-hora del sistema se utilizará el Reloj de Tiempo Real (RTC) y para generar sonidos el timer conectado al altavoz del sistema. Reloj de Tiempo Real El Reloj de Tiempo Real (RTC) disponible en los PCs es el MC146818 (Motorola) o compatible (DS12887 de Dallas Semiconductor, etc.). Incluye un completo reloj con alarma, calendario, interrupción periódica, generador de onda cuadrada, etc. El RTC está diseñado para ser usado en un bus multiplexado: necesita dos accesos para realizar una lectura o escritura. En el primer acceso se coloca la dirección del registro a acceder y en el segundo se lee o escribe el dato. Para el primer acceso se utiliza el puerto 70h y para el segundo el puerto 71h. A continuación se muestra el mapa de registros del dispositivo (sólo las posiciones que nos interesan): Dirección (Hex) 00 02 04 06 07 08 09 0A 32 Contenido Segundos Minutos Horas Día de la semana Día del mes Mes Año (dos últimas cifras) Estado Año (dos primeras cifras) Mientras el RTC actualiza la fecha y hora del sistema (un breve lapso de tiempo cada segundo) los registros asociados (todos los que se muestran en la tabla menos el de estado) no se encuentran disponibles. Por ello, el registro de estado incluye un bit (7) que indica, cuando se pone a uno, que se está actualizando el reloj del sistema. La información correspondiente a la fecha y hora está codificada en BCD empaquetado (dos dígitos BCD en cada byte). El campo día de la semana está codificado de la siguiente manera: 1 para el lunes, 2 para el martes,… y 6 para el sábado. El domingo se representa con un 7 si el reloj está configurado como que la semana comienza en lunes ó 0 si comienza en domingo. 1 Altavoz del sistema El altavoz del sistema está conectado a un timer 8254 o compatible (8253, etc.) para poder generar diferentes sonidos (señales con diferente frecuencia). Este dispositivo dispone de 3 contadores que pueden ser configurados de 6 maneras diferentes (generador de frecuencias, generador de onda cuadrada, interrupción al final de cuenta, etc.). Cada contador dispone de una señal de reloj Clk, de una entrada Gate y de una señal de salida Out (ver Figura 1). En función del modo elegido para el contador el significado de las líneas será uno u otro. 8 A la CPU ___ WR RD Características CONTROL • • Clk Gate Out Contador 0 • Contador 1 • A1 A0 • Contador 2 Bus de datos de 8 bits Mapa de registro de cuatro posiciones: Un registro de control y tres contadores independientes entre sí. Se elige la posición mediante las señales de dirección A1 y A0 Los contadores son de 16 bits y la cuenta siempre es descendente Dispone de 6 modos distintos de funcionamiento Cada contador lleva tres señales: Clk (entrada): Señal de reloj externa o (no tiene por qué ser el de la CPU) Gate(entrada): (depende del modo) o Out (salida): (depende del modo) o Figura 1 El modo 3 permite generar una onda cuadrada cuyo periodo es el valor cargado en el contador. La señal Gate inicia la cuenta y la señal Out contiene la onda cuadrada. Para la configuración de los diferentes contadores el 8254 dispone de un registro de control. Se encuentra en la dirección 43h y su significado es el siguiente: Bit 7, 6 5, 4 3, 2, 1 0 Función Contador Acceso al contador 00: Latch 01: sólo el LSB 10: sólo el MSB 11: 1º el LSB y 2º el MSB, en dos accesos consecutivos Modo 0 → binario 1 → BCD Los contadores son de 16 bits, sin embargo, el bus de datos es de sólo 8 bits. Por ello, se requieren dos accesos consecutivos para actualizar su valor. Los contadores 0, 1 y 2 ocupan las posiciones 40h, 41h y 42h, respectivamente. El contador asociado al altavoz es el 2 (ver Figura 2). El bit 0 del puerto 61h es la entrada Gate y el bit 1 permite conectar la salida Out del contador al altavoz. Para generar un determinado sonido en el altavoz, debe configurar el contador 2 en modo 3, escribir en el contador el valor del periodo de la señal a generar (nota musical) y activar los bits 0 y 1 del puerto 61h. La frecuencia del reloj es 1193180Hz, por lo que para obtener una señal cuadrada de frecuencia f, hay que cargar en el contador el valor 1193180/f. A continuación se muestra una tabla con las frecuencias asociadas a una octava: NOTA Hz DO 262 RE 294 MI 330 2 FA 349 SOL 392 LA 440 SI 494 Figura 2 DESARROLLO DE LA PRÁCTICA Para la realización de esta práctica debe utilizarse el sistema operativo Linux (en concreto se usará el S.O. Fedora con sistema de escritorio KDE) y el lenguaje de programación C. El alumno se deberá posicionar en el directorio “practica” dentro de un terminal (una consola de comandos) y después deberá allí crear por ejemplo otro directorio para la práctica de E/S. En Linux se crea un directorio desde un terminal con el mandato mkdir pero también se puede hacer desde el escritorio con un navegador de archivos como por ejemplo el Konqueror. Para editar el código del programa fuente (.c) puede usar cualquiera de los editores disponibles en el entorno de escritorio tales como kedit o kwrite. Los puede lanzar desde su consola de comandos o terminal simplemente introduciendo kedit& ó kwrite&. Para compilar los programas de C utilice el compilador gcc de Linux. Ejemplo de uso: gcc mi_programa.c –o mi_programa En este caso el archivo ejecutable se llama mi_programa.out y el código fuente se haya en el archivo mi_programa.c. Para ejecutar un el archivo ejecutable en Linux deberá teclear el siguiente comando o mandato dentro de la consola de comandos: ./mi_programa Para poder acceder a los puertos a nivel de aplicación (no mediante un módulo) debe utilizarse la función iopl en el programa en C pasándole un 3 como único parámetro (utilice el comando man iopl en la consola de comandos para obtener más información o busque en Internet). La función iopl está incluida en la librería sys/io.h. La aplicación (programa ejecutable) debe ejecutarse con permisos de root (superusuario o administrador). Para obtener permisos de root debe usar el comando su en su terminal. Para ello debe teclear en su terminal “su nombre_superusuario”. El “nombre_superusuario” y la contraseña se proporcionarán en clase por el profesor. Una vez introducida la contraseña el alumno podrá comprobar en la consola como el símbolo del terminal cambia (pasa del $ al #). Para salir del modo superusuario basta con teclear el comando exit. Para acceder a los puertos el alumno dispone de las funciones inb y outb. Para poder utilizar ambas funciones, y las básicas de entrada salida, deberán instanciar en el programa las librerías sys/io.h y stdio.h respectivamente. Los prototipos de estas funciones se muestran a continuación: 3 Con la cabecera #include <sys/io.h> Æ unsigned char inb(unsigned short puerto); /* Lee un valor de 8 bits por el puerto especificado y lo devuelve */ void outb (unsigned char valor, unsigned short Puerto); /* Escribe un valor de 8 bits en el puerto especificado */ Con la cabecera #include <sys/io.h> Æ void printf (“ %s … %02x … \r”, “lunes”, “13”, …); /* Escribe por pantalla un texto, en este caso un string y dos caracteres ASCII */ void scanf (“%d”, &num); /* Lee por teclado un valor, en este caso un número entero, y lo guarda en la variable num de tipo int */ El alumno debe programar una aplicación que muestre permanentemente la fecha y hora del sistema con el siguiente formato “Dia_semana, DD/MM/AAAA – HH:MM:SS”. Debe utilizarse el retorno de carro (\r) en el printf para conseguir que la fecha-hora se actualice en la misma línea. Además deberá a continuación llamar a continuación a la función fflush con el parámetro stdout para que se visualice por pantalla la actualización efectiva de la fecha y hora del sistema. La función fflush está incluida en la librería stdio.h. Además, cuando se inicie la aplicación debe permitirse la introducción de la hora a la que queremos que se active la alarma (HH:MM). Cuando esto ocurra, debe sonar alguna melodía (si el alumno es incapaz de componer alguna melodía, basta con que haga sonar las notas de una octava) . Conforme el alumno va realizando la aplicación, debe contestar el siguiente cuestionario. CUESTIONARIO 1. ¿Qué diferencias existen entre la función iopl y ioperm? Para ello utilizar el comando “man” en linux, o bien buscar en Internet) ¿Podría haberse utilizado en este caso ioperm en vez de iopl? 2. Escribe el trozo de código en C que permita leer el día de la semana. 3. Para imprimir la fecha y hora del sistema, ¿es necesario convertir los valores de BCD empaquetado a binario? Justifique su respuesta. 4. Suponga que deseamos hacer un programa que al iniciarse muestre la hora del sistema e inmediatamente después finalice. Si verificamos el estado antes de leer la hora del sistema, podría ocurrir que el RTC no se esté actualizando en ese momento pero sí un instante después (en la lectura de la hora, los minutos o los segundos), por lo que la lectura sería errónea. Proponga alguna solución a este problema. 5. Escribe tres funciones en C que sirvan para (a) configurar el timer, (b) activar y (c) desactivar la alarma. La alarma puede ser simplemente hacer sonar la nota DO, por ejemplo. Utiliza los siguientes prototipos: void configurar_timer() void alarma_on() void alarma_off() 6. ¿Cómo puede hacerse más eficiente desde el punto de vista del uso de CPU la actualización del reloj? ¿Y la alarma? Explicar detalladamente el procedimiento haciendo uso de los datasheets (el RTC DS12887) que se encuentran disponibles en la página web de la asignatura. 4