Escolar Documentos
Profissional Documentos
Cultura Documentos
DRIVERWORKS
El asistente de DriverWorks
Para iniciar Visual C++ con soporte para DDK utilizaremos: Programas->Compuware
DriverStudio->Tools->DDK Build Settings(SetDDKGo) ->launch program.
A continuacin se explican los pasos seguidos para generar el driver de la FPGA; algunos
de los pasos son especficos para PCI, y otros son comunes a todos los drivers que se desarrollen
con DriverWorks.
PASO 1
Escogemos ruta y nombre para el driver.
PASO 2
En nuestro caso el tipo de driver a utilizar es WDM Driver; puesto que el driver que se
desea conseguir es el ms genrico posible en Windows.
PASO 3
WDM Function Driver: nuestro driver va a controlar un dispositivo hardware directamente,
no a travs de otro driver.
PASO 4
Bus PCI. Rellenamos los datos del fabricante y dispositivo. En nuestro caso:
PASO 5
Establecemos los nombres para la clase que se va a generar, y el nombre de fichero.
PASO 6
Dependiendo de lo que se haya implementado en la placa. Las opciones marcadas por
defecto crean funciones de lectura y escritura genricas. Quitaremos read y write, puesto que el
dispositivo que tenemos para realizar ejemplo se puede leer y escribir en diferentes direcciones,
por lo que las funciones de lectura y escritura genricas no tienen mucho sentido.
PASO 7
Si utilizamos la primera opcin, las peticiones que se hagan al driver se atendern
directamente, en lugar de encolarlas. En caso de elegir encolar las peticiones en el cdigo
generado se encontrarn las sentencias necesarias para ir pasando de una peticin a la siguiente
en la cola, lo cual corresponde a las siguientes opciones.
PASO 8
Parmetros que se guardarn en el registro de windows. El que viene por defecto se puede
dar por bueno.
PASO 9
En este paso es donde definiremos los recursos que utilizar nuestro dispositivo.
Pestaa Resources
Aadiremos tantos IO Ports como direcciones base tengamos contempladas para
nuestro dispositivo; en nuestro caso aadiremos un IO Port con la direccin base 0 (los
dispositivos WDM son plug and play, y la direccin real se asignar; aqu se pone el ndice
de la direccin base a utilizar.).
Pestaa Interface
Lo normal es utilizar el interfaz WDM, definiendo el class GUID, usndose el que
define el propio asistente. El interfaz de enlace se utiliza cuando se hace un driver ms
genrico, para sistemas operativo que no utilizan el WDM para crear drivers
Pestaa Buffers
Siempre he utilizado Direct, puesto que nuestra placa cuando se desea leer o
escribir en un registro se desea hacerlo en un instante determinado; es decir, la lectura y la
escritura son directas. Slo se utilizara BUFFER si deseamos crear una pequea reserva
de memoria para realizar a travs e ella toda la transferencia
Pestaa Power
Aqu escogeremos si el driver manejar el estado de energa de la placa, es decir;
qu hacer al iniciarla, qu hacer si se va a suspender, qu hacer al recuperarse, etc.
PASO 10
Aqu aadiremos todas las funciones que se utilizarn para acceder a la placa; en este
paso conviene pensar bien todas las operaciones que se desean aadir, aunque se incluyan
algunas que despus no se utilicen, puesto que despus en el cdigo es muy fcil cometer errores
al aadir una nueva funcin (ver apartado Cmo aadir una nueva funcin de control desde el
cdigo fuente?).
Al aadir desde el asistente una nueva IOCTL, se nos pedirn los siguientes parmetros:
El nombre de la funcin.
El mtodo. En los tres modos que se muestran a continuacin, viene implementado parte
del acceso a los parmetros pasados y al lugar donde dejar el resultado; lo nico que
habr que hacer es leer lo que nos interese, y proporcionar los resultados que nos
interese. Los modos son:
o
Neither (En este modo, y bajo el punto de vista de DriverWorks se utilizar un tercer
Buffer; de todos modos tambin debe venir implementado parte del acceso).
El tipo de acceso:
o
PASO 11
Normalmente en esta pestaa se pide que genere una aplicacin de prueba, que haga una
seal en el punto de entrada del driver, que genere cdigo para depuracin (Trace Code), se
cambia el smbolo que se utilizar para etiquetar las reas de memoria que el driver reserve, de
manera que haya algo que se entienda mejor (tener en cuenta en este punto que la etiqueta que
se ponga aqu debe ir escrita al revs). Se debe quitar la opcin de la configuracin de 64 bits,
puesto que no tenemos de momento necesidad de drivers para un ordenador de 64bits de ancho
de palabra de datos. Tras este ltimo paso hacemos click en Finish y se nos generar el cdigo
fuente segn todas las opciones antes proporcionadas.
entrada/salida de la funcin los tenemos en un buffer que est en I.IoctlBuffer(); para obtener los
de entrada simplemente definiremos un puntero y haremos un cast a I.IoctlBuffer para asignarlo a
este puntero, por ejemplo:
ULONG *inbuffer=(ULONG *)I.IoctlBuffer();
variable_iorange->outb(ULONG
ByteOffset,
PUCHAR
Buffer,
ULONG
Operaciones con palabras (mismo funcionamiento que las anteriores pero lee datos
de 16bits):
Operaciones con long (mismo funcionamiento que la anterior pero lee datos de
32bits):
Una vez hecho esto buscamos la funcin DeviceControl(KIrp I); cuyo cuerpo tendr una
sentencia switch, en la que aadimos un nuevo caso llamado como nuestro IOCTL, y dentro del
cual llamamos a la funcin definida anteriormente.
NOTA: para depurar el funcionamiento interno de cualquier parte del driver podemos
mostrar mensajes del sistema utilizando una instruccin del tipo t<<Mensaje a mostrar<<EOL;
para ver estos mensajes utilizaremos la herramienta DriverMonitor que viene en Compuware
DriverStudio; esta herramienta suele estar en: Programas->Compuware DriverStudio->Tools>DriverMonitor.
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if(hDev == INVALID_HANDLE_VALUE)
*pError = GetLastError();
return hDev;
}
CreateFile
CREATE
Create
ReadFile
READ
Read
WriteFile
WRITE
Write
DeviceIoControl DEVICE_CONTROL
DeviceControl
CloseHandle
CLOSE
Close
CLEANUP
CleanUp
if (!DeviceIoControl(hDevice,
IOCTL_READ_BYTE,
bufInput,
IOCTL_INBUF_SIZE,
bufOutput,
IOCTL_OUTBUF_SIZE,
&nOutput,
NULL)
)
{
Exit(1);
}
CloseIfOpen();
return bufOutput[0];
Abrimos un nuevo proyecto en Visual C++, del tipo Win32 Dinamic-Link Library;
escogeremos del tipo de proyecto A simple DLL project. Esto crea un proyecto de
DLL con un fichero de cdigo fuente que tiene el mismo nombre que el proyecto.
Tambin genera un fichero stdafx.cpp; que es necesario, pero normalmente no
necesitars editarlo.
Cada DLL debe tener una funcin llamada DllMain, que ser el punto de entrada a
la DLL; a no ser que se necesite una inicializacin compleja, o la DLL sea para un
nico propsito, bastar con la funcin creada al crear el proyecto. En caso
contrario, complete la funcin.
3. Exportar smbolos.
Para podder acceder a las funciones de la DLL desde una aplicacin es necesario
indicar al compilador que exporte los smbolos deseados.
Para evitar que Visual C++ compile las funciones a modo C++, declararemos todas
las funciones a exportar como extern C en la declaracin de la funcin.
extern C int suma(int x, int y);
int y);
...
extern C __declspec(dllexport) int __stdcall suma(int x,
int y)
{
...
}
Una vez que tenemos escrito el cdigo, las funciones a exportar declaradas como
tales, y establecida la convencin de llamada a funciones, ests listo para construir
la DLL. Ve al men Build->Build <tu proyecto>. Debera compilar y enlazar la
DLL.
2. PIODIO_InputByte
Recoge un byte de entrada del dispositivo. Parmetros:
3. PIODIO_OutputByte
Escribe un byte en el dispositivo. Parmetros:
4. PIODIO_OutputMatrixDLL
Escribe una matriz en el dispositivo. Parmetros:
wIndexAddr: offset del registro donde se escribe el ndice que recorre la matriz.
NOTA: por compatibilidad con LabView la matriz debe ser bidimensional, pero slo
utilizaremos la primera fila, se considerarn datos tiles a partir de la 4 posicin.
void __stdcall PIODIO_OutputMatrixDLL(unsigned long
wPortAddr,unsigned long wIndexAddr, unsigned long width, unsigned long
5. PIODIO_InputMatrixDLL
Lee una matriz del dispositivo. Parmetros:
wIndexAddr: offset del registro donde se escribe el ndice que recorre la matriz.
NOTA: por compatibilidad con LabView la matriz debe ser bidimensional, pero slo
utilizaremos la primera fila, se considerarn datos tiles a partir de la 4 posicin.
void __stdcall PIODIO_InputMatrixDLL( unsigned long wPortAddr,
unsigned long wIndexAddr, unsigned long width, unsigned long height,
short int **bInputValue);
6. PIODIO_Output1DArray
Pasa un array de 1dimension al dispositivo. Parmetros:
wIndexAddr: offset del registro donde se escribe el ndice que recorre el array.
7. PIODIO_Input1DArray
Lee un array de 1dimension del dispositivo. Parmetros:
wIndexAddr: offset del registro donde se escribe el ndice que recorre el array.