终端设备驱动(Linxu驱动9)

说明:

linux中的终端设备有以下几类:串口终端:ttySn,伪终端pty,控制终端ttyn,console.伪终端在linux中用pts(pseudo terminal slave)和ptmx(pseudo terminal master)实现.
控制终端用于登录linux,进行操作.在系统启动时,可以在初始化的时候通过console=device,options来配置控制终端,可以同时配置多个控制终端,当打开console时,返回的是最后一个console.
tty0是当前使用的控制终端别名.
tty驱动包括tty核心(tty_io.c),线路配置,tty具体驱动构成.
uart驱动是在tty_io之上通过serial_core再封装,将tty驱动转换成uart驱动.

变量:

struct ktermios{
c_cflag;//控制模式
c_iflag;//输入模式
c_oflag;//输出模式
c_lflag;//线路模式
c_cc;//控制字符
c_ispeed;//输入速率
c_ospeed;//输出速率
}

struct tty_operations{
struct tty_struct *(*lookup)(struct tty_driver*driver,struct inode *inode,int idx);
int (install)(struct tty_driver driver,struct tty_struct *tty);
void (*remove)(struct tty_driver *driver ,struct tty_struct *tty);
int (*open)(struct tty_struct *tty,struct file *filep);
void (*close)(struct tty_struct *tty,struct file *filep);
int (*write)(struct tty_struct *tty,const char *buf,int len);
int (*put_char)(struct tty_struct *tty,unsigned char c);
int (*ioctl)(struct tty_struct *tty,struct file *filep,unsigned int cmd,unsigned int arg);

void (*set_temios)(struct tty_struct *tty,kermios*old);//设置termios
int (*tiocmget)(struct tty_struct *tty,struct file *filep);//设置modem函数
int (*tiocmset)(struct tty_struct *tty,struct file *filep,unsigned int set ,unsigned int clear);
}

tty_struct{
struct kref kref;
struct device *dev;
struct tty_driver *driver;
struct tty_operations *ops;

struct ktermios *termios;

unsigned int receive_room;
tty_struct *link;
fasync_struct *fasync;

wait_queue_head_t write_wait;
wait_queue_head_t read_wait;
void * driver_data;

}

tty_driver{
int magic;
struct kref kref;
struct cdev cdev;
struct module *owner;
const char * driver_name;//用于/proc/tty,sysfs中
const char *name;//设备节点

int major;
int minor_start;
int minor_num;
int num;
int type;
int subtype;
ktermios init_termios;
int flags;
tty_driver *other;//仅对pty驱动有用
ktermios **termios;
tty_struct **ttys;
void * tty_state;

const tty_operatios * ops;
}

struct tty_port {
struct tty_struct tty; / Back pointer */
const struct tty_port_operations ops; / Port operations */

wait_queue_head_t open_wait; /* Open waiters */

unsigned long flags; /* TTY flags ASY_*/
unsigned char console:1; /* port is a console */
struct mutex mutex; /* Locking */

unsigned int close_delay; /* Close port delay */
unsigned int closing_wait; /* Delay for output */

struct kref kref; /* Ref counter */
};

struct uart_ops{//此结构提供外设具体接口函数
unsigned int (tx_empty)(struct uart_port );
(*start_tx)
(*stop_tx)
(*send_xchar)
(*stop_rz)

}

struct uart_port{//此结构用于描述外设资源
spinlock_t lock;
unsigned int iobase;
unsigned char __iomem *membase;
unsigned int irq;
unsigned int uartclk;

struct console *cons;

const struct uart_ops *ops;
void *private_data;

}

struct uart_driver{//此结构用于在用户空间呈现接口
struct module *owner;
const char *dev_name;//设备节点名ttyxx
const char *driver_name;//驱动名
int nr;
struct console *cons;

    struct uart_state *state;
    struct tty_driver*tty_driver;
}

struct uart_state{
struct tty_port *port;
struct uart_port* uart_port;

}

struct console{
char name[];
(*read)
(*write)
(*setup)
(*early_serup)
struct tty_driver*(*device)
void *data;

}

函数:

struct tty_driver* alloc_tty_driver(int lines);
int tty_register_driver(struct tty_driver*driver);
void tty_unregister_driver(struct tty_driver*driver);
void tty_register_device(struct tty_driver*driver,int index,struct tty_device*dev);
void tty_unregister_device(struct tty_driver*driver,int index);
void tty_set_operations(struct tty_driver*driver,struct tty_operations *ops);

  • 用户空间函数
    包括termios.h文件
    int tcgetattr(int fd,struct termios*termios);
    int tcsetattr(int fd,int operatios,struct termios*termios);
    int cfsetospeed(struct termios *termios,speed_t speed);
    int cfsetispeed(struct termios * termios,speed_t speed);//speed 是B0 B50 等
    speed_t cfgetospeed(struct termios*termios);
    speed_t cfgetispeed(struct termios *termios);

    int tcdrain(int fd);//等待所有输出被发送
    int tcflush(int fd,int queue_selector);//flush输入/输出
    int tcflow(int fd,int actios);//对输入/输出进行流控制
    int tcsendbreak(int fd,int duration);//发送break字符

  • uart驱动函数

    int uart_register_driver(struct uart_driver*);
    void uart_unregister_driver(struct uart_driver*);
    int uart_add_one_port(struct uart_dirver*drv,struct uart_port *port);
    int uart_remove_one_port(struct uart_driver *drv,struct uart_port*port);

    void register_console(struct console *con);
    int unregister_console(struct console *con);
    console_initcall(fn);//将cosole初始化函数放到系统的.con_initcall.init节中
    扩展:
    initcall节分为:initcall0.init,initcall.init …initcall7.init,对应的宏有pure_initcall(fn),core_initcall(fn)
    postcore_initcall(fn),arch_initcall(fn),subsys_initcall(fn),fs_initcall(fn),device_initcall(fn),late_initcall(fn).
    同时对于1~7节对应有sync版本pure_initcall_sync(fn)…

用法:

  • 设备的资源
    1 在设备的资源文件中定义uart的platform_device
    struct resources xx_resources[]={
    [0]={
    .start=
    .end=
    .flags=
    }

    }
    struct platform_device xx_uart_device={
    .name=”xx_uart”;
    .id=
    .num_resources=ARRAY_SIZE(xx_resources);
    .resources=&xx_resources;
    }
    2.在板子的初始化部分调用platform_device_register
    platform_device_register(&xx_uart_device);

  • 驱动部分

    • 定义uart_ops,uart_driver以及实现其中函数

      xx_tx_empty(){
          ...
      }
      xx_start_tx(){
          ...
      }
      
      struct uart_ops xx_ops={
          .tx_empty=xx_tx_empty;
          .start_tx=xx_start_tx;
          ...
      }
      struct uart_driver xx_uart_driver={
          .dev_name="ttyxx"
          .driver_name="xxuart";
          ...
      }       
      
    • 定义platform_driver

      int xx_probe(struct platform_device *pdev){
          ...
          填充合适的uart_port结构
          uart_add_one_port(&xx_uart_driver,&xx_uart_port);//此部分完成具体设备的功能添加,不同设备调用不同函数
          platform_set_drvdata(pdev,xx_data);
      }
      
      int xx_remove(struct platform_device *pdev){
          ...
          进行必要的清除操作
          uart_remove_one_port(&xx_uart_driver,&xx_uart_port);
      }
      
      struct platform_driver xx_platform_uart_driver={
          .probe=xx_probe;
          .remove=xx_remove;
          .driver={
              .name="xx_uart";
          }
      }
      
      xx_init(void){
          platform_driver_register(&xx_platform_uart_driver);
      }
      
      xx_exit(void){
          platform_driver_unregister(&xx_platform_uart_driver);
      }
      
    • console实现

      xx_setup(){//console setup
          根据填充的port信息
          调用uart_set_options(uart_port,console,baund,parity,bits,flow);
      }
      xx_write(){//console write
      
      }
      
      struct console xx_console={
          .setup=xx_setup;
          .write=xx_write;
      
      }
      xx_console_init(){
          填充uart_port结构
          register_console(&xx_console);
      }
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值