linux 串口uart驱动简析

 

在S3C2440中

Linux系统的串口驱动与一般字符设备并一样,它采用层次化的架构,从而看做是一个串行系统来实现。

(1)关注UART或其他底层串行硬件特征的底层驱动程序。

(2)和底层驱动程序接口的TTY驱动程序。

(3)加工用于和TTY驱动程序交换数据的线路规程。

下图描述了串行系统间的层次结构关系(s3c2440串口实现例),可以概括为:用户应用层 --> 线路规划层 -->TTY层 -->底层驱动层 -->物理硬件层

路规程和TTY驱动程序是与硬件平台无关的,Linux源码中已经提供了实现,所以对于具体的平台,我们只需实现底层驱动程序即可,这也是我们最关心的。在s3c2440a中,主要由dirivers/serial/下的s3c2410.c和samsung.c实现。

Uart驱动程序主要围绕三个关键的数据结构展开(include/linux/serial_core.h中定义):

UART特定的驱动程序结构定义:struct uart_driver s3c24xx_uart_drv;

UART端口结构定义: struct uart_port s3c24xx_serial_ops;

UART相关操作函数结构定义: struct uart_ops s3c24xx_serial_ops;

基于以上三个结构体,来看看s3c2440是如何挂接到Linux中串口构架的:

s3c24xx_serial_ops:S3c2440串口相关操作函数(drivers/serial/S3c2410.c)

static struct uart_ops s3c24xx_serial_ops={

.pm=s3c24xx_serial_pm,//电源管理相关的函数

.tx_empty=s3c24xx_serial_tx_empty,//检查发送的fifo是为空

.get_mctrl=s3c24xx_serial_get_mctrl,//是否串口流控

.set_mctrl=s3c24xx_serial_set_mctrl,//是否设置串口流控cts

.stop_tx=s3c24xx_serial_stop_tx,//停止发送

.start_tx=s3c24xx_serial_start_tx,//启动发送

.stop_rx=s3c24xx_serial_stop_rx,//停止接受

.enable_ms=s3c24xx_serial_enable_ms,//空函数

.break_ctl=s3c24xx_serial_break_ctl,//发送break信号

.startup=s3c24xx_serial_startup,//串口发送接受以及中断申请的初始化设置函数

.shutdown=s3c24xx_serial_shutdown,//关闭串口

.set_termios=s3c24xx_serial_set_termios,//串口时钟,波特率,数据位等的参数设置

.type=s3c24xx_serial_type,

.release_port=s3c24xx_serial_release_port,//释放串口

.request_port=s3c24xx_serial_request_port,//申请串口

.config_port=s3c24xx_serial_config_port,//串口的一些配置信息

.verify_port=s3c24xx_serial_verify_port,//串口检测

};

驱动程序结构定义:

static struct uart_driver s3c24xx_uart_drv={

.owner=THIS_MODULE,

.dev_name="s3c2410_serial",//具体设备的名称

.nr=3,//定义几个端口

.cons=S3C24XX_SERIAL_CONSOLE,//console端口号

.driver_name=S3C24XX_SERIAL_NAME,//串口名

.major=S3C24XX_SERIAL_MAJOR,//主设备号

.minor=S3C24XX_SERIAL_MINOR,//次设备号

};

端口配置结构定义,其中包括了一个struct uart_ports结构(下面的赋值都是对uart_port的填充):

staticstructs3c24xx_uart_ports3c24xx_serial_ports[NR_PORTS]={

    [0] = {
        .port = {
            .lock        = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock),
            .iotype        = UPIO_MEM,
            .irq        = IRQ_S3CUART_RX0,
            .uartclk    = 0,
            .fifosize    = 16,
            .ops        = &s3c24xx_serial_ops,
            .flags        = UPF_BOOT_AUTOCONF,
            .line        = 0,
        }
    },

    [1] = {
        .port = {
            .lock        = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[1].port.lock),
            .iotype        = UPIO_MEM,
            .irq        = IRQ_S3CUART_RX1, //接收中断号
            .uartclk    = 0,
            .fifosize    = 16,  //fifo缓冲的大小
            .ops        = &s3c24xx_serial_ops,  //串口的操作函数
            .flags        = UPF_BOOT_AUTOCONF,
            .line        = 1,
        }
    },

#if NR_PORTS > 2

    [2] = {
        .port = {
            .lock        = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[2].port.lock),
            .iotype        = UPIO_MEM,
            .irq        = IRQ_S3CUART_RX2,
            .uartclk    = 0,
            .fifosize    = 16,
            .ops        = &s3c24xx_serial_ops,
            .flags        = UPF_BOOT_AUTOCONF,
            .line        = 2,
        }
    }
#endif
};
 

在串口进行收发操作时,内核会调用s3c24xx_serial_ops结构体中相关函数。

s3c24xx_serial_stop_tx:停止发送

.3c24xx_serial_start_tx:启动发送

s3c24xx_serial_startup:串口发送接受以及中断申请的初始化设置函数

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值