Linux RS232/485/GPS 驱动实验(1)

Linux UART 驱动框架
1 uart_driver 注册与注销

uart_driver需要驱动编写人员实现,并使用uart_register_driver注册到内核,卸载驱动的时候,使用uart_unregister_driver卸载。同 I2CSPI 一样,Linux 也提供了串口驱动框架,我们只需要按照相应的串口框架编写驱动程序即可。串口驱动没有什么主机端和设备端之分,就只有一个串口驱动,而且这个驱动也已经由NXP 官方已经编写好了,我们真正要做的就是在设备树中添加所要使用的串口节点信息。当系统启动以后串口驱动和设备匹配成功,相应的串口就会被驱动起来,生成 /dev/ttymxcX(X=0….n)文件。虽然串口驱动不需要我们去写,但是串口驱动框架我们还是需要了解的,uart_driver 结构体表示 UART 驱动,uart_driver 定义在 include/linux/serial_core.h 文件中,内容如下:

295 struct uart_driver {
296 struct module *owner; /* 模块所属者 */
297 const char *driver_name; /* 驱动名字 */
298 const char *dev_name; /* 设备名字 */
299 int major; /* 主设备号 */
300 int minor; /* 次设备号 */
301 int nr; /* 设备数 */
302 struct console *cons; /* 控制台 */
303
304 /*
305 * these are private; the low level driver should not
306 * touch these; they should be initialised to NULL
307 */
308 struct uart_state *state; 
309 struct tty_driver *tty_driver;
310 };
每个串口驱动都需要定义一个 uart_driver ,加载驱动的时候通过 uart_register_driver 函数向
系统注册这个 uart_driver ,此函数原型如下:
int uart_register_driver(struct uart_driver *drv)
函数参数和返回值含义如下:
drv 要注册的 uart_driver
返回值: 0 ,成功;负值,失败。
注销驱动的时候也需要注销掉前面注册的 uart_driver ,需要用到 uart_unregister_driver 函数,
函数原型如下:
void uart_unregister_driver(struct uart_driver *drv)
函数参数和返回值含义如下:
drv 要注销的 uart_driver
返回值: 无。
2 uart_port 的添加与移除

用于描述一个具体的串口端口,驱动编写人员需要实现uart_port,然后使用uart_add_one_port函数向内核添加一个uart端口,卸载的时候uart_remove_one_port卸载。uart_port里面有个非常重要的成员变量uart_ops,此结构体包含了针对uart端口进行的所有操作,需要驱动编写人员实现。

uart_port 表示一个具体的 port uart_port 定义在 include/linux/serial_core.h 文件,内容部分如下
117 struct uart_port {
118 spinlock_t lock; /* port lock */
119 unsigned long iobase; /* in/out[bwl] */
120 unsigned char __iomem *membase; /* read/write[bwl] */
......
235 const struct uart_ops *ops;
236 unsigned int custom_divisor;
237 unsigned int line; /* port index */
238 unsigned int minor;
239 resource_size_t mapbase; /* for ioremap */
240 resource_size_t mapsize;
241 struct device *dev; /* parent device */
......
250 };
uart_port 中最主要的就是第 235 行的 ops ops 包含了串口的具体驱动函数,这个我们稍后
再看。每个 UART 都有一个 uart_port ,那么 uart_port 是怎么和 uart_driver 结合起来的呢?这里
要用到 uart_add_one_port 函数,函数原型如下:
int uart_add_one_port(struct uart_driver *drv, 
 struct uart_port *uport)
函数参数和返回值含义如下:
drv :此 port 对应的 uart_driver
uport 要添加到 uart_driver 中的 port
返回值: 0 ,成功;负值,失败。
卸载 UART 驱动的时候也需要将 uart_port 从相应的 uart_driver 中移除,需要用到
uart_remove_one_port 函数,函数原型如下:
int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
函数参数和返回值含义如下:
drv :要卸载的 port 所对应的 uart_driver
uport 要卸载的 uart_port
返回值: 0 ,成功;负值,失败。
3 uart_ops 实现
在上面讲解 uart_port 的时候说过, uart_port 中的 ops 成员变量很重要,因为 ops 包含了针
UART 具体的驱动函数, Linux 系统收发数据最终调用的都是 ops 中的函数。 ops uart_ops
类型的结构体指针变量, uart_ops 定义在 include/linux/serial_core.h 文件中,内容如下:
49 struct uart_ops {
50 unsigned int (*tx_empty)(struct uart_port *);
51 void (*set_mctrl)(struct uart_port *, unsigned int mctrl);
52 unsigned int (*get_mctrl)(struct uart_port *);
53 void (*stop_tx)(struct uart_port *);
54 void (*start_tx)(struct uart_port *);
55 void (*throttle)(struct uart_port *);
56 void (*unthrottle)(struct uart_port *);
57 void (*send_xchar)(struct uart_port *, char ch);
58 void (*stop_rx)(struct uart_port *);
59 void (*enable_ms)(struct uart_port *);
60 void (*break_ctl)(struct uart_port *, int ctl);
61 int (*startup)(struct uart_port *);
62 void (*shutdown)(struct uart_port *);
63 void (*flush_buffer)(struct uart_port *);
64 void (*set_termios)(struct uart_port *, struct ktermios *new,
65 struct ktermios *old);
66 void (*set_ldisc)(struct uart_port *, struct ktermios *);
67 void (*pm)(struct uart_port *, unsigned int state,
68 unsigned int oldstate);
69
70 /*
71 * Return a string describing the type of the port
72 */
73 const char *(*type)(struct uart_port *);
74
75 /*
76 * Release IO and memory resources used by the port.
77 * This includes iounmap if necessary.
78 */
79 void (*release_port)(struct uart_port *);
80
81 /*
82 * Request IO and memory resources used by the port.
83 * This includes iomapping the port if necessary.
84 */
85 int (*request_port)(struct uart_port *);
86 void (*config_port)(struct uart_port *, int);
87 int (*verify_port)(struct uart_port *, struct serial_struct *);
88 int (*ioctl)(struct uart_port *, unsigned int, unsigned long);
89 #ifdef CONFIG_CONSOLE_POLL
90 int (*poll_init)(struct uart_port *);
91 void (*poll_put_char)(struct uart_port *, unsigned char);
92 int (*poll_get_char)(struct uart_port *);
93 #endif
94 };
UART 驱动编写人员需要实现 uart_ops ,因为 uart_ops 是最底层的 UART 驱动接口,是实
实在在的和 UART 寄存器打交道的。关于 uart_ops 结构体中的这些函数的具体含义请参考
Documentation/serial/driver 这个文档。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值