4 ms·
Writing serial port interrupt handler in linux
I got a new 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 !!
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#define PORT 0x3F8
irq_handler_t isrSerialPort (int irq, void dev_id, struct pt_regs regs)
{
printk ("\nThank god !\n");
return (irq_handler_t) IRQ_HANDLED;
}
int init_module ()
{
outb (0x01, PORT + 1);
outb (0x83, PORT + 3);
// Set Baud rate - Divisor Latch Low Byte
outb (0x0C, PORT + 0);
// Set Baud rate - Divisor Latch High Byte
outb (0x00, PORT + 1);
// number of bytes to read
outb (0x07, PORT + 2);
outb (0x03, PORT + 3);
int h = request_irq (4, (irq_handler_t) isrSerialPort,
SA_SHIRQ, "God", (void *) (isrSerialPort));
// Interrupt when data received
outb (0x01, PORT + 1);
return h;
}
MODULE_LICENSE ("GPL");
- a-priori 17y agoI'm going to assume you're doing this for intellectual curiosity, because I'm sure the existing serial port drivers work fine. That's okay; I used to do operating system development (aka "osdev") a few years back as a hobby, so I understand how you feel :) Here are my hunches for what the problem is: you're initializing the UART wrong (it's been a while and I forget the details), you're conflicting with something else that's using the serial port, or you're registering your ISR wrong. To test whether your UART initialization is correct, you can try removing Linux from the mix. It's pretty simple to create a binary that GRUB can boot (Google: multiboot specification), and that way you can test out your code in isolation. You'll want to use polling rather than ISRs to wait for data, and write directly into the VGA buffer (it's on the even bytes starting at 0xB8000) to print your data to screen. You also might want to try running this through Bochs, because it can give you hardware-level logs about what's going on. Are bytes actually being received? Is the IRQ actually being raised? That sort of thing. If that works, then your problem is with Linux itself, and I can't be much help there. I suggest looking through the source for other drivers that register IRQ handlers, or asking the linux-kernel mailing list. Best of luck.
- aquarius 17y agoThanks for the guidelines !!
- brtzsnr 17y agoHomework? I had this assignment while studying Operating Systems Design during college. I can tell you I failed miserable. We used documentation from: http://www.beyondlogic.org/serial/serial.htm http://www.beyondlogic.org/serial/serial.htm. You can find some examples there, but not for the Linux kernel.
- JoeAltmaier 17y agoStart with outb (0x00, PORT + 1);
- aquarius 17y agoDoes the order of specification matter ?
- srn 17y agoThis may not be likely, but - you don't specify a level for your printk statement. It could be your message is just not getting printed to console. Check out info for "/proc/sys/kernel/printk" as well as information about syslogd and klogd as the message may be logged to somewhere else. I also would like to mention that in general memory barriers can be useful for working with i/o irrespective of your particular situation.
- srn 17y agoMore explicit handling of error conditions is also good FWIW - don't see you doing it here. The kernel is not forgiving of using resources your don't have or failing to free resources acquired.
- srn 17y agoAlso from what I know, which is not much, you should be requesting the ports via request_region. If that fails you should probably not be writing to the ports and should also mean you're sharing the port with another module. kernel newbies is theoretically a good place to go with these kinds of questions too.