• No se han encontrado resultados

Estado y Actualización de Registros

6. EXPERIMENTOS DE VALIDACIÓN

6.3 Estado y Actualización de Registros

6.3.1 Formato del mensaje

Como se ha mencionado antes, para implementar las funciones de este apartado se tendrán que añadir nuevas líneas de código en el programa servidor. Al igual que en el apartado anterior habrá que decidir que cadena de caracteres se espera en el servidor para la ejecución de estas funciones:

 Para la función de aporte de información sobre el valor del registro del timer se configurará para detectar la letra “T” en mayúscula.

 Para las funciones de lectura y escritura de registros de memoria se usarán dos cadenas distintas. Para la primera función se usará la cadena “RR0xXXXXXXXX” en la que “RR” hace mención a Register Read, “0x” hace mención a que el número que viene a continuación se encuentra en hexadecimal y “XXXXXXXX” es la dirección del registro que se quiere leer, en hexadecimal. Para la segunda función la cadena será “RW0xXXXXXXXXYYYYYY” en la que “RW” hace mención a Register Write, “0x” y “XXXXXXXX” se usan para lo mismo que en la primera función y “YYYYYY” es el valor que se quiere introducir en el registro, en decimal.

6.3.2 Código para la Lectura del Timer

Una vez decidida la cadena a detectar para la ejecución de esta función se procederá a incluir el código.

Para empezar, se incluirá una biblioteca creada por Xilinx para poder controlar el valor de los timers, que es xtime_l.h:

Si se abre la biblioteca se podrá observar que se encuentra declarada una función para la lectura del registro de cuenta del timer. Esta función es XTime_GetTime( ), a la cual habrá que pasar como parámetro un puntero a una variable de tipo entero sin signo de 64 bits, introduciendo la función el valor del registro en la variable. Para ello declararemos la variable como se indica:

Aunque podría haberse declarado directamente como “u64 tiempo”, pero si se desease hacer uso de la función de lectura del timer en alguna otra parte del código, quedará más visible declarar las variables siempre con el formato “XTime” definido en la biblioteca xtime_l.h.

Una vez que se tiene la variable sólo quedará hacer uso de la función, por lo que se incluirán las siguientes líneas de código dentro de la función process_echo_request( ):

Figura 6.3.1: Función XTime_GetTime().

Figura 6.3.2: Validación de lectura del timer con el cliente programado

Mediante este código la variable “recv_buf” será una cadena de caracteres con el valor del registro, que se enviará al cliente por la conexión establecida. Para comprobar el funcionamiento del código se hará uso, al igual que en el apartado 6.2, del programa cliente desarrollado en el apartado 6.1:

6.3.3 Estado y Actualización de registros de memoria

En este apartado se aprenderá a leer y escribir en los propios registros mapeados en la memoria del microprocesador. En este caso las modificaciones en el servidor son válidas para ambos microprocesadores ARM y MicroBlaze.

Para poder llevar a cabo la programación habrá que saber de qué funciones se dispone. Si se abre la biblioteca xil_IO.h se podrá ver que se dispone de funciones específicas para ello, al igual que en los ejemplos anteriores. Se incluirá, por tanto, esta biblioteca:

En la biblioteca se verá que hay distintas funciones para la lectura y escritura de registros según el tamaño de la palabra del microprocesador. Este ejemplo se hará sobre un microprocesador ARM de 32 bits (al igual que el MicroBlaze), pero habrá que tener en cuenta que otros microprocesadores con otro tamaño de palabra, como, por ejemplo, el soft processor PicoBlaze que cuenta con un bus de datos de 8 bits. Se usarán, por tanto, las funciones Xil_In32( ) y Xil_Out32( ) para leer y escribir en registros respectivamente. La primera función devolverá el valor del registro cuya dirección se le pasará como parámetro, devolviendo el valor con el formato “long unsigned int”. La segunda

Figura 6.3.3: Variables a usar para lectura y escritura de registros.

Figura 6.3.4: Código para lectura y escritura de registros.

función es de tipo “void”, por lo que no devolverá ningún dato y únicamente escribirá en la dirección del registro pasada como primer parámetro el valor pasado como segundo parámetro a la función.

Antes de desarrollar el código declararemos las variables:

Las variables que no estaban ya declaradas son:

 “*modo”: para distinguir entre el modo Read y el modo Write. En este caso solo se leerá un carácter, por lo que se podría declarar como “char” sin tener que ser un puntero, pero se dejará así por posibles cambios futuros en los que se incluyan nuevos modos reconocibles como cadenas de caracteres.

 “valoru” y “numero”: se usarán para convertir el numero pasado como cadena de caracteres a un entero de 32 bits.

 “i” y “l”: servirán como variables para llevar a cabo un bucle en el que se recorrerán únicamente los caracteres “YYYYY” para convertirlos a enteros. Teniendo ya las variables declaradas el código quedará de la siguiente forma:

Puede observarse que para convertir el número a introducir en el registro a un “long int” se hace uso de la función pow( ). Esta función es propia de la biblioteca math.h, por lo que habrá que incluirla también:

La demostración a realizar será semejante a la realizada en los anteriores apartados, usándose el mismo programa cliente. Para comprobar que ambas funciones se realizan correctamente se realizará la siguiente secuencia:

Leer el registro 0x12341234 –> Escribir en ese mismo registro el valor 167 –> Leer de nuevo el mismo registro para comprobar que se ha actualizado el valor:

El código completo del servidor con las tres funciones implementadas puede encontrarse en los anexos.

CAPÍTULO 7