linux的串口驱动分析
1、串口驱动中的数据结构
• UART驱动程序结构:struct uart_driver 驱动
• UART端口结构: struct uart_port 串口
• UART相关操作函数结构: struct uart_ops 串口操作函数集
• UART状态结构: struct uart_state 串口状态
• UART信息结构: struct uart_info 串口信息
2、串口驱动程序-初始化

3、串口驱动分析-打开设备

static int s3c24xx_serial_startup(struct uart_port *port)
{
struct s3c24xx_uart_port *ourport = to_ourport(port);
int ret; dbg("s3c24xx_serial_startup: port=%p (%08lx,%p)\n",
port->mapbase, port->membase); rx_enabled(port) = ; ret = request_irq(ourport->rx_irq, s3c24xx_serial_rx_chars, ,
s3c24xx_serial_portname(port), ourport); if (ret != ) {
printk(KERN_ERR "cannot get irq %d\n", ourport->rx_irq);
return ret;
} ourport->rx_claimed = ; dbg("requesting tx irq...\n"); tx_enabled(port) = ; ret = request_irq(ourport->tx_irq, s3c24xx_serial_tx_chars, ,
s3c24xx_serial_portname(port), ourport); if (ret) {
printk(KERN_ERR "cannot get irq %d\n", ourport->tx_irq);
goto err;
} ourport->tx_claimed = ; dbg("s3c24xx_serial_startup ok\n"); /* the port reset code should have done the correct
* register setup for the port controls */ return ret; err:
s3c24xx_serial_shutdown(port);
return ret;
}

3、串口驱动程序-数据发送

static void s3c24xx_serial_start_tx(struct uart_port *port)
{
struct s3c24xx_uart_port *ourport = to_ourport(port);
static int a =;//temp
if (port->line == ) {
// printk("485_start_tx\n"); if(a){
s3c_gpio_cfgpin(S3C64XX_GPK(), S3C_GPIO_SFN());
a=;
}
gpio_set_value(S3C64XX_GPK(), );
}
if (!tx_enabled(port)) {
if (port->flags & UPF_CONS_FLOW)
s3c24xx_serial_rx_disable(port); enable_irq(ourport->tx_irq);
tx_enabled(port) = ;
}
}
static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
{
struct s3c24xx_uart_port *ourport = id;
struct uart_port *port = &ourport->port;
struct circ_buf *xmit = &port->state->xmit;
int count = ; if (port->x_char) {
wr_regb(port, S3C2410_UTXH, port->x_char);
port->icount.tx++;
port->x_char = ;
goto out;
} /* if there isn't anything more to transmit, or the uart is now
* stopped, disable the uart and exit
*/ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
s3c24xx_serial_stop_tx(port);
goto out;
} /* try and drain the buffer... */ while (!uart_circ_empty(xmit) && count-- > ) {
if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
break; wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + ) & (UART_XMIT_SIZE - );
port->icount.tx++;
} if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port); if (uart_circ_empty(xmit))
s3c24xx_serial_stop_tx(port); out:
return IRQ_HANDLED;
}

4、串口驱动程序-数据接收

s3c24xx_serial_rx_chars(int irq, void *dev_id)
{
struct s3c24xx_uart_port *ourport = dev_id;
struct uart_port *port = &ourport->port;
struct tty_struct *tty = port->state->port.tty;
unsigned int ufcon, ch, flag, ufstat, uerstat;
int max_count = ; while (max_count-- > ) {
ufcon = rd_regl(port, S3C2410_UFCON);
ufstat = rd_regl(port, S3C2410_UFSTAT); if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == )
break; uerstat = rd_regl(port, S3C2410_UERSTAT);
ch = rd_regb(port, S3C2410_URXH); if (port->flags & UPF_CONS_FLOW) {
int txe = s3c24xx_serial_txempty_nofifo(port); if (rx_enabled(port)) {
if (!txe) {
rx_enabled(port) = ;
continue;
}
} else {
if (txe) {
ufcon |= S3C2410_UFCON_RESETRX;
wr_regl(port, S3C2410_UFCON, ufcon);
rx_enabled(port) = ;
goto out;
}
continue;
}
} /* insert the character into the buffer */ flag = TTY_NORMAL;
port->icount.rx++; if (unlikely(uerstat & S3C2410_UERSTAT_ANY)) {
dbg("rxerr: port ch=0x%02x, rxs=0x%08x\n",
ch, uerstat); /* check for break */
if (uerstat & S3C2410_UERSTAT_BREAK) {
dbg("break!\n");
port->icount.brk++;
if (uart_handle_break(port))
goto ignore_char;
} if (uerstat & S3C2410_UERSTAT_FRAME)
port->icount.frame++;
if (uerstat & S3C2410_UERSTAT_OVERRUN)
port->icount.overrun++; uerstat &= port->read_status_mask; if (uerstat & S3C2410_UERSTAT_BREAK)
flag = TTY_BREAK;
else if (uerstat & S3C2410_UERSTAT_PARITY)
flag = TTY_PARITY;
else if (uerstat & (S3C2410_UERSTAT_FRAME |
S3C2410_UERSTAT_OVERRUN))
flag = TTY_FRAME;
} if (uart_handle_sysrq_char(port, ch))
goto ignore_char; uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN,
ch, flag); ignore_char:
continue;
}
tty_flip_buffer_push(tty); out:
return IRQ_HANDLED;
}

附:linux系统中一般的流控技术

linux的串口驱动分析的更多相关文章
- linux串口驱动分析
linux串口驱动分析 硬件资源及描写叙述 s3c2440A 通用异步接收器和发送器(UART)提供了三个独立的异步串行 I/O(SIO)port,每一个port都能够在中断模式或 DMA 模式下操作 ...
- linux UART串口驱动开发文档
转:http://www.360doc.com/content/10/0417/18/829197_23519037.shtml linux UART串口驱动开发文档时间:2010-01-09 14: ...
- linux串口驱动分析——发送数据
一.应用程序中write函数到底层驱动历程 和前文提到的一样,首先先注册串口,使用uart_register_driver函数,依次分别为tty_register_driver,cdev_init函数 ...
- linux串口驱动分析——打开设备
串口驱动是由tty_driver架构实现的.一个应用程序中的函数要操作硬件,首先会经过tty,级级调用之后才会到达驱动之中.本文先介绍应用程序中打开设备的open函数的整个历程. 首先在串口初始化中会 ...
- linux串口驱动分析【转】
转自:http://blog.csdn.net/hanmengaidudu/article/details/11946591 硬件资源及描述 s3c2440A 通用异步接收器和发送器(UART)提供了 ...
- tiny4412 串口驱动分析七 --- log打印的几个阶段之内核启动阶段(earlyprintk)
作者:彭东林 邮箱:pengdonglin137@163.com 开发板:tiny4412ADK+S700 4GB Flash 主机:Wind7 64位 虚拟机:Vmware+Ubuntu12_04 ...
- tiny4412 串口驱动分析四 --- 修改默认的串口输出
作者:彭东林 邮箱:pengdonglin137@163.com 开发板:tiny4412ADK+S700 4GB Flash 主机:Wind7 64位 虚拟机:Vmware+Ubuntu12_04 ...
- tiny4412 串口驱动分析一 --- u-boot中的串口驱动
作者:彭东林 邮箱:pengdonglin137@163.com 开发板:tiny4412ADK+S700 4GB Flash 主机:Wind7 64位 虚拟机:Vmware+Ubuntu12_04 ...
- (linux)MMC 卡驱动分析
最近花时间研究了一下 MMC 卡驱动程序,开始在网上找了很多关于 MMC 卡驱动的分析文章,但大都是在描述各个层,这对于初学者来讲帮助并不大,所以我就打算把自己的理解写下来,希望对大家有用.个人觉得理 ...
随机推荐
- Android——TableLayout
TableLayout的行数由开发人员直接指定,即有多少个TableRow对象(或View控件),就有多少行. TableLayout的列数等于含有最多子控件的TableRow的列数.如第一Table ...
- silverlight,动态数据集合中,移除动态集合自身的内容
在xaml的页面上创建一个x:Name为_list1的ListBox,其中ListBox里面的每一项是ListBoxItem if (_list1.SelectedItem == null)//如果_ ...
- dedecms首页怎么调用公司简介的内容
DeDeCMS功能虽然强大,但还是有些细节上的功能没有实现,正如本文描述的问题一样,DEDECMS要在网站首页调用公司简介的内容,而且还要截取前多少个字符数的时候,DEDECMS标签中没有能实现这样的 ...
- tesseract-orc 合并识别结果
在实际使用 tesseract-orc 识别库的时候,初次制作的识别库很有可能识别率不太理想,需要后期慢慢补充 本文演示如何将多个修正过的box文件合并成一个识别库. 首先,需要图片样本.tif文件, ...
- CDN缓存策略FAQ
1.CDN加速原理通过动态域名解析,网友的请求被分配到离自己最快的服务器.CDN服务器直接返回缓存文件或通过专线代理原站的内容.网络加速+内容缓存,有效提供访问速度 2.CDN节点数量全国多个机房,每 ...
- memcached学习(3)memcached的删除机制和发展方向
memcached是缓存,所以数据不会永久保存在服务器上,这是向系统中引入memcached的前提. 本次介绍memcached的数据删除机制,以及memcached的最新发展方向--二进制协议(Bi ...
- eclipse中logcat偶尔不显示log的问题解决办法
Android开发过程中 eclipse 经常会出现 logcat突然就是不现实log的情况.经常遇到,一直没有解决.后来解决了,记录一下. 默认的设置是error 改成verbos 问题解决.
- Linux下搭建Lotus Domino集群
Linux下搭建Lotus Domino 集群 本文内容是Linux平台下Lotus Domino服务器部署案例(http://chenguang.blog.51cto.com/350944/1334 ...
- C# 特性Attributes 和反射
一,Attributes 类新建一个子类,DetailAttributes 二, 在类的属性声明上面加Attributes public class testAttributes { [Detail( ...
- EFDC_EE如何设置自适应时间步长
下图是EFDC_EE的运行时间参数的设置界面,在时间步长的设置中,如果“Safety Factor”参数,设置为非0,即可实现自适应时间步长的设置,但要注意如下几点: 1.“Safety Factor ...