[SOLVED] Trouble getting all data out of usbserial (/dev/ttyUSBx)
Linux - SoftwareThis forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Trouble getting all data out of usbserial (/dev/ttyUSBx)
This question could possibly fall under: application architecture, USBSERIAL driver settings, or OS scheduling rules.
MontaVista Linux on Intel Z530 1.6 GHz board.
I have an embedded device which employs several serial USB inputs. All are serial, one of them is the main piece which operates at 115,.2K N81, and from measurements and calculations, we're filling approximately 1/5 of the available bandwidth.
I have a line tracer which allows me to grab the 232 data directly from the generating hardware. This is my gold level standard, because it's the originating data.
I noticed that the embedded data had some gaps and upon looking further, the gaps are frequent and large.
Diagnosing these ways shows the following results:
1.) If I cat the /dev/ttyUSBx to a file and then compare against my line trace, no problems. Great news, the driver is working fine.
2.) If I write a test application which all it does is read /dev/ttyUSBx and writes this data to a file; then compare against my line trace, no problems. Good, because it is possible to see valid data via a program.
My application employs three processes, one reads a lower speed and not-normally talking serial USB. It is a device which responds only when queried. The main process reads the 115.2K serial USB, deframes the data, and dispatches it to the third process, a Qt GUI. I have already debugged that virtually any thing at any rate sent from the main process to the GUI works fine. I have also verified that this main process absolutely is the culprit where my data loss is occurring.
I've trimmed down this main process so that it does nothing besides reads the data and send it to a log file. And there are still problems. This is similar with my test application above. The difference is that these three applications are related actually by a forth process which acts as a main daemon. The daemon spawns each child via fork(), and merely waits on signals in case any of the children die. The child processes therefore have the same characteristics of the daemon, no special scheduling was established. The difference is that instead of my test app which ran in a continual loop, never giving up any CPU time, these children perform nanosleep() in order to give up their CPU time. I've played with nanosleep times and reduced them to either 1 mS or even 0 with no real differences.
- Nobody is hogging the CPU, top doesn't show this.
- Common sense tells me that this should absolutely be capable of dealing with 1/5 the rate of 115.2K with zero problems.
- The previous test application is proof of that.
- I've written horrible code. O.K. try and cut it down, still no solution.
- I need to play with the scheduler and make one or more of my processes higher priorities. I'm exploring this option now.
- I could write a buffer application which solely reads the serial USB and dispatches it via a file PIPE to my main application, thus allowing me to potentially never lose any data.
That last possibility made me wonder if there are buffer size settings for usbserial where I could adjust them so that if I have application latency of a certain slowness that I will be able to store some of that data in the driver's buffers itself.
If anyone has any suggestions how best to run this problem down, I would appreciate.
What do you mean by 'embedded data had some gaps and upon looking further, the gaps are frequent and large'. Are you trying to timestamp the data? The driver will buffer data, so the userspace application won't see it immediately. Do you mean that data is being lost, or merely delayed?
The wording of your question leaves it unclear to me about what is sending the data and what is listening and what part of the system is your code. To rephrase what I think you mean: your code listens to multiple serial ports (that they are USB-Serial should be irrelevant if we trust the driver). The serial data is somehow transferred (dispatched?) to a third process for display. What mechanism is used to 'dispatch' the data to the Qt GUI process? I assume some kind of interprocess communication mechanism. How does the process that listens to serial interfaces perform the multiplexing of its listening time? Using select()? Or, do you have a process dedicated per port with blocking read()s?
In your test case that seemed to work, was there an issue with CPU usage? If no, what prompted you to implement nanosleep()s?
Your problem seems to revolve around techniques used in your code, and yet you've not provided any of the detail about what techniques you've used.
Thanks for your reply and the questions you posed back.
I feel the problem lay within how I configured my application architecture. I do use select() to listen to file pipe() commands from the GUI downwards to my application, but do not use select() to govern whether or not I have any data from my serial port. I've been polling my serial port, and hence using the nanosleep() calls to yield the CPU. However it's incorrect architecture because I'm already yielding the CPU via select() listening to some, but not all descriptors into my application. I'll try to more correctly use the outcome of select(), because my guess now is that when I do receive a command from the GUI, select() is telling me more than "you have a GUI command" it is also telling me, "Hey, you have received serial data, too!" and I'm ignoring this fact; hence I'm losing data because I'm ignoring it. Which makes sense, but doesn't because if I don't invoke read() to the serial port, then I believe it should buffer that data. Maybe in that case it isn't and if I examine this architecture point, maybe I'll find my problem.
Sorry for the confusing question. I do appreciate you taking the time to try and understand what the circumstances were.
For future readers if they encounter this. There was NOT any problem with my usbserial driver or getting data from it. My user application had problems because I was practicing two different methods of yielding the CPU when I should have been solely using one.
select() seems to be an excellent alternative to polling for data, I had been resisting using it for all my inputs and that was part of my mistake.