Serial Communication Problem

G

Guest

Hi.
Please give me some advise.
I want to communicate with a device via COM port and coded typical
communication program using Windows SDK.

The program sequence is thus...
(1) CreateFile with overlap mode.
ComID = CreateFile("COM1",GENERIC_READ | GENERIC_WRITE, 0,NULL,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);

(2) BuildCommDCB
BuildCommDCB("COM1",&dcb);

(3) SetCommState with some parameter set by the value the device requires
and others by default.
SetCommState(ComID, &dcb);

(4) SetCommTimeouts with no timeout.
SetCommTimeouts(ComID, &comm_timeout);

(5) SetCommMask
SetCommMask(ComID, EV_RXCHAR);

(6) CreateThread.

(7) In the thread created above, WaitCommEvent for a data sent from the
device.
WaitCommEvent(ComID, &EventMask, &event);

(8) Wait until the overlapped operation complete.
GetOverlappedResult(ComID, &event, &Transfer, TRUE);

(9) Get error code and clear.
ClearCommError(ComID, &Error, &ComStat);

(10) Check the receive queue if some data is received.

The problem is that function WaitCommEvent never return!
Instead of WaitCommEvent, I tried to ReadFile(COM1) directly in while loop,
but the loop never ended.

I confirmed that the command from application to the device is correctly sent.
And also confirmed by line monitor connected between the device and COM port
that the device returns correct response for the command sent by my
application.
But why my application can't receive any data?
Almost all the settings are set by general value.

OS is Windows XP Embedded with almost full functionality configuration.

Please help me. Thanks.
 
S

Slobodan Brcin \(eMVP\)

Hi George,

Does this work on XP Pro?

Why do you create new thread for simple test? Simplify your test case.
Always use timeouts for receive operation. (Unless you want your program to stuck if there is not enough data requested by read
operation).
Either SetCommMask or WaitCommEvent caused problems for me long time ago so I do not use them.(There is no need for them especially
since you use overlapped access).
Where are read and write file in your example?

Regards,
Slobodan
 
D

Doug G

I have no problems reading from a serial port within a sub-thread. Here is
the basic loop within the thread, with app-specific stuff removed:

while (TRUE) {
success = ReadFile(MhComm, cBuf, 1, &mRead, &MOverlapR);

// Wait for async completion
success = GetOverlappedResult(MhComm, &MOverlapR, &mRead, TRUE);

if (success && mRead) {
// app-specific processing
}

ResetEvent(MhReadEvt); // reset overlap event
} // while forever
 
G

Guest

Hi Slobodan,
I have not tested another OS than Windows XP Embedded.
Does OS matter about this phenomenon?

OK I'll try to make test program without sub-thread and set timeout properly.

R/W file operation is simple as below. This operation is done after (10)'s
check.
ReadFile(ComID, lpvBuf, nRead, &BytesRead, &read);
WriteFile(ComID, lpvBuf, nWrite, &BytesWritten, &write);

Wait for completion of overlapped operaion.
GetOverlappedResult(ComID, &write, &BytesWritten, FALSE);

Check if "BytesWritten" is over zero, and application specific process.

I also tried without using WaitCommEvent but only ReadFile within eternal
while loop, but the result was same. No data could be read.

What is wrong?
BIOS level setting?
OS setting?
Shortage of pre-configuration in my application?
 
S

Slobodan Brcin \(eMVP\)

Hi George,
I have not tested another OS than Windows XP Embedded.
Does OS matter about this phenomenon?

Not really, but this NG is less apropriate for this type (API programmming type) of questions. And one SDK/DDK related would be
better for obtaining answers on these topics. When you have something tha twork on XP Pro and do not work on XPe then this is NG to
ask for help.
OK I'll try to make test program without sub-thread and set timeout properly.

R/W file operation is simple as below. This operation is done after (10)'s
check.
ReadFile(ComID, lpvBuf, nRead, &BytesRead, &read);
WriteFile(ComID, lpvBuf, nWrite, &BytesWritten, &write);

With overlapped structured BytesRead, BytesWritten usually do not contain values that you expect and they will be most likely 0
(depending on queue status).
Wait for completion of overlapped operaion.
GetOverlappedResult(ComID, &write, &BytesWritten, FALSE);

Since both read and write are overlapped, please use GetOverlappedResults to wait for operation to complete after both read and
write operations. Ase last parameter as TRUE for test cases.
Check if "BytesWritten" is over zero, and application specific process.

I also tried without using WaitCommEvent but only ReadFile within eternal
while loop, but the result was same. No data could be read.

What is wrong?

Probably you do not wait to receive data with GetOverlappedResult. (Without complete code I can't tell for sure).
BIOS level setting?
NO. Has nothing to do with this.
OS setting?
NO, since you configure DCB, timeouts etc.
Shortage of pre-configuration in my application?
NO. You have configured all that is needed. But set timeouts (if you want them, for test they are not important)

Regards,
Slobodan
 
K

KM

George,
Hi Slobodan,
I have not tested another OS than Windows XP Embedded.
Does OS matter about this phenomenon?

I guess Slobodan meant that if you can make it working on XPPro, you can make it working on XPe.
For your code, there is nothing XPe specific.

I wonder how your create the Event passed as a part of OVERLAPPED structure?
Is it manual reset event?
OK I'll try to make test program without sub-thread and set timeout properly.

R/W file operation is simple as below. This operation is done after (10)'s
check.
ReadFile(ComID, lpvBuf, nRead, &BytesRead, &read);
WriteFile(ComID, lpvBuf, nWrite, &BytesWritten, &write);

Wait for completion of overlapped operaion.
GetOverlappedResult(ComID, &write, &BytesWritten, FALSE);

Since you set bWait parameter to FALSE, what the return codes from GetOverlappedResult and GetLastError()?
 
G

Guest

Depend on queue status? What's that?

Yes, I tried to GetOverlappedResult() with 3rd parameter TRUE, but no
difference.
GetOverlappedResult() returns successfully but "BytesRead" is always 0.
 
S

Slobodan Brcin \(eMVP\)

Hi George,

One basic question do you know how overlapped operation are working?

You should choose between one of two following syntaxes.
ReadFile(ComID, lpvBuf, nRead, 0, &read); -----> For overlapped access
ReadFile(ComID, lpvBuf, nRead, &BytesRead, 0); ---> For regular access.

Using both values with overlapped access does not make sense since all operations will return immediately and set BytesRead to 0 or
some unknown value that represent some data that was already available in internal OS buffers, depending on driver that you use. But
this length info is usually 0 (treat is as undefined).

Length info is filled only during the IO API call not later.
So only way for you to obtain current results of overlapped operation is to read overlapped structure directly or use API functions
like GetOverlappedResult.

Also all operations on buffer are not synchronous but rather asynchronous. This mean that you can issue few different read and write
operations on different handles and still execute some other code while drivers and hardware gather your data.

Regards,
Slobodan
 
K

KM

Just to add to that..

George, look at the HasOverlappedIoCompleted macro to see if it can help to determine the completion of an outstanding I/O
operation.
 
G

Guest

HasOverlappedIoCompleted returns FALSE.

By the way, just after SetCommMask() returns TRUE, GetCommMask() returns
FALSE. Why?
Any 2nd parameter of SetCommMask() results in the same.
 
S

Slobodan Brcin \(eMVP\)

Hi George,
HasOverlappedIoCompleted returns FALSE.

I do not know what you expected to get?
It will return true if or when overlapped operation is completed.
By the way, just after SetCommMask() returns TRUE, GetCommMask() returns
FALSE. Why?
Any 2nd parameter of SetCommMask() results in the same.

I do not know why CommMask flags are relevant to you?

Like I said this is wrong NG for you, although if you post complete test source in reply and what do you expect that it does we can
point you to the error.

Regards,
Slobodan
 
K

KM

George,

Somehow I seem to overlook your reply in this thread.
HasOverlappedIoCompleted returns FALSE.

Yup. This is what we expected, right?
It would be worse if it returned TRUE while GetOverlappedResult returned 0 bytes transferred.
By the way, just after SetCommMask() returns TRUE, GetCommMask() returns
FALSE. Why?

How about checking with GetLastError?
Any 2nd parameter of SetCommMask() results in the same.

Please look at this MSDN sample code to see how it should work in a simple case:
http://msdn.microsoft.com/library/en-us/devio/base/monitoring_communications_events.asp

Your problem does not seem to be related to XPe. You would better off developing, texting and debugging the app on XP Pro first and
then move to XPe.
As Slobodan mentioned you can get more help if you open more sources and post in more appropriate NG.

Regards,
KM
 
G

Guest

I tested with a simple application in a simple condition.
Connect 2 PCs with serial cable and run above application on both PC.

Everything went well all around.
The data packet sent from 1 PC could be correctly received by another PC.
If some character data is reached to the system receive buffer,
WaitCommEvent is terminated and ReadFile correctly read buffer data.
According to this result, I think the receive data logic is not wrong.
Some field of DCB structure, 2nd parameter of SetCommState, may be wrong for
my appllication or device (or XP Embedded component configuration).

By the way, I found the API SetupComm. Is this API necessary for our
application?
 
S

Slobodan Brcin \(eMVP\)

Hi George,

No matter what SetumComm settings that you use (default) serial driver should work.
You have a logic error in your code regarding when you expect to get some data.

Post here complete segment starting with readfile and explain what do you expect to get with each next API call. (This is few lines
that you should try to explain to your-self, but doing that "aloud" ca usually help)

Regards,
Slobodan
 
G

Guest

This is the part of my application that regards to commport communication.
Wait CommEvent thread loop terminates only when application terminated or
fContinue flag turned into ON.
WriteFile() goes well without any problem and the device connected works as
designed.
The device returns correct data for the command sent from my application.
But WaitCommEvent() never returns though the data sent from the device
correctly arrive at the comport.

/***********************************************************************************************
*******************************************Open
ComPort****************************************
************************************************************************************************/
long OpenCommPort(){
DCB dcb;
HANDLE nComID;
COMSTAT ComStat;
BOOL bBuildComm;
BOOL bSetCommStateRtn;
char szPortSet[256];

//////////////////////// CreateFile
/////////////////////////////////////////////////

nComID = CreateFile("COM1",
GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);


//////////////////////// BuildComm
/////////////////////////////////////////////////

dcb.DCBlength = sizeof(DCB);
GetCommState(nComID, &dcb);
strcpy(szPortSet, "COM1:9600,e,7,2");

bBuildComm = BuildCommDCB(szPortSet,&dcb);


/////////////////////// SetCommState
/////////////////////////////////////////////

ZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
dcb.wReserved = 0;

dcb.BaudRate = CBR_9600;
dcb.fParity = TRUE;
dcb.Parity = 2;
dcb.ByteSize = 7;
dcb.StopBits = 2;

dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fDsrSensitivity = FALSE;
//XON/XOFF
dcb.fOutX = TRUE;
dcb.fInX = TRUE;
dcb.fTXContinueOnXoff = TRUE;
dcb.XonLim = 2048;
dcb.XoffLim = 2048;
dcb.XonChar = 0x11;
dcb.XoffChar = 0x13;

dcb.fBinary = TRUE;
dcb.fNull = FALSE;
dcb.fAbortOnError = TRUE;
dcb.fErrorChar = FALSE;
dcb.ErrorChar = 0x00;

bSetCommStateRtn = SetCommState(nComID, &dcb);


/////////////////////////////////////////////////////////////////////////////////////////////

if (PurgeComm(nComID, PURGE_TXCLEAR | PURGE_RXCLEAR) != TRUE) {
if (GetLastError() != CE_MODE) {
DWORD dwErrors;
if (ClearCommError(nComID, &dwErrors, &ComStat) != TRUE) {
return GetLastError();
}
}
}

COMMTIMEOUTS comm_timeout;
comm_timeout.ReadIntervalTimeout = MAXDWORD;
comm_timeout.ReadTotalTimeoutMultiplier = 0;
comm_timeout.ReadTotalTimeoutConstant = 0;
comm_timeout.WriteTotalTimeoutMultiplier = 0;
comm_timeout.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(nComID, &comm_timeout)) {
return -1;
}

if (ThreadHdl == NULL) {
ThreadHdl = CreateThread(NULL, 0, CommPortMonitor,
this, CREATE_SUSPENDED, &ThreadID);
if (ThreadHdl == NULL) {
return -1;
}
ResumeThread(ThreadHdl);
}

return 0;
}

/***********************************************************************************************
***********************************Wait CommEvent
Thread****************************************
************************************************************************************************/
extern "C"
DWORD __stdcall CommPortMonitor( void* pparam )
{
DWORD dwEvtMask; // kind of communication event(set in
WaitCommEvent())
DWORD dwError;
COMSTAT ComStat; // status of communication port(set in
ClearCommClear())
BOOL bRet;
int nReadCnt; // bytes received(return value of ReadComPort())

bSetMask = SetCommMask(nComID, EV_RXCHAR | EV_ERR);

while (TRUE) {
bRet = WaitCommEvent(nComID, &dwEvtMask, NULL);
if (!fContinue) {
break;
}
ClearCommError(nComID, &dwError, &ComStat);
if (!bRet) {
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
continue;
}
}

if (dwEvtMask & EV_ERR) { // CE_FRAME, CE_OVERRUN, CE_RXPARITY
//error-handling
continue;
}

if (ComStat.cbInQue > 0) { // check existence of receive data
ReadComPort(nComID, byBuffer, 1024);
//data-handling
}
}

return TRUE;
}

/***********************************************************************************************
*****************************************Read
Data***********************************************
************************************************************************************************/
int HWPIN::ReadComPort(HANDLE hComm, void* lpvBuf, int cbRead)
{
DWORD dwError;
COMSTAT comstat;

BOOL bContinue = TRUE;
DWORD dwBytesRead = 0;
BOOL rc = 0;

read_os.Offset = 0;

rc = ReadFile(hComm, lpvBuf, cbRead, &dwBytesRead, &read_os);
if (!rc && (GetLastError() == ERROR_IO_PENDING)) {
if (WaitForSingleObject(read_os.hEvent, 1000)) {
dwBytesRead = 0;
} else {
rc = GetOverlappedResult(nComID, &read_os, &dwBytesRead, FALSE);
if (rc) {
read_os.Offset = dwBytesRead;
}
}
} else {
read_os.Offset = dwBytesRead;
}

if (rc) {
return read_os.Offset;
} else {
// error handling
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
ClearCommError(nComID, &dwError, &comstat);
return -1;
}
}

/***********************************************************************************************
****************************************Write
Data**********************************************
************************************************************************************************/
int HWPIN::WriteComPort(HANDLE hComm, const void* lpvBuf, int cbWrite)
{
DWORD dwError;
COMSTAT comstat;
DWORD dwBytesWritten = 0;
BOOL rc = 0;

write_os.Offset = 0;

rc = WriteFile(hComm, lpvBuf, cbWrite, &dwBytesWritten, &write_os);
if (!rc && (GetLastError() == ERROR_IO_PENDING)) {
if (WaitForSingleObject(write_os.hEvent, 1000)) {
dwBytesWritten = 0 ;
} else {
rc = GetOverlappedResult( nComID,
&write_os,
&dwBytesWritten, FALSE);
if (rc) {
write_os.Offset = dwBytesWritten;
}
}
} else {
write_os.Offset = dwBytesWritten;
}

if (rc) {
return write_os.Offset;
} else {
// error handling
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
ClearCommError(nComID, &dwError, &comstat);
return -1;
}
}
 
K

KM

George,

Not going deeply in to the code, a couple of glitches:

- If you open file with FILE_FLAG_OVERLAPPED, you must set the last parameter of the WaitCommEvent to not NULL and pass a
manual-reset event object.
You have, however, this: WaitCommEvent(nComID, &dwEvtMask, NULL);
Please see the msdn sample the link to I posted in some previous reply in this thread.

- For debugging purposes make your code single threading. That may be easy if instead of CreateThread(..., CommPortMonitor,...)
you just call CommPortMonitor.

KM
This is the part of my application that regards to commport communication.
Wait CommEvent thread loop terminates only when application terminated or
fContinue flag turned into ON.
WriteFile() goes well without any problem and the device connected works as
designed.
The device returns correct data for the command sent from my application.
But WaitCommEvent() never returns though the data sent from the device
correctly arrive at the comport.

/***********************************************************************************************
*******************************************Open
ComPort*****************************************
************************************************************************************************/
long OpenCommPort(){
DCB dcb;
HANDLE nComID;
COMSTAT ComStat;
BOOL bBuildComm;
BOOL bSetCommStateRtn;
char szPortSet[256];

//////////////////////// CreateFile
/////////////////////////////////////////////////

nComID = CreateFile("COM1",
GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);


//////////////////////// BuildComm
/////////////////////////////////////////////////

dcb.DCBlength = sizeof(DCB);
GetCommState(nComID, &dcb);
strcpy(szPortSet, "COM1:9600,e,7,2");

bBuildComm = BuildCommDCB(szPortSet,&dcb);


/////////////////////// SetCommState
/////////////////////////////////////////////

ZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
dcb.wReserved = 0;

dcb.BaudRate = CBR_9600;
dcb.fParity = TRUE;
dcb.Parity = 2;
dcb.ByteSize = 7;
dcb.StopBits = 2;

dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fDsrSensitivity = FALSE;
//XON/XOFF
dcb.fOutX = TRUE;
dcb.fInX = TRUE;
dcb.fTXContinueOnXoff = TRUE;
dcb.XonLim = 2048;
dcb.XoffLim = 2048;
dcb.XonChar = 0x11;
dcb.XoffChar = 0x13;

dcb.fBinary = TRUE;
dcb.fNull = FALSE;
dcb.fAbortOnError = TRUE;
dcb.fErrorChar = FALSE;
dcb.ErrorChar = 0x00;

bSetCommStateRtn = SetCommState(nComID, &dcb);


/////////////////////////////////////////////////////////////////////////////////////////////

if (PurgeComm(nComID, PURGE_TXCLEAR | PURGE_RXCLEAR) != TRUE) {
if (GetLastError() != CE_MODE) {
DWORD dwErrors;
if (ClearCommError(nComID, &dwErrors, &ComStat) != TRUE) {
return GetLastError();
}
}
}

COMMTIMEOUTS comm_timeout;
comm_timeout.ReadIntervalTimeout = MAXDWORD;
comm_timeout.ReadTotalTimeoutMultiplier = 0;
comm_timeout.ReadTotalTimeoutConstant = 0;
comm_timeout.WriteTotalTimeoutMultiplier = 0;
comm_timeout.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(nComID, &comm_timeout)) {
return -1;
}

if (ThreadHdl == NULL) {
ThreadHdl = CreateThread(NULL, 0, CommPortMonitor,
this, CREATE_SUSPENDED, &ThreadID);
if (ThreadHdl == NULL) {
return -1;
}
ResumeThread(ThreadHdl);
}

return 0;
}

/***********************************************************************************************
***********************************Wait CommEvent
Thread*****************************************
************************************************************************************************/
extern "C"
DWORD __stdcall CommPortMonitor( void* pparam )
{
DWORD dwEvtMask; // kind of communication event(set in
WaitCommEvent())
DWORD dwError;
COMSTAT ComStat; // status of communication port(set in
ClearCommClear())
BOOL bRet;
int nReadCnt; // bytes received(return value of ReadComPort())

bSetMask = SetCommMask(nComID, EV_RXCHAR | EV_ERR);

while (TRUE) {
bRet = WaitCommEvent(nComID, &dwEvtMask, NULL);
if (!fContinue) {
break;
}
ClearCommError(nComID, &dwError, &ComStat);
if (!bRet) {
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
continue;
}
}

if (dwEvtMask & EV_ERR) { // CE_FRAME, CE_OVERRUN, CE_RXPARITY
//error-handling
continue;
}

if (ComStat.cbInQue > 0) { // check existence of receive data
ReadComPort(nComID, byBuffer, 1024);
//data-handling
}
}

return TRUE;
}

/***********************************************************************************************
*****************************************Read
Data***********************************************
************************************************************************************************/
int HWPIN::ReadComPort(HANDLE hComm, void* lpvBuf, int cbRead)
{
DWORD dwError;
COMSTAT comstat;

BOOL bContinue = TRUE;
DWORD dwBytesRead = 0;
BOOL rc = 0;

read_os.Offset = 0;

rc = ReadFile(hComm, lpvBuf, cbRead, &dwBytesRead, &read_os);
if (!rc && (GetLastError() == ERROR_IO_PENDING)) {
if (WaitForSingleObject(read_os.hEvent, 1000)) {
dwBytesRead = 0;
} else {
rc = GetOverlappedResult(nComID, &read_os, &dwBytesRead, FALSE);
if (rc) {
read_os.Offset = dwBytesRead;
}
}
} else {
read_os.Offset = dwBytesRead;
}

if (rc) {
return read_os.Offset;
} else {
// error handling
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
ClearCommError(nComID, &dwError, &comstat);
return -1;
}
}

/***********************************************************************************************
****************************************Write
Data**********************************************
************************************************************************************************/
int HWPIN::WriteComPort(HANDLE hComm, const void* lpvBuf, int cbWrite)
{
DWORD dwError;
COMSTAT comstat;
DWORD dwBytesWritten = 0;
BOOL rc = 0;

write_os.Offset = 0;

rc = WriteFile(hComm, lpvBuf, cbWrite, &dwBytesWritten, &write_os);
if (!rc && (GetLastError() == ERROR_IO_PENDING)) {
if (WaitForSingleObject(write_os.hEvent, 1000)) {
dwBytesWritten = 0 ;
} else {
rc = GetOverlappedResult( nComID,
&write_os,
&dwBytesWritten, FALSE);
if (rc) {
write_os.Offset = dwBytesWritten;
}
}
} else {
write_os.Offset = dwBytesWritten;
}

if (rc) {
return write_os.Offset;
} else {
// error handling
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
ClearCommError(nComID, &dwError, &comstat);
return -1;
}
}


Slobodan Brcin (eMVP) said:
Hi George,

No matter what SetumComm settings that you use (default) serial driver should work.
You have a logic error in your code regarding when you expect to get some data.

Post here complete segment starting with readfile and explain what do you expect to get with each next API call. (This is few
lines
that you should try to explain to your-self, but doing that "aloud" ca usually help)

Regards,
Slobodan
 
S

Slobodan Brcin \(eMVP\)

George,

And my 0.02$ to this:

There is no offset value on pipes and serial drivers. (What would offset mean in a continuous stream without beginning and the end
to the driver)

To reduce confusion to yourself instead of:
rc = ReadFile(hComm, lpvBuf, cbRead, &dwBytesRead, &read_os);
Use:
rc = ReadFile(hComm, lpvBuf, cbRead, 0, &read_os);

dwBytesRead in overlapped case has no meaning.

WaitForSingleObject do not use this, especially not in test sample.
Also use GetOverlappedResult with TRUE.

For instance following should work instead of your code above:

ReadFile(hComm, lpvBuf, cbRead, 0, &read_os);
GetOverlappedResult(nComID, &read_os, &dwBytesRead, TRUE);

Regards,
Slobodan


KM said:
George,

Not going deeply in to the code, a couple of glitches:

- If you open file with FILE_FLAG_OVERLAPPED, you must set the last parameter of the WaitCommEvent to not NULL and pass a
manual-reset event object.
You have, however, this: WaitCommEvent(nComID, &dwEvtMask, NULL);
Please see the msdn sample the link to I posted in some previous reply in this thread.

- For debugging purposes make your code single threading. That may be easy if instead of CreateThread(..., CommPortMonitor,...)
you just call CommPortMonitor.

KM
This is the part of my application that regards to commport communication.
Wait CommEvent thread loop terminates only when application terminated or
fContinue flag turned into ON.
WriteFile() goes well without any problem and the device connected works as
designed.
The device returns correct data for the command sent from my application.
But WaitCommEvent() never returns though the data sent from the device
correctly arrive at the comport.

/***********************************************************************************************
*******************************************Open
ComPort*****************************************
************************************************************************************************/
long OpenCommPort(){
DCB dcb;
HANDLE nComID;
COMSTAT ComStat;
BOOL bBuildComm;
BOOL bSetCommStateRtn;
char szPortSet[256];

//////////////////////// CreateFile
/////////////////////////////////////////////////

nComID = CreateFile("COM1",
GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);


//////////////////////// BuildComm
/////////////////////////////////////////////////

dcb.DCBlength = sizeof(DCB);
GetCommState(nComID, &dcb);
strcpy(szPortSet, "COM1:9600,e,7,2");

bBuildComm = BuildCommDCB(szPortSet,&dcb);


/////////////////////// SetCommState
/////////////////////////////////////////////

ZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
dcb.wReserved = 0;

dcb.BaudRate = CBR_9600;
dcb.fParity = TRUE;
dcb.Parity = 2;
dcb.ByteSize = 7;
dcb.StopBits = 2;

dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fDsrSensitivity = FALSE;
//XON/XOFF
dcb.fOutX = TRUE;
dcb.fInX = TRUE;
dcb.fTXContinueOnXoff = TRUE;
dcb.XonLim = 2048;
dcb.XoffLim = 2048;
dcb.XonChar = 0x11;
dcb.XoffChar = 0x13;

dcb.fBinary = TRUE;
dcb.fNull = FALSE;
dcb.fAbortOnError = TRUE;
dcb.fErrorChar = FALSE;
dcb.ErrorChar = 0x00;

bSetCommStateRtn = SetCommState(nComID, &dcb);


/////////////////////////////////////////////////////////////////////////////////////////////

if (PurgeComm(nComID, PURGE_TXCLEAR | PURGE_RXCLEAR) != TRUE) {
if (GetLastError() != CE_MODE) {
DWORD dwErrors;
if (ClearCommError(nComID, &dwErrors, &ComStat) != TRUE) {
return GetLastError();
}
}
}

COMMTIMEOUTS comm_timeout;
comm_timeout.ReadIntervalTimeout = MAXDWORD;
comm_timeout.ReadTotalTimeoutMultiplier = 0;
comm_timeout.ReadTotalTimeoutConstant = 0;
comm_timeout.WriteTotalTimeoutMultiplier = 0;
comm_timeout.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(nComID, &comm_timeout)) {
return -1;
}

if (ThreadHdl == NULL) {
ThreadHdl = CreateThread(NULL, 0, CommPortMonitor,
this, CREATE_SUSPENDED, &ThreadID);
if (ThreadHdl == NULL) {
return -1;
}
ResumeThread(ThreadHdl);
}

return 0;
}

/***********************************************************************************************
***********************************Wait CommEvent
Thread*****************************************
************************************************************************************************/
extern "C"
DWORD __stdcall CommPortMonitor( void* pparam )
{
DWORD dwEvtMask; // kind of communication event(set in
WaitCommEvent())
DWORD dwError;
COMSTAT ComStat; // status of communication port(set in
ClearCommClear())
BOOL bRet;
int nReadCnt; // bytes received(return value of ReadComPort())

bSetMask = SetCommMask(nComID, EV_RXCHAR | EV_ERR);

while (TRUE) {
bRet = WaitCommEvent(nComID, &dwEvtMask, NULL);
if (!fContinue) {
break;
}
ClearCommError(nComID, &dwError, &ComStat);
if (!bRet) {
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
continue;
}
}

if (dwEvtMask & EV_ERR) { // CE_FRAME, CE_OVERRUN, CE_RXPARITY
//error-handling
continue;
}

if (ComStat.cbInQue > 0) { // check existence of receive data
ReadComPort(nComID, byBuffer, 1024);
//data-handling
}
}

return TRUE;
}

/***********************************************************************************************
*****************************************Read
Data***********************************************
************************************************************************************************/
int HWPIN::ReadComPort(HANDLE hComm, void* lpvBuf, int cbRead)
{
DWORD dwError;
COMSTAT comstat;

BOOL bContinue = TRUE;
DWORD dwBytesRead = 0;
BOOL rc = 0;

read_os.Offset = 0;

rc = ReadFile(hComm, lpvBuf, cbRead, &dwBytesRead, &read_os);
if (!rc && (GetLastError() == ERROR_IO_PENDING)) {
if (WaitForSingleObject(read_os.hEvent, 1000)) {
dwBytesRead = 0;
} else {
rc = GetOverlappedResult(nComID, &read_os, &dwBytesRead, FALSE);
if (rc) {
read_os.Offset = dwBytesRead;
}
}
} else {
read_os.Offset = dwBytesRead;
}

if (rc) {
return read_os.Offset;
} else {
// error handling
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
ClearCommError(nComID, &dwError, &comstat);
return -1;
}
}

/***********************************************************************************************
****************************************Write
Data**********************************************
************************************************************************************************/
int HWPIN::WriteComPort(HANDLE hComm, const void* lpvBuf, int cbWrite)
{
DWORD dwError;
COMSTAT comstat;
DWORD dwBytesWritten = 0;
BOOL rc = 0;

write_os.Offset = 0;

rc = WriteFile(hComm, lpvBuf, cbWrite, &dwBytesWritten, &write_os);
if (!rc && (GetLastError() == ERROR_IO_PENDING)) {
if (WaitForSingleObject(write_os.hEvent, 1000)) {
dwBytesWritten = 0 ;
} else {
rc = GetOverlappedResult( nComID,
&write_os,
&dwBytesWritten, FALSE);
if (rc) {
write_os.Offset = dwBytesWritten;
}
}
} else {
write_os.Offset = dwBytesWritten;
}

if (rc) {
return write_os.Offset;
} else {
// error handling
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
ClearCommError(nComID, &dwError, &comstat);
return -1;
}
}


Slobodan Brcin (eMVP) said:
Hi George,

No matter what SetumComm settings that you use (default) serial driver should work.
You have a logic error in your code regarding when you expect to get some data.

Post here complete segment starting with readfile and explain what do you expect to get with each next API call. (This is few
lines
that you should try to explain to your-self, but doing that "aloud" ca usually help)

Regards,
Slobodan

I tested with a simple application in a simple condition.
Connect 2 PCs with serial cable and run above application on both PC.

Everything went well all around.
The data packet sent from 1 PC could be correctly received by another PC.
If some character data is reached to the system receive buffer,
WaitCommEvent is terminated and ReadFile correctly read buffer data.
According to this result, I think the receive data logic is not wrong.
Some field of DCB structure, 2nd parameter of SetCommState, may be wrong for
my appllication or device (or XP Embedded component configuration).

By the way, I found the API SetupComm. Is this API necessary for our
application?

:

George,

Somehow I seem to overlook your reply in this thread.

HasOverlappedIoCompleted returns FALSE.

Yup. This is what we expected, right?
It would be worse if it returned TRUE while GetOverlappedResult returned 0 bytes transferred.

By the way, just after SetCommMask() returns TRUE, GetCommMask() returns
FALSE. Why?

How about checking with GetLastError?

Any 2nd parameter of SetCommMask() results in the same.

Please look at this MSDN sample code to see how it should work in a simple case:
http://msdn.microsoft.com/library/en-us/devio/base/monitoring_communications_events.asp

Your problem does not seem to be related to XPe. You would better off developing, texting and debugging the app on XP Pro
first
and
then move to XPe.
As Slobodan mentioned you can get more help if you open more sources and post in more appropriate NG.

Regards,
KM

:

Just to add to that..

George, look at the HasOverlappedIoCompleted macro to see if it can help to determine the completion of an outstanding
I/O
operation.

--
Regards,
KM, BSquare Corp.


Hi George,

One basic question do you know how overlapped operation are working?

You should choose between one of two following syntaxes.
ReadFile(ComID, lpvBuf, nRead, 0, &read); -----> For overlapped access
ReadFile(ComID, lpvBuf, nRead, &BytesRead, 0); ---> For regular access.

Using both values with overlapped access does not make sense since all operations will return immediately and set
BytesRead to
0
or
some unknown value that represent some data that was already available in internal OS buffers, depending on driver that
you
use.
But
this length info is usually 0 (treat is as undefined).

Length info is filled only during the IO API call not later.
So only way for you to obtain current results of overlapped operation is to read overlapped structure directly or use
API
functions
like GetOverlappedResult.

Also all operations on buffer are not synchronous but rather asynchronous. This mean that you can issue few different
read
and
write
operations on different handles and still execute some other code while drivers and hardware gather your data.

Regards,
Slobodan


Depend on queue status? What's that?

Yes, I tried to GetOverlappedResult() with 3rd parameter TRUE, but no
difference.
GetOverlappedResult() returns successfully but "BytesRead" is always 0.


:

Hi George,

I have not tested another OS than Windows XP Embedded.
Does OS matter about this phenomenon?

Not really, but this NG is less apropriate for this type (API programmming type) of questions. And one SDK/DDK
related
would
be
better for obtaining answers on these topics. When you have something tha twork on XP Pro and do not work on XPe
then
this
is
NG
to
ask for help.

OK I'll try to make test program without sub-thread and set timeout properly.

R/W file operation is simple as below. This operation is done after (10)'s
check.
ReadFile(ComID, lpvBuf, nRead, &BytesRead, &read);
WriteFile(ComID, lpvBuf, nWrite, &BytesWritten, &write);

With overlapped structured BytesRead, BytesWritten usually do not contain values that you expect and they will be
most
likely
0
(depending on queue status).

Wait for completion of overlapped operaion.
GetOverlappedResult(ComID, &write, &BytesWritten, FALSE);

Since both read and write are overlapped, please use GetOverlappedResults to wait for operation to complete after
both
read
and
write operations. Ase last parameter as TRUE for test cases.

Check if "BytesWritten" is over zero, and application specific process.

I also tried without using WaitCommEvent but only ReadFile within eternal
while loop, but the result was same. No data could be read.

What is wrong?

Probably you do not wait to receive data with GetOverlappedResult. (Without complete code I can't tell for sure).

BIOS level setting?
NO. Has nothing to do with this.
OS setting?
NO, since you configure DCB, timeouts etc.

Shortage of pre-configuration in my application?
NO. You have configured all that is needed. But set timeouts (if you want them, for test they are not important)

Regards,
Slobodan


:

Hi George,

Does this work on XP Pro?

Why do you create new thread for simple test? Simplify your test case.
Always use timeouts for receive operation. (Unless you want your program to stuck if there is not enough data
requested by
read
operation).
Either SetCommMask or WaitCommEvent caused problems for me long time ago so I do not use them.(There is no need
for
them
especially
since you use overlapped access).
Where are read and write file in your example?

Regards,
Slobodan

Hi.
Please give me some advise.
I want to communicate with a device via COM port and coded typical
communication program using Windows SDK.

The program sequence is thus...
(1) CreateFile with overlap mode.
ComID = CreateFile("COM1",GENERIC_READ | GENERIC_WRITE, 0,NULL,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);

(2) BuildCommDCB
BuildCommDCB("COM1",&dcb);

(3) SetCommState with some parameter set by the value the device requires
and others by default.
SetCommState(ComID, &dcb);

(4) SetCommTimeouts with no timeout.
SetCommTimeouts(ComID, &comm_timeout);

(5) SetCommMask
SetCommMask(ComID, EV_RXCHAR);

(6) CreateThread.

(7) In the thread created above, WaitCommEvent for a data sent from the
device.
WaitCommEvent(ComID, &EventMask, &event);

(8) Wait until the overlapped operation complete.
GetOverlappedResult(ComID, &event, &Transfer, TRUE);

(9) Get error code and clear.
ClearCommError(ComID, &Error, &ComStat);

(10) Check the receive queue if some data is received.

The problem is that function WaitCommEvent never return!
Instead of WaitCommEvent, I tried to ReadFile(COM1) directly in while loop,
but the loop never ended.

I confirmed that the command from application to the device is correctly sent.
And also confirmed by line monitor connected between the device and COM port
that the device returns correct response for the command sent by my
application.
But why my application can't receive any data?
Almost all the settings are set by general value.

OS is Windows XP Embedded with almost full functionality configuration.

Please help me. Thanks.
 
G

Guest

I modified the program regarding to WaitCommEvent as following.
If the 2nd parameter of WaitCommEvent() is set NULL, GetLastError() doesn't
return ERROR_IO_PENDING.

GetOverlappedResult() function never terminates though line monitor catches
the char data sent from the device to the commport.

----------------------------------------------------------------------------------------------------
SetCommMask(nComID, EV_RXCHAR | EV_ERR);

while(TRUE){
bRet = WaitCommEvent(nComID, &dwEvtMask, &event_os);
unsigned long ulError = GetLastError();
if (!bRet && ulError == ERROR_IO_PENDING){
dwRes = WaitForSingleObject(event_os.hEvent, INFINITE); // wait
infinitely until the data is put into input queue
switch(dwRes)
{
// Event occurred.
case WAIT_OBJECT_0:
if (!GetOverlappedResult(nComID, &event_os,
&dwTransfer, FALSE))
continue;
else
ClearCommError(nComID, &dwError, &ComStat);
break;
case WAIT_TIMEOUT:
continue;
default:
// Error in the WaitForSingleObject; abort
// This indicates a problem with the OVERLAPPED
structure's
// event handle.
CloseHandle(event_os.hEvent);
return FALSE;
}
}

// application specific input-data processing

}


KM said:
George,

Not going deeply in to the code, a couple of glitches:

- If you open file with FILE_FLAG_OVERLAPPED, you must set the last parameter of the WaitCommEvent to not NULL and pass a
manual-reset event object.
You have, however, this: WaitCommEvent(nComID, &dwEvtMask, NULL);
Please see the msdn sample the link to I posted in some previous reply in this thread.

- For debugging purposes make your code single threading. That may be easy if instead of CreateThread(..., CommPortMonitor,...)
you just call CommPortMonitor.

KM
This is the part of my application that regards to commport communication.
Wait CommEvent thread loop terminates only when application terminated or
fContinue flag turned into ON.
WriteFile() goes well without any problem and the device connected works as
designed.
The device returns correct data for the command sent from my application.
But WaitCommEvent() never returns though the data sent from the device
correctly arrive at the comport.

/***********************************************************************************************
*******************************************Open
ComPort*****************************************
************************************************************************************************/
long OpenCommPort(){
DCB dcb;
HANDLE nComID;
COMSTAT ComStat;
BOOL bBuildComm;
BOOL bSetCommStateRtn;
char szPortSet[256];

//////////////////////// CreateFile
/////////////////////////////////////////////////

nComID = CreateFile("COM1",
GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);


//////////////////////// BuildComm
/////////////////////////////////////////////////

dcb.DCBlength = sizeof(DCB);
GetCommState(nComID, &dcb);
strcpy(szPortSet, "COM1:9600,e,7,2");

bBuildComm = BuildCommDCB(szPortSet,&dcb);


/////////////////////// SetCommState
/////////////////////////////////////////////

ZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
dcb.wReserved = 0;

dcb.BaudRate = CBR_9600;
dcb.fParity = TRUE;
dcb.Parity = 2;
dcb.ByteSize = 7;
dcb.StopBits = 2;

dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fDsrSensitivity = FALSE;
//XON/XOFF
dcb.fOutX = TRUE;
dcb.fInX = TRUE;
dcb.fTXContinueOnXoff = TRUE;
dcb.XonLim = 2048;
dcb.XoffLim = 2048;
dcb.XonChar = 0x11;
dcb.XoffChar = 0x13;

dcb.fBinary = TRUE;
dcb.fNull = FALSE;
dcb.fAbortOnError = TRUE;
dcb.fErrorChar = FALSE;
dcb.ErrorChar = 0x00;

bSetCommStateRtn = SetCommState(nComID, &dcb);


/////////////////////////////////////////////////////////////////////////////////////////////

if (PurgeComm(nComID, PURGE_TXCLEAR | PURGE_RXCLEAR) != TRUE) {
if (GetLastError() != CE_MODE) {
DWORD dwErrors;
if (ClearCommError(nComID, &dwErrors, &ComStat) != TRUE) {
return GetLastError();
}
}
}

COMMTIMEOUTS comm_timeout;
comm_timeout.ReadIntervalTimeout = MAXDWORD;
comm_timeout.ReadTotalTimeoutMultiplier = 0;
comm_timeout.ReadTotalTimeoutConstant = 0;
comm_timeout.WriteTotalTimeoutMultiplier = 0;
comm_timeout.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(nComID, &comm_timeout)) {
return -1;
}

if (ThreadHdl == NULL) {
ThreadHdl = CreateThread(NULL, 0, CommPortMonitor,
this, CREATE_SUSPENDED, &ThreadID);
if (ThreadHdl == NULL) {
return -1;
}
ResumeThread(ThreadHdl);
}

return 0;
}

/***********************************************************************************************
***********************************Wait CommEvent
Thread*****************************************
************************************************************************************************/
extern "C"
DWORD __stdcall CommPortMonitor( void* pparam )
{
DWORD dwEvtMask; // kind of communication event(set in
WaitCommEvent())
DWORD dwError;
COMSTAT ComStat; // status of communication port(set in
ClearCommClear())
BOOL bRet;
int nReadCnt; // bytes received(return value of ReadComPort())

bSetMask = SetCommMask(nComID, EV_RXCHAR | EV_ERR);

while (TRUE) {
bRet = WaitCommEvent(nComID, &dwEvtMask, NULL);
if (!fContinue) {
break;
}
ClearCommError(nComID, &dwError, &ComStat);
if (!bRet) {
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
continue;
}
}

if (dwEvtMask & EV_ERR) { // CE_FRAME, CE_OVERRUN, CE_RXPARITY
//error-handling
continue;
}

if (ComStat.cbInQue > 0) { // check existence of receive data
ReadComPort(nComID, byBuffer, 1024);
//data-handling
}
}

return TRUE;
}

/***********************************************************************************************
*****************************************Read
Data***********************************************
************************************************************************************************/
int HWPIN::ReadComPort(HANDLE hComm, void* lpvBuf, int cbRead)
{
DWORD dwError;
COMSTAT comstat;

BOOL bContinue = TRUE;
DWORD dwBytesRead = 0;
BOOL rc = 0;

read_os.Offset = 0;

rc = ReadFile(hComm, lpvBuf, cbRead, &dwBytesRead, &read_os);
if (!rc && (GetLastError() == ERROR_IO_PENDING)) {
if (WaitForSingleObject(read_os.hEvent, 1000)) {
dwBytesRead = 0;
} else {
rc = GetOverlappedResult(nComID, &read_os, &dwBytesRead, FALSE);
if (rc) {
read_os.Offset = dwBytesRead;
}
}
} else {
read_os.Offset = dwBytesRead;
}

if (rc) {
return read_os.Offset;
} else {
// error handling
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
ClearCommError(nComID, &dwError, &comstat);
return -1;
}
}

/***********************************************************************************************
****************************************Write
Data**********************************************
************************************************************************************************/
int HWPIN::WriteComPort(HANDLE hComm, const void* lpvBuf, int cbWrite)
{
DWORD dwError;
COMSTAT comstat;
DWORD dwBytesWritten = 0;
BOOL rc = 0;

write_os.Offset = 0;

rc = WriteFile(hComm, lpvBuf, cbWrite, &dwBytesWritten, &write_os);
if (!rc && (GetLastError() == ERROR_IO_PENDING)) {
if (WaitForSingleObject(write_os.hEvent, 1000)) {
dwBytesWritten = 0 ;
} else {
rc = GetOverlappedResult( nComID,
&write_os,
&dwBytesWritten, FALSE);
if (rc) {
write_os.Offset = dwBytesWritten;
}
}
} else {
write_os.Offset = dwBytesWritten;
}

if (rc) {
return write_os.Offset;
} else {
// error handling
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
ClearCommError(nComID, &dwError, &comstat);
return -1;
}
}


Slobodan Brcin (eMVP) said:
Hi George,

No matter what SetumComm settings that you use (default) serial driver should work.
You have a logic error in your code regarding when you expect to get some data.

Post here complete segment starting with readfile and explain what do you expect to get with each next API call. (This is few
lines
that you should try to explain to your-self, but doing that "aloud" ca usually help)

Regards,
Slobodan

I tested with a simple application in a simple condition.
Connect 2 PCs with serial cable and run above application on both PC.

Everything went well all around.
The data packet sent from 1 PC could be correctly received by another PC.
If some character data is reached to the system receive buffer,
WaitCommEvent is terminated and ReadFile correctly read buffer data.
According to this result, I think the receive data logic is not wrong.
Some field of DCB structure, 2nd parameter of SetCommState, may be wrong for
my appllication or device (or XP Embedded component configuration).

By the way, I found the API SetupComm. Is this API necessary for our
application?

:

George,

Somehow I seem to overlook your reply in this thread.

HasOverlappedIoCompleted returns FALSE.

Yup. This is what we expected, right?
It would be worse if it returned TRUE while GetOverlappedResult returned 0 bytes transferred.

By the way, just after SetCommMask() returns TRUE, GetCommMask() returns
FALSE. Why?

How about checking with GetLastError?

Any 2nd parameter of SetCommMask() results in the same.

Please look at this MSDN sample code to see how it should work in a simple case:
http://msdn.microsoft.com/library/en-us/devio/base/monitoring_communications_events.asp

Your problem does not seem to be related to XPe. You would better off developing, texting and debugging the app on XP Pro
first
and
then move to XPe.
As Slobodan mentioned you can get more help if you open more sources and post in more appropriate NG.

Regards,
KM

:

Just to add to that..

George, look at the HasOverlappedIoCompleted macro to see if it can help to determine the completion of an outstanding
I/O
operation.

--
Regards,
KM, BSquare Corp.


Hi George,

One basic question do you know how overlapped operation are working?

You should choose between one of two following syntaxes.
ReadFile(ComID, lpvBuf, nRead, 0, &read); -----> For overlapped access
ReadFile(ComID, lpvBuf, nRead, &BytesRead, 0); ---> For regular access.

Using both values with overlapped access does not make sense since all operations will return immediately and set
BytesRead to
0
or
some unknown value that represent some data that was already available in internal OS buffers, depending on driver that
you
use.
But
this length info is usually 0 (treat is as undefined).

Length info is filled only during the IO API call not later.
So only way for you to obtain current results of overlapped operation is to read overlapped structure directly or use
API
functions
like GetOverlappedResult.

Also all operations on buffer are not synchronous but rather asynchronous. This mean that you can issue few different
read
and
write
operations on different handles and still execute some other code while drivers and hardware gather your data.

Regards,
Slobodan


Depend on queue status? What's that?

Yes, I tried to GetOverlappedResult() with 3rd parameter TRUE, but no
difference.
GetOverlappedResult() returns successfully but "BytesRead" is always 0.


:

Hi George,

I have not tested another OS than Windows XP Embedded.
Does OS matter about this phenomenon?

Not really, but this NG is less apropriate for this type (API programmming type) of questions. And one SDK/DDK
related
would
be
better for obtaining answers on these topics. When you have something tha twork on XP Pro and do not work on XPe
then
this
is
NG
to
ask for help.

OK I'll try to make test program without sub-thread and set timeout properly.

R/W file operation is simple as below. This operation is done after (10)'s
check.
ReadFile(ComID, lpvBuf, nRead, &BytesRead, &read);
WriteFile(ComID, lpvBuf, nWrite, &BytesWritten, &write);

With overlapped structured BytesRead, BytesWritten usually do not contain values that you expect and they will be
most
likely
0
(depending on queue status).

Wait for completion of overlapped operaion.
GetOverlappedResult(ComID, &write, &BytesWritten, FALSE);

Since both read and write are overlapped, please use GetOverlappedResults to wait for operation to complete after
both
read
and
write operations. Ase last parameter as TRUE for test cases.

Check if "BytesWritten" is over zero, and application specific process.

I also tried without using WaitCommEvent but only ReadFile within eternal
while loop, but the result was same. No data could be read.

What is wrong?

Probably you do not wait to receive data with GetOverlappedResult. (Without complete code I can't tell for sure).

BIOS level setting?
NO. Has nothing to do with this.
OS setting?
NO, since you configure DCB, timeouts etc.

Shortage of pre-configuration in my application?
NO. You have configured all that is needed. But set timeouts (if you want them, for test they are not important)

Regards,
Slobodan


:

Hi George,

Does this work on XP Pro?

Why do you create new thread for simple test? Simplify your test case.
Always use timeouts for receive operation. (Unless you want your program to stuck if there is not enough data
requested by
read
operation).
Either SetCommMask or WaitCommEvent caused problems for me long time ago so I do not use them.(There is no need
for
them
especially
since you use overlapped access).
Where are read and write file in your example?

Regards,
Slobodan

Hi.
Please give me some advise.
I want to communicate with a device via COM port and coded typical
communication program using Windows SDK.

The program sequence is thus...
(1) CreateFile with overlap mode.
ComID = CreateFile("COM1",GENERIC_READ | GENERIC_WRITE, 0,NULL,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);

(2) BuildCommDCB
BuildCommDCB("COM1",&dcb);

(3) SetCommState with some parameter set by the value the device requires
and others by default.
SetCommState(ComID, &dcb);

(4) SetCommTimeouts with no timeout.
SetCommTimeouts(ComID, &comm_timeout);

(5) SetCommMask
SetCommMask(ComID, EV_RXCHAR);

(6) CreateThread.

(7) In the thread created above, WaitCommEvent for a data sent from the
device.
WaitCommEvent(ComID, &EventMask, &event);

(8) Wait until the overlapped operation complete.
GetOverlappedResult(ComID, &event, &Transfer, TRUE);

(9) Get error code and clear.
ClearCommError(ComID, &Error, &ComStat);

(10) Check the receive queue if some data is received.

The problem is that function WaitCommEvent never return!
Instead of WaitCommEvent, I tried to ReadFile(COM1) directly in while loop,
but the loop never ended.

I confirmed that the command from application to the device is correctly sent.
And also confirmed by line monitor connected between the device and COM port
that the device returns correct response for the command sent by my
application.
But why my application can't receive any data?
Almost all the settings are set by general value.

OS is Windows XP Embedded with almost full functionality configuration.

Please help me. Thanks.
 
S

Slobodan Brcin \(eMVP\)

George,

Oh, why don't you ever listen.:-(

We told you that this is wrong NG, but nevertheless we want to help you.
1. Have you seen my response from above? Since you still pursue code path that will probably not work. I fail to see how you were
able to overcomplicate so simple thing.
2. Please post full sources. From your previous code post you don't know how to properly initialize event_os structure. You need to
give it a valid event handle as part of initialization.
3. DO NOT USE WaitCommEvents and WaitForSingleObject.

Use something like.

But please before you use it clear write_os, read_os structure and set two valid handles to them. (Use CreateEvent)

WriteFile(hComm, lpvBuf, cbWrite, 0, &write_os);
GetOverlappedResult(nComID, &write_os, &dwBytesWrite, TRUE);

ReadFile(hComm, lpvBuf, cbRead, 0, &read_os);
GetOverlappedResult(nComID, &read_os, &dwBytesRead, TRUE);

Regards,
Slobodan



George said:
I modified the program regarding to WaitCommEvent as following.
If the 2nd parameter of WaitCommEvent() is set NULL, GetLastError() doesn't
return ERROR_IO_PENDING.

GetOverlappedResult() function never terminates though line monitor catches
the char data sent from the device to the commport.

----------------------------------------------------------------------------------------------------
SetCommMask(nComID, EV_RXCHAR | EV_ERR);

while(TRUE){
bRet = WaitCommEvent(nComID, &dwEvtMask, &event_os);
unsigned long ulError = GetLastError();
if (!bRet && ulError == ERROR_IO_PENDING){
dwRes = WaitForSingleObject(event_os.hEvent, INFINITE); // wait
infinitely until the data is put into input queue
switch(dwRes)
{
// Event occurred.
case WAIT_OBJECT_0:
if (!GetOverlappedResult(nComID, &event_os,
&dwTransfer, FALSE))
continue;
else
ClearCommError(nComID, &dwError, &ComStat);
break;
case WAIT_TIMEOUT:
continue;
default:
// Error in the WaitForSingleObject; abort
// This indicates a problem with the OVERLAPPED
structure's
// event handle.
CloseHandle(event_os.hEvent);
return FALSE;
}
}

// application specific input-data processing

}


KM said:
George,

Not going deeply in to the code, a couple of glitches:

- If you open file with FILE_FLAG_OVERLAPPED, you must set the last parameter of the WaitCommEvent to not NULL and pass a
manual-reset event object.
You have, however, this: WaitCommEvent(nComID, &dwEvtMask, NULL);
Please see the msdn sample the link to I posted in some previous reply in this thread.

- For debugging purposes make your code single threading. That may be easy if instead of CreateThread(..., CommPortMonitor,...)
you just call CommPortMonitor.

KM
This is the part of my application that regards to commport communication.
Wait CommEvent thread loop terminates only when application terminated or
fContinue flag turned into ON.
WriteFile() goes well without any problem and the device connected works as
designed.
The device returns correct data for the command sent from my application.
But WaitCommEvent() never returns though the data sent from the device
correctly arrive at the comport.

/***********************************************************************************************
*******************************************Open
ComPort*****************************************
************************************************************************************************/
long OpenCommPort(){
DCB dcb;
HANDLE nComID;
COMSTAT ComStat;
BOOL bBuildComm;
BOOL bSetCommStateRtn;
char szPortSet[256];

//////////////////////// CreateFile
/////////////////////////////////////////////////

nComID = CreateFile("COM1",
GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);


//////////////////////// BuildComm
/////////////////////////////////////////////////

dcb.DCBlength = sizeof(DCB);
GetCommState(nComID, &dcb);
strcpy(szPortSet, "COM1:9600,e,7,2");

bBuildComm = BuildCommDCB(szPortSet,&dcb);


/////////////////////// SetCommState
/////////////////////////////////////////////

ZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
dcb.wReserved = 0;

dcb.BaudRate = CBR_9600;
dcb.fParity = TRUE;
dcb.Parity = 2;
dcb.ByteSize = 7;
dcb.StopBits = 2;

dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fDsrSensitivity = FALSE;
//XON/XOFF
dcb.fOutX = TRUE;
dcb.fInX = TRUE;
dcb.fTXContinueOnXoff = TRUE;
dcb.XonLim = 2048;
dcb.XoffLim = 2048;
dcb.XonChar = 0x11;
dcb.XoffChar = 0x13;

dcb.fBinary = TRUE;
dcb.fNull = FALSE;
dcb.fAbortOnError = TRUE;
dcb.fErrorChar = FALSE;
dcb.ErrorChar = 0x00;

bSetCommStateRtn = SetCommState(nComID, &dcb);


/////////////////////////////////////////////////////////////////////////////////////////////

if (PurgeComm(nComID, PURGE_TXCLEAR | PURGE_RXCLEAR) != TRUE) {
if (GetLastError() != CE_MODE) {
DWORD dwErrors;
if (ClearCommError(nComID, &dwErrors, &ComStat) != TRUE) {
return GetLastError();
}
}
}

COMMTIMEOUTS comm_timeout;
comm_timeout.ReadIntervalTimeout = MAXDWORD;
comm_timeout.ReadTotalTimeoutMultiplier = 0;
comm_timeout.ReadTotalTimeoutConstant = 0;
comm_timeout.WriteTotalTimeoutMultiplier = 0;
comm_timeout.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(nComID, &comm_timeout)) {
return -1;
}

if (ThreadHdl == NULL) {
ThreadHdl = CreateThread(NULL, 0, CommPortMonitor,
this, CREATE_SUSPENDED, &ThreadID);
if (ThreadHdl == NULL) {
return -1;
}
ResumeThread(ThreadHdl);
}

return 0;
}

/***********************************************************************************************
***********************************Wait CommEvent
Thread*****************************************
************************************************************************************************/
extern "C"
DWORD __stdcall CommPortMonitor( void* pparam )
{
DWORD dwEvtMask; // kind of communication event(set in
WaitCommEvent())
DWORD dwError;
COMSTAT ComStat; // status of communication port(set in
ClearCommClear())
BOOL bRet;
int nReadCnt; // bytes received(return value of ReadComPort())

bSetMask = SetCommMask(nComID, EV_RXCHAR | EV_ERR);

while (TRUE) {
bRet = WaitCommEvent(nComID, &dwEvtMask, NULL);
if (!fContinue) {
break;
}
ClearCommError(nComID, &dwError, &ComStat);
if (!bRet) {
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
continue;
}
}

if (dwEvtMask & EV_ERR) { // CE_FRAME, CE_OVERRUN, CE_RXPARITY
//error-handling
continue;
}

if (ComStat.cbInQue > 0) { // check existence of receive data
ReadComPort(nComID, byBuffer, 1024);
//data-handling
}
}

return TRUE;
}

/***********************************************************************************************
*****************************************Read
Data***********************************************
************************************************************************************************/
int HWPIN::ReadComPort(HANDLE hComm, void* lpvBuf, int cbRead)
{
DWORD dwError;
COMSTAT comstat;

BOOL bContinue = TRUE;
DWORD dwBytesRead = 0;
BOOL rc = 0;

read_os.Offset = 0;

rc = ReadFile(hComm, lpvBuf, cbRead, &dwBytesRead, &read_os);
if (!rc && (GetLastError() == ERROR_IO_PENDING)) {
if (WaitForSingleObject(read_os.hEvent, 1000)) {
dwBytesRead = 0;
} else {
rc = GetOverlappedResult(nComID, &read_os, &dwBytesRead, FALSE);
if (rc) {
read_os.Offset = dwBytesRead;
}
}
} else {
read_os.Offset = dwBytesRead;
}

if (rc) {
return read_os.Offset;
} else {
// error handling
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
ClearCommError(nComID, &dwError, &comstat);
return -1;
}
}

/***********************************************************************************************
****************************************Write
Data**********************************************
************************************************************************************************/
int HWPIN::WriteComPort(HANDLE hComm, const void* lpvBuf, int cbWrite)
{
DWORD dwError;
COMSTAT comstat;
DWORD dwBytesWritten = 0;
BOOL rc = 0;

write_os.Offset = 0;

rc = WriteFile(hComm, lpvBuf, cbWrite, &dwBytesWritten, &write_os);
if (!rc && (GetLastError() == ERROR_IO_PENDING)) {
if (WaitForSingleObject(write_os.hEvent, 1000)) {
dwBytesWritten = 0 ;
} else {
rc = GetOverlappedResult( nComID,
&write_os,
&dwBytesWritten, FALSE);
if (rc) {
write_os.Offset = dwBytesWritten;
}
}
} else {
write_os.Offset = dwBytesWritten;
}

if (rc) {
return write_os.Offset;
} else {
// error handling
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
ClearCommError(nComID, &dwError, &comstat);
return -1;
}
}


:

Hi George,

No matter what SetumComm settings that you use (default) serial driver should work.
You have a logic error in your code regarding when you expect to get some data.

Post here complete segment starting with readfile and explain what do you expect to get with each next API call. (This is few
lines
that you should try to explain to your-self, but doing that "aloud" ca usually help)

Regards,
Slobodan

I tested with a simple application in a simple condition.
Connect 2 PCs with serial cable and run above application on both PC.

Everything went well all around.
The data packet sent from 1 PC could be correctly received by another PC.
If some character data is reached to the system receive buffer,
WaitCommEvent is terminated and ReadFile correctly read buffer data.
According to this result, I think the receive data logic is not wrong.
Some field of DCB structure, 2nd parameter of SetCommState, may be wrong for
my appllication or device (or XP Embedded component configuration).

By the way, I found the API SetupComm. Is this API necessary for our
application?

:

George,

Somehow I seem to overlook your reply in this thread.

HasOverlappedIoCompleted returns FALSE.

Yup. This is what we expected, right?
It would be worse if it returned TRUE while GetOverlappedResult returned 0 bytes transferred.

By the way, just after SetCommMask() returns TRUE, GetCommMask() returns
FALSE. Why?

How about checking with GetLastError?

Any 2nd parameter of SetCommMask() results in the same.

Please look at this MSDN sample code to see how it should work in a simple case:
http://msdn.microsoft.com/library/en-us/devio/base/monitoring_communications_events.asp

Your problem does not seem to be related to XPe. You would better off developing, texting and debugging the app on XP Pro
first
and
then move to XPe.
As Slobodan mentioned you can get more help if you open more sources and post in more appropriate NG.

Regards,
KM

:

Just to add to that..

George, look at the HasOverlappedIoCompleted macro to see if it can help to determine the completion of an outstanding
I/O
operation.

--
Regards,
KM, BSquare Corp.


Hi George,

One basic question do you know how overlapped operation are working?

You should choose between one of two following syntaxes.
ReadFile(ComID, lpvBuf, nRead, 0, &read); -----> For overlapped access
ReadFile(ComID, lpvBuf, nRead, &BytesRead, 0); ---> For regular access.

Using both values with overlapped access does not make sense since all operations will return immediately and set
BytesRead to
0
or
some unknown value that represent some data that was already available in internal OS buffers, depending on driver that
you
use.
But
this length info is usually 0 (treat is as undefined).

Length info is filled only during the IO API call not later.
So only way for you to obtain current results of overlapped operation is to read overlapped structure directly or use
API
functions
like GetOverlappedResult.

Also all operations on buffer are not synchronous but rather asynchronous. This mean that you can issue few different
read
and
write
operations on different handles and still execute some other code while drivers and hardware gather your data.

Regards,
Slobodan


Depend on queue status? What's that?

Yes, I tried to GetOverlappedResult() with 3rd parameter TRUE, but no
difference.
GetOverlappedResult() returns successfully but "BytesRead" is always 0.


:

Hi George,

I have not tested another OS than Windows XP Embedded.
Does OS matter about this phenomenon?

Not really, but this NG is less apropriate for this type (API programmming type) of questions. And one SDK/DDK
related
would
be
better for obtaining answers on these topics. When you have something tha twork on XP Pro and do not work on XPe
then
this
is
NG
to
ask for help.

OK I'll try to make test program without sub-thread and set timeout properly.

R/W file operation is simple as below. This operation is done after (10)'s
check.
ReadFile(ComID, lpvBuf, nRead, &BytesRead, &read);
WriteFile(ComID, lpvBuf, nWrite, &BytesWritten, &write);

With overlapped structured BytesRead, BytesWritten usually do not contain values that you expect and they will be
most
likely
0
(depending on queue status).

Wait for completion of overlapped operaion.
GetOverlappedResult(ComID, &write, &BytesWritten, FALSE);

Since both read and write are overlapped, please use GetOverlappedResults to wait for operation to complete after
both
read
and
write operations. Ase last parameter as TRUE for test cases.

Check if "BytesWritten" is over zero, and application specific process.

I also tried without using WaitCommEvent but only ReadFile within eternal
while loop, but the result was same. No data could be read.

What is wrong?

Probably you do not wait to receive data with GetOverlappedResult. (Without complete code I can't tell for sure).

BIOS level setting?
NO. Has nothing to do with this.
OS setting?
NO, since you configure DCB, timeouts etc.

Shortage of pre-configuration in my application?
NO. You have configured all that is needed. But set timeouts (if you want them, for test they are not important)

Regards,
Slobodan


:

Hi George,

Does this work on XP Pro?

Why do you create new thread for simple test? Simplify your test case.
Always use timeouts for receive operation. (Unless you want your program to stuck if there is not enough data
requested by
read
operation).
Either SetCommMask or WaitCommEvent caused problems for me long time ago so I do not use them.(There is no need
for
them
especially
since you use overlapped access).
Where are read and write file in your example?

Regards,
Slobodan

Hi.
Please give me some advise.
I want to communicate with a device via COM port and coded typical
communication program using Windows SDK.

The program sequence is thus...
(1) CreateFile with overlap mode.
ComID = CreateFile("COM1",GENERIC_READ | GENERIC_WRITE, 0,NULL,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);

(2) BuildCommDCB
BuildCommDCB("COM1",&dcb);

(3) SetCommState with some parameter set by the value the device requires
and others by default.
SetCommState(ComID, &dcb);

(4) SetCommTimeouts with no timeout.
SetCommTimeouts(ComID, &comm_timeout);

(5) SetCommMask
SetCommMask(ComID, EV_RXCHAR);

(6) CreateThread.

(7) In the thread created above, WaitCommEvent for a data sent from the
device.
WaitCommEvent(ComID, &EventMask, &event);

(8) Wait until the overlapped operation complete.
GetOverlappedResult(ComID, &event, &Transfer, TRUE);

(9) Get error code and clear.
ClearCommError(ComID, &Error, &ComStat);

(10) Check the receive queue if some data is received.

The problem is that function WaitCommEvent never return!
Instead of WaitCommEvent, I tried to ReadFile(COM1) directly in while loop,
but the loop never ended.

I confirmed that the command from application to the device is correctly sent.
And also confirmed by line monitor connected between the device and COM port
that the device returns correct response for the command sent by my
application.
But why my application can't receive any data?
Almost all the settings are set by general value.

OS is Windows XP Embedded with almost full functionality configuration.

Please help me. Thanks.
 
G

Guest

As mentioned in the previous reply post, if 2nd parameter of ReadFile is set
NULL, GetLastError doesn't return ERROR_IO_PENDING.

I modified the code thus,
ReadFile(hComm, lpvBuf, cbRead, &dwBytesRead, &read_os);
GetOverlappedResult(nComID, &read_os, &dwBytesRead, TRUE);

This code worked well. But the problem is that overlapped operation does not
terminate both WaitCommEvent and ReadFile.

I used some free tools that monitor serial port I/O. I could confirm the
output data flow but not input data at all.
Does this mean that OS input queue does not receive any data from commport?

Slobodan Brcin (eMVP) said:
George,

And my 0.02$ to this:

There is no offset value on pipes and serial drivers. (What would offset mean in a continuous stream without beginning and the end
to the driver)

To reduce confusion to yourself instead of:
rc = ReadFile(hComm, lpvBuf, cbRead, &dwBytesRead, &read_os);
Use:
rc = ReadFile(hComm, lpvBuf, cbRead, 0, &read_os);

dwBytesRead in overlapped case has no meaning.

WaitForSingleObject do not use this, especially not in test sample.
Also use GetOverlappedResult with TRUE.

For instance following should work instead of your code above:

ReadFile(hComm, lpvBuf, cbRead, 0, &read_os);
GetOverlappedResult(nComID, &read_os, &dwBytesRead, TRUE);

Regards,
Slobodan


KM said:
George,

Not going deeply in to the code, a couple of glitches:

- If you open file with FILE_FLAG_OVERLAPPED, you must set the last parameter of the WaitCommEvent to not NULL and pass a
manual-reset event object.
You have, however, this: WaitCommEvent(nComID, &dwEvtMask, NULL);
Please see the msdn sample the link to I posted in some previous reply in this thread.

- For debugging purposes make your code single threading. That may be easy if instead of CreateThread(..., CommPortMonitor,...)
you just call CommPortMonitor.

KM
This is the part of my application that regards to commport communication.
Wait CommEvent thread loop terminates only when application terminated or
fContinue flag turned into ON.
WriteFile() goes well without any problem and the device connected works as
designed.
The device returns correct data for the command sent from my application.
But WaitCommEvent() never returns though the data sent from the device
correctly arrive at the comport.

/***********************************************************************************************
*******************************************Open
ComPort*****************************************
************************************************************************************************/
long OpenCommPort(){
DCB dcb;
HANDLE nComID;
COMSTAT ComStat;
BOOL bBuildComm;
BOOL bSetCommStateRtn;
char szPortSet[256];

//////////////////////// CreateFile
/////////////////////////////////////////////////

nComID = CreateFile("COM1",
GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);


//////////////////////// BuildComm
/////////////////////////////////////////////////

dcb.DCBlength = sizeof(DCB);
GetCommState(nComID, &dcb);
strcpy(szPortSet, "COM1:9600,e,7,2");

bBuildComm = BuildCommDCB(szPortSet,&dcb);


/////////////////////// SetCommState
/////////////////////////////////////////////

ZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
dcb.wReserved = 0;

dcb.BaudRate = CBR_9600;
dcb.fParity = TRUE;
dcb.Parity = 2;
dcb.ByteSize = 7;
dcb.StopBits = 2;

dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fDsrSensitivity = FALSE;
//XON/XOFF
dcb.fOutX = TRUE;
dcb.fInX = TRUE;
dcb.fTXContinueOnXoff = TRUE;
dcb.XonLim = 2048;
dcb.XoffLim = 2048;
dcb.XonChar = 0x11;
dcb.XoffChar = 0x13;

dcb.fBinary = TRUE;
dcb.fNull = FALSE;
dcb.fAbortOnError = TRUE;
dcb.fErrorChar = FALSE;
dcb.ErrorChar = 0x00;

bSetCommStateRtn = SetCommState(nComID, &dcb);


/////////////////////////////////////////////////////////////////////////////////////////////

if (PurgeComm(nComID, PURGE_TXCLEAR | PURGE_RXCLEAR) != TRUE) {
if (GetLastError() != CE_MODE) {
DWORD dwErrors;
if (ClearCommError(nComID, &dwErrors, &ComStat) != TRUE) {
return GetLastError();
}
}
}

COMMTIMEOUTS comm_timeout;
comm_timeout.ReadIntervalTimeout = MAXDWORD;
comm_timeout.ReadTotalTimeoutMultiplier = 0;
comm_timeout.ReadTotalTimeoutConstant = 0;
comm_timeout.WriteTotalTimeoutMultiplier = 0;
comm_timeout.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(nComID, &comm_timeout)) {
return -1;
}

if (ThreadHdl == NULL) {
ThreadHdl = CreateThread(NULL, 0, CommPortMonitor,
this, CREATE_SUSPENDED, &ThreadID);
if (ThreadHdl == NULL) {
return -1;
}
ResumeThread(ThreadHdl);
}

return 0;
}

/***********************************************************************************************
***********************************Wait CommEvent
Thread*****************************************
************************************************************************************************/
extern "C"
DWORD __stdcall CommPortMonitor( void* pparam )
{
DWORD dwEvtMask; // kind of communication event(set in
WaitCommEvent())
DWORD dwError;
COMSTAT ComStat; // status of communication port(set in
ClearCommClear())
BOOL bRet;
int nReadCnt; // bytes received(return value of ReadComPort())

bSetMask = SetCommMask(nComID, EV_RXCHAR | EV_ERR);

while (TRUE) {
bRet = WaitCommEvent(nComID, &dwEvtMask, NULL);
if (!fContinue) {
break;
}
ClearCommError(nComID, &dwError, &ComStat);
if (!bRet) {
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
continue;
}
}

if (dwEvtMask & EV_ERR) { // CE_FRAME, CE_OVERRUN, CE_RXPARITY
//error-handling
continue;
}

if (ComStat.cbInQue > 0) { // check existence of receive data
ReadComPort(nComID, byBuffer, 1024);
//data-handling
}
}

return TRUE;
}

/***********************************************************************************************
*****************************************Read
Data***********************************************
************************************************************************************************/
int HWPIN::ReadComPort(HANDLE hComm, void* lpvBuf, int cbRead)
{
DWORD dwError;
COMSTAT comstat;

BOOL bContinue = TRUE;
DWORD dwBytesRead = 0;
BOOL rc = 0;

read_os.Offset = 0;

rc = ReadFile(hComm, lpvBuf, cbRead, &dwBytesRead, &read_os);
if (!rc && (GetLastError() == ERROR_IO_PENDING)) {
if (WaitForSingleObject(read_os.hEvent, 1000)) {
dwBytesRead = 0;
} else {
rc = GetOverlappedResult(nComID, &read_os, &dwBytesRead, FALSE);
if (rc) {
read_os.Offset = dwBytesRead;
}
}
} else {
read_os.Offset = dwBytesRead;
}

if (rc) {
return read_os.Offset;
} else {
// error handling
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
ClearCommError(nComID, &dwError, &comstat);
return -1;
}
}

/***********************************************************************************************
****************************************Write
Data**********************************************
************************************************************************************************/
int HWPIN::WriteComPort(HANDLE hComm, const void* lpvBuf, int cbWrite)
{
DWORD dwError;
COMSTAT comstat;
DWORD dwBytesWritten = 0;
BOOL rc = 0;

write_os.Offset = 0;

rc = WriteFile(hComm, lpvBuf, cbWrite, &dwBytesWritten, &write_os);
if (!rc && (GetLastError() == ERROR_IO_PENDING)) {
if (WaitForSingleObject(write_os.hEvent, 1000)) {
dwBytesWritten = 0 ;
} else {
rc = GetOverlappedResult( nComID,
&write_os,
&dwBytesWritten, FALSE);
if (rc) {
write_os.Offset = dwBytesWritten;
}
}
} else {
write_os.Offset = dwBytesWritten;
}

if (rc) {
return write_os.Offset;
} else {
// error handling
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
ClearCommError(nComID, &dwError, &comstat);
return -1;
}
}


:

Hi George,

No matter what SetumComm settings that you use (default) serial driver should work.
You have a logic error in your code regarding when you expect to get some data.

Post here complete segment starting with readfile and explain what do you expect to get with each next API call. (This is few
lines
that you should try to explain to your-self, but doing that "aloud" ca usually help)

Regards,
Slobodan

I tested with a simple application in a simple condition.
Connect 2 PCs with serial cable and run above application on both PC.

Everything went well all around.
The data packet sent from 1 PC could be correctly received by another PC.
If some character data is reached to the system receive buffer,
WaitCommEvent is terminated and ReadFile correctly read buffer data.
According to this result, I think the receive data logic is not wrong.
Some field of DCB structure, 2nd parameter of SetCommState, may be wrong for
my appllication or device (or XP Embedded component configuration).

By the way, I found the API SetupComm. Is this API necessary for our
application?

:

George,

Somehow I seem to overlook your reply in this thread.

HasOverlappedIoCompleted returns FALSE.

Yup. This is what we expected, right?
It would be worse if it returned TRUE while GetOverlappedResult returned 0 bytes transferred.

By the way, just after SetCommMask() returns TRUE, GetCommMask() returns
FALSE. Why?

How about checking with GetLastError?

Any 2nd parameter of SetCommMask() results in the same.

Please look at this MSDN sample code to see how it should work in a simple case:
http://msdn.microsoft.com/library/en-us/devio/base/monitoring_communications_events.asp

Your problem does not seem to be related to XPe. You would better off developing, texting and debugging the app on XP Pro
first
and
then move to XPe.
As Slobodan mentioned you can get more help if you open more sources and post in more appropriate NG.

Regards,
KM

:

Just to add to that..

George, look at the HasOverlappedIoCompleted macro to see if it can help to determine the completion of an outstanding
I/O
operation.

--
Regards,
KM, BSquare Corp.


Hi George,

One basic question do you know how overlapped operation are working?

You should choose between one of two following syntaxes.
ReadFile(ComID, lpvBuf, nRead, 0, &read); -----> For overlapped access
ReadFile(ComID, lpvBuf, nRead, &BytesRead, 0); ---> For regular access.

Using both values with overlapped access does not make sense since all operations will return immediately and set
BytesRead to
0
or
some unknown value that represent some data that was already available in internal OS buffers, depending on driver that
you
use.
But
this length info is usually 0 (treat is as undefined).

Length info is filled only during the IO API call not later.
So only way for you to obtain current results of overlapped operation is to read overlapped structure directly or use
API
functions
like GetOverlappedResult.

Also all operations on buffer are not synchronous but rather asynchronous. This mean that you can issue few different
read
and
write
operations on different handles and still execute some other code while drivers and hardware gather your data.

Regards,
Slobodan


Depend on queue status? What's that?

Yes, I tried to GetOverlappedResult() with 3rd parameter TRUE, but no
difference.
GetOverlappedResult() returns successfully but "BytesRead" is always 0.


:

Hi George,

I have not tested another OS than Windows XP Embedded.
Does OS matter about this phenomenon?

Not really, but this NG is less apropriate for this type (API programmming type) of questions. And one SDK/DDK
related
would
be
better for obtaining answers on these topics. When you have something tha twork on XP Pro and do not work on XPe
then
this
is
NG
to
ask for help.

OK I'll try to make test program without sub-thread and set timeout properly.

R/W file operation is simple as below. This operation is done after (10)'s
check.
ReadFile(ComID, lpvBuf, nRead, &BytesRead, &read);
WriteFile(ComID, lpvBuf, nWrite, &BytesWritten, &write);

With overlapped structured BytesRead, BytesWritten usually do not contain values that you expect and they will be
most
likely
0
(depending on queue status).

Wait for completion of overlapped operaion.
GetOverlappedResult(ComID, &write, &BytesWritten, FALSE);

Since both read and write are overlapped, please use GetOverlappedResults to wait for operation to complete after
both
read
and
write operations. Ase last parameter as TRUE for test cases.

Check if "BytesWritten" is over zero, and application specific process.

I also tried without using WaitCommEvent but only ReadFile within eternal
while loop, but the result was same. No data could be read.

What is wrong?

Probably you do not wait to receive data with GetOverlappedResult. (Without complete code I can't tell for sure).

BIOS level setting?
NO. Has nothing to do with this.
OS setting?
NO, since you configure DCB, timeouts etc.

Shortage of pre-configuration in my application?
NO. You have configured all that is needed. But set timeouts (if you want them, for test they are not important)

Regards,
Slobodan


:

Hi George,

Does this work on XP Pro?

Why do you create new thread for simple test? Simplify your test case.
Always use timeouts for receive operation. (Unless you want your program to stuck if there is not enough data
requested by
read
operation).
Either SetCommMask or WaitCommEvent caused problems for me long time ago so I do not use them.(There is no need
for
them
especially
since you use overlapped access).
Where are read and write file in your example?

Regards,
Slobodan

Hi.
Please give me some advise.
I want to communicate with a device via COM port and coded typical
communication program using Windows SDK.

The program sequence is thus...
(1) CreateFile with overlap mode.
ComID = CreateFile("COM1",GENERIC_READ | GENERIC_WRITE, 0,NULL,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);

(2) BuildCommDCB
BuildCommDCB("COM1",&dcb);

(3) SetCommState with some parameter set by the value the device requires
and others by default.
SetCommState(ComID, &dcb);

(4) SetCommTimeouts with no timeout.
SetCommTimeouts(ComID, &comm_timeout);

(5) SetCommMask
SetCommMask(ComID, EV_RXCHAR);

(6) CreateThread.

(7) In the thread created above, WaitCommEvent for a data sent from the
device.
WaitCommEvent(ComID, &EventMask, &event);

(8) Wait until the overlapped operation complete.
GetOverlappedResult(ComID, &event, &Transfer, TRUE);

(9) Get error code and clear.
ClearCommError(ComID, &Error, &ComStat);

(10) Check the receive queue if some data is received.

The problem is that function WaitCommEvent never return!
Instead of WaitCommEvent, I tried to ReadFile(COM1) directly in while loop,
but the loop never ended.

I confirmed that the command from application to the device is correctly sent.
And also confirmed by line monitor connected between the device and COM port
that the device returns correct response for the command sent by my
application.
But why my application can't receive any data?
Almost all the settings are set by general value.

OS is Windows XP Embedded with almost full functionality configuration.

Please help me. Thanks.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top