Accessing half-duplex serial port with POSIX - serial-port

I'm asked to read from and write to a half-duplex serial connection using POSIX calls (more specifically, writing in C on Linux 2.6.x). I'm having slight troubles finding detailed information on that particular model (most pages concentrate on full-duplex) and as I am getting slight anomalies when reading, I wanted to check whether maybe I am doing something wrong here.
With a half-duplex serial connection, I can only read or write. This is not a problem, as there is no unsolicited incoming data on the line - the only time any packages are sent to me (for reading) is when I asked for them beforehand.
So what my code does is to write() to the port whenever something needs to be sent. Should this data result in a response (something I know beforehand), I simply read(). There are no special functions I am calling - but maybe I should? And is this approach correct? I.e. write when the line is free?

I would read the Linux kernel source documentation, there may be a text file about the serial driver; if not, you could read through the actual driver code to see what it does (it's not as scary as it sounds, I promise!)

Related

Why is reading and writing to serial so unreliable?

I've been having to come back to a modem I have and sending AT commands to it, and I need to do this programmatically. Sending AT commands works fine if using Minicom, but when using any kind of programatic method it's just super unreliable. I've tried echos and redirection with bash, the atinout program, and the pyserial module in Python, but no matter what sending and receiving commands is iffy at best. It is very rare that I attempt to run the same AT command twice and get consistent output back. I'll get the complete response one time, but then a partial response the next, or maybe no response.
Admittedly I don't know much about serial, so maybe it's my hardware, or maybe the protocol for reading and writing to serial is just unreliable. Can someone please explain how, in general, reading and writing output over a serial port may be unreliable, and any good techniques or libraries to help guarantee a stable flow of reading and writing?
There was another service on my system called ModemManager that was consuming the serial device at the same time I was running through my commands. Once that was disabled all of my programmatic efforts started producing reliable IO to the device.

Forcing a signal on an interface (RS-232)

Firstly, this may be a stupid question or one that has been asked before but I am not quite sure how to google it.
I try to learn a bit about using modbus to communicate over serial interfaces and I have trouble understanding the mechanic of getting your signal on the wire/connection. I do unterstand how protocols (e.g. Modbus) encode and decode their Data. I'm interested in the process of getting your bitcode through the interface (preferably rs232) to the other machine.
In other words: How can I write a piece of code myself (no libraries etc. I want to learn how to do it) where I can input a couple of binary numbers and maybe the baudrate so that another device with a working modbus driver can receive it via direct cable connection.
If the matter is too complicated for an answer here, I'd be happy to get a link to some resources to teach myself as well. Or even some help for the right search terms.

how to know when no data is coming on serial port unix

I'm working with 2 little machines with limited unix tools. Both are conected between each other via serial. I'm transfering binary data, so the devices are on raw mode. The sending machine is sending files to the other one and between there's a delay of X ms (specified as parameter). I would like to know if it's possible to measure those delays on destination machine in order to identify how many files are coming. Till now i was using cat < /dev/ttyS5, but this is not a option to my purpose.
Any idea?
Thanks
IMHO the easiest way is to write a little program which is waiting for bytes on the serial line.
Everytime a character arrives some sort of timer/timestamp is reset.
Another thread could be evaluation this timer/timestamp in a loop and increment a counter if it's larger than a defined value.
But please be aware that you might experience delays from the serial line as there's the kernel and its scheduler "in between". Furthermore you'll need appropriate locking of course!

Designing a protocol for commands and data over serial

I need (to design?) a protocol for communication between a microprocessor-driven data logger, and a PC (or similar) via serial connection. There will be no control lines, the only way the device/PC can know if they're connected is by the data they're receiving. Connection might be broken and re-established at any time. The serial connection is full-duplex. (8n1)
The problem is what sort of packets to use, handshaking codes, or similar. The microprocessor is extremely limited in capability, so the protocol needs to be as simple as possible. But the data logger will have a number of features such as scheduling logging, downloading logs, setting sample rates, and so on, which may be active simultaneously.
My bloated version would go like this: For both the data logger and PC, a fixed packet size of 16 bytes with a simple 1 byte check sum, perhaps a 0x00 byte at the beginning/end to simplify recognition of packets, and one byte denoting the kind of data in the packet (command / settings / log data / live feed values etc). To synchronize, a unique "hello/reset" packet (of all zero's for example) could be sent by the PC, which when detected by the device is then returned to confirm synchronization.
I'd appreciate any comments on this approach, and welcome any other suggestions as well as general observations.
Observations: I think I will have to roll my own, since I need it to be as lightweight as possible. I'll be taking bits and pieces from protocols suggested in answers, as well as some others I've found... Slip,
PPP and HLDC.
You can use Google's Protocol Buffers as a data exchange format (also check out the C bindings project if you're using C). It's a very efficient format, well suited to such tasks.
Microcontroller Interconnect Network (MIN) is designed for just this purpose: tiny 8-bit microcontrollers talking to something else.
The code is MIT licensed and there's embedded C and also Python implementations:
https://github.com/min-protocol/min
I wouldn't try to invent something from scratch, perhaps you could reuse something from the past like ZMODEM or one of its cousins? Most of the problems you mention have been solved, and there are probably a number of other cases you haven't even though of yet.
Details on zmodem:
http://www.techfest.com/hardware/modem/zmodem.htm
And the c source code is in the public domain.

Serial Comms dies in WinXP

A bit of history: We have an application, which was originally written many years ago (1998 is the first date in PVCS but the app is about 5 years older than that as it originally was a DOS program). This application communicates with a piece of hardware via serial. When we got to Windows XP we started receiving reports of the app dying after a short time of running. It seems that the serial comms just 'died' and the app was left in a stuck state. The only way to recover from this situation was to restart the application.
The only information I can find regarding this problem was apparently the Windows Message system would miss that information was received, the buffer would fill and the system would get stuck. This snippet of information was left in a old word document, but there's no evidence to back this up. It also mentions that this is only prevalent at high baud rates (115200+).
The solution was to provide customers with USB->Serial converters along with the hardware.
Today: We are working on a new version of the hardware that will run across a network as well as serial ports. So to allow me to work on the network code, minus the actual hardware we are using a VSCOM NetCom113 device. It also installs a virtual comm port on the users (ie: mine) machine.
Now I have got the network code integrated with the app, it appears that the NetCom device exhibits the same behaviour as a physical commport. This is undesirable as I need the app to run longer than ~30 seconds.
Google turns up zero problems that we experience.
I was wondering:
Has anyone experienced this before? If so what did you do to fix/workaround the problem?
Does anyone have any suggestions as to whether the original author of the document is correct and what I can do to test the theory?
Unfortunately I can't post code as the serial code is tightly couple with the rest of the system, though if you have questions regarding it I can answer questions about it.
Updates:
The code is written using Win32 Comm routines - so I am using CreateFile, ReadFile. There's also judicious calls to GetOverlappedResult.
It's not hanging per se, it's just that the comms stops. You can access the menus, click the buttons, but nothing can interact with the connected hardware. Using realterm you can see that no data is coming in or going out.
I think the reference to the windows message is that the problem is internal to windows. Data has arrived but the kernal has missed it and thus not told the rest of the system about it.
Flow control is not used.
Writing a 'simple' test is difficult due the the fact that the code is tightly coupled and the underlying protocol is quite complex and would require a lot of work.
Are you using DOS-style serial code, or the Win32 CreateFile approach?
If the former, be very suspicious: if at all possible I'd convert to the latter.
If the latter, do you know on what kind of system call it's hanging? Are you in a blocking read call? or an overlapped I/O call? or waiting on an event? (I'm not sure I have enough experience to help, but those are the kinds of questions that come to mind)
You might also check into the queue size, which you can set with the SetupComm function.
I don't buy the "Windows Message system" stuff -- it sounds fishy; you can write good Win32 serial i/o code that never uses Windows messages.
edit: does your Overlapped I/O use events? I seem to remember something about auto-reset events occasionally missing their trigger... check your overlapped I/O calls very carefully to see whether you're handling the possible outcomes properly. Perhaps there's a way to make your code more robust by automatically cancelling the overlapped i/o and restarting another read. (I assume the problem is in the read half, not the write half?)
edit 2: A suggestion: assuming the win32 side has missed a byte or packet, and your devices are in deadlock because they're both expecting each other to respond to something, can you tweak the other side of the serial I/O to regularly send some type of "ping" packet with an incrementing counter? (and log the ping packets on the PC side; that way you can see whether you've missed any)
Are you sure you have your flow control set up correctly? DTR, RTS, etc...
-Adam
i have written apps that use usb / bluetooth serial ports and have never had an issue. with bluetooth i have seen bit rates (sustained) of 800,000 bps for long periods of time. most people don't properly implement the port.
My serial port
Not sure if this is a possibility for you, but if you could re-write the code using C#.NET you'd have access to the SerialPort class there. It might remedy your problem. I know a lot of legacy code based around the Win32 API for hardware I/O ports tended to fail in XP due to timing (had a small bit of experience with MIDI).
In addition, I don't know if you can use the Win32 method of Serial Port access in Vista, so that might shut out future MS OSes from being able to use your code.

Resources