next up previous
Siguiente: 7. Conclusiones Superior: Hospedaje Linux de multicomputadores Anterior: 5. El hardware de

Subsecciones

6. Uso del driver

El driver, exaustivamente documentado en [IRA00], es un módulo cargable ([RUB98]) denominado Módulo QPC/C40S, según muestra la Fig. 14.



\resizebox*{5cm}{3cm}{\includegraphics{imagenes/pu_modulo.ps}}



Fig. 14. Ubicación del driver en Linux 2.0.x.

6.1. Definción de interfaz

Nuestro driver ofrece una interfaz a los procesos de usuario basada en dispositivos para gestinar los recursos de la QPC-C40S. Soporta los siguientes:

La interfaz /dev/lia permite realizar operaciones de lectura y escritura con un tamaño de datos múltiplo de 4 octetos. El resto de los dispositivos sirven para acceder a la memoria DPRAM, que se ha modelado como un disco RAM. Hay cuatro dispositivos dedicados a la memoria de intercambio, porque el driver realiza una división lógica de esta memoria en tres regiones, cada una de ellas es manejado por el dispositivo dpramX correspondiente sin solapamiento; excepto dpram0, que sirve para acceder a toda la memoria DPRAM en modo crudo. El número de divisiones lógicas de la memoria DPRAM y su tamaño puede variar, dependiendo de las necesidades de las aplicaciones que se ejecuten.

Las operaciones de lectura y escritura en estos dispositivos hacen accesible la memoria de intercambio a los procesos de usuario. El tamaño de los datos a intercambiar está en función del tamaño de cada partición. Las llamadas al sistema que soporta el driver son las siguientes:

La llamada lseek sólo es aplicable a los dispositivos DPRAM, cada uno de ellos puede desplazar el puntero virtual en todo su rango lógico. Dpram0 , sin embargo, puede desplazar su puntero virtual en todo el rango de la memoria DPRAM.

Las operaciones read y write se pueden utilizar con todos los dispositivos. El tamaño de los datos puede ser cualquier número de octetos, excepto para LIA, que ha de ser múltiplo de cuatro. Estas llamadas son bloqueantes tanto para LIA como para DPRAM, excepto en dpram0. En LIA el proceso invocante es bloqueado si los datos que pide no están disponibles (en una operación de lectura), o cuando el dispositivo no está vacío a fin de recibir datos (en las operaciones de escritura).

El criterio para bloquear los procesos en los dispositivos dpramX se implementa con semáforos, que informan sobre quién es el propietario temporal de la memoria correspondiente. La propiedad de la memoria alterna entre el DSP y el PC cuando uno escribe y el otro lee. Por ejemplo, el procesador I del DSP escribe una cadena de caracteres en /dev/dpram1, entonces dicho procesador no podrá volver a escribir hasta que alguien (lo más normal es que sea el PC) lea de /dev/dpram1 momento en el que se cambia el semáforo.

La llamada ioctl está indicada para realizar operaciones de configuración sobre un dispositivo. Estas operaciones son dos, el reset y la inicialización de la tarjeta, las cuales configuran la tarjeta usando los registros de entrada salida. Por ejemplo:

/*Reset de la tarjeta.*/

if(ioctl(LIA, QPCC40S_IOCTL_RESET) != 0){

  printf("Imposible reset QPC\n");

  exit (1);

}

 

/*Inicializar la tarjeta.*/

if(ioctl(LIA, QPCC40S_IOCTL_INIT) != 0){

  printf("Imposible inicializar QPC\n");

    exit (1);

}

El parámetro LIA es un descriptor del dispositivo LIA, el segundo parámetro especifica la operación deseada. La llamada ioctl también se aprovecha para que los procesos de usuario puedan leer y escribir cualquier registro de entrada salida de la tarjeta. Para esto se utiliza el tercer parámetro de la llamada ioctl. Con él se accede a una estructura con dos campos: el número de registro y su valor. Por ejemplo, con las siguientes instrucciones se puede leer el registro de estado de la QPC:

DatosIoctl.NumReg = QPC_R_STATUS;

if(ioctl(descriptor,

     QPCC40S_IOCTL_LEER_REGISTRO,

     &DatosIoctl) != 0)           {

  printf("Imposible leer Reg. Estado\n");

  exit (1);

}

La variable descriptor es un descriptor de cualquier dispositivo atendido por el driver. La variable DatosIoctl es una estructura de la siguiente forma:

struct Ioctl_Estructura{

        unsigned short  NumReg;

        unsigned short  ValorReg;

};

Cuando retorna, la llamada ioctl el campo ValorReg de la estructura contendrá el valor del registro de estado de la tarjeta.

Las macros

QPCC40S_IOCTL_LEER_REGISTRO,

QPCC40S_IOCTL_RESET,

QPC_R_STATUS...

y la estructura Ioctl_Estructura están definidas en el fichero de cabecera del driver: qpcc40s.h, por lo que dicho fichero debe ser incluido en los programas de usuario.

6.2. La biblioteca de usuario QpcLib

Hemos desarrollado una biblioteca de usuario que implementa utilidades de gestión de la QPC-C40S, según muestra la Fig. 15. De momento, la utilidad más importante es el manejo de los ficheros ejecutables en formato COFF ([GIN98]), a fin cargarlos en los procesadores C44. Se espera que con el tiempo esta biblioteca vaya aumentando sus utilidades, a medida que ganemos experiencia en este trabajo.



\resizebox*{5cm}{3cm}{\includegraphics{imagenes/qpclib.ps}}



Fig. 15. La biblioteca QpcLib facilita el manejo de la tarjeta a los procesos de usuario.

6.2.1 Gestión de errores

Cuando una función de la biblioteca encuentra un error devuelve un valor negativo, su valor absoluto especifica el tipo de error producido. Esta clasificación de los errores se ha hecho imitando la biblioteca NetAPI de Blue Wave. Cada error tiene una macro asociada en el fichero de cabecera de la biblioteca (qpclib.h), y se ha implementado una función que a partir de ese código devuelve una cadena de texto explicativo del error:

char* QpcLib_TextoDeError(int);

Por ejemplo, si se produce un error al cargar el programa COFF en el C44, se usa la función anterior para dar una información más ampliada al usuario:

/* Cargar el programa C40 deseado en el

 * procesador I                       */

if((ret = QpcLib_CargarPrograma(LIA,

           argv[1])) != QPCLIB_E_NOERR){

  printf("Error al cargar %s en LIA: ",

            argv[1]);

  printf("\n%s\n",

            QpcLib_TextoDeError(ret));

  exit(1);

}

6.2.2 Manipulación del formato COFF C40

El compilador de Texas Instruments para la arquitectura C40 genera los programas en formato COFF. Esto nos obliga a comprender este formato de ficheros objeto a la hora de usar el driver para cargar programas en los procesadores C44. No se trata de comunicar el fichero COFF, tal cual, al procesador, sino interpretar dicho fichero y comunicar la información precisa. La biblioteca QpcLib ofrece la siguiente función para realizar este trabajo:

int QpcLib_CargarPrograma (int, char *);

El primer parámetro es un descriptor del dispositivo /dev/lia, la función supone que ya está abierto y lo utiliza para escribir la información extraída del fichero COFF. El segundo parámetro es el camino para encontrar el fichero COFF en el sistema. Devuelve un código de error de la biblioteca.

Esta forma de cargar programas en un C40 obliga a tener un sistema operativo con sistema de ficheros. Puede ocurrir que el PC huésped de la tarjeta ejecute un sistema de tiempo real sin sistema de ficheros. Para solucionar esto, las rutinas que interpretan el formato COFF (fichero coff.c de la biblioteca) están controladas por una directiva de compilación que, en vez de escribir el ejecutable C40 sobre el dispositivo LIA, lo escriben en un fichero de texto, en forma de secuencia de números, de esta forma:

unsigned long ArrayCoff[] = {

  796360720L   /* 0x2F778010 */,

  1038852176L  /* 0x3DEBA050 */,

  1L              /* 0x1        */,

  ......       ........

  3145728L     /* 0x300000    */

};

Los números se escriben formando la declaración de un vector, con la intención de que el fichero resultante pueda ser incluido en los fuentes de un programa. Ese programa, a la hora de cargar el ejecutable en el C40, no usaría la función QpcLib_CargarPrograma, sino que escribiría en el dispositivo LIA cada uno de los números de este vector. De esta forma no se necesita sistema de ficheros para cargar un ejecutable en los procesadores DSP. Para ello hay que compilar la biblioteca QpcLib con la opción coff_to_array:

make coff_to_array

De esta forma, el fichero coff.c de la biblioteca se transforma en un ejecutable llamado coff_to_array, que admite los siguientes parámetros:

coff_to_array Nombre_Fichero_COFF [Nombre_Fichero_Destino]

El primer parámetro es el fichero objeto en formato COFF, tal como lo deja el enlazador de Texas Instruments. El segundo parámetro es el nombre del fichero donde escribir el vector de números. Si se omite, se escribe en un fichero llamado array.hh.


next up previous
Siguiente: 7. Conclusiones Superior: Hospedaje Linux de multicomputadores Anterior: 5. El hardware de

Download this document: [src.tar.gz][ps.gz][html.tar.gz][dvi.gz]

Congreso HispaLinux 2000