我是靠谱客的博主 霸气镜子,这篇文章主要介绍Uart Controller --- 架构uart controller driver,现在分享给大家,希望可以做个参考。

复制代码
1
2
3
4
/* Register uart Line Status Register */ #define UART_REGISTER_LSR
复制代码
1
2
3
4
5
6
driver 的第一要义是要 深刻理解 该hardware所拥有的行为, 比如Altera cyclone V 的 Can controller 的 mo interrupt,印象好深刻 好了,这些hardware的行为背后是一大堆复杂的电路呈现出来的register, 下面会有对 触发器的详细介绍,一定要让你彻底明白什么是 D trigger

https://github.com/leesagacious/lee-TEE/tree/master/core/driver

在Linux kernel中 bitmap使用很是广泛, Register 是hardware中真正的 “位图”
这里写图片描述

1 : 看一下tee kernel中的实现

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
/* 也许会问 不是有 Rx interrupt 吗 ? */ static bool serial8250_uart_have_rx_data(.....) { /* #define LSR_DR 0x01 DATA Ready 就是读取LSR register 判断该register的bit[0]. */ return (read32(base + UART_LSR) & LSR_DR); }

2 : 下面是linux kernel 中的实现

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/* 刷缓冲区中的数据到线路规程中. flush data from the buffer chain to the line discipline 1 : 幕后推手是谁 ? software interrupt, 好,为什么是software interrupt, 而不是其他 */ static void flush_to_ldisc(struct work_struct *work) { /** tty_port 它也维护了一个缓冲区,类比uart_port也维护了一个缓冲区, (每个port的发送数据的 struct circ_buf 发送缓冲区) 只是这两个buffer分别在不同的层中,他们是间接的联系在一起的. 层多了,显然影响效率,那就使用缓存了, 哈哈 其实,整个写入的流程是: tty core -> line discipline -> tty driver ->uart driver -> circ_buf 发送缓冲区中的 好,上面说了 推动数据最终流动到circ_buf中的是 software interrupt 下面详细说这个circ_buf是怎么分配的 为什么要分配一个page大小, 这和 UART_MAX_SIZE 有关系吗 你仔细看这个 contianer_of() 实现的很妙, 当然了用户空间也可 使用container_of() , 只是您必须加上头文件 #include <stddef.h> 好了,来看看这个tty_port 是什么了, 1. uart_state,tty_struct, tty_driver 都维护了它, 果然集千万宠爱于一身, 2. 在uart_register_driver()注册uart_driver的时候被初始化 uart_state的时候被初始化了 https://blog.csdn.net/leesagacious/article/details/54670735 int uart_register_driver(...) { ..... 支持多少个物理port, 就给你几个圈圈转转 好了,你想想物理port与tty_port之间的对应关系吧,一对一 ? for (i = 0; i < drv->nr; i++) { struct uart_state *state = drv->state + i; struct tty_port *port = &state->port; 初始化tty_port 吧. 无非是初始化 mutex , buf ,wait_queue 之类的 tty_port_init(port); port->ops = &uart_port_ops; ..... } } tty_port 在整个uart体系中只是一个配角. 重要性低于tty_driver,tty_struct,以及 各个 ops. 好了,用到了在说吧. 这里拿出来tty_port是为了什么呢 ? 很显然 : 1 : 是为了获取它维护的缓冲区 2 :获取维护的tty_struct, 因为tty_struct维护了线路规程, 该函数的目的就是 将tty_port中维护的缓冲区的数据刷入到线路规程中 该函数一上来就开始准备这些, 最终一个一个位写入到uart register的时候 速度是恒定的,发送一个位 耗时 1/115200 (s) ,显然速度很慢 在这里临时抱抱佛脚,也没关系的. 是吧? 哈哈 3 : tty_port维护了一个32位的位图,iflags, 正在刷入线路规程的时候 缓冲区是锁定的, 看下面的图示 */ struct tty_port *port = container_of(work, struct tty_port, buf.work); /* port维护的这个buf 很有意义. 下面用到了再说吧 这里先放过他. */ struct tty_bufhead *buf = &port->buf; /** 这个鬼也来凑热闹,... 上面说了,获取它就是为了获取它维护的线路规程. 看.. serial_in()从 register中读取字符开始,到这里刷入line discipline之前各路大神都请来了,不容易呀. */ struct tty_struct *tty; /* 该变量你应该知道的. 哈哈, */ unsigned long flags; /* 线路规程, 下面会给它赋值, 看到了吧, 在这里开始进行"串线", 可增加独有的线路规程, 然后将数据刷入到自定义的线路规程中 当然了,如果不想这样做, 还有其他更好的方法. 请移步 ; https://blog.csdn.net/leesagacious/article/details/78237306 底层统一的数据, 从这里要开始分道扬镳了. 而不是像signal那样速途同归. https://blog.csdn.net/leesagacious/article/details/53678666 */ struct tty_ldisc *disc; /* 获取tty_struct. 什么时候开始建立关联关系的 ? 当用户空间调用 open()的时候, tty_open() 会被调用 于是 : tty_open() { .... 初始化一个 tty device. tty = tty_init_dev(driver, index); { struct tty_struct *tty; tty = alloc_tty_struct(); // 分配 .... tty->port->itty = tty; // 赋值 } } */ tty = port->itty; if (tty == NULL) return; /* 怎么获取的 ? 请移步 : https://blog.csdn.net/leesagacious/article/details/77170670 */ disc = tty_ldisc_ref(tty); if (disc == NULL) /* !TTY_LDISC */ return; /* 这个一定要有的. https://blog.csdn.net/leesagacious/article/details/64980255 */ spin_lock_irqsave(&buf->lock, flags); /* 还好,这不是"独角戏" 该来的大神都请来了, 登台演戏吧, */ if (!test_and_set_bit(TTYP_FLUSHING, &port->iflags)) { } }

这里写图片描述

最后

以上就是霸气镜子最近收集整理的关于Uart Controller --- 架构uart controller driver的全部内容,更多相关Uart内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(63)

评论列表共有 0 条评论

立即
投稿
返回
顶部