login
Header Space

 
 

Serial Driver Implementation Help

December 1, 2008 - 10:22am
Submitted by developer on December 1, 2008 - 10:22am.
Linux

hi

I am implementing a serial driver for linux. Can somebody show me an example about how to implement Hardware flow control in a driver?

Another issue concerning the transmit interrupt. I have enabled the transmit interrupt with FIFO equal to 16 bytes and this is function used to transmit:

void tiny_tx_chars(struct uart_port *port)
{

printk("tiny_tx_chars is called\n");

struct circ_buf *xmit = &port->info->xmit;
int count;
int i;

if (port->x_char) {
//for software flow control xon/xoff character
outb(xmit->buf[xmit->tail],port->iobase);
printk(" Sent first : %x\n",port->x_char);
port->icount.tx++;
port->x_char = 0;
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
tiny_stop_tx(port, 0);
return;
}

count = port->fifosize >> 1; //the interrupt is called every 8 bytes

do {
outb((unsigned char )(xmit->buf[xmit->tail]),port->iobase);
printk("Sent: %02x\n",(unsigned char )(xmit->buf[xmit->tail]));
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
if (uart_circ_empty(xmit))
break;
} while (--count > 0);

printk("\n");

if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);

if (uart_circ_empty(xmit))
tiny_stop_tx(port, 0);
}

The problem is that when i want to send more than 16 bytes all together at the same time, it sends only the first 16 bytes (the size of the fifo) and waits for an "Enter" from the console to send the other bytes. The problem is that after the 16 bytes are sent, no Transmit Interrupt is generated!!!!!!!

This is my interrupt:

irqreturn_t short_interrupt(int irq, void *dev_id)
{

int status;

struct uart_port *port=dev_id;

status=inb(port->iobase + 2);

if( (status & 0x02) == 0x02){
printk("Transmit Empty Buffer interrupt, Interupt register is %02x\n",inb(port->iobase + 2) );
tiny_tx_chars(port);
}
if( (status & 0x04) == 0x04){
printk("Receive interrupt\n Interupt register is %02x\n",inb(port->iobase + 2) );
tiny_rx_chars(port);
// printk("IIR Register Value =: %2x\n",status);
//a function is called here
}
if( (status & 0x06) == 0x00){
//printk("Modem Status Interrupt, Interupt register is %02x\n",inb(port->iobase + 2) );
tiny_modem_status(port);
}

return IRQ_HANDLED;
}

Any idea??? Thanks for your help

interrupt enable code?

December 4, 2008 - 6:09pm
Ferdinand (not verified)

Where's the code to enable the transmit interrupt?

Normally the transmit routine looks like this:

-- copy as many bytes as possible from the tx buffer to the FIFO
-- if there are more bytes to transmit, enable transmit interrupts, otherwise disable them

And the write routine looks like this:

-- add the character to the tx buffer
-- call the transmit routine

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
speck-geostationary