LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 10-21-2009, 10:48 PM   #1
TheIndependentAquarius
Senior Member
 
Registered: Dec 2008
Posts: 4,619
Blog Entries: 29

Rep: Reputation: 896Reputation: 896Reputation: 896Reputation: 896Reputation: 896Reputation: 896Reputation: 896
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 TheIndependentAquarius; 04-25-2012 at 04:47 AM. Reason: semicolon
 
Old 10-21-2009, 11:09 PM   #2
TB0ne
Guru
 
Registered: Jul 2003
Location: Birmingham, Alabama
Distribution: SuSE, RedHat, Slack,CentOS
Posts: 14,210

Rep: Reputation: 2473Reputation: 2473Reputation: 2473Reputation: 2473Reputation: 2473Reputation: 2473Reputation: 2473Reputation: 2473Reputation: 2473Reputation: 2473Reputation: 2473
Quote:
Originally Posted by anishakaul View Post
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.
 
0 members found this post helpful.
Old 10-21-2009, 11:16 PM   #3
TheIndependentAquarius
Senior Member
 
Registered: Dec 2008
Posts: 4,619
Blog Entries: 29

Original Poster
Rep: Reputation: 896Reputation: 896Reputation: 896Reputation: 896Reputation: 896Reputation: 896Reputation: 896
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 TheIndependentAquarius; 04-20-2012 at 12:49 AM. Reason: replaced !! with .
 
Old 10-27-2009, 01:35 AM   #4
TheIndependentAquarius
Senior Member
 
Registered: Dec 2008
Posts: 4,619
Blog Entries: 29

Original Poster
Rep: Reputation: 896Reputation: 896Reputation: 896Reputation: 896Reputation: 896Reputation: 896Reputation: 896
Here by I am presenting the fully functional code for serial port RS232 interrupt handler routine.

Code:
#include <linux/kernel.h>
#include <linux/interrupt.h> 
#include <asm/io.h>

#define PORT 0x3F8

void resetRegisters (unsigned long currentlyUnused);
DECLARE_TASKLET     (rs232Tasklet, resetRegisters, 0);

static int times;

irq_handler_t isrSerialPort (int irq, void *dev_id, struct pt_regs *regs)
{
	times++;
	printk (KERN_ALERT "\nisrSerialPort called %d ", times);

	tasklet_schedule (&rs232Tasklet);
	
	return (irq_handler_t) IRQ_HANDLED;
}

int 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);

	printk ("\nU pressed %c ", inb (PORT));
}

void cleanup_module ()
{
	free_irq (4, NULL);
	printk   (KERN_ALERT "\ncleanup_module called\n");
}

MODULE_LICENSE ("GPL");

Last edited by TheIndependentAquarius; 04-20-2012 at 12:48 AM. Reason: replaced !! with .
 
Old 12-10-2012, 04:19 AM   #5
Anamr
LQ Newbie
 
Registered: Dec 2012
Posts: 4

Rep: Reputation: Disabled
Error Compiling the code

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

static int times;

irq_handler_t isrSerialPort (int irq, void *dev_id, struct pt_regs *regs)
{
times++;
printk (KERN_ALERT "\nisrSerialPort called %d ", times);

tasklet_schedule (&rs232Tasklet);

return (irq_handler_t) IRQ_HANDLED;
}

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

printk ("\nU pressed %c ", inb (PORT));
}

void __exit cleanup_module ()
{
free_irq (4, NULL);
printk (KERN_ALERT "\ncleanup_module called\n");
}



-------------------------------------------------------------------------------------------------------------------

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

else
KERNEL_SOURCE := /usr/src/linux-headers-2.6.28-11-generic/
PWD := $(shell pwd)
default:
${MAKE} -C ${KERNEL_SOURCE} SUBDIRS=${PWD} modules

clean:
${MAKE} -C ${KERNEL_SOURCE} SUBDIRS=${PWD} clean
endif

Last edited by Anamr; 12-10-2012 at 04:21 AM. Reason: different code pasted
 
1 members found this post helpful.
Old 12-10-2012, 04:41 AM   #6
TheIndependentAquarius
Senior Member
 
Registered: Dec 2008
Posts: 4,619
Blog Entries: 29

Original Poster
Rep: Reputation: 896Reputation: 896Reputation: 896Reputation: 896Reputation: 896Reputation: 896Reputation: 896
My Makefile is as follows, but AFAIR I had compiled this on openSUSE 10.3 with kernel version 2.6.22. Your kernel version is different.

Code:
obj-m += serialPortISR.o

all:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Quote:
Originally Posted by Anamr View Post
/home/user/Desktop/an/serialint/serialint.c:27: error: ‘SA_INTERRUPT’ undeclared (first use in this function)
I just now downloaded the source of kernel 2.6.22 and looked in its interrupt.h.
Code:
#define SA_INTERRUPT		deprecated_irq_flag(IRQF_DISABLED)
#define SA_SAMPLE_RANDOM	deprecated_irq_flag(IRQF_SAMPLE_RANDOM)
#define SA_SHIRQ		deprecated_irq_flag(IRQF_SHARED)
#define SA_PROBEIRQ		deprecated_irq_flag(IRQF_PROBE_SHARED)
#define SA_PERCPU		deprecated_irq_flag(IRQF_PERCPU)

#define SA_TRIGGER_LOW		deprecated_irq_flag(IRQF_TRIGGER_LOW)
#define SA_TRIGGER_HIGH		deprecated_irq_flag(IRQF_TRIGGER_HIGH)
#define SA_TRIGGER_FALLING	deprecated_irq_flag(IRQF_TRIGGER_FALLING)
#define SA_TRIGGER_RISING	deprecated_irq_flag(IRQF_TRIGGER_RISING)
#define SA_TRIGGER_MASK		deprecated_irq_flag(IRQF_TRIGGER_MASK)
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 TheIndependentAquarius; 12-11-2012 at 02:10 AM.
 
Old 12-11-2012, 01:57 AM   #7
Anamr
LQ Newbie
 
Registered: Dec 2012
Posts: 4

Rep: Reputation: Disabled
Solved

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.
 
1 members found this post helpful.
Old 12-11-2012, 02:09 AM   #8
TheIndependentAquarius
Senior Member
 
Registered: Dec 2008
Posts: 4,619
Blog Entries: 29

Original Poster
Rep: Reputation: 896Reputation: 896Reputation: 896Reputation: 896Reputation: 896Reputation: 896Reputation: 896
Am glad I could help you.
Thanks for following up.
 
Old 12-27-2012, 01:31 AM   #9
Anamr
LQ Newbie
 
Registered: Dec 2012
Posts: 4

Rep: Reputation: Disabled
Hello,

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.

Thank you.
 
Old 12-27-2012, 05:32 AM   #10
TheIndependentAquarius
Senior Member
 
Registered: Dec 2008
Posts: 4,619
Blog Entries: 29

Original Poster
Rep: Reputation: 896Reputation: 896Reputation: 896Reputation: 896Reputation: 896Reputation: 896Reputation: 896
Quote:
Originally Posted by Anamr View Post
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 pass that data to the user
space.

Check this out:
http://www.gnugeneration.com/mirrors...api/r4208.html

Also, for new questions start a new thread in a relevant sub forum.

Last edited by TheIndependentAquarius; 12-27-2012 at 05:34 AM.
 
Old 12-31-2012, 11:42 PM   #11
dgashu
Member
 
Registered: Apr 2010
Location: Banglore
Distribution: fedora , rhel,Ubuntu
Posts: 61

Rep: Reputation: 0
Hi Anisha Kaul,

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 .....
 
Old 12-31-2012, 11:44 PM   #12
dgashu
Member
 
Registered: Apr 2010
Location: Banglore
Distribution: fedora , rhel,Ubuntu
Posts: 61

Rep: Reputation: 0
Sorry Missed the point that it is marked as solved !!!
 
Old 01-01-2013, 12:36 AM   #13
TheIndependentAquarius
Senior Member
 
Registered: Dec 2008
Posts: 4,619
Blog Entries: 29

Original Poster
Rep: Reputation: 896Reputation: 896Reputation: 896Reputation: 896Reputation: 896Reputation: 896Reputation: 896
Quote:
Originally Posted by dgashu View Post
Sorry Missed the point that it is marked as solved !!!
Nevermind, it was indeed solved - 3 years back! Thanks for bothering though.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
How to register my interrupt service routine with kernel john_crichton Programming 1 04-09-2007 01:39 PM
Driver interrupt routine problem in Gentoo Linux briek Linux - Kernel 0 08-31-2006 11:57 AM
problem in invoking interrupt handler for serial port in 2.4.21-ELsmp Redhat linux mrinal mishra Linux - Kernel 1 08-15-2006 02:52 PM
Unable to hit my serial port interrupt routine hguts Linux - Software 1 07-15-2003 07:45 AM
IRQ4 - Serial Port Interrupt not invoked. sinux Linux - General 1 03-06-2003 04:23 PM


All times are GMT -5. The time now is 01:31 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration