ARM-Linux S5PV210 UART驱动(3)----串口核心层、关键结构体、接口关系

发布时间:2024-09-19  

      尽管一个特定的UART设备驱动完全可以按照tty驱动的设计方法来设计,即定义tty_driver并实现tty_operations其中的成员函数,但是Linux已经在文件serial_core.c中实现了UART设备的通用tty驱动层,称为串口核心层,这样,UART驱动的主要任务变成了实现serial_core.c中定义的一组uart_xxx接口而非tty_xxx接口。    

  uart设备是继tty_driver的又一层封装.实际上uart_driver就是对应tty_driver.在它的操作函数中,将操作转入uart_port.在写操作的时候,先将数据放入一个叫做circ_buf的环形缓存区.然后uart_port从缓存区中取数据,将其写入到串口设备中.当uart_port从serial设备接收到数据时,会将设备放入对应line discipline的缓存区中.这样.用户在编写串口驱动的时候,只先要注册一个uart_driver.它的主要作用是定义设备节点号.然后将对设备的各项操作封装在uart_port.驱动工程师没必要关心上层的流程,只需按硬件规范将uart_port中的接口函数完成就可以了.

1.下图描述了串行系统间的层次结构关系,可以概括为:用户应用层 --> 线路规划层 --> TTY层 --> 底层驱动层 --> 物理硬件层

 

2.下图是串口核心层在整个tty源文件关系及数据流向中的位置:

  其中的xxx_uart.c在此处就是drivers/serial/samsung.c和s5pv210.c

 

3.接口关系:

从接口关系图可以看出,用户对uart设备操作的调用关系非常简单,

file_operations => [tty_ldisc_ops] => tty_operations => uart ops

其中tty_ldisc_ops线路规程并不是必要的,依赖于应用层设置是否使用ldisc处理数据。

 

4.UART驱动的总图:

 

 5.uart驱动常用的数据结构表示如下:

6.Uart驱动程序主要围绕三个关键的数据结构展开(include/linux/serial_core.h中定义):


   UART特定的驱动程序结构定义:struct uart_driver s3c24xx_uart_drv;


  UART端口结构定义: struct s3c24xx_uart_port s3c24xx_serial_ports;


  UART相关操作函数结构定义: struct uart_ops s3c24xx_serial_ops;


 


 【1】uart_driver 封装了tty_driver,使得底层的UART驱动无需关心tty_driver


struct uart_driver {

    struct module        *owner;

    const char        *driver_name;

    const char        *dev_name;

    int             major;

    int             minor;

    int             nr;

    struct console        *cons;


    /*

     * 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;

};


 其中的uart_state是设备私有信息结构体,


 在uart_open()中:


 tty->driver_data = state;


 在其他uart_xxx()中:


 struct uart_state *state = tty->driver_data;


 就可以获取设备私有信息结构体。


static struct uart_driver s3c24xx_uart_drv= {

      .owner           =THIS_MODULE,

      .dev_name      = 's3c2440_serial',  //具体设备名称

      .nr          =CONFIG_SERIAL_SAMSUNG_UARTS,  //定义有几个端口

      .cons             = S3C24XX_SERIAL_CONSOLE,  //console接口

       .driver_name  =S3C24XX_SERIAL_NAME,  //串口名:ttySAC

      .major            =S3C24XX_SERIAL_MAJOR,  //主设备号

      .minor            =S3C24XX_SERIAL_MINOR,   //次设备号

};


 一个tty驱动必须注册/注销tty_driver,而一个UART驱动则变为注册/注销uart_driver,使用如下接口:


int uart_register_driver(struct uart_driver *drv);


void uart_unregister_driver(struct uart_driver *drv);


【2】uart_port用于描述一个UART端口(直接对应于一个串口)的I/O端口或者IO内存地址等信息。


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);

    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 type IO */

#define UPIO_TSI        (5)            /* Tsi108/109 type IO */

#define UPIO_DWAPB        (6)            /* DesignWare APB UART */

#define UPIO_RM9000        (7)            /* RM9000 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))

#define UPF_CONS_FLOW        ((__force upf_t) (1 << 23))

#define UPF_SHARE_IRQ        ((__force upf_t) (1 << 24))

/* 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;//UART操作集------->     

    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        unused[2];

    void            *private_data;        /* generic platform data pointer */

};


s3c24xx_uart_port 封装了uart_port:


struct s3c24xx_uart_port {

    unsigned char            rx_claimed;

    unsigned char            tx_claimed;

    unsigned int            pm_level;

    unsigned long            baudclk_rate;


    unsigned int            rx_irq;

    unsigned int            tx_irq;


    struct s3c24xx_uart_info    *info;

    struct s3c24xx_uart_clksrc    *clksrc;

    struct clk            *clk;

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>