linux内核串口接入pps,Linux串口(serial、uart)驱动程序设计

本文详细介绍了Linux内核串口驱动中的核心数据结构,包括uart_driver、uart_port和uart_info,以及如何通过uart_register_driver、uart_unregister_driver等API进行注册和注销。此外,还讲解了S3C2410串口控制器的配置和操作函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、核心数据结构

串口驱动有3个核心数据结构,它们都定义在

1、uart_driver

uart_driver包含了串口设备名、串口驱动名、主次设备号、串口控制台(可选)等信息,还封装了tty_driver(底层串口驱动无需关心tty_driver)。

struct uart_driver {

struct module     *owner;           /* 拥有该uart_driver的模块,一般为THIS_MODULE */

const char        *driver_name;     /* 串口驱动名,串口设备文件名以驱动名为基础 */

const char        *dev_name;        /* 串口设备名 */

int                major;           /* 主设备号 */

int                minor;           /* 次设备号 */

int                nr;              /* 该uart_driver支持的串口个数(最大) */

struct console    *cons;            /* 其对应的console.若该uart_driver支持serial console,否则为NULL *//*

* these are private; the low level driver should not

* touch these; they should be initialised to NULL

*/

struct uart_state *state;

struct tty_driver *tty_driver;

};

2、uart_port

uart_port用于描述串口端口的I/O端口或I/O内存地址、FIFO大小、端口类型、串口时钟等信息。实际上,一个uart_port实例对应一个串口设备

struct uart_port {

spinlock_t             lock;           /* 串口端口锁 */

unsigned int           iobase;         /* IO端口基地址 */

unsigned char __iomem *membase;    /* IO内存基地址,经映射(如ioremap)后的IO内存虚拟基地址 */

unsigned int           irq;           /* 中断号 */

unsigned int           uartclk;        /* 串口时钟 */

unsigned int           fifosize;       /* 串口FIFO缓冲大小 */

unsigned char          x_char;         /* xon/xoff字符 */

unsigned char          regshift;       /* 寄存器位移 */

unsigned char          iotype;         /* IO访问方式 */

unsigned char          unused1;

#define UPIO_PORT        (0)               /* IO端口 */

#define UPIO_HUB6        (1)

#define UPIO_MEM         (2)               /* IO内存 */

#define UPIO_MEM32       (3)

#define UPIO_AU          (4)               /* Au1x00 type IO */

#define UPIO_TSI         (5)               /* Tsi108/109 type IO */

#define UPIO_DWAPB       (6)               /* DesignWare APB UART */

#define UPIO_RM9000      (7)               /* RM9000 type IO */

unsigned int        read_status_mask;  /* 关心的Rx error status */

unsigned int        ignore_status_mask;/* 忽略的Rx error status */

struct uart_info      *info;           /* pointer to parent info */

struct uart_icount     icount;         /* 计数器 */

struct console        *cons;           /* console结构体 */

#ifdef CONFIG_SERIAL_CORE_CONSOLE

unsigned long         sysrq;           /* sysrq timeout */

#endif

upf_t                 flags;

#define UPF_FOURPORT         ((__force upf_t) (1 << 1))

#define UPF_SAK              ((__force upf_t) (1 << 2))

#define UPF_SPD_MASK         ((__force upf_t) (0x1030))

#define UPF_SPD_HI           ((__force upf_t) (0x0010))

#define UPF_SPD_VHI          ((__force upf_t) (0x0020))

#define UPF_SPD_CUST         ((__force upf_t) (0x0030))

#define UPF_SPD_SHI          ((__force upf_t) (0x1000))

#define UPF_SPD_WARP         ((__force upf_t) (0x1010))

#define UPF_SKIP_TEST        ((__force upf_t) (1 << 6))

#define UPF_AUTO_IRQ         ((__force upf_t) (1 << 7))

#define UPF_HARDPPS_CD       ((__force upf_t) (1 << 11))

#define UPF_LOW_LATENCY      ((__force upf_t) (1 << 13))

#define UPF_BUGGY_UART       ((__force upf_t) (1 << 14))

#define UPF_MAGIC_MULTIPLIER ((__force upf_t) (1 << 16))

#define UPF_CONS_FLOW        ((__force upf_t) (1 << 23))

#define UPF_SHARE_IRQ        ((__force upf_t) (1 << 24))

#define UPF_BOOT_AUTOCONF    ((__force upf_t) (1 << 28))

#define UPF_FIXED_PORT       ((__force upf_t) (1 << 29))

#define UPF_DEAD             ((__force upf_t) (1 << 30))

#define UPF_IOREMAP          ((__force upf_t) (1 << 31))

#define UPF_CHANGE_MASK      ((__force upf_t) (0x17fff))

#define UPF_USR_MASK         ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY))

unsigned int             mctrl;        /* 当前的moden设置 */

unsigned int             timeout;      /* character-based timeout */

unsigned int             type;         /* 端口类型 */

const struct uart_ops   *ops;          /* 串口端口操作函数集 */

unsigned int             custom_divisor;

unsigned int             line;         /* 端口索引 */

resource_size_t          mapbase;      /* IO内存物理基地址,可用于ioremap */

struct device           *dev;          /* 父设备 */

unsigned char            hub6;         /* this should be in the 8250 driver */

unsigned char            suspended;

unsigned char            unused[2];

void                    *private_data; /* 端口私有数据,一般为platform数据指针 */

};

uart_iconut为串口信息计数器,包含了发送字符计数、接收字符计数等。在串口的发送中断处理函数和接收中断处理函数中,我们需要管理这些计数。

struct uart_icount {

__u32    cts;

__u32    dsr;

__u32    rng;

__u32    dcd;

__u32    rx;/* 发送字符计数 */

__u32    tx;/* 接受字符计数 */

__u32    frame;/* 帧错误计数 */

__u32    overrun;/* Rx FIFO溢出计数 */

__u32    parity;/* 帧校验错误计数 */

__u32    brk;/* break计数 */

__u32    buf_overrun;

};

uart_info有两个成员在底层串口驱动会用到:xmit和tty。用户空间程序通过串口发送数据时,上层驱动将用户数据保存在xmit;而串口发送中断处理函数就是通过xmit获取到用户数据并将它们发送出去。串口接收中断处理函数需要通过tty将接收到的数据传递给行规则层。

/* uart_info实例仅在串口端口打开时有效,它可能在串口关闭时被串口核心层释放。因此,在使用uart_port的uart_info成员时必须保证串口已打开。底层驱动和核心层驱动都可以修改uart_info实例。

* This is the state information which is only valid when the port

* is open; it may be freed by the core driver once the device has

* been closed. Either the low level driver or the core can modify

* stuff here.

*/

struct uart_info {

struct tty_struct     *tty;

struct circ_buf        xmit;

uif_t                  flags;/*

* Definitions for info->flags. These are _private_ to serial_core, and

* are specific to this structure. They may be queried by low level drivers.

*/

#define UIF_CHECK_CD        ((__force uif_t) (1 << 25))

#define UIF_CTS_FLOW        ((__force uif_t) (1 << 26))

#define UIF_NORMAL_ACTIVE    ((__force uif_t) (1 << 29))

#define UIF_INITIALIZED        ((__force uif_t) (1 << 31))

#define UIF_SUSPENDED        ((__force uif_t) (1 << 30))

int                     blocked_open;

struct tasklet_struct   tlet;

wait_queue_head_t       open_wait;

wait_queue_head_t       delta_msr_wait;

};

3、uart_ops

uart_ops涵盖了串口驱动可对串口设备进行的所有操作。

/*

* This structure describes all the operations that can be

* done on the physical hardware.

*/

struct uart_ops {

unsigned int (*tx_empty)(struct uart_port *); /* 串口的Tx FIFO缓存是否为空 */

void         (*set_mctrl)(struct uart_port *, unsigned int mctrl);/* 设置串口modem控制 */

unsigned int (*get_mctrl)(struct uart_port *);/* 获取串口modem控制 */

void         (*stop_tx)(struct uart_port *);/* 禁止串口发送数据 */

void         (*start_tx)(struct uart_port *);/* 使能串口发送数据 */

void         (*send_xchar)(struct uart_port *, char ch);/* 发送xChar */

void         (*stop_rx)(struct uart_port *);/* 禁止串口接收数据 */

void         (*enable_ms)(struct uart_port *);/* 使能modem的状态信号 */

void         (*

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值