您的位置:首页 > 其它

[国嵌攻略][132][串口驱动实现]

2016-03-11 15:00 302 查看
如何开发Linux驱动程序

一般情况下都会有现成的驱动程序,不需要从零开始开发驱动程序。所以Linux驱动开发主要分为两个步骤:1.读得懂驱动程序;2.写的了核心功能。

发送中断处理程序

发送中断处理函数在/drivers/serial/samsung.c的s3c24xx_serial_tx_chars

循环缓冲

struct circ_buf {

char *buf;

int head;

int tail;

};

存数据的时候移动head,取数据的时候移动tail。

static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id){
//判断发送流控
struct s3c24xx_uart_port *ourport = id;
struct uart_port *port = &ourport->port;

if(port->x_char){   //是否有发送流控字符
//写入流控字符
wr_regb(port, S3C2410_UTXH, port->x_char);

//修改发送计数
port->icount.tx++;

//清除流控字符
port->x_char = 0;

return IRQ_HANDLED;   //中断处理完成
}

//判断数据发送
struct circ_buf *xmit = &port->state->xmit;

if(uart_circ_empty(xmit) || uart_tx_stopped(port)){   //是否循环缓冲为空或者串口停止发送
s3c24xx_serial_stop_tx(port);

return IRQ_HANDLED;   //中断处理完成
}

//循环发送数据
int count = 256;

while(!uart_circ_empty(xmit) && (count-- > 0)){   //是否循环缓冲不为空并且发送数据小于256字节
//判断循环缓冲
if(rd_regl(port, S3C2410_UFSTAT) & (1<<14)){   //是否循环缓冲已满
break;
}

//写入发送数据
wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);

//移动缓冲位置
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);   //循环移动尾部

//修改发送计数
port->icount.tx++;
}

//唤醒阻塞进程
if(uart_circ_chars_pending(xmit) < 256){   //是否循环缓冲数目小于256
uart_write_wakeup(port);
}

//关闭发送使能
if(uart_circ_empty(xmit)){   //是否循环缓冲为空
s3c24xx_serial_stop_tx(port);
}

return IRQ_HANDLED;   //中断处理完成
}


接收中断处理程序

接收中断处理函数在/drivers/serial/samsung.c的s3c24xx_serial_rx_chars

static irqreturn_t s3c24xx_serial_rx_chars(int irq, void *dev_id){
//循环接收数据
struct s3c24xx_uart_port *ourport = dev_id;
struct uart_port *port = &ourport->port;
int max_count = 64;

while((max_count--) > 0){   //是否接收数据小于64字节
//判断接收缓冲
unsigned int ufstat;

ufstat = rd_regl(port, S3C2410_UFSTAT);
if((ufstat & 0x3F) == 0){   //是否接收缓冲为空
break;
}

//读取错误状态
unsigned int uerstat;

uerstat = rd_regl(port, S3C2410_UERSTAT);

//读取接收数据
unsigned int ch;

ch = rd_regb(port, S3C2410_URXH);

//写入接收缓冲
uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN, ch, TTY_NORMAL);
}

//写入线路规程
struct tty_struct *tty = port->state->port.tty;

tty_flip_buffer_push(tty);

return IRQ_HANDLED;   //中断处理完成
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: