Serial I / O with overlap / no overlap with Windows / Windows CE

I'm sorry this is not a question, but more to help people who have problems with these specific things. The problem I'm working on requires the use of serial I / O, but mostly works under Windows CE 6.0. However, I was recently asked if the application can also work under Windows, so I decided to solve this problem. I spent quite a bit of time looking to see if anyone had the answers I was looking for, and all this came across a lot of misinformation and things that in some cases were mostly wrong. Therefore, having solved this problem, I decided to share my conclusions with everyone so that everyone who faced these difficulties would receive answers.

In Windows CE, OVERLAPPED I / O is NOT supported. This means that bidirectional communication through the serial port can be quite troublesome. The main problem is that when you expect data from the serial port, you cannot send data, because it will block the main thread until the read operation or timeouts are complete (depending on whether you have timeouts set)

Like most people doing serial I / O, I had a serial reader stream to read the serial port, which used WaitCommEvent () with the EV_RXCHAR mask to wait for serial data. Now this difficulty arises in Windows and Windows CE.

If I have a simple stream of readers like this, as an example: -

UINT SimpleReaderThread(LPVOID thParam)
{
    DWORD eMask;
    WaitCommEvent(thParam, &eMask, NULL);
    MessageBox(NULL, TEXT("Thread Exited"), TEXT("Hello"), MB_OK);
}

, - , , thParam .. Windows, WaitCommEvent(), , . , , ... MessageBox()? , , Windows CE Windows , -.

Windows CE , WaitCommEvent(), SetCommMask (COMMPORT_HANDLE, 0) CloseHandle (COMMPORT_HANDLE). , , , . Windows, , , , WaitCommEvent(). , WaitCommEvent() Windows? , OVERLAPPED I/O, , Windows CE, OVERLAPPED I/O . , Windows, WaitCommEvent(), CancelSynchronousIo(), WaitCommEvent(), , . CancelSynchronousIo() , Windows CE, !

, ? , WaitCommEvent(), Windows, Windows CE. ReadFile(), , NON OVERLAPPED I/O, WILL .

ReadFile() COMMTIMEOUTS , , , , . - , , 100% . , , , , .

typedef struct
{
    UINT8 sync;
    UINT8 op
    UINT8 dev;
    UINT8 node;
    UINT8 data;
    UINT8 csum;
} COMMDAT;

COMSTAT cs = {0};
DWORD byte_count;
COMMDAT cd;

ZeroMemory(&cd, sizeof(COMMDAT));
bool recv = false;
do
{
    ClearCommError(comm_handle, 0, &cs);
    if (cs.cbInQue == sizeof(COMMDAT))
    {
        ReadFile(comm_handle, &cd, sizeof(COMMDAT), &byte_count, NULL);
        recv = true;
    }
} while ((WaitForSingleObject(event_handle, 2) != WAIT_OBJECT_0) && !recv);
ThreadExit(recv ? cd.data : 0xFF);

, , event_handle Windows Windows CE.

, , , .

+5
1

, , , . , , , ( ), #ifdef, , .

-, CancelSynchonousIo , . - Cancel for CE (, , ?);

typedef BOOL (WINAPI *CancelIo)(HANDLE hThread);

HANDLE hPort;

BOOL CancelStub(HANDLE h)
{
    // stub for WinCE
    CloseHandle(hPort);
}

void IoWithCancel()
{
    CancelIo cancelFcn;

    cancelFcn = (CancelIo)GetProcAddress(
        GetModuleHandle(_T("kernel32.dll")), 
        _T("CancelSynchronousIo"));

    // if for some reason you want something to happen in CE
    if(cancelFcn == NULL)
    {
        cancelFcn = (CancelIo)CancelStub;
    }

    hPort = CreateFile( /* blah, blah */);

    // do my I/O

    if(cancelFcn != NULL)
    {
        cancelFcn(hPort);
    }
}

, , , , (, ++, ) :

HANDLE hPort;

void IoWithOverlapped()
{
    DWORD overlapped = 0;
    OSVERSIONINFO version;

    GetVersionEx(&version);
    version.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    if((version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
        || (version.dwPlatformId == VER_PLATFORM_WIN32_NT))
    {
        overlapped = FILE_FLAG_OVERLAPPED;
    }
    else
    {
        // create a receive thread
    }

    hPort = CreateFile(
        _T("COM1:"), 
        GENERIC_READ | GENERIC_WRITE, 
        FILE_SHARE_READ | FILE_SHARE_WRITE, 
        NULL, 
        OPEN_EXISTING, 
        overlapped,
        NULL);
}
+5

All Articles