[SOLVED] Coding an Interrupt Service Routine for the serial port in Linux !!
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
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.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Coding an Interrupt Service Routine for the serial port in Linux !!
I got a problem with the following interrupt handler code with respect to serial port 1. I have a cable connecting two serial ports of two computers with linux on them. On one computer there is minicom installed and on another I have compiled and successfully insmoded the below shown module. But when I type on minicom, it doesnt show anything (by the command 'dmesg') on the other computer where my module is loaded!
Kindly help me debug this code.
_______________________________________________________________
Code:
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <linux/fs.h>
#define PORT 0x3F8
irq_handler_t isrSerialPort (int irq, void *dev_id, struct pt_regs *regs)
{
printk ("\n Thank god \n");
return (irq_handler_t) IRQ_HANDLED;
}
int init_module ()
{
request_irq (4, (irq_handler_t) isrSerialPort, SA_SHIRQ, "God", (void *)(isrSerialPort));
outb (0x80, PORT + 3);
outb (0x03, PORT + 0);
outb (0x00, PORT + 1);
outb (0xC7, PORT + 2);
outb (0x01, PORT + 1);
}
MODULE_LICENSE ("GPL");
Last edited by Aquarius_Girl; 04-25-2012 at 04:47 AM.
Reason: semicolon
I got a problem with the following interrupt handler code with respect to serial port 1. I have a cable connecting two serial ports of two computers with linux on them. On one computer there is minicom installed and on another I have compiled and successfully insmoded the below shown module. But when I type on minicom, it doesnt show anything (by the command 'dmesg') on the other computer where my module is loaded !
Kindly help me debug this code !!
Kindly don't post the same question twice, a day apart, because you didn't get an answer in your other thread.
I posted the same question here because I thought General forum was wrong place for the question to be! Actually I thought moderator will move this question himself, but he didnt, so I posted it here. And there is no way to delete misplaced questions either.
Last edited by Aquarius_Girl; 04-20-2012 at 12:49 AM.
Reason: replaced !! with .
I tried to compile the following code. And I am encounter some compiling errors(see at the bottom)
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/version.h>
#include <linux/fs.h>
#include <asm/io.h>
#include <asm/signal.h>
#include <linux/irq.h>
#define PORT 0x3F8
void resetRegisters (unsigned long currentlyUnused);
DECLARE_TASKLET (rs232Tasklet, resetRegisters, 0);
int __init init_module ()
{
int result = request_irq (4, (irq_handler_t) isrSerialPort, SA_INTERRUPT, "softbrainISR", NULL);
outb (0x83, PORT + 3);
outb (0x01, PORT + 0);
outb (0x00, PORT + 1);
outb (0x03, PORT + 3);
outb (0x01, PORT + 1);
outb (0x23, PORT + 2);
outb (0x08, PORT + 4);
return result;
}
void resetRegisters (unsigned long currentlyUnused)
{
outb (0x83, PORT + 3);
outb (0x01, PORT + 0);
outb (0x00, PORT + 1);
outb (0x03, PORT + 3);
outb (0x01, PORT + 1);
outb (0x23, PORT + 2);
outb (0x08, PORT + 4);
Error- 2
user@-desktop:~/Desktop/an/serialint$ make -C /usr/src/linux-headers-2.6.28-11-generic/ SUBDIRS=${PWD} modules
make: Entering directory `/usr/src/linux-headers-2.6.28-11-generic'
CC [M] /home/user/Desktop/an/serialint/serialint.o
/home/user/Desktop/an/serialint/serialint.c:26: warning: function declaration isn’t a prototype
/home/user/Desktop/an/serialint/serialint.c: In function ‘init_module’:
/home/user/Desktop/an/serialint/serialint.c:27: error: ‘SA_INTERRUPT’ undeclared (first use in this function)
/home/user/Desktop/an/serialint/serialint.c:27: error: (Each undeclared identifier is reported only once
/home/user/Desktop/an/serialint/serialint.c:27: error: for each function it appears in.)
/home/user/Desktop/an/serialint/serialint.c: At top level:
/home/user/Desktop/an/serialint/serialint.c:54: warning: function declaration isn’t a prototype
make[1]: *** [/home/user/Desktop/an/serialint/serialint.o] Error 1
make: *** [_module_/home/user/Desktop/an/serialint] Error 2
make: Leaving directory `/usr/src/linux-headers-2.6.28-11-generic'
Can You help me out to resolve these errors.
The makefile that i used is
--------------------------------------------------------------------------------------
ifneq (${KERNELRELEASE},)
obj-m := serialint.o
That #define SA_INTERRUPT is there but it is listed as deprecated.
And now I checked the interrupt.h of kernel 3.2.1, this #define is NOT there at all.
Following is the list of different interrupt type flags listed in the interrupt.h of the latest kernel 3.2.1. You can use the one that suits you.
Code:
/*
* These flags used only by the kernel as part of the
* irq handling routines.
*
* IRQF_DISABLED - keep irqs disabled when calling the action handler.
* DEPRECATED. This flag is a NOOP and scheduled to be removed
* IRQF_SAMPLE_RANDOM - irq is used to feed the random generator
* IRQF_SHARED - allow sharing the irq among several devices
* IRQF_PROBE_SHARED - set by callers when they expect sharing mismatches to occur
* IRQF_TIMER - Flag to mark this interrupt as timer interrupt
* IRQF_PERCPU - Interrupt is per cpu
* IRQF_NOBALANCING - Flag to exclude this interrupt from irq balancing
* IRQF_IRQPOLL - Interrupt is used for polling (only the interrupt that is
* registered first in an shared interrupt is considered for
* performance reasons)
* IRQF_ONESHOT - Interrupt is not reenabled after the hardirq handler finished.
* Used by threaded interrupts which need to keep the
* irq line disabled until the threaded handler has been run.
* IRQF_NO_SUSPEND - Do not disable this IRQ during suspend
* IRQF_FORCE_RESUME - Force enable it on resume even if IRQF_NO_SUSPEND is set
* IRQF_NO_THREAD - Interrupt cannot be threaded
* IRQF_EARLY_RESUME - Resume IRQ early during syscore instead of at device
* resume time.
*/
Also, for a new question I suggest you to open a new thread to get better attention.
Last edited by Aquarius_Girl; 12-11-2012 at 02:10 AM.
Hi, thanks for the inputs. Yup i referred the latest source code 3.6.9 interrupt.h and used IRQF_IRQPOLL. Also printk ("\nU pressed %c ", inb (PORT)); was not printing any character. I think the baud rate is not correctly configured.
I figured out for 9600 baud (x86 PC16550D), i should set
outb (0x0C, PORT + 0);
outb (0x00, PORT + 1);
and it is working fine.
Hi, taking the simple serial driver in irq mode further to writing a simple minicomm like user application.
I wrote a simple minicomm like user application that would transmit and receive characters on a console. Two threads one for receiver that continuously polls (calls the read function) the serial driver and another polls for user data in(use scanf)and writes character by character to serial driver when user enters data.
By above method i have to infinitely poll(call read function of serial driver) to check if serial driver has any data.
This is inefficient way.
So I wanted to know a possible concept in which kernel driver asynchronously sends signal or informs user application about received data availability. It would be great if you could give some pointers on this. or suggest the design for simple [(serial driver in irq mode) to (user application)] , asynchronous communication.
By above method i have to infinitely poll(call
read function of serial driver) to check if serial driver has any
data.
This is inefficient way.
???
You just have to pass the data from the kernel space to the user
space.
The interrupt handler is already there, which means that when you
press a key on the keyboard the above program will display that
particular key id and you just have to passthatdata to the user
space.
For debugging purpose just do an loop-back on the cable[by shorting the RX & TX pin] and test
with your application . With this you can figure out if at-least ur code is pumping the data to serial port .....
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.