LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Coding serial ISR for UART 16550 under Linux kernel 3.18 (https://www.linuxquestions.org/questions/linux-newbie-8/coding-serial-isr-for-uart-16550-under-linux-kernel-3-18-a-4175604741/)

annjer 04-27-2017 02:27 AM

Coding serial ISR for UART 16550 under Linux kernel 3.18
 
Hello,
I have a problem with my ISR made on the basis of http://http://www.linuxquestions.org...-linux-763595/Coding an Interrupt Service Routine for the serial port in Linux !! post. Here is my code:
Code:

#include <linux/kernel.h>
#include <linux/module.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 delayedOp (unsigned long currentlyUnused);
DECLARE_TASKLET (rs232Tasklet, delayedOp, 0);

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

        intr_identify = inb( PORT + 2 ) & 0x0F;
        if ( intr_identify == 0x01 ) return  IRQ_NONE;
       
        if ( intr_identify == 0x04 )    // a new character has arrived
        znak=inb( PORT );
        printk ("  irq =  %x, intr = %x ", znak,intr_identify);
        outb(znak,PORT);
        tasklet_schedule (&rs232Tasklet);
        outb(0x20,0x20);
        return (irq_handler_t) IRQ_HANDLED;
}

int init_module ()
{
        int        status;
        int result = request_irq (4, (irq_handler_t) isrSerialPort, IRQF_DISABLED, "softbrainISR", NULL);

        outb(0x0b,PORT+4);        //ster_modem - DTR,RTS,OUT2
        outb( 0x07, PORT + 2 );        // turn off FIFO-mode
        inb(PORT+6);        //stan_modem
        inb(PORT+5);        //status_port
        inb(PORT);                //dane
        outb(0x8b,PORT+3);                //LCR=1, param_trans = 0x0b - parity even (b3-b5), 1 bit stopu(b2), 8 bitów danych (b0,b1)
                                                        //03 - dla parity none
        outb(0x0c,PORT);                //9600 bodów
        outb(0x0b,PORT+3);                //LCR=0
        outb(01,PORT+1);                //przerwanie od odbiornika aktyw_przerw=1
        status=inb(PORT+5);               
        if(status&01)inb(PORT);
        inb(PORT);
        printk (KERN_INFO "\ncinit_module called\n");
        return result;
}

void delayedOp (unsigned long currentlyUnused)
{
        printk ("\nznak =  %x ", znak);
}

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

The problem is that the first interrupt doesn't come - the first character I send comes after I send the next character and so on... In effect I never get the last one - It waits for interrupt until next character.

Where is the problem?
Please help me
Anna

AwesomeMachine 04-28-2017 06:48 PM

Hi Anna,

Welcome to LQ!

OK, for this you must learn the debugger. It will allow you to step through the code while monitoring what is going on. If I had to figure this out, that is what I'd need to do.


All times are GMT -5. The time now is 12:29 PM.