Thanks
Robert
"Arkej" <NOSPAMro...@REPLACESINETsiol.si> wrote in message
news:%23ZBhNTj...@TK2MSFTNGP02.phx.gbl...
And you must call "timeBeginPeriod(1)".
--
Greetings
Jochen
My blog about Win32 and .NET
http://blog.kalmbachnet.de/
Also, for real time serial protocols I'd warmly recommend
a cheap programmable microcontroller, connected to PC
over USB, ethernet or even serial port (not in real-time, of course).
Regards,
--PA
thanks for the tips. I'm gonna try to read the comm with timeouts,
completion ports etc... What I tried was a loop in a thread with a
Sleep(1)(I guess this one does not come back in time when load on the system
increments). In my test I log what and when I've read and it's interesting
that when there is a delay it also logs all the bytes accumulated in the
buffer. I supposed the driver is in fact reading from the device and filling
the buffer. My approach was maybe wrong because using ClearCommError to get
num of bytes in the buffer and then start an asynch readfile on it in a loop
that is sleeped looks like no good for fluency.
As much as I've had time to look in the WDF it is all new to me and it would
take a lot of time to learn and get experience.
Thanks again.
Robert
"Jochen Kalmbach [MVP]" <nospam-Joch...@holzma.de> wrote in message
news:%23LrgVyk...@TK2MSFTNGP05.phx.gbl...
> What I tried was a loop in a thread with a
> Sleep(1)
This implies a wait of about 12-15 ms!
Set "timeBeginPersion(1)", this will decrese the delay to 2 ms...
> I supposed the driver is in fact reading from the device and filling
> the buffer.
Yes.
thank you for your hints. What I did in my test with timeouts was to set
ReadIntervalTimout = MAXDWORD to make a call to Readfile function return
immediately. That's all I do with timeouts.
As described in reply above this thread I then read in a loop using
ClearCommError to get the status of the device and read asynchronously the
bytes. Realtime priority gave some results but still sometimes there were
delays(I guess sleep(1) is the most delaying line in my code but also
without it there are still delays and the system gets nonresponsive). I'm
already looking for a hw/sw solution but I need a quick one now until the
hw(microcontroller) is built.
Regards,
Robert
"Pavel A." <pav...@NOfastmailNO.fm> wrote in message
news:%23osAvHm...@TK2MSFTNGP02.phx.gbl...
> delays(I guess sleep(1) is the most delaying line in my code but also
> without it there are still delays and the system gets nonresponsive). I'm
You need at least *two* core-CPUs to use "realtime-priority" with an
endless loop! If you have just one core, then the UI will never respond...
Regards
Robert
"Jochen Kalmbach [MVP]" <nospam-Joch...@holzma.de> wrote in message
news:emTn8ls9...@TK2MSFTNGP06.phx.gbl...
Again, spinning in the app is absolutely pointless.
The app won't see the i/o completed before the driver completes it.
And the driver will complete it *immediately* when the preset
condition occurs, this isn't bound by timer resolution.
Regards,
--PA
On this page http://www.lvr.com/serport.htm
you can find more info on serial ports under Windows.
Regards,
--PA
int CCOMreader::Read()
{
DWORD dwError;
DWORD dwRes;
COMSTAT pStat;
bool bResult;
if (bReadWaiting)
{//if previous read hasn't finish return
if ((dwRes = WaitForSingleObjectEx( hReadCompleted, 0, FALSE)) !=
WAIT_OBJECT_0)
{
return 0;//read still in progress
};
if (!GetOverlappedResult(hStream, &olRead, &nBytesRead, TRUE))
{
char cstrTemp[80];
sprintf(cstrTemp, "Read GetOverlappedResult error: %d", GetLastError());
Output(cstrTemp);
};
bReadWaiting = false;//reading finished
ResetEvent(olRead.hEvent);
};
//dump the buffer into log
if (nBytesRead > 0)
{
Output("iC:" + DumpData((BYTE *)bufMsg, nBytesRead));
ZeroMemory(bufMsg,sizeof(bufMsg));
nBytesRead = 0;
};
//if anything on the device call ReadFile asynchronously
ClearCommError( hStream, &dwError, &pStat);
if( dwError )
{
char strE[80];
ZeroMemory(strE,sizeof(strE));
sprintf( strE, "ERR: dwError on comm port check == 0x%08x", dwError);
Output(strE);
}
if (pStat.cbInQue > 0) //read if anything
{
bResult = ReadFile( hStream,
bufMsg,
pStat.cbInQue,
&nBytesRead,
&olRead
);
if (!bResult)
{
dwError = GetLastError();
if (dwError != ERROR_IO_PENDING)
{
char strE[100];
ZeroMemory(strE,sizeof(strE));
sprintf( strE, "ERR: FATAL I/O Error %ld I/O Context %lx.%lx\n",
dwError, &(olRead), olRead.hEvent);
Output(strE);
}
else
{
bReadWaiting = true;//overlapped read in process
};
};
};
}
"Pavel A." <pav...@NOfastmailNO.fm> wrote in message
news:uLJUxLv9...@TK2MSFTNGP02.phx.gbl...
That is what hardware flow control is used for.
There are two sides to this which I can generalized as follows:
- Receive as fast as you can with high buffers
- Transmit as fast as you can with lower buffers.
This "bucket brigade" concept is simple:
The sender will never know how big or how fast the receiver can handle
the sender's pumping of data. If you used high transmit buffer, the
odds are very good you will get flow control signals. Its not
efficient. In a bucket brigade, one node can not go any faster than
the next and you can't fill it any more than bucket can hold. So an
efficient brigade is one that is near continuous without stopping.
On the other hand, the receiver is fully aware of what it can handle
so it should not be designed to slow down its reception of data -
"Give me what you got" attitude, "I can handle whatever you can send."
It should be a draining concept, don't read a few bytes at time. Get
it all during that one signal instance. But you need to do this
asynchronously and not ask for too much because that can put pressure
on the system to fulfill your request.
Most high end com packages traditionally used a three threads per PORT
approach:
- a receiver thread using a circular buffer, i.e., 16K
- a sender thread using a circular buffer, i.e, 4K
- a UI thread (passive, main or otherwise), that
can read events from the receiver thread or transmit
thread, or it can be done procedurally.
The receiver/transmit thread might run in a lightly higher priority.
Also, the protocols you might use, i.e, transfer a file with ZMODEM,
XMODEM, YMODEM, KERMIT, etc, will help design some of the settings
too. For example, ZMODEM can start with 16K windows that can be
reduced during the protocol transmission if it finds too many retries.
XMODEM on the other hand is a fixed 128 BYTE block concept - very
inefficient.
Overall, the key is to make sure you get your flow control right. You
need to prepare the port with the right set of hardware flow control
flags with the right sizes for buffers and also your timeouts to
minimize the number of cycles.
Finally, a general rule of thumb in thread synchronization
(especially in a non-RTOS) is to stay away from depending on "sleep"
and loop designs in a vain attempt to synchronize I/O. You might get
it to work in one environment, but inevitably its going to bite you
:-) There are scores of books discussions on the subject. Google it.
Keep in mind these designs pre-dated I/O Comp ports ideas, that may
help reduced threads and scalability issues. In my exploration done a
few years ago, I found there some efficiency issues - never mind the
more complex designs especially with our virtual com I/O model, i.e, I
found issues with using the same IOCP model used for sockets, for
RS232. Theoretically should work the same but it doesn't. :)
I do want to give it another shot one day, but we have yet to find a
good reason to break what isn't broke. :-)
--
Yes to the first question, "no guarantees" to the second.
Until now the WaitCommEvent solution with readfile after that gave me the
best results. I'm trying now to achieve the same without WaitCommEvent but
only by setting the commtimeouts. As for now the best is RIT = MAXDWORD,
RTTM = MAXDWORD, RTTC = 30. And no more sleeps in there! Timeperiod set to
1! Pretty promising on a dual core machine.
Thanks again for all the tips to all!
Robert
"Ben Voigt [C++ MVP]" <r...@nospam.nospam> wrote in message
news:%23rRHJ5$9IHA...@TK2MSFTNGP05.phx.gbl...