Windows Embedded CE 6.0
Developer Guide for Exar PCI UARTs
Revision: 1.0 – April 2007.
The Windows Embedded CE 6.0 driver support for Exar’s PCI UART family of devices (XR17C152/154/158, XR17D152/154/158 and XR17V252/254/258) is achieved by 3 sets of .dlls, viz, xrpci.dll, xrserial.dll and xrisr.dll. (In Windows CE, the drivers contain the extension as .dll.) This package supports any number of cards.
Xrpci.dll:
This is a kind of class driver which loads for the PCI card and depending on the device like 0x152, 0x154, 0x158, 0x252, 0x254 and 0x258 loads the required number of xrserial.dll, each per port available and also requests and allocates the required memory and interrupt resources for each port. The initialization of this driver thus loads the xrserial.dll and the de-initialization closes and clears all the resources that were acquired during the init.
Xrserial.dll:
This driver is loaded for each port in the card as a separate instance with unique resources and memory area. This driver follows the standard Windows CE serial interface with standard MDD (Model Device Driver) interface exposed to the user level and has Exar specific Platform Dependent Driver interface that is specific to Exar UARTs. This driver connects or attaches the ISR for its System Interrupt. Thus each xrserial.dll driver will load its own instance of xrisr.dll.
Xrisr.dll:
This is the Interrupt Service Routine driver for the UARTs. This driver follows the same conventions of CE’s standard ISR driver.
Implementation through Microsoft Visual Studio 2005 integrated with Platform
Builder CE 6.0:
The developer should follow these steps for incorporating the driver into his platform. These steps are tested with Microsoft Visual Studio 2005.
Create XRPCI driver in your existing platform project:
Create XRISR driver in the platform:
Create XRSERIAL driver in the platform:
NOTE:
If all the above steps are done successfully, the platform can be built by “Build Solution” option in Visual Studio or by any other Build method that you always do to build Windows Embedded CE 6.0 project. With this newly created CE 6.0 image file, the system will find the Exar card and all the ports should be enumerated. User should check the registry to check the “COMx:” for the proper value to open the ports through CreateFile API in the user level application. To check whether the ports are working are not, the user can use the Exar supplied xrCEgui.exe tool.
IOCTL
support in driver for special features:
Windows CE 6.0 PCI UART Driver set has support for special features in the form of IOCTLs, which can be accessed from applications using Windows CE API, DeviceIoControl. The supported IOCTLs are;
IOCTL_XR17C15X_ENABLE_HWFLOWCONTROL
IOCTL_XR17C15X_DISABLE_HWFLOWCONTROL
IOCTL_XR17C15X_ENABLE_SWFLOWCONTROL
IOCTL_XR17C15X_DISABLE_SWFLOWCONTROL
IOCTL_XR17C15X_ENABLE_IR
IOCTL_XR17C15X_DISABLE_IR
IOCTL_XR17C15X_ENABLE_SLEEPMODE
IOCTL_XR17C15X_DISABLE_SLEEPMODE
IOCTL_XR17C15X_ENABLE_INTERNAL_LOOPBACK
IOCTL_XR17C15X_DISABLE_INTERNAL_LOOPBACK
IOCTL_XR17C15X_ENABLE_AUTORS485
IOCTL_XR17C15X_DISABLE_AUTORS485
IOCTL_XR17C15X_CONFIG_REG_READ
IOCTL_XR17C15X_CONFIG_REG_WRITE
The sample code to use these
IOCTLs in an application:
Step 1: Include the
declarations below in an appropriate header file.
// All Windows CE specific EXAR IOCTL codes and the related data types are defined here
// the IOCTL index starts from 50 (in pegdser.h the last ioctl index ends at 25)
#define IOCTL_XR17C15X_ENABLE_HWFLOWCONTROL CTL_CODE(FILE_DEVICE_SERIAL_PORT,50,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_XR17C15X_DISABLE_HWFLOWCONTROL CTL_CODE(FILE_DEVICE_SERIAL_PORT,51,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_XR17C15X_ENABLE_SWFLOWCONTROL CTL_CODE(FILE_DEVICE_SERIAL_PORT,52,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_XR17C15X_DISABLE_SWFLOWCONTROL CTL_CODE(FILE_DEVICE_SERIAL_PORT,53,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_XR17C15X_ENABLE_IR CTL_CODE(FILE_DEVICE_SERIAL_PORT,54,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_XR17C15X_DISABLE_IR CTL_CODE(FILE_DEVICE_SERIAL_PORT,55,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_XR17C15X_ENABLE_SLEEPMODE CTL_CODE(FILE_DEVICE_SERIAL_PORT,56,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_XR17C15X_DISABLE_SLEEPMODE CTL_CODE(FILE_DEVICE_SERIAL_PORT,57,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_XR17C15X_ENABLE_INTERNAL_LOOPBACK CTL_CODE(FILE_DEVICE_SERIAL_PORT,58,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_XR17C15X_DISABLE_INTERNAL_LOOPBACK CTL_CODE(FILE_DEVICE_SERIAL_PORT,59,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_XR17C15X_ENABLE_AUTORS485 CTL_CODE(FILE_DEVICE_SERIAL_PORT,60,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_XR17C15X_DISABLE_AUTORS485 CTL_CODE(FILE_DEVICE_SERIAL_PORT,61,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_XR17C15X_CONFIG_REG_READ CTL_CODE(FILE_DEVICE_SERIAL_PORT,62,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_XR17C15X_CONFIG_REG_WRITE CTL_CODE(FILE_DEVICE_SERIAL_PORT,63,METHOD_BUFFERED,FILE_ANY_ACCESS)
typedef struct /* Software Flow Control Enable Options*/
{
BOOL custom; /* if YES, please specify Xon/Xoff chars */
BYTE One_or_Two_Char; /* if 1 - and custom-Yes, specify Xon1 and Xoff1 chars. If 2 and custom-Yes, specify both Xon1/Xoff1 and Xon2 and Xon2 */
BYTE Xon1;
BYTE Xoff1;
BYTE Xon2;
BYTE Xoff2;
} SW_FLOW_CONTROL_PARAMS;
typedef struct
{
unsigned char bReg;
unsigned char bData;
} CONFIG_WRITE, *PCONFIG_WRITE;
Step 2: Include the below code in an appropriate C/C++ file
{
BOOL Status;
DWORD dwIoControlCode;
PVOID pInBuffer, pOutBuffer;
DWORD nInBufferSize, nOutBufferSize, cbReturned;
//
// all input/output variables for whole function scope are defined here
//
SW_FLOW_CONTROL_PARAMS SWFCParams;
BOOL bInvert;
UCHAR ucTemp1, ucTemp2;
CONFIG_WRITE CfgWrite;
pInBuffer = pOutBuffer = NULL;
nInBufferSize = nOutBufferSize = 0;
switch(dwIoCtlCodeIndex)
{
case 0: //ENABLE_HWFLOWCONTROL
{
dwIoControlCode = IOCTL_XR17C15X_ENABLE_HWFLOWCONTROL;
}
break;
case 1: //DISABLE_HWFLOWCONTROL
{
dwIoControlCode = IOCTL_XR17C15X_DISABLE_HWFLOWCONTROL;
}
break;
case 2: //ENABLE_SWFLOWCONTROL
{
SWFCParams.custom = TRUE; // FALSE if you want default
SWFCParams.One_or_Two_Char = 2;
SWFCParams.Xoff1 = 0x13;
SWFCParams.Xoff2 = 0x14;
SWFCParams.Xon1 = 0x11;
SWFCParams.Xon2 = 0x12;
pInBuffer = &SWFCParams;
nInBufferSize = sizeof(SW_FLOW_CONTROL_PARAMS);
dwIoControlCode = IOCTL_XR17C15X_ENABLE_SWFLOWCONTROL;
}
break;
case 3: //DISABLE_SWFLOWCONTROL
{
dwIoControlCode = IOCTL_XR17C15X_DISABLE_SWFLOWCONTROL;
}
break;
case 4: //ENABLE_IR
{
bInvert = TRUE; // FALSE if you don't want invert
pInBuffer = &bInvert;
nInBufferSize = sizeof(BOOL);
dwIoControlCode = IOCTL_XR17C15X_ENABLE_IR;
}
break;
case 5: //DISABLE_IR
{
dwIoControlCode = IOCTL_XR17C15X_DISABLE_IR;
}
break;
case 6: //ENABLE_SLEEPMODE
{
// This will put all the channels into sleep
// This operation can only be called from the
// first Channel's COM port handle
dwIoControlCode = IOCTL_XR17C15X_ENABLE_SLEEPMODE;
}
break;
case 7: //DISABLE_SLEEPMODE
{
// This will bring out all the channels from sleep
// This operation can only be called from the
// first Channel's COM port handle
dwIoControlCode = IOCTL_XR17C15X_DISABLE_SLEEPMODE;
}
break;
case 8: //ENABLE_INTERNAL_LOOPBACK
{
dwIoControlCode = IOCTL_XR17C15X_ENABLE_INTERNAL_LOOPBACK;
}
break;
case 9: //DISABLE_INTERNAL_LOOPBACK
{
dwIoControlCode = IOCTL_XR17C15X_DISABLE_INTERNAL_LOOPBACK;
}
break;
case 10: //PCIUART_CONFIG_REG_READ
{
ucTemp1 = 0x80 to 0x93; // configuration registers offset range
is 0x80 to 0x93; provide appropriate register offset
pInBuffer = &ucTemp1;
pOutBuffer = &ucTemp2;
nInBufferSize = nOutBufferSize = sizeof(UCHAR);
dwIoControlCode = IOCTL_XR17C15X_CONFIG_REG_READ;
}
break;
case 11: //PCIUART_CONFIG_REG_WRITE
{
CfgWrite.bReg = 0x80 to 0x93; // configuration registers offset range
is 0x80 to 0x93; provide appropriate register offset
CfgWrite.bData = your data to write;
pInBuffer = (PVOID)&CfgWrite;
nInBufferSize = sizeof(CONFIG_WRITE);
dwIoControlCode = IOCTL_XR17C15X_CONFIG_REG_WRITE;
}
break;
default:
{
CString str;
str.Format(_T("Error: Invalid IOCTL !!!"));
MessageBox (str, TEXT("Failure"), MB_OK);
}
break or return;
}
Status = DeviceIoControl( hPort,
dwIoControlCode,
pInBuffer,
nInBufferSize,
pOutBuffer,
nOutBufferSize,
&cbReturned,
0);
if (!Status)
{
CString str;
str.Format(_T("Error: This operation failed!!!"));
MessageBox (str, TEXT("Failure"), MB_OK);
}
else
{
// for Config Read we need to do extra work like displaying the data here
if(dwIoControlCode == IOCTL_XR17C15X_CONFIG_REG_READ)
{
ucTemp2 contains the Cnfig Regsiter’s Read data;
}
}
}