2
votes

I'm trying to implement a protocol over serial port on a windows(xp) machine. The problem is that message synchronization in the protocol is done via a gap in the messages, i.e., x millisecond gap between sent bytes signifies a new message. Now, I don't know if it is even possible to accurately detect this gap.
I'm using win32/serport.h api to read in one of the many threads of our server. Data from the serial port gets buffered, so if there is enough (and there will be enough) latency in our software, I will get multiple messages from the port buffer in one sequence of reads.

Is there a way of reading from the serial port, so that I would detect gaps in when particular bytes were received?

4
Best example of how not to define a protocol I've ever come across.anon
Well, I think that in this situation, I would suggest digging up an FPGA and programming it to read the protocol, then sending messages out to you on Ethernet or a serial port. I don't see how you're going to manage real-time control on windows without some serious driver hacking.Paul Nathan
Additional info: there is a standard header (one byte) in the message and a message size indicator, but IMHO this is not enough. If ever the size of message is transmitted with an error, I would read an incomplete message from the buffer (or a piece of following message). What is more, the header is just a byte value so same bit pattern can (and will) occur in message internal data. If I start reading the data as a new message I will be out of synch with the sender. That's why I want to actually use that timing info as described in the protocol.Marcin K
I thought so. You all grew up with the web, I didn't. Let me guess, the one byte is 1(SOH) or 2(STX)? IMVEO it is enough. You just need to think outside the box. You receive message_delimiter followed by 4 (as length) and then 4 bytes of data. A valid message is not those 6 bytes. A valid message is always bounded by the message_delimiter, so it would look like message_delimiter 4 - length (4 data bytes) message_delimiter I'll post this as an answer so it will be clearer.dbasnett
This is well after the fact, but future readers should probably be made aware that modern serial chips can have VERY large FIFOs (128 bytes or more, compared to 16 in the origina 16550), which can mean the time between when a set of characters is received by the serial chip, and when it gets around to alerting the driver may by very large (perhaps 32 character times). If you are dealing with short messages and low latency requirements, this can be deadly, and may require custom drivers, or perhaps even custom hardware to make work properly.Michael Kohne

4 Answers

2
votes

If you want more control over a Windows serial port, you will have to write your own driver.

The problem I see is that Windows may be executing other tasks or programs (such as virus checking) which will cause timing issues with your application. You application will not know when it has been swapped out for another application.

If possible, I suggest your program time stamp the end of the last message. When the next message arrives, another time stamp is taken. The difference between time stamps may help in detecting new messages.

I highly suggest changing the protocol so that timing is not a factor.

1
votes

I've had to do something similar in the past. Although the protocol in question did not use any delimiter bytes, it did have a crc and a few fixed value bytes at certain positions so I could speculatively decode the message to determine if it was a complete individual message.

It always amazes me when I encounter these protocols that have no context information in them.

Look for crc fields, length fields, type fields with a corresponding indication of the expected message length or any other fixed offset fields with predictable values that could help you determine when you have a single complete message.

Another approach might be to use the CreateFile, ReadFile and WriteFile API functions. There are settings you can change using the SetCommTimeouts function that allows you to halt the i/o operation when a certain time gap is encountered.

Doing that along with some speculative decoding could be your best bet.

0
votes

It sounds odd that there is no sort of data format delineating a "message" from the device. Every serial port device I've worked with has had some form of a header that described the data it transmitted.

Just throwing this out there, but could you use the Win32 Asynchronous ReadFileEx() and WriteFileEx() system calls? They allow you to attach a callback function, and then you might be able to manage a timer within the callback. The timer would only provide you a rough estimation, however.

If you need to write your own driver, the Windows Driver Kit has a sample that shows how to write a serial port driver. I can't imagine that you'll be able to override the Windows serial port bus driver(the driver that directly controls the serial port on your Windows machine), but you might be able to write a driver that sits on top of the bus driver.

0
votes

I thought so. You all grew up with the web, I didn't, though I was present at the birth. Let me guess, the one byte is 1(SOH) or 2(STX)? IMVEO it is enough. You just need to think outside the box.

You receive message_delimiter followed by 4 (as length) and then 4 bytes of data. A valid message is not those 6 bytes.

    message_delimiter - 1 byte
    4 - length - 1 byte
    (4 data bytes) - 4 bytes

A valid message is always bounded by the message_delimiter, so it would look like

    message_delimiter - 1 byte
    4 - length - 1 bytes
    (4 data bytes) - 4 bytes
    message_delimiter - 1 byte