0

I am working on imx283 platform using linux kernel-2.6.35.3 and using all the 3 uart ports for communication.

I want to collect data from UART-1 but needs to have an accurate interval.

The Data is collected from a Sensor.

I need to send a command to the sensor to get the data.

The interval can range from 10ms to 2sec.

I need some help for the kernel module , can i use kernel timers and collect data from uart .

The kernel timers have good accuracy so whether i can use them.

Thanks,

nema
  • 23
  • 4
  • It's not possible, you need a RTOS, not Linux, especially so **antique** one. – 0andriy Jul 22 '17 at 10:09
  • *"I need some help for the kernel module"* -- Why a kernel module? There's probably already a device driver handling the UART, so you should *"collect data from UART-1"* in userspace. *"...but needs to have an accurate interval"* -- To do what? The data will arrive asynchronously, so what, you want to poll the device or poll the receive buffer? FYI the existing UART driver surely uses interrupts (instead of polling) to service the UART. Why do you want less performance than the existing driver? OTOH there are special circumstances when polling is preferred, but you haven't cited anything. – sawdust Jul 24 '17 at 01:59
  • PLEASE, EXPLAIN WHAT YOU MEAN WITH _I want to collect data from UART-1 but needs to have an accurate interval_, as this is something that demands some explanation. RS232 data transmission depends, amongst other things, with the baudrate selected, what means a single 8bit, no parity, one stop bit to use 1ms at 9600 baudrate. – Luis Colorado Jul 24 '17 at 05:46
  • By the way, the standard tty driver is enough for even the most weird specifications, see `termios(4)` for an explanation on how to use `VMIN` and `VTIME` parameters for timeout and packeted data. – Luis Colorado Jul 24 '17 at 05:50
  • @LuisColorado Actually, to get data on UART, I have to send a command to my sensor. I want the data to be of fixed interval always. i can do it from userspace but to make it very accurate and fixed interval...i want to keep it in kernel...using the kernel timers so a "kernel module" – nema Jul 25 '17 at 01:47
  • @sawdust i have a specific need for the data to be of fixed interval always. – nema Jul 25 '17 at 02:14
  • @nema, What do you mean to be very accurate? It's impossible to be very accurate with a serial line to demand a kernel module, as, in case you begin sending a command at time T, the command will not be transferred completely until it is time T + delay (that depends on baudrate and number of characters, even if you are able to select no delay between chars) Repeat: What do you mean (in ms.) to be very accurate? – Luis Colorado Jul 25 '17 at 11:15
  • @LuisColorado i agree with you that the time T is added. But i need accuracy atleast in ms. – nema Jul 25 '17 at 12:23
  • @nema, Then you don't need a kernel module.... IMHO. – Luis Colorado Jul 26 '17 at 06:29
  • @nema, I have not written an answer because I think you are in an instance of the XY problem. You want to solve some X hidden problem (you don't want to share with us) and you have locked at some point Y, in your trial to solve it. If you share your actual problem and tell us probably a simple solution without touching your kernel will be available. NTP is a very stringent protocol and only asks for the kernel to provide an internal timestamp of the arrival of a network packet... everything else can be done without kernel programming. But only if you need several orders of magnitude less. – Luis Colorado Jul 26 '17 at 06:36
  • 1
    @LuisColorado Thanks for the feedback.Actually, according to my understanding ,if i perform this task in userspace of sending a command and receiving data using usleep(interval) in while loop, it has chances to being interrupted as .... i am also running 3 process and 4 threads along with this task as a pthread. So to make it uninterruptible ...i was thinking whether it is possible do it in kernel like and collect data in a ring-buffer because for this task ....i am only concerned about the data i collect and interval. – nema Jul 26 '17 at 08:47
  • *"receiving data using usleep(interval) in while loop, it has chances to being interrupted as .... "* -- You have a poor grasp of how this works. See [Linux serial drivers](http://www.linux.it/~rubini/docs/serial/serial.html). The kernel receives the data (typically using DMA) and buffers it. Userspace "reads" the data from the buffer, not the hardware. Your concerns are probably misplaced. – sawdust Jul 28 '17 at 06:31
  • @sawdust i don't receive data by usleep , i just use usleep for the interval .so here the loop is like " usleep(interval) -> send_command -> read_data " and I do know that kernel receives the data by DMA if enabled and buffers it. Do you agree that the usleep in userspace is as accurate as hrtimer in kernel???. – nema Jul 31 '17 at 02:58
  • *"Do you agree that the usleep in userspace is as accurate as hrtimer in kernel?"* -- No, if you want an accurate periodic event, then the use of any kind of delay or sleep will accumulate time errors. Use a Posix timer, i.e. **timer_create()**, to generate a periodic signal (event), and issue the **write()** from the signal handler. For latency considerations, see https://stackoverflow.com/questions/11724141/how-long-does-it-take-for-a-non-blocked-signal-get-delivered – sawdust Jul 31 '17 at 06:52

1 Answers1

0

With the standard driver for rs232, there's no delay from the time you issue the write(2) system call to the time the kernel drivers begin outputting bytes to the serial line (remember the driver is running in kernel mode already). Writing a driver or kernel module for this will be error prone, will have to be maintained by you, and you'll need to be clever at kernel programming to do it well and not crash in the way (you 'll have to cope with the standard driver trying to get use of the port, as it is automatically done by the driver and your driver has to reserve the port for own use, to not interfere with it). Only in case you fill completely the buffer, your process will have to wait for the buffer to get empty, but by definition, this is not going to happen, as you cannot compensate (you are filling the output line quicker than the chars go out, and this will make your process to block once the buffer is full) for that and be real timer altogether, in that case. On input, you have a similar process. You'll have an input character that triggers some interrupt to take it from the device to the buffer, and this normally (if you configure VMIN to 1 on termio) means your process will be awaken immediately, on each character read (as soon as each character comes in) I recommend you to use VMIN set to 1 and VTIME set to 0 (read the standard termios(3) manual page for a full explanation of the serial driver) to awaken your process as soon as each character is received. Your process will be awaken and scheduled, depending on system load and cpu speed, but normally this means usecs in time for a normal up to date cpu. You can timestamp the reading as soon as you come from the read(2) call or try to get a read timestamp from the kernel in a separate ioctl(2) call to check when in time was the character received (I know this is possible in linux, at least for sockets, without needing to program a module for that) (but not when it was transmitted from the remote end, think on this) but I think to get msec timing, it's enough to do everything in user mode and not complicate things going into kernel mode. RS232 lines were no designed for realtime, so what you are trying can be ok with millisec resolution without going to program in kernel side.

In addition, doing all in user mode allows your program to move from system to system without having to do complex installations of kernel modules before trying your software, and even more.... knowing how to use the tty driver allow you to run your code in non-linux systems (like BSD, Solaris or MAC, for example)

Luis Colorado
  • 10,974
  • 1
  • 16
  • 31
  • You perhaps didn't look into the UART drivers in Linux kernel, besides complexity of the kernel itself (interrupt handling, DMA, etc), the driver (if we talk about 8250) has its own issues. What you describe is applicable for uControllers where you have full control over the things, in Linux, unfortunately, UART is pretty much one of the heaviest tasks to be done (CPU is not fast enough to serve UART interrupts, mostly because of other tasks scheduled and buffers being too small). – 0andriy Jul 26 '17 at 17:04
  • @0andriy, of course, if we talk about 8250 the uart is not precisely the best in technology. But you are talking about a chip that has been superseeded since long time ago. Nowadays I think it's quite strange to see one of these. Perhaps you want to describe how is implemented the tty driver of the pdp-11 or the pdp-7 ??? I have of course looked into the kernel drivers for the rs232 in linux... also in unix, and in BSD systems. My first experience programming uarts dates from up when there was no other alternative than the 8250 and I know its limitations well. – Luis Colorado Jul 27 '17 at 05:10
  • @0andriy, now, no computer is sold with less than a 16550A (or B), or even better devices. What is the exact purpose of your comment? – Luis Colorado Jul 27 '17 at 05:11
  • Okay, someone from us didn't read carefully. I wrote about driver, but it's really doesn't matter, 16550a or even 16750 (64 bytes of FIFO) doesn't make situation much better. Besides the fact that you are wrong in *no computer is sold with less than a 16550A (or B), or even better devices*. – 0andriy Jul 27 '17 at 08:12
  • And to the point, Linux kernel is not tuned to serve UARTs in real time. Period. – 0andriy Jul 27 '17 at 08:12
  • @0andriy, if you have written about rs232 driver, then you had better to add to the answer by constructively adding to it, and not being so critic with the answers of others. Full stop. – Luis Colorado Jul 27 '17 at 08:17
  • Do you mean I need to explain how to tune Linux kernel for low latency operations? Key points to check are a) Interrupt affinity (try to assign UART interrupt to a free CPU), b) take care of PM QoS (though it seems only 8250 OMAP driver which does power management for now), c) disable DMA for UART, d) expand buffers (currently it's only 4k), though it depends on the speed of input. – 0andriy Jul 27 '17 at 09:21
  • @0andriy i agree with you that ,I need some kind of RTOS here. if i use xenomai patch will that be enough. Also do i need to port my whole application with xenomai api or just this particular task under xenomai. thanks for all the feedback – nema Jul 28 '17 at 02:50
  • *"On input, ... means your process will be awaken immediately,"* -- That's bogus, the termios processing is notorious for introducing latency. See [Linux serial drivers](http://www.linux.it/~rubini/docs/serial/serial.html). However there are tricks without resorting to the RT patches; see https://stackoverflow.com/questions/4667141/high-delay-in-rs232-communication-on-a-pxa270 – sawdust Jul 28 '17 at 06:25