Click to See Complete Forum and Search --> : Simultaneous access to a serial device from two threads


Juergen Kordes
July 6th, 2005, 04:00 AM
Hi,
can anybody tell me how to access to a serial device from two different threads simultaneously?
The problem: I open a serial device in a function (with 'CreateFile(...)'), then I start one thread for writing to this device and one for reading. Reading and writing must be independent, because I can receive unexpected data or have to send some unexpectedly.
Passing the device's handle to the threads just lets one thread (the one which tries to access later) crash. In the writing thread I call 'WriteFile(hdlSerDev,...)', in the reading thread I call 'WaitCommEvent( hdlSerDev,...)'.

naddad
July 6th, 2005, 09:16 AM
Do you know about mutexes??

MrViggy
July 6th, 2005, 11:47 AM
How is it crashing? Are you passing the "FILE_FLAG_OVERLAPPED" flag, for read/write access to the handle?

Viggy

Juergen Kordes
July 7th, 2005, 03:17 AM
How is it crashing? Are you passing the "FILE_FLAG_OVERLAPPED" flag, for read/write access to the handle?

Viggy
Hi Viggy,
it depends, which thread is faster than the other. If for example the read-thread starts first and calls 'WaitCommEvent(pSerial->hComPort,&dwCommModemStatus,NULL);' the write-thread crashes when calling 'if(!WriteFile(pSerial->hComPort,...);'. It just calls the function and never comes back.
I guess, just as you mentioned, that I have to use the OVERLAPPED-structure when creating and accessing the handle. Yesterday I found an article about that, but I'm not shure how to use this functionality. Do you know where I can read something about it?

Thank you for your help!

Best regards

Juergen

MrViggy
July 7th, 2005, 11:22 AM
Did you try the MSDN:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/createfile.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/devio/base/communications_resources.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/devio/base/read_and_write_operations.asp

The serial ports (and parallel ports) are considered "communication resources." There should be some examples on Microsoft's web site as well.

Viggy

Juergen Kordes
July 8th, 2005, 09:16 AM
Hi Viggy,
I've got it, it's working properly now. Thank you very much!

Juergen

Paul_C.
August 3rd, 2005, 07:51 AM
How did you achieve it? It seems that I am working on a similar project. I have to do reading and writing via rs-232. Can you give me a hint?
I would go for overlapped communication. At the moment I have only one thread, but I intend in creating another. Or is it not useful?

Juergen Kordes
August 10th, 2005, 08:46 AM
Hi Paul,

1. Open the device with the FILE_FLAG_OVERLAPPED attribute.

2. When writing to or reading from the device generate a variable like this

OVERLAPPED ov;
memset(&ov,0,sizeof(ov));
ov.hEvent = CreateEvent( 0,true,0,0);

and pass this variable to your WaitCommEvent, ReadFile or WriteFile(..., &ov) calls.

3. Use WaitForSingleObject(...) to wait for the event created for the OVERLAPPED structure and passed to the WaitCommEvent function.
Don't forget to use a CRITICAL_SECTION, if you read und write in two different threads.

For further information just write me (JuergenKordes@cinram.com) or visit the sites Viggy mentioned above. Or just have a look at codeguru or codeproject.

Best regards

Juergen

Paul_C.
August 17th, 2005, 09:46 AM
Sorry for not answering for a while. I am trying now to put all pieces together. I will let you know if I got any problem with this. And I am pretty sure about this. ;)
And thanks for the help.

Bharath Reddy k
August 19th, 2005, 06:18 AM
Hi,
I am writing an program using embedded vc++ for WinCe OS. WinCe doesn't support Overlapped structure and also WaitCommEvent function.
I am using two threads to read data from serial port and another thread to write. now i am facing a porblem, after receving data from port i need to send an acknowledgement to port so that i can read further data.

if any body can help me regarding this problem.

i have written below code to read data from Serial port.

BOOL CSerialPortComm::ReadFromPort(char* lpBuf,int &nCount,HANDLE handle)
{
DWORD dwCommEvent = 0;
DWORD dwRead;
CString str= "";
do
{
BOOL bRet = ReadFile(m_hPort, &lpBuf,8, &dwRead, NULL);
if(bRet == TRUE && dwRead > 0)
{
DWORD dWord = 0;
WriteFile(handle,&lpBuf,8,&dWord,NULL);
SetFilePointer(handle,NULL,NULL,FILE_END);
g_bReadReturn = TRUE;
nCount = dwRead;

lpBuf++;
g_bReadReturn = TRUE;


}
else
{
g_bReadReturn = FALSE;
}

}while(dwRead > 0);
}

can anybody explains me how to send an acknowledgement to port and read further data.

with ,
kind regards,

Juergen Kordes
September 5th, 2005, 06:32 AM
Hi,
I am writing an program using embedded vc++ for WinCe OS. WinCe doesn't support Overlapped structure and also WaitCommEvent function.
I am using two threads to read data from serial port and another thread to write. now i am facing a porblem, after receving data from port i need to send an acknowledgement to port so that i can read further data.

if any body can help me regarding this problem.

i have written below code to read data from Serial port.

BOOL CSerialPortComm::ReadFromPort(char* lpBuf,int &nCount,HANDLE handle)
{
DWORD dwCommEvent = 0;
DWORD dwRead;
CString str= "";
do
{
BOOL bRet = ReadFile(m_hPort, &lpBuf,8, &dwRead, NULL);
if(bRet == TRUE && dwRead > 0)
{
DWORD dWord = 0;
WriteFile(handle,&lpBuf,8,&dWord,NULL);
SetFilePointer(handle,NULL,NULL,FILE_END);
g_bReadReturn = TRUE;
nCount = dwRead;

lpBuf++;
g_bReadReturn = TRUE;


}
else
{
g_bReadReturn = FALSE;
}

}while(dwRead > 0);
}

can anybody explains me how to send an acknowledgement to port and read further data.

with ,
kind regards,
Hi Barath,
I'm not sure if I understood your problem, but it's not necessary to use the send-thread for this task. Just add the following lines to your code:

BYTE Byte = 0x06; // Acknowledge

DWORD dwNumBytesWritten;
if(!WriteFile(m_hPort, // port handle
&Byte, // Pointer to the data to write
1, // Number of bytes to write
&dwNumBytesWritten, // Number of written bytes
NULL) // must be NULL for Windows CE
)
// Do some error reporting
{... }

Then embrace the whole stuff (your code and the new one) with a while(...)-statement to loop.

Another way could be setting a variable, an event or so to inform the write-thread to send an acknowledge.
In Windows CE it's possible to access a device from two threads at the same time without locking it (e.g. with a CRITICAL_SECTION). You just call WaitCommEvent(...) in the receive-thread and WriteFile(...) in the send-thread. In Windows 2000 for example this is not allowed and the later thread crashes.

Hope this could help you solve the problem.

Best regards

Juergen

Siddhartha
September 5th, 2005, 07:16 AM
Yes, using CRITICAL SECTIONS makes a piece of code thread safe - such that only one thread is allowed to enter the bracketed code at a time.

A sample Critical Section is created and initialized using -
// Create a Critical Section Object - outside the function that needs thread safety
CRITICAL_SECTION myCS = {0};

// Initialize it...
::InitializeCriticalSection (&myCS);This Critical Section is made accessible from the code that is called by multiple threads.

The actual workings of it inside this method invoked by multiple threads are... // Mark entry... This is inside the code that is accessed by two threads - Pass myCS to the method - not a copy
::EnterCriticalSection (pmyCS);

// Your thread safe code comes here...

// Mark exit...
::LeaveCriticalSection (pmyCS);Once the threads-related activity is over, one needs to free the resource -
// Done with the threads? Delete the Critical Section.
::DeleteCriticalSection (&myCS); For references on Thread Synchronization, read -


FAQ: Where can I find references on Multithreading? (http://www.codeguru.com/forum/showthread.php?p=1222389#post1222389)

cvogt61457
September 5th, 2005, 10:37 AM
When working with hardware devices, I would suggest that you limit the
access to the device to a single thread to elminate the problem that you
are having. Search for the CSerialPort project here or on CodeProject.

Multiple points of control make it very difficult to debug later once
the program has been distributed.

:confused: Also, how do you determine where the received data goes to?
Does it go to thread 1 or thread 2?