Hi all, I am writing code for reading & writing the data from serial port (UART of ARM Processor). But i am facing a problem in reading. As written in man page the read call returns the character till it will get 'Enter/Carriage return' or 'EOF'.
I am interfacing the GPRS modem on this serial port. So from Modem there is no way to get me 'Enter/Carriage return' or 'EOF'. Because of this read gets blocked.
I am a little bit confused about reading and writing to a serial port. I have a USB device in Linux that uses the FTDI USB serial device converter driver. When I plug it in, it creates: /dev/ttyUSB1. I thought itd be simple to open and read/write from it in C. I know the baud rate and parity information, but it seems like there is no standard.
Is there any other way to just read the received characters without EOF & returns that characters? Please help me for this.
Hello, newbie here I'm writing a program in C to write/select/read on a serial port in Linux. I have the serial port code all set up, but the problem is that I need this operation to be very fast (time is the issue here).
I need to keep the write/select/read operation atomic and uninterruptable. Basically, I don't want a context switch while I'm waiting for select to return (so I don't think semaphores will work). I've looked at a couple options, but I'm kinda running out of ideas. (1) locking with saveflags/cli/sti/restoreflags, gah, ugly option. (2) spinlocks, but that's kernel code, so I'm not sure if that would work since the program's running in user space. Are there other options I'm missing?
Linux isn't a realtime platform so there aren't any guarantees that you will get to run on time. Now, the point of the select call is to enable programs waiting on one or more file descriptors to allow other programs to run while they are waiting and so not requiring them to poll (i.e.
Attempting a non-blocking read) on each and every file descriptor. The context switch when waiting for select to return is somewhat the whole point of the select call Your only hope of doing something like this uninterrupted and atomic is doing it in kernel space.
Quote: Origianlly posted by mahoney: The context switch when waiting for select to return is somewhat the whole point of the select call Wink Yup, I know that, now I just have to convince my supervisor about that. Quote: Originally posted by snotnose: You don't say which kernel you're using, so look into the Low Latency patch and the re-entrant kernel patch.
As another poster pointed out, you just ain't that busy on a serial port, espcially as you've got a 16 byte FIFO in the UART. What exactly are the requirements? Being able to maintain 115kbps on a sustained basis is a lot different than 'the system shall respond within 10 us of getting a command packet'. Kernel is 2.6.5 (? Not completely sure of the minor number) with Fedora Core 2. The serial port is sending at 9600bps, and a desired maximum response time of 6ms after sending a command pack (i.e. Write something and have response in under 6ms).
In response to LordFrith, I was thinking about a module, but we want the program to stay in userspace. Quote: Originally posted by Arakageeta: How does this process run? Linux can support FIFO and Round Robin scheduling algorithms for 'real time' applications. I tried those scheduling algorithms, but it doesn't appear to have improved performance at all. Basically, the results I'm getting right now are from a simulation. The test program is running on a serial loopback, and I'm trying to guage the response time from there. I'm running the tests on a desktop machine with Fedora Core 2.
The intent is to eventually put the code into an embedded system. The strange thing is, with this test program that I wrote, I'm getting some response times in the 20us range, but then a huge delay spike of about 70ms every 40 cycles of my write/select/read sequence (I have the write/select/read inside a for loop right now). Any suggestions as to why this might be happening? And how to suppress that (relatively) large delay spike in response time? 70 ms could be one of several things in the system. Track down the 2 patches I mentioned earlier (low latency, reentrant kernel) and read the docs that go with them. Those docs tell you what subsystems can lock out interrupts for a long time.
However, I don't think you need those patches in a 2.6 kernel (but I've never used 2.6, so I donno). But unless you do some heavy kernel work then you ain't gonna get rid of those occasional long delays.
If your spec is 'the system shall respond within 6 ms', then Linux probably isn't what you want. If the spec is 'the system shall typically respond with 6 ms' then Linux will be fine. You might want to look up the definition of hard real time and soft real time.
Linux is the latter. Making a kernel module won't help the latency, there are fundamental kernel issues at work.
When I said 'heavy kernel work' I wasn't joking, there has already been a lot of work applied to minimize the latency. There is a real time linux out there that essentially runs Linux as a seperate task, that lets it be hard real time. Unless you do this Linux will always be soft real time. I wouldn't roll your own OS either. That's harder than most people realize, and there are some free/cheap ones out there (is pSos still available?). 3 years ago I had to deal with a 54 mbit/sec data stream with a 128 byte FIFO. Stalling going out was no big deal, just a loss of throughput.
Stalling on receive sucked though, data fell on the floor and the whole packet needed to be resent. Puts a huge chokehold on your incoming throughput. I spent several months getting the latency to where I very seldom dropped data, it wasn't easy.
Soft real-time is what we're aiming for. That's why we're looking at Linux in the first place, since we know it's not hard real-time. We want 'the system to typically respond in 6ms'. But I was hoping to reduce the latency as much as possible. LordFrith, I'll check out those suggestions you made. If those things don't help, then I'll look into the patches that snotnose mentioned.
I have read a bunch of intro material on the low latency and reentrant kernel, but I believe most of the patches are for the 2.4 kernel. Having done next to no kernel work myself, I'm not sure if I could apply the old patches to the new kernel.
Anyone know if there's work being done for these patches for the 2.6 kernel? I would give RTLinux a shot. It was alluded to in an earlier post. FSM labs now maintains it, but you can get a gpl version from their site.
![Linux Serial Port Read Linux Serial Port Read](/uploads/1/2/5/6/125602654/703356795.png)
It implements the POSIX real-time API. It will give you the ability to have both periodic and interrupt-driven tasks, with the linux kernel having the lowest priority among the tasks. There are other commercial RTOS such as TimeSys that will provide the same thing. QNX is another. I think TimeSys has a free version for non-commercial use. Here is a decent link that will describe this in more detail: To me, using something such as RTLinux would be easier than trying to patch a kernel to support code that may or may not work. Also, I'm not sure if you when you were talking about using the RR and FIFO scheduling methods, if you were referencing the real-time API, but it wouldnt have worked unless your kernel supported the real-time API (and AFAIK, 2.6 does not).
Maybe I didn't understand what you were talking about though.that is possible. Quote: Originally posted by reveng: To me, using something such as RTLinux would be easier than trying to patch a kernel to support code that may or may not work.
Also, I'm not sure if you when you were talking about using the RR and FIFO scheduling methods, if you were referencing the real-time API, but it wouldnt have worked unless your kernel supported the real-time API (and AFAIK, 2.6 does not). Maybe I didn't understand what you were talking about though.that is possible Smile Hmm. Perhaps I will check out RTLinux. Might be a possibility if I can't get the desired response time. As for RR and FIFO, I was referencing the real-time API, but I was under the impression that 2.6 did support it. I might be completely wrong.
Anyone know for sure? If it's not supported, that might explain why my results didn't show any improvement when I attempted to use the real-time API. I'm pretty sure the low latency and re-entrant kernel patches from 2.4 are in the 2.6 series kernels, so trying to wedge them in is counter productive. I just wanted you to read the docs so you'd know why it wasn't easy to make Linux hard real time.
IMHO, you neither need nor want a kernel module. Just open up the serial port, sit on it's fd via a select call, and see how you do. If it's not good enough (I think it will be fine) then try spawning a new thread to read, have it just sit on the fd in a read call waiting for data. My gut says this will have more latency than select, although I haven't tried it. I think you'll find 99% of your packets will be handled in. First, depending on your loopback setup, that could very well be the problem? Do you just have the TX and RX lines on the RS-232 looped into each other?
Second, if oyu're running the simulator on the same machine, stop. Its not a fair test. That could easily be the problem. Third, run the configuration as close as possible to what it will be in the real world. Even little stuff that you don't think is important can be, if you really want to track this down.
Quote: Originally posted by b.lau: The strange thing is, with this test program that I wrote, I'm getting some response times in the 20us range, but then a huge delay spike of about 70ms every 40 cycles of my write/select/read sequence (I have the write/select/read inside a for loop right now). Any suggestions as to why this might be happening? And how to suppress that (relatively) large delay spike in response time?
That almost sounds like your program is doing something else or that it is being preempted. You know, that if your program doesn't need to do anything while its waiting for input/output operations to complete, you don't have to use select at all. That may make the problem go away completely, or at least show that it is beyond your control via editing code (e.g., because something funny is happening with the scheduler, the kernel has some sort of internal latency problem, etc.). Quote: Originally posted by LordHunter: First, depending on your loopback setup, that could very well be the problem? Do you just have the TX and RX lines on the RS-232 looped into each other?
No, I have a full 9-pin serial loopback connector made. Quote: Second, if oyu're running the simulator on the same machine, stop. Its not a fair test.
That could easily be the problem. I'm sorry, I don't quite understand what you mean by this. Can you elaborate? Quote: You know, that if your program doesn't need to do anything while its waiting for input/output operations to complete, you don't have to use select at all.
That may make the problem go away completely, or at least show that it is beyond your control via editing code (e.g., because something funny is happening with the scheduler, the kernel has some sort of internal latency problem, etc.) Hmm. I gave this a try, and it did eliminate the problems I saw before with adequate response times and then huge delay. Unfortunately, it's now losing data, since I think read is picking up whatever's in the buffer and then continuing on before the rest of it is transmitted. Or am I misunderstanding how read works? Snotnose, thanks for the info, my program is running at about the stats that you quoted, so it's nice to know that it's doing as expected. Could someone confim my understanding of the serial port?
Still relatively new at this If I write enough data into the FIFO of the UART, as I'm reading the data off the port, I should be able to get pretty good response times, since the read buffer will hold the excess data until my program reads it. Not sure if that made sense, but moving on. If I'm only trying to write and read a single byte on the serial port, I can't really make use of the buffering capabilities of the UART, and therefore my response times will typically be slower, correct? From my understanding of intentions of the program, I want to have a single byte be written and read back very quickly (is 1ms even realistic for this?). It's used more or less as a poll of the line to see if it's free. Then the subsequent bytes can be as fast or slow as necessary. It's this inital byte that I'm concerned about the response time for.
Sorry for the confusion. I'm getting really confused myself.
Quote: Originally posted by b.lau: quote: Second, if oyu're running the simulator on the same machine, stop. Its not a fair test. That could easily be the problem. I'm sorry, I don't quite understand what you mean by this. Can you elaborate? I was slightly confused by what you were doing.
Anyway, take this as future advice: If you ever use a simulation program that pretends to be the other end the computer is talking to, run it on a different computer. Otherwise, you're not making a fair test. I say this only because I had people who ran the simulation on the same machine at a previous job and wondered why they got bad results. Quote: Unfortunately, it's now losing data, since I think read is picking up whatever's in the buffer and then continuing on before the rest of it is transmitted. Or am I misunderstanding how read works?
Read doesn't provide any assurances that the number of bytes you ask for will be the number of bytes returned. You have to check the return value of read to make sure you got all the bytes you wanted. Quote: Origianlly posted by LordHunter: If you ever use a simulation program that pretends to be the other end the computer is talking to, run it on a different computer.
Otherwise, you're not making a fair test. I say this only because I had people who ran the simulation on the same machine at a previous job and wondered why they got bad results. Ah, now I understand.
Thanks, and I was wondering about that. Currently it is all running on the same machine, but I'll look into changing that soon. Quote: read doesn't provide any assurances that the number of bytes you ask for will be the number of bytes returned. You have to check the return value of read to make sure you got all the bytes you wanted.
I knew I was forgetting to do something. Thank you very much for the reminder, I don't think I'll be forgetting that one for a while now shouldn't have forgoten it in the first place.