Search code examples
linuxtimerlinux-kernelkerneluart

kernel module to collect data from UART with periodic kernel timer (jiffies or hrtimer)


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,


Solution

  • 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)