linux串口驱动

来源:互联网 发布:淘宝指数数据 编辑:程序博客网 时间:2024/05/16 21:57
一.常见结构体的分析
1.tty_driver结构体:
 struct tty_driver                                                            
 {                                                                            
   int magic;                                                                 
   struct cdev cdev; /* 对应的字符设备cdev */                                                          
   struct module *owner;   /*这个驱动的模块拥有者 */                                                   
   const char *driver_name;                                                   
   const char *devfs_name;                                                    
   const char *name;   /* 设备名 */                                                       
   int name_base; /* offset of printed name */                    
   int major; /* 主设备号 */                                                  
   int minor_start; /* 开始次设备号 */                     
   int minor_num; /* 设备数量 */                                              
   int num; /* 被分配的设备数量 */                                            
   short type; /* tty驱动的类型 */                        
   short subtype; /* tty驱动的子类型 */             
   struct termios init_termios; /* 初始线路设置 */             
   int flags; /* tty驱动标志 */                          
   int refcount; /*引用计数(针对可加载的tty驱动) */                   
   struct proc_dir_entry *proc_entry; /* /proc文件系统入口 */         
   struct tty_driver *other; /* 仅对PTY驱动有意义 */          
   ...                                                                        
   /* 接口函数 */
}
magic表示给这个结构体的“幻数”,设为 TTY_DRIVER_MAGIC,在 alloc_tty_driver()函数中被初始化。
name与driver_name的不同在于后者表示驱动的名字,用在 /proc/tty 和 sysfs中,而前者表示驱动的
设备节点名。type 与subtype描述tty驱动的类型和子类型,subtype的值依赖于type,type值可为
TTY_DRIVER_TYPE_SERIAL(被任何串行类型驱动使用,subtype 应当设为 SERIAL_TYPE_NORMAL
或SERIAL_TYPE_CALLOUT),TTY_DRIVER_TYPE_CONSOLE(仅被控制台驱动使用。
init_termios 为初始线路设置,为一个termios结构体,这个成员被用来提供一个线路设置集合。
termios 用于保存当前的线路设置,这些线路设置控制当前波特率、数据大小、数据流控设置等:                                           
struct termios tty_std_termios =                             
{                                                            
 .c_iflag = ICRNL | IXON, /* 输入模式 */                     
 .c_oflag = OPOST | ONLCR, /* 输出模式 */                    
 .c_cflag = B38400 | CS8 | CREAD | HUPCL, /* 控制模式 */     
 .c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |           
 ECHOCTL | ECHOKE | IEXTEN,  /* 本地模式 */                  
 .c_cc = INIT_C_CC  /* 控制字符,用来修改终端的特殊字符映射 */
};
tty_driver 结构体中的major、minor_start、minor_num表示主设备号、次设备号及可能的次设备数,name
表示设备名。当tty 驱动要在 RS-232 端口上打开或关闭线路的 BREAK 状态时,break_ctl()线路中断控制
函数被调用。如果state状态设为-1,BREAK 状态打开,如果状态设为 0,BREAK 状态关闭。
2.uart_port
用于描述串口端口的I/O端口或I/O内存地址、FIFO大小、端口类型、串口时钟等信息。实际上,一个uart_port实例对应一个串口设备                                                                                                                                         
  struct uart_port {                                                                                         
  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;                                                                                                                                                            
  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数据指针 */                                                                
  };                                                                                                                           
 3.uart_info
 有两个成员在底层串口驱动会用到:xmit和tty。用户空间程序通过串口发送数据时,上层驱动将用户数据保存在xmit;而串口发送中断处理函数就是通过
 xmit获取到用户数据并将它们发送出去。串口接收中断处理函数需要通过tty将接收到的数据传递给行规则层。
/* uart_info实例仅在串口端口打开时有效,它可能在串口关闭时被串口核心层释放。因此,在使用uart_port的uart_info成员时必须保证串口已打开。
底层驱动和核心层驱动都可以修改uart_info实例。
struct uart_info {
struct tty_struct *tty;
struct circ_buf xmit;
uif_t flags;
}; 
二.常用函数
1./*用于将串口驱动uart_driver注册到内核中*/
int uart_register_driver(struct uart_driver *drv)
2./* uart_unregister_driver用于注销我们已注册的uart_driver*/
void uart_unregister_driver(struct uart_driver *drv)
3./*为串口驱动添加一个串口端口,通常在探测到设备后(驱动的设备probe方法)调用该函数*/
int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
4./* 删除一个已添加到串口驱动中的串口端口,通常在驱动卸载时调用该函数*/
int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
5./* 唤醒上层因向串口端口写数据而阻塞的进程,通常在串口发送中断处理函数中调用该函数*/
void uart_write_wakeup(struct uart_port *port)
6./* 用于挂起特定的串口端口*/
int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
7./*用于恢复某一已挂起的串口*/
int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
8./* 通过解码termios结构体来获取指定串口的波特率*/
unsigned int
uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
struct ktermios *old, unsigned int min, unsigned int max)
9./* 计算某一波特率的串口时钟分频数(串口波特率除数)*/
unsigned int uart_get_divisor(struct uart_port *port, unsigned int baud)
10./* 更新(设置)串口FIFO超时时间*/
void uart_update_timeout(struct uart_port *port, unsigned int cflag, unsigned int baud)
11./* 判断两串口端口是否为同一端口*/
int uart_match_port(struct uart_port *port1, struct uart_port *port2)
12.向串口端口写一控制台信息
void uart_console_write(struct uart_port *port, const char *s,
unsigned int count,
void (*putchar)(struct uart_port *, int)) 
原创粉丝点击