viernes, 9 de enero de 2009

El Reloj de Tiempo Real (RTC)

El MC 146818

En nuestra entrega sobre Gestión de Entrada/Salida realizamos la experiencia de programar el contador 8253 en forma directa a través de los puertos, es decir, por medio del BUS de la PC. En nuestro caso, esto está justificado, porque estudiamos la forma en que trabajan los servicios de E/S del Sistema Operativo. Sin embargo, en la práctica cotidiana, este tipo de acceso es raro ya que contamos precisamente con los servicios que nos ofrece el Sistema Operativo.


Fig. 1 El 6818 RTC

En esta ocasión vamos a estudiar el Reloj de Tiempo Real o RTC en inglés que también mencionamos en el artículo Gestión de Entrada/Salida, el MC 146818 (una versión del 6818) de Motorola. Pero en esta oportunidad vamos a emplear el servicio que ofrece BIOS Basic Input Output System (Sistema Básico de Entrada Salida) por medio de la Interrupción 1A. Recordemos que el BIOS está compuesto de código de máquina, es decir software, pero que reside en un chip de memoria ROM, por eso suele referirse genericamente a estas funciones/componente como ROM-BIOS. Esta combinación de código residente en una memoria ROM también suele denominársele FIRMWARE para distinguirlo del SOFTWARE. Los modelos de computadora tienen ROM-BIOS diferentes debido a que el BIOS es el que conoce los detalles de HARDWARE de los equipos en particular y almacena todas las direcciones de los puertos.


Fig. 2 El Reloj de Windows

La Interrupción Int 1Ah

Genéricamente esta interrupción permite el acceso al reloj interno de la PC (146818). Este reloj realiza un conteo de 1193180/65536 tics/segundo, esto es 18,2 tics por segundo (65536 es el número de cuentas entre 0000 y FFFF, es decir, un registro de 16 bits).

Fig.3 Primer Ejercicio: Leer el RTC

Como sabemos las interrupciones son procedimientos que reciben sus parámetros por medio de los registros (ver Ensamblador (Entrega 3)).

Leer el Reloj del Sistema

Se realiza la interrupción 1A con AH=0

En este caso, se usa AH el byte alto del registro AX y devuelve en CX:DX (los valores mayores en CX) el número de tics desde la medianoche a una razón de 18.2 tics por segundo o un tic cada 54.92 ms (milisegundos). Los valores estarán en hexadecimal, por lo que hay que convertirlos a decimal para su interpretación.

Primer Ejercicio

Para nuestro primer ejercicio (ver Fig. 3), Se recomienda realizar la lectura del reloj para obtener un valor relativamente grande (a menos que recientemente haya pasado la medianoche).

Abrimos una sesión de DOS (Inicio/Ejecutar command) y dentro de la ventana de DOS iniciamos DEBUG (C:\> DEBUG [INTRO]) e ingresamos lo siguiente:

-A
MOV AH,0
INT 1A
MOV AX,4C
INT 21
[INTRO]
-G 100
-p
-p

Aquí se leen los valores que aparecen en CD:DX y se interpretan con la calculadora de Windows en su versión científica, es decir, cargar los valores con la selección Hex y luego cambiar la selección a Dec.

-p
-p

Recuerden que Int 21 con AX=4C es la salida normal del programa y siempre deben usarla. Si tienen dudas respecto de debug, lean los artículos sobre lenguaje ensamblador en este BLOG.

Realizar un Cronómetro

Uno de los elementos mas útiles para la observación de eventos, ya sea en la ciencia como en los deportes es el cronómetro. En la programación, especialmente cuando trabajamos con protocolos, también es muy útil establecer límites de tiempo (timeout) para ciertas operaciones. En el caso de los protocolos de comunicación, se denomina “negociación” al establecimiento de contacto que generalmente comienza con una máquina que envía un byte ENQ (5h) INTERROGA y la otra máquina envía ACK (6h) ACEPTA o NAK (15h) No ACEPTA, etcétera. En estos casos, se establece un límite de tiempo en el que puede realizarse la respuesta y luego, por ejemplo, se envía un paquete.

Fig. 4 El Cronómetro en Assembler

Este tipo de "medición" es precisamente lo que se puede lograr si ponemos a cero del contador del Reloj de Tiempo Real y luego “leemos” el tiempo transcurrido, simpre recordemos que el reloj realiza 18.2 tics por segundo.

Poner a Cero el Reloj de Sistema

Se realiza la interrupción 1A con AH=1

Segundo Ejecicio

Para nuestro segundo ejercicio (ver Fig. 4), se recomienda abrir el reloj de Windows para contar 10 segundos antes de leer el valor que entrega el RTC. Los 10 segundos se deben contar a partir de que se envía la primera interrupción Int 1A hasta que se envía la segunda. A partir de allí se leen los registros CX:DX

Abrimos una sesión de DOS (Inicio/Ejecutar command) e ingresamos lo siguiente:
-A
MOV AH,1
INT 1A
MOV AH,0
INT 1A
MOV AX,4C
INT 21
[INTRO]
-G 100

-P (se ejecuta el MOV)

Esperamos a que el reloj de windows marque un minuto justo, por ejemplo 12:23 (ver Fig. 2) y oprimimos P nuevamente y se ejecuta el Int 1A.

-P (inmediatamente se ejecuta el MOV)

Esperamos que el reloj de windows marque que transcurrieron 10 segundos, por ejemplo 12:23:10 (ver Fig. 2) y oprimimos P nuevamente.

Fig. 5 Prueba del Cronómetro

Aquí leemos los valores que aparecen en CD:DX y los interpretamos con la calculadora de Windows en su versión científica, es decir, cargamos los valores con la selección Hex (hexadecimal) y luego cambiamos la selección a Dec (decimal).

Precisamente, observamos que en CD:DX tenemos 0000:00B6, lo que traducido a decimal es 182 que justamente corresponde a 18.2 x 10 tics del reloj. En mi trabajo profesional, antes de programar con los compiladores visuales utilicé muchísimo estas interrupciones de BIOS, tanto en Assembler como en leguajes C, Pascal y Quick Basic entre otros; en muy variadas aplicaciones, manejadores de dispositivos, protocolos de comunicación, etcétera.

Funciones de la Interrupción 1A de BIOS

AH = 00h Tics del día
AH = 01h Poner a Cero el Contador de Ticks
AH = 02h Leer la Hora del Reloj de Tiempo Real
AH = 03h Establecer la Hora del Reloj de Tiempo Real
AH = 04h Leer la Fecha del Reloj de Tiempo Real
AH = 05h Establecer la Fecha del Reloj de Tiempo Real
AH = 06h Establecer la Alarma del Reloj de Tiempo Real
AH = 07h Poner a Cero la Alarma del Reloj de Tiempo Real
AH = 08h Establecer el Modo de Encendido Activado del RTC
AH = 09h Leer la Hora y el Estatus la Alarma del RTC
AH = 0Ah Leer el Contador de Días del Temporizador del Sistema
AH = 0Bh Establecer el Contador de Días del Temporizador del Sistema

Hasta la Próxima,

Sergio Otaño

8 comentarios:

Anónimo dijo...

buenas mi nombre es manuel.....muchs gracias por el post.....llevaba tiempo buscando la forma de programar en RTC desde assembler....pro tngo una duda...como puedes mostrar los valores( en decimales) en la pantalla de la hora....y no se si la hora verdadera es la hora del sistema o es la hora real, pq son 2 interrupciones diferentes!!!:s
(estoy usando nasm)...

Sergio Otaño dijo...

Para mostrar los valores en la pantalla con notación decimal, debes emplear procedimientos estándar de Assembler. Con respecto a las definiciones de los sistemas de "Relojes" de la PC hay dos entradas de este Blog que pueden ser de interés: 1) Gestión de Entrada/Salida y 2) Concepto de Sistema Operativo. Este Blog está enfocado en cuestiones prácticas de implementación ya que sobre teoría hay superabundancia en Internet.

Miguel dijo...

Sergio, tienes un exelente blog, has hecho lo que hacia falta en la red que es enseñar las aplicaciones practicas del lenguaje emsablador

Randy Ortega dijo...

un saludo oye muy bueno este blog yo necesito hacer que mientras transcurra el cronometro vaya contando pasos(simulado con 2 teclas) y haga instantaneamente los calculos de velocidad y consumo calorico es q estoy haciendo una trotadora

Randy Ortega dijo...

lo malo es q muchos ejemplos aparecen en nasm o masm y y uso es tasmide

Sergio Otaño dijo...

En realidad, ninguno de los ejemplos está en Masm ya que todos se programan por medio de Debug.

demóstenes dijo...

No entiendo todo lo que has puesto pero me parece muy interesante. Tengo una duda, programando en ensamblador ¿se podría modificar el relor del sistema para que, por ejemplo, cuente un segundo a cada dos? ¿Y que ese hecho repercuta en todas las aplicaciones que leen el reloj?
Un saludo y gracias

Sergio Otaño dijo...

Tal como señala el articulo, el BIOS esta "grabado" en una ROM (memoria de solo lectura). Modificar el BIOS es posible, pero requiere del conocimiento del hardware y de la version del BIOS que esta en uso. Ademas, para grabar se requiere de un grabador de EPROMS y del software correspondiente. Recomiendo, en cambio, realizar ejemplos y ejercicios de assembler que se desarrollan en varios articulos del blog y que se pueden realizar sin riesgo para la PC.