首页 > 其他分享 >RK3568平台 Uart驱动框架

RK3568平台 Uart驱动框架

时间:2024-04-06 22:58:06浏览次数:17  
标签:struct 框架 Uart RK3568 void uart int 串口 port

一.TTY子系统

在Linux kernel中,tty驱动不像于spi,iic等那么架构简单,它是一个庞大的系统,它的框架大体如下图一。我们作为普通的驱动开发移植人员,不会从零写tty驱动,一般都是厂家根据现有的tty驱动和自家芯片修改,拿到板子按照厂家的配置,串口应该使能直接使用的。但是开发的过程中也有可能需要用到串口,一般会修改serial驱动,这样我们不会动tty_core层。

Linux tty子系统包含:tty核心(tty_core),tty线路规程(tty_line_discipine)和tty驱动(tty_driver)。tty核心是对整个tty设备的抽象,对用户提供统一的接口,tty线路规程是对传输数据的格式化,tty驱动则是面向tty设备的硬件驱动。其整体框架如下图所示:

 二.UART 驱动关键数据结构

 同 I2C、SPI 一样,Linux 也提供了串口驱动框架,我们只需要按照相应的串口框架编写驱 动程序即可。串口驱动没有什么主机端和设备端之分,就只有一个串口驱动,而且这个驱动也 已经由 原厂编写好了,我们真正要做的就是在设备树中添加所要使用的串口节点信 息。当系统启动以后串口驱动和设备匹配成功,相应的串口就会被驱动起来,生成 /dev/ttymxcX(X=0….n)文件。

struct uart_driver:

uart_driver 包含了串口设备名,串口驱动名,主次设备号,串口控制台(可选))等信息,还封装了tty_driver (底层串口驱动无需关心tty_driver)

struct uart_driver {
        struct module    *owner; /*拥有该uart_driver的模块,一般为THIS_MODULE*/
        const char        *driver_name; /*驱动串口名,串口设备名以驱动名为基础*/
        const char        *dev_name; /*串口设备名*/
        int                 major; /*主设备号*/
        int                 minor; /*次设备号*/
        int                 nr; /*该uart_driver支持的串口数*/
        struct console    *cons; /*其对应的console,若该uart_driver支持serial console,
*否则为NULL*/
/*
* these are private; the low level driver should not
* touch these; they should be initialised to NULL
*/
struct uart_state *state; /*下层,窗口驱动层*/
struct tty_driver  *tty_driver; /*tty相关*/
 

struct console

实现控制台打印功能必须要注册的结构体

struct console {
      char name[16];
      void(*write)(struct console *,const char *, unsigined);
      int (*read)(struct console *, char *, unsigned);
      struct tty_driver *(struct console *,int*);
      void (*unblank)(void);
      int  (*setup)(struct console *, char *);
      int  (*early_setup)(void);
      short  flags;
      short  index; /*用来指定该console使用哪一个uart port (对应的uart_port中的line),如果为-1,kernel会自动选择第一个uart port*/
      int   cflag;
      void  *data;
      struct   console *next;
};
 

struct uart_state:

每一个uart端口对应着一个uart_state,该结构体将uart_port与对应的circ_buf联系起来。uart_state有两个成员在底层串口驱动会用到:xmit和port。

用户空间程序通过串口发送数据时,上层驱动将用户数据保存在xmit;而串口发送中断处理函数就是通过xmit获取到用户数据并将它们发送出去。串口接收中断处理函数需要通过port将接收到的数据传递给线路规程层。

struct uart_state {
       struct  tty_port  port;
       
       enum uart_pm_state   pm_state;
       struct circ_buf     xmit;
       
       struct uart_port     *uart_port; /*对应于一个串口设备*/
};
 

struct uart_port:

uart_port用于描述串口端口的I/O端口或I/O内存地址、FIFO大小、端口类型、串口时钟等信息。实际上,一个uart_port实现对应一个串口设备。

struct uart_port {
        spinlock_t              lock;                   /* port lock */
        unsigned long           iobase;                 /* in/out[bwl] */
        unsigned char __iomem   *membase;               /* read/write[bwl] */
        unsigned int            (*serial_in)(struct uart_port *, int);
        void                    (*serial_out)(struct uart_port *, int, int);
        void                    (*set_termios)(struct uart_port *,
                                               struct ktermios *new,
                                               struct ktermios *old);
        int                     (*handle_irq)(struct uart_port *);
        void                    (*pm)(struct uart_port *, unsigned int state,
                                      unsigned int old);
        void                    (*handle_break)(struct uart_port *);
        unsigned int            irq;                    /* irq number */
        unsigned long           irqflags;               /* irq flags  */
        unsigned int            uartclk;                /* base uart clock */
        unsigned int            fifosize;               /* tx fifo size */
        unsigned char           x_char;                 /* xon/xoff char */
        unsigned char           regshift;               /* reg offset shift */
        unsigned char           iotype;                 /* io access style */
        unsigned char           unused1;
 
#define UPIO_PORT               (0)
#define UPIO_HUB6               (1)
#define UPIO_MEM                (2)
#define UPIO_MEM32              (3)
#define UPIO_AU                 (4)                     /* Au1x00 and RT288x type IO */
#define UPIO_TSI                (5)                     /* Tsi108/109 type IO */
 
        unsigned int            read_status_mask;       /* driver specific */
        unsigned int            ignore_status_mask;     /* driver specific */
        struct uart_state       *state;                 /* pointer to parent state */
        struct uart_icount      icount;                 /* statistics */
 
        struct console          *cons;                  /* struct console, if any */
#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(SUPPORT_SYSRQ)
        unsigned long           sysrq;                  /* sysrq timeout */
#endif
 
        upf_t                   flags;
 
#define UPF_FOURPORT            ((__force upf_t) (1 << 1))
#define UPF_SAK                 ((__force upf_t) (1 << 2))
#define UPF_SPD_MASK            ((__force upf_t) (0x1030))
#define UPF_SPD_HI              ((__force upf_t) (0x0010))
#define UPF_SPD_VHI             ((__force upf_t) (0x0020))
#define UPF_SPD_CUST            ((__force upf_t) (0x0030))
#define UPF_SPD_SHI             ((__force upf_t) (0x1000))
#define UPF_SPD_WARP            ((__force upf_t) (0x1010))
#define UPF_SKIP_TEST           ((__force upf_t) (1 << 6))
#define UPF_AUTO_IRQ            ((__force upf_t) (1 << 7))
#define UPF_HARDPPS_CD          ((__force upf_t) (1 << 11))
#define UPF_LOW_LATENCY         ((__force upf_t) (1 << 13))
#define UPF_BUGGY_UART          ((__force upf_t) (1 << 14))
#define UPF_NO_TXEN_TEST        ((__force upf_t) (1 << 15))
#define UPF_MAGIC_MULTIPLIER    ((__force upf_t) (1 << 16))
/* Port has hardware-assisted h/w flow control (iow, auto-RTS *not* auto-CTS) */
#define UPF_HARD_FLOW           ((__force upf_t) (1 << 21))
/* Port has hardware-assisted s/w flow control */
#define UPF_SOFT_FLOW           ((__force upf_t) (1 << 22))
#define UPF_CONS_FLOW           ((__force upf_t) (1 << 23))
#define UPF_SHARE_IRQ           ((__force upf_t) (1 << 24))
#define UPF_EXAR_EFR            ((__force upf_t) (1 << 25))
#define UPF_BUG_THRE            ((__force upf_t) (1 << 26))
/* The exact UART type is known and should not be probed.  */
#define UPF_FIXED_TYPE          ((__force upf_t) (1 << 27))
#define UPF_BOOT_AUTOCONF       ((__force upf_t) (1 << 28))
#define UPF_FIXED_PORT          ((__force upf_t) (1 << 29))
#define UPF_DEAD                ((__force upf_t) (1 << 30))
#define UPF_IOREMAP             ((__force upf_t) (1 << 31))
 
#define UPF_CHANGE_MASK         ((__force upf_t) (0x17fff))
#define UPF_USR_MASK            ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY))
 
        unsigned int            mctrl;                  /* current modem ctrl settings */
        unsigned int            timeout;                /* character-based timeout */
        unsigned int            type;                   /* port type */
        const struct uart_ops   *ops;
        unsigned int            custom_divisor;
        unsigned int            line;                   /* port index */
        resource_size_t         mapbase;                /* for ioremap */
        struct device           *dev;                   /* parent device */
        unsigned char           hub6;                   /* this should be in the 8250 driver */
        unsigned char           suspended;
        unsigned char           irq_wake;
        unsigned char           unused[2];
        void                    *private_data;          /* generic platform data pointer */
};
 

struct uart_ops:

struct uart_ops涵盖了驱动可对串口的所有操作

 struct uart_ops {
        unsigned int    (*tx_empty)(struct uart_port *);
        void            (*set_mctrl)(struct uart_port *, unsigned int mctrl);
        unsigned int    (*get_mctrl)(struct uart_port *);
        void            (*stop_tx)(struct uart_port *);
        void            (*start_tx)(struct uart_port *);
        void            (*throttle)(struct uart_port *);
        void            (*unthrottle)(struct uart_port *);
        void            (*send_xchar)(struct uart_port *, char ch);
        void            (*stop_rx)(struct uart_port *);
        void            (*enable_ms)(struct uart_port *);
        void            (*break_ctl)(struct uart_port *, int ctl);
        int             (*startup)(struct uart_port *);
        void            (*shutdown)(struct uart_port *);
        void            (*flush_buffer)(struct uart_port *);
        void            (*set_termios)(struct uart_port *, struct ktermios *new,
                                       struct ktermios *old);
        void            (*set_ldisc)(struct uart_port *, int new);
        void            (*pm)(struct uart_port *, unsigned int state,
                              unsigned int oldstate);
        int             (*set_wake)(struct uart_port *, unsigned int state);
 
        /*
         * Return a string describing the type of the port
         */
        const char      *(*type)(struct uart_port *);
 
        /*
         * Release IO and memory resources used by the port.
         * This includes iounmap if necessary.
         */
        void            (*release_port)(struct uart_port *);
 
        /*
         * Request IO and memory resources used by the port.
         * This includes iomapping the port if necessary.
         */
        int             (*request_port)(struct uart_port *);
        void            (*config_port)(struct uart_port *, int);
        int             (*verify_port)(struct uart_port *, struct serial_struct *);
        int             (*ioctl)(struct uart_port *, unsigned int, unsigned long);
#ifdef CONFIG_CONSOLE_POLL
        int             (*poll_init)(struct uart_port *);
        void            (*poll_put_char)(struct uart_port *, unsigned char);
        int             (*poll_get_char)(struct uart_port *);
#endif
};
 

三.UART关键流程

注册uart_driver:

此接口在uart driver中调用,用来注册uart_driver到kernel中,调用阶段在uart driver的初始阶段,例如:module_init(), uart_driver的注册流程图。

 添加uart_port:

此接口用于注册一个uart port 到uart driver上,通过注册,uart driver就可以访问对应的uart port,进行数据收发。该接口在uart driver中的probe函数调用,必须保证晚于uart_register_drver的注册过程。

打开设备(open操作):

数据发送流程(write操作):

数据接收流程(read操作) :

关闭设备(close操作): 

除uart_port:

此接口用于从uart driver上注销一个uart port,该接口在uart driver中的remove函数中调用。

四.RS-232通信

(1) 基本概念

RS-232接口符合美国电子工业联盟(EIA)制定的串行数据通信的接口标准,被广泛用于计算机串行接口外设连接,像有些老式PC机上就配置有RS232接口。RS232的工作方式是单端工作方式,这是一种不平衡的传输方式,收发端信号的逻辑电平都是相对于信号地而言的,RS232最初是DTE(数字终端设备)和DCE(数据通信设备)一对一通信,也就是点对点,一般是用于全双工传送,也可以用于半双工传送。

采用负逻辑传送,规定逻辑“1”的电平为-5V~-15 V,逻辑“0”的电平为+5 V~+15 V。选用该电气标准的目的在于提高抗干扰能力,增大通信距离。RS -232的噪声容限为2V,接收器将能识别高至+3V的信号作为逻辑“0”,将低到-3 V的信号作为逻辑“1”。

传输距离短,只有15米,实际应用可以达到50米,再长的距离就须加调制了。

RS232标准物理接口是25个引脚的,因为常用的是9个引脚,后来基本采用DB9连接器了。

RS-232标准主要规定了信号用途、通讯接口和信号电平标准。如下图为常见的设备间串口通讯结构图。

下面介绍下DB9接口。如下图为DB9标准的公头、母头接法(接线口以针式引出信号线为公头,以孔式引出信号线为母头)。

 

如上图,以公头为例,有9条信号线,其中,

RXD:用于接收DCE发来的数据信号,即输入;
TXD:用于发送DTE的信号,即输出。公头和母头的RXD和TXD应交叉连接;
GND:用于平衡设备双方的地电位,即共地。
其他信号线如DCD、DTR、DSR、RTS、CTS等,使用逻辑1表示有效信号,逻辑0表示无效信号。如DTE端的RTS信号线置1时,是为了告知DCE设备本机已准备好 接收数据,而置0则表示未准备就绪。

(2)通信方式

RS232 可做到双向传输,全双工通讯,最高传输速率 20kbps。

(3)与UART异同点

逻辑电平不同:UART是TTL电平,RS232是RS232电平,不能直接相连,需要电平转换芯片(MAX3232等)。

协议层完全相同:UART和RS232的协议层可以共享,没有较大区别。

(4)缺点

接口电平值较高,易损坏接口电路的芯片;又因为与TTL电平不兼容故需使用电平转换电路方能与TTL电路连接。

传输速率较低,大约为20Kbps;传输距离较短,大约为15米左右。

接口由三根线TX、RX、GND组成,没有构成差分线形式,容易产生共地共模干扰,抗干扰能力弱。

标签:struct,框架,Uart,RK3568,void,uart,int,串口,port
From: https://blog.csdn.net/weixin_49303682/article/details/137207869

相关文章

  • Django框架之ORM操作
    一、选择数据库1、默认数据库Django默认的数据库是sqlite3数据库DATABASES={'default':{'ENGINE':'django.db.backends.sqlite3','NAME':BASE_DIR/'db.sqlite3',}}2、指定数据库修改连接到MySQL数据库DATABASES......
  • Django框架之请求生命周期流程图
    一、引言WSGI、wsgiref、uwsgi三者是什么关系?WSGI是协议,小写的wsgiref和uwsgi是实现该协议的功能模块缓存数据库提前已经将你想要的数据准备好了,需要的时候直接拿就可以,提高了效率和响应时间。eg:当你在修改你的数据的时候,你会发现数据并不是立刻修改完成的,而是需要经......
  • Django框架之路由层
    一、路由匹配1、什么是路由在计算机领域中,路由(Routing)通常指的是确定数据包在网络中传输的路径的过程。当数据包从源主机发送到目标主机时,路由是决定数据包应该沿着哪条路径传输的方法。路由器是负责执行这种路由功能的设备。在Web开发中,路由通常指的是将特定的URL请求映射到相......
  • 接口自动化框架设计
    框架通用性:哪里都可以使用可扩展性:方便新增和修改功能可维护性:是否便于修改,适当封装但不能过度、分层设计(同一类型放一块)分层设计框架思路:1、写测试用例数据:test_data,存放excel2、测试用例文件:test_cases,写测试流程、业务流程、接口要干什么3、封装的工具类:tools,类似日志收......
  • 基于java中的springboot框架实现服装销售平台系统【附项目源码+论文说明】
    基于SpringBoot实现服装销售平台系统设计演示摘要随着信息互联网购物的飞速发展,一般企业都去创建属于自己的电商平台以及购物管理系统。本文介绍了“衣依”服装销售平台的开发全过程。通过分析企业对于“衣依”服装销售平台的需求,创建了一个计算机管理“衣依”服装销售平......
  • 从像素游戏到 3A 大作的游戏引擎/框架
    Bevy——Rust构建的游戏引擎Bevy是一款由Rust语言构建且简单明了的数据驱动的游戏引擎,并将永远保持开源且免费。Mach——Zig游戏引擎和图形工具包Mach是一个Zig游戏引擎和图形工具包,用于构建高性能、真正跨平台、健壮且模块化的游戏,可视化和桌面/移动图形用......
  • scrapy框架之CrawlSpider全站爬取
    一、什么是全站爬取全站爬取(CrawltheEntireSite)是指通过网络爬虫程序遍历并获取一个网站上的所有页面或资源的过程。这种爬取方式旨在获取网站的全部内容,包括文本、图片、视频、链接等,以建立网站的完整内容索引或进行数据分析。二、全栈爬取介绍1、全站数据爬取的方式(1)通过......
  • scrapy框架之中间件
    一、中间件介绍中间件是Scrapy里面的一个核心概念。使用中间件可以在爬虫的请求发起之前或者请求返回之后对数据进行定制化修改,从而开发出适应不同情况的爬虫。“中间件”这个中文名字和前面章节讲到的“中间人”只有一字之差。它们做的事情确实也非常相似。中间件和中间人都......
  • Golang中的强大Web框架Fiber详解
    Golang 取消首页编程手机软件硬件安卓苹果手游教程平面服务器首页 > 脚本专栏 > Golang >Golang Web框架FiberGolang中的强大Web框架Fiber详解2023-10-2410:31:51 作者:技术的游戏在不断发展的Web开发领域中,选择正确的框架可以极大地影响项目的效......
  • 如何读懂串口通讯波形图(TTL,RS232,UART)
    考考你,这是什么字符串,提示串口通讯,8N1 ......