Parallel Port Interrupt problem with C code?
The problem is that this code does not work correctly and I am not quite sure why, the problems I have are:
1) The code works the first time it is loaded and picks up the first generated interrupt, but when i generate a 2nd or 3rd interrupt this is not picked up, even if i rmmod the module and insmod it again does not pick up an interrupt until i reset? this could be because of the next problem! 2) when i use the make command i get the following compile error: in function `xinit_module`: warning: passing arg 2 of `request_irq` from incompatible pointer type I have checked the modules (more modules) and the module is added and removed correctly, there is no error code generated by ret (from request_irq), more interrupts says that 2 interrupts have been produced! any light you could shed over the problems would be much appreciated, obviously it would be ideal to get rid of warning, but more importantly the fact that it only picks up one interrupt per boot is the most annoying thing!! THanks James The code: #include <linux/slab.h> #include <linux/sched.h> #include <linux/module.h> #include <linux/interrupt.h> #include <asm/io.h> #define BASEPORT 0x378 static int handler(void) { // do stuff printk(">>> PARALLEL PORT INT HANDLED\n"); return 0; } int xinit_module(void) { int ret; ret = request_irq(7, handler(), SA_INTERRUPT, "parallelport", NULL); //set port to interrupt mode; pins are output outb_p(0x10, BASEPORT + 2); printk("return code = %d\n", ret); printk("Wait for interrupt to be generated\n"); return 0; } void xcleanup_module(void) { disable_irq(7); free_irq(7, NULL); printk ("closed\n"); } module_init(xinit_module); module_exit(xcleanup_module); MODULE_LICENSE("GPL"); |
Got to the bottom of the repeating the interrupt problem, something to do with the kernel of vector linux 3.0 I think, am trying to install 4.0 now to see if that sorts out the problem, i still get the error message though if anyone can help with that?
thanks James |
I don't know so much about interrupt handling under linux; maybe the kernel does this automatically, but from my MS-DOS days I know you had to end a hardware interrupt by resetting the interrupt controller status. In assembler language, it was done like this:
Code:
Just a thought... (Boy, I really miss doing that kind of stuff. I really need to get back into it somehow.) --- rod. |
The best way to attack this sort of problem is ... "use the Source, Luke!" :) Go out to some of the existing hardware-driver source-code and find some piece of existing code that's doing something similar to yours. And, read it carefully.
Then, go to the kernel directories and look at the actual source code of the routines that you are calling. Look also at the Documentation subdirectory. "grep" can be your best friend. This is easily the best, fastest, and most authoritative way to deal with issues and questions like these. "You have All Of The Source: you don't have to guess." :) |
see the status port
the bit no 2 of parallel port status register (BASE + 1) contains IRQ status. may be u to have clear it before leaving the irq handler.
|
The error you are talking about is not really an error, it is just a warning that there is a type mismatch. You can ignore it
For your missing interrupt problems, I think you are not clearing the interrupt status bit in your interrupt handler so you are not getting the succeeding interrupts. Try adding in your handler code some status cleanup mechanism. If that does not work, try disabling then re-enabling the interrupt in your handler and see if that helps. |
Thanks, I tried removing and adding handler but it still requires reset to pick up a second interrupt!!
The program works with the warning under redhat8.0, picking up multiple interrupts, so i dont know if it is a vector linux problem or if it just handles it differently, and what you said is happening, Unfortunately my laptop im using isnt powerful enough for read hat 8.0, so currently trying to install slack 10.2, hoping that this will work. |
Quote:
so, have u added the code to reset the IRQ status in port 379? please post your modified interrupt handler code... |
Oh sorry jineshkj i see what you mean now, i thought you meant to remove the module and reload.
do you mean if i put into my handler routine 2 lines to clear then reset it to high to enable interrupts again like this? static int handler(void) { // do stuff printk(">>> PARALLEL PORT INT HANDLED\n"); outb_p(0x00, BASEPORT + 2); outb_p(0x10, BASEPORT + 2); return 0; } I havent yet tried this, will give it a go now, if this isnt what you mean please could you let me know!! thanks James |
i'm sorry, but what i meant was something like:
outb_p( inb_p(BASE+1) & ~(1<<2), BASE+1 ); to reset the "IRQ Status bit" in the "IRQ Status register". |
Ok, thanks I will try that.
sorry i am not very experienced with c and linux, took it on as a final year uni project (which is due in next week ahhhh!!) and have had to teach myself!! Just getting vector back up and running now will post outcome!! |
Hi thanks very much for your time and help,
unfortunately what you suggested didnt make any difference, so i thought i would just have a play around with it adding different bits and pieces. and the code which works is as follows: (clearing the irq register and reloading it when an interrupt occurs) #include <linux/slab.h> #include <linux/sched.h> #include <linux/module.h> #include <linux/interrupt.h> #include <asm/io.h> #define BASEPORT 0x378 static int handler(void) { // do stuff printk(">>> PARALLEL PORT INT HANDLED\n"); outb_p(0x00, BASEPORT +2); outb_p(0x10, BASEPORT +2); return 0; } int xinit_module(void) { int ret; ret = request_irq(7, handler, SA_INTERRUPT, "parallelport", NULL); //set port to interrupt mode; pins are output outb_p(0x00, BASEPORT + 2); outb_p(0x10, BASEPORT + 2); printk("wait for interrupt\n"); printk("return code %d \n", ret); return 0; } void xcleanup_module(void) { disable_irq(7); free_irq(7, NULL); printk("closed\n"); } module_init(xinit_module); module_exit(xcleanup_module); MODULE_LICENSE("GPL"); Quite strange though, the interrupt only works when i send a signal to set all the parallel port pins to high. I have pins 9 and 10 connected together, but tried leaving the port set at high and then touching the connectors together like an external switch but no interrupt generates, does anyone know any thing about this or why its doing it? thanks James |
good to hear that the code is working now. see if u can get the book "The Indispensable PC Hardware Book" from ur library. it should give u most of the details of the most commonly used pc hardware and more...
|
Sorted now thanks, just needed to condition the input signal! to make a nice square wave!!
Now all thats left to do is make the module interact with my user programs! from what i understand before i try there is a fork command and exec which is what i require!! |
A few Years Later ...
I have the same problem ... The kernel changes but hard to make work simple things. I just read : www(dot)captain(dot)at (slash) howto-linux-kernel-parallel-port-interrupt(dot)php And try to make it work under : Ubuntu Karmic Koala (Linux 2.6.31-16) I added : #define SA_INTERRUPT IRQF_DISABLED SA_INTERRUPT seems deprecated Further later when i make the : sudo insmod ./parint.ko and see what happen in dmesg ... i don't see any IRQ Handler Trace and in cat /proc/interrupt i see no interrupt I also try to kill all device attached to IRQ 7 sudo rmod lp sudo rmod parport_pc sudo rmod ppdev sudo rmod parport I also tested the older version skeleton.c from the same site It does not work better but i see interrupt in cat /proc/interrupt. Perhaps someone can help me figure out what happens .. To generate IRQ i have a frequency generator Wired to the right pins of Parallel port. Best Regards and Happy New Year Ps: Sorry for link but site does not accept links (spam protection i suppose) |
All times are GMT -5. The time now is 09:18 PM. |