linux uart驱动——相关数据结构以及API(二)
一、核心数据结构
串口驱动有3个核心数据结构,它们都定义在<#include linux/serial_core.h>
1、uart_driver
uart_driver包含了串口设备名、串口驱动名、主次设备号、串口控制台(可选)等信息,还封装了tty_driver(底层串口驱动无需关心tty_driver)。
1: struct uart_driver {
2: struct module *owner; /* 拥有该uart_driver的模块,一般为THIS_MODULE */
3: const char *driver_name; /* 串口驱动名,串口设备文件名以驱动名为基础 */
4: const char *dev_name; /* 串口设备名 */
5: int major; /* 主设备号 */
6: int minor; /* 次设备号 */
7: int nr; /* 该uart_driver支持的串口个数(最大) */
8: struct console *cons; /* 其对应的console.若该uart_driver支持serial console,否则为NULL */
9:
10: /*
11: * these are private; the low level driver should not
12: * touch these; they should be initialised to NULL
13: */
14: struct uart_state *state;
15: struct tty_driver *tty_driver;
16: };
2、uart_port
uart_port用于描述串口端口的I/O端口或I/O内存地址、FIFO大小、端口类型、串口时钟等信息。实际上,一个uart_port实例对应一个串口设备
1: struct uart_port {
2: spinlock_t lock; /* port lock 串口端口锁 */
3: unsigned long iobase; /* in/out[bwl] io端口基地 */
4: unsigned char __iomem *membase;/* read/write[bwl] IO内存基地址,经映射(如ioremap)后的IO内存虚拟基地址 */
5: unsigned int (*serial_in)(struct uart_port *, int);
6: void (*serial_out)(struct uart_port *, int, int);
7: void (*set_termios)(struct uart_port *,
8: struct ktermios *new,
9: struct ktermios *old);
10: void (*pm)(struct uart_port *, unsigned int state,
11: unsigned int old);
12: unsigned int irq; /* irq number */
13: unsigned long irqflags; /* irq flags */
14: unsigned int uartclk; /* base uart clock */
15: unsigned int fifosize; /* tx fifo size */
16: unsigned char x_char; /* xon/xoff char */
17: unsigned char regshift; /* reg offset shift */
18: unsigned char iotype; /* io access style */
19: unsigned char unused1;
20:
21: #define UPIO_PORT (0)
22: #define UPIO_HUB6 (1)
23: #define UPIO_MEM (2)
24: #define UPIO_MEM32 (3)
25: #define UPIO_AU (4) /* Au1x00 type IO */
26: #define UPIO_TSI (5) /* Tsi108/109 type IO */
27: #define UPIO_DWAPB (6) /* DesignWare APB UART */
28: #define UPIO_RM9000 (7) /* RM9000 type IO */
29: #define UPIO_DWAPB32 (8) /* DesignWare APB UART (32 bit accesses) */
30:
31: unsigned int read_status_mask; /* driver specific */
32: unsigned int ignore_status_mask; /* driver specific */
33: struct uart_state *state; /* pointer to parent state */
34: struct uart_icount icount; /* statistics */
35:
36: struct console *cons; /* struct console, if any */
37: #if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(SUPPORT_SYSRQ)
38: unsigned long sysrq; /* sysrq timeout */
39: #endif
40:
41: upf_t flags;
42:
43: #define UPF_FOURPORT ((__force upf_t) (1 << 1))
44: #define UPF_SAK ((__force upf_t) (1 << 2))
45: #define UPF_SPD_MASK ((__force upf_t) (0x1030))
46: #define UPF_SPD_HI ((__force upf_t) (0x0010))
47: #define UPF_SPD_VHI ((__force upf_t) (0x0020))
48: #define UPF_SPD_CUST ((__force upf_t) (0x0030))
49: #define UPF_SPD_SHI ((__force upf_t) (0x1000))
50: #define UPF_SPD_WARP ((__force upf_t) (0x1010))
51: #define UPF_SKIP_TEST ((__force upf_t) (1 << 6))
52: #define UPF_AUTO_IRQ ((__force upf_t) (1 << 7))
53: #define UPF_HARDPPS_CD ((__force upf_t) (1 << 11))
54: #define UPF_LOW_LATENCY ((__force upf_t) (1 << 13))
55: #define UPF_BUGGY_UART ((__force upf_t) (1 << 14))
56: #define UPF_NO_TXEN_TEST ((__force upf_t) (1 << 15))
57: #define UPF_MAGIC_MULTIPLIER ((__force upf_t) (1 << 16))
58: #define UPF_CONS_FLOW ((__force upf_t) (1 << 23))
59: #define UPF_SHARE_IRQ ((__force upf_t) (1 << 24))
60: /* The exact UART type is known and should not be probed. */
61: #define UPF_FIXED_TYPE ((__force upf_t) (1 << 27))
62: #define UPF_BOOT_AUTOCONF ((__force upf_t) (1 << 28))
63: #define UPF_FIXED_PORT ((__force upf_t) (1 << 29))
64: #define UPF_DEAD ((__force upf_t) (1 << 30))
65: #define UPF_IOREMAP ((__force upf_t) (1 << 31))
66:
67: #define UPF_CHANGE_MASK ((__force upf_t) (0x17fff))
68: #define UPF_USR_MASK ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY))
69:
70: unsigned int mctrl; /* current modem ctrl settings */
71: unsigned int timeout; /* character-based timeout */
72: unsigned int type; /* port type */
73: const struct uart_ops *ops;
74: unsigned int custom_divisor;
75: unsigned int line; /* port index */
76: resource_size_t mapbase; /* for ioremap */
77: struct device *dev; /* parent device */
78: unsigned char hub6; /* this should be in the 8250 driver */
79: unsigned char suspended;
80: unsigned char irq_wake;
81: unsigned char unused[2];
82: void *private_data; /* generic platform data pointer */
83: };.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
uart_iconut为串口信息计数器,包含了发送字符计数、接收字符计数等。在串口的发送中断处理函数和接收中断处理函数中,我们需要管理这些计数。
1: struct uart_icount {
2: __u32 cts;
3: __u32 dsr;
4: __u32 rng;
5: __u32 dcd;
6: __u32 rx; /* 发送字符计数 */
7: __u32 tx; /* 接受字符计数 */
8: __u32 frame; /* 帧错误计数 */
9: __u32 overrun; /* Rx FIFO溢出计数 */
10: __u32 parity; /* 帧校验错误计数 */
11: __u32 brk; /* break计数 */
12: __u32 buf_overrun;
13: };
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
uart_stat有两个成员在底层串口驱动会用到:xmit和port。用户空间程序通过串口发送数据时,上层驱动将用户数据保存在xmit;而串口发送中断处理函数就是通过xmit获取到用户数据并将它们发送出去。串口接收中断处理函数需要通过port将接收到的数据传递给行规则层。
1: /*
2: * This is the state information which is persistent across opens.
3: */
4: struct uart_state {
5: struct tty_port port;
6:
7: int pm_state;
8: struct circ_buf xmit;
9:
10: struct tasklet_struct tlet;
11: struct uart_port *uart_port;
12: };
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
3、uart_ops
uart_ops涵盖了串口驱动可对串口设备进行的所有操作
1: /*
2: * This structure describes all the operations that can be
3: * done on the physical hardware.
4: */
5: struct uart_ops {
6: unsigned int (*tx_empty)(struct uart_port *);/* 串口的Tx FIFO缓存是否为空 */
7: void (*set_mctrl)(struct uart_port *, unsigned int mctrl);/* 设置串口modem控制 */
8: unsigned int (*get_mctrl)(struct uart_port *); /* 获取串口modem控制 */
9: void (*stop_tx)(struct uart_port *);/* 禁止串口发送数据 */
10: void (*start_tx)(struct uart_port *);/* 使能串口发送数据 */
11: void (*send_xchar)(struct uart_port *, char ch);/* 发送xChar */
12: void (*stop_rx)(struct uart_port *);/* 禁止串口接收数据 */
13: void (*enable_ms)(struct uart_port *);/* 使能modem的状态信号 */
14: void (*break_ctl)(struct uart_port *, int ctl); /* 设置break信号 */
15: int (*startup)(struct uart_port *);/* 启动串口,应用程序打开串口设备文件时,该函数会被调用 */
16: void (*shutdown)(struct uart_port *);/* 关闭串口,应用程序关闭串口设备文件时,该函数会被调用 */
17: void (*flush_buffer)(struct uart_port *);
18: void (*set_termios)(struct uart_port *, struct ktermios *new,
19: struct ktermios *old);/* 设置串口参数 */
20: void (*set_ldisc)(struct uart_port *, int new);
21: void (*pm)(struct uart_port *, unsigned int state,
22: unsigned int oldstate);/* 串口电源管理 */
23: int (*set_wake)(struct uart_port *, unsigned int state);
24: void (*wake_peer)(struct uart_port *);
25:
26: /*
27: * Return a string describing the type of the port
28: */
29: const char *(*type)(struct uart_port *);/* 返回一描述串口类型的字符串 */
30:
31: /*
32: * Release IO and memory resources used by the port.
33: * This includes iounmap if necessary.
34: */
35: void (*release_port)(struct uart_port *);/* 释放串口已申请的IO端口/IO内存资源,必要时还需iounmap */
36:
37: /*
38: * Request IO and memory resources used by the port.
39: * This includes iomapping the port if necessary.
40: */
41: int (*request_port)(struct uart_port *); /* 申请必要的IO端口/IO内存资源,必要时还可以重新映射串口端口 */
42: void (*config_port)(struct uart_port *, int);/* 执行串口所需的自动配置 */
43: int (*verify_port)(struct uart_port *, struct serial_struct *);/* 验证串口所需的自动配置 */
44: int (*ioctl)(struct uart_port *, unsigned int, unsigned long);
45: #ifdef CONFIG_CONSOLE_POLL
46: void (*poll_put_char)(struct uart_port *, unsigned char);
47: int (*poll_get_char)(struct uart_port *);
48: #endif
49: };
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
1、uart_register_driver
1: / * 功能:uart_register_driver用于将串口驱动uart_driver注册到内核(串口核心层)中,通常在模块初始化函数调用该函数。
2: * 参数 drv:要注册的uart_driver
3: * 返回值: 成功,返回0;否则返回错误码
4: */
5: int uart_register_driver(struct uart_driver *drv)
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
2、uart_unregister_driver
1: /* 功能: uart_unregister_driver用于注销我们已注册的uart_driver,通常在模块卸载函数调用该函数
2: * 参数 drv:要注销的uart_driver
3:
4: * 返回值: 成功,返回0;否则返回错误码
5: */
6: void uart_unregister_driver(struct uart_driver *drv)
7:
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
3、uart_add_one_port
1: /* 功能: uart_add_one_port用于为串口驱动添加一个串口端口,通常在探测到设备后(驱动的设备probe方法)调用该函数
2: * 参数 drv:串口驱动
3: * port:要添加的串口端口
4:
5: * 返回值: 成功,返回0;否则返回错误码
6: */
7: int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
4、uart_remove_one_port
1: /* 功能: uart_remove_one_port用于删除一个已添加到串口驱动中的串口端口,通常在驱动卸载时调用该函数
2: * 参数 drv: 串口驱动
3: * port: 要删除的串口端口
4: * 返回值: 成功,返回0;否则返回错误码
5: */
6: int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
5、uart_write_wakeup
1: /* 功能: uart_write_wakeup唤醒上层因向串口端口写数据而阻塞的进程,通常在串口发送中断处理函数中调用该函数
2: * 参数 port:需要唤醒写阻塞进程的串口端口
3: */
4: void uart_write_wakeup(struct uart_port *port)
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
6、uart_suspend_port
1: /* 功能: uart_suspend_port用于挂起特定的串口端口
2: * 参数 drv: 要挂起的串口端口所属的串口驱动
3: * port:要挂起的串口端口
4: * 返回值: 成功返回0;否则返回错误码
5: */
6: int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
7、uart_resume_port
1: /* 功能: uart_resume_port用于恢复某一已挂起的串口
2: * 参数 drv: 要恢复的串口端口所属的串口驱动
3: * port:要恢复的串口端口
4: * 返回值: 成功返回0;否则返回错误码
5: */
6: int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
8、uart_get_baud_rate
1: /* 功能: uart_get_baud_rate通过解码termios结构体来获取指定串口的波特率
2: * 参数 port: 要获取波特率的串口端口
3: * termios:当前期望的termios配置(包含串口波特率)
4: * old: 以前的termios配置,可以为NULL
5: * min: 可接受的最小波特率
6: * max: 可接受的最大波特率
7: * 返回值: 串口的波特率
8: */
9: unsigned int
10: uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
11: struct ktermios *old, unsigned int min, unsigned int max)
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
9、uart_get_divisor
1: /* 功能: uart_get_divisor用于计算某一波特率的串口时钟分频数(串口波特率除数)
2: * 参数 port:要计算时钟分频数的串口端口
3: * baud:期望的波特率
4: *返回值: 串口时钟分频数
5: */
6: unsigned int uart_get_divisor(struct uart_port *port, unsigned int baud)
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
10、uart_update_timeout
1: /* 功能: uart_update_timeout用于更新(设置)串口FIFO超时时间
2: * 参数 port: 要更新超时时间的串口端口
3: * cflag:termios结构体的cflag值
4: * baud: 串口的波特率
5: */
6: void uart_update_timeout(struct uart_port *port, unsigned int cflag, unsigned int baud)
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
11、uart_match_port
1: /* 功能:uart_match_port用于判断两串口端口是否为同一端口
2: * 参数 port1、port2:要判断的串口端口
3: * 返回值:不同返回0;否则返回非0
4: */
5: int uart_match_port(struct uart_port *port1, struct uart_port *port2)
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
12、uart_console_write
1: /* 功能: uart_console_write用于向串口端口写一控制台信息
2:
3: * 参数 port: 要写信息的串口端口
4: * s: 要写的信息
5: * count: 信息的大小
6: * putchar: 用于向串口端口写字符的函数,该函数函数有两个参数:串口端口和要写的字符
7: */
8: void uart_console_write(struct uart_port *port, const char *s,
9: unsigned int count,
10: void (*putchar)(struct uart_port *, int))
11:
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
linux uart驱动——相关数据结构以及API(二)的更多相关文章
- linux设备驱动归纳总结(十二):简单的数码相框【转】
本文转载自:http://blog.chinaunix.net/uid-25014876-id-116926.html linux设备驱动归纳总结(十二):简单的数码相框 xxxxxxxxxxxxxx ...
- 【Linux开发】linux设备驱动归纳总结(十二):简单的数码相框
linux设备驱动归纳总结(十二):简单的数码相框 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...
- Linux UART驱动分析
1. 介绍 8250是IBM PC及兼容机使用的一种串口芯片; 16550是一种带先进先出(FIFO)功能的8250系列串口芯片; 16550A则是16550的升级版本, 修复了FIFO相关BUG, ...
- Linux kernel驱动相关抽象概念及其实现 之“bus,device,driver”
bus,device,driver三个很重要的概念贯穿Linux内核驱动架构,特转载一篇博文: (转载自http://blog.csdn.net/gdt_a20/article/details/642 ...
- Linux内核驱动之GPIO子系统API接口概述
1.前言 在嵌入式Linux开发中,对嵌入式SoC中的GPIO进行控制非常重要,Linux内核中提供了GPIO子系统,驱动开发者在驱动代码中使用GPIO子系统提供的API函数,便可以达到对GPIO控制 ...
- Linux kernel驱动相关抽象概念及其实现 之“linux设备模型kobject,kset,ktype”
kobject,kset,ktype三个很重要的概念贯穿Linux内核驱动架构,特转载一篇博文: (转载自http://blog.csdn.net/gdt_a20/article/details/64 ...
- 【linux驱动笔记】字符设备驱动相关数据结构与算法
欢迎转载,转载时需保留作者信息,谢谢. 邮箱:tangzhongp@163.com 博客园地址:http://www.cnblogs.com/embedded-tzp Csdn博客地址:http:// ...
- (转)FS_S5PC100平台上Linux Camera驱动开发详解(二)
4-3 摄像头的初始化流程及v4l2子设备驱动 这个问题弄清楚了以后下面就来看获得Camera信息以后如何做后续的处理: 在fimc_init_global调用结束之后我们获得了OV9650的信息,之 ...
- Linux设备驱动剖析之Input(二)
分别是总线类型.厂商号.产品号和版本号. 1156行,evbit,设备支持的事件类型的位图,每一位代表一种事件,比如EV_KEY.EV_REL事件等等.BITS_TO_LONGS(nr)是一个宏,假设 ...
随机推荐
- 《Linux命令行与shell脚本编程大全 第3版》Linux命令行---22
以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:
- Linux Shell 文本处理工具集锦【转】
转自:http://www.cnblogs.com/me115/p/3427319.html 内容目录: find 文件查找 grep 文本搜索 xargs 命令行参数转换 sort 排序 uniq ...
- ubuntu下使用OBS开斗鱼直播
系统环境:ubuntu 15.10,OBS Studio 0.13.1 OBS是可以在linux,windows,mac下直播的开源软件,官方地址:https://obsproject.com/ 斗鱼 ...
- class.getDeclaredFields()与class.getFields()
* getFields()与getDeclaredFields()区别:getFields()只能访问类中声明为公有的字段,私有的字段它无法访问.getDeclaredFields()能访问类中所有的 ...
- iptables之centos6版本详解
1 Linux防火墙概述 Linux防火墙实际指的是Linux下的Netfilter/Iptables.Netfilter/Iptables是2.4.x/2.6.x版本Linux内核集成的IP信息包过 ...
- 洛谷——P1227 [JSOI2008]完美的对称
P1227 [JSOI2008]完美的对称 题目描述 在峰会期间,必须使用许多保镖保卫参加会议的各国代表.代表们除了由他自己的随身保镖保护外,组委会还指派了一些其他的特工和阻击手保护他们.为了使他们的 ...
- [原创]Getting Started with Skywalking
Getting Started with Skywalking Pre JDK 1.8+ Skywalking(v3.2.6) (All packages can be download from G ...
- Spring IOC(转载)
学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的,今天和大家 ...
- Scut游戏服务器引擎6.5.8.6发布
1.增加从Redis中加载数据到Cache可设置筛选条件2.修改在Web项目中的不能支持自定协议问题3.修改Share类型的Model在Redis中为空时会尝试从DB中加载数据4.修改Model命名空 ...
- Scut游戏服务器引擎6.0.5.0发布-支持C#脚本
1. 增加C#脚本支持2. 增加Pay和Sns中间件对Mysql数据库支持3. 精简布署步骤,取消Redis写入程序,将其移到游戏底层运行4. 修正Mysql对中文可能会出现乱码的BUG 点击下载:S ...