uart串口驱动

/dev/ttymxcX=UART1作为终端

两个重要结构体:uart_driver和uart_port

每个串口驱动都需要定义一个 uart_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_driver:int uart_register_driver(struct uart_driver *drv)
注销驱动的时候也需要注销掉前面注册的 uart_driver:void uart_unregister_driver(struct uart_driver *drv)

——————————————————————————

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);
    void            (*set_mctrl)(struct uart_port *, unsigned int);
    int            (*startup)(struct uart_port *port);
    void            (*shutdown)(struct uart_port *port);
    void            (*throttle)(struct uart_port *port);
    void            (*unthrottle)(struct uart_port *port);
    int            (*handle_irq)(struct uart_port *);
    void            (*pm)(struct uart_port *, unsigned int state,
                      unsigned int old);
    void            (*handle_break)(struct uart_port *);
    int            (*rs485_config)(struct uart_port *,
                        struct serial_rs485 *rs485);
···

    const struct uart_ops    *ops;//包含了对串口操作的函数 需要我们实现

。。。。。。。。

}

向内核添加一个uart端口

int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
卸载
int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
——————————————————————————————
从设备树开始
uart串口驱动_第1张图片

 

根据属性找到匹配的驱动文件(可以看出串口驱动是和TTY联系在一起的)
uart串口驱动_第2张图片

static struct platform_driver serial_imx_driver = {
    .probe        = serial_imx_probe,//匹配成功后probe函数要执行 此为原版的驱动文件
    .remove        = serial_imx_remove,

    .suspend    = serial_imx_suspend,
    .resume        = serial_imx_resume,
    .id_table    = imx_uart_devtype,
    .driver        = {
        .name    = "imx-uart",
        .of_match_table = imx_uart_dt_ids,
    },
};

//模仿原版的驱动文件

为什么IMX6ULL的串口为dev/ttymxc0,1

    int ret = uart_register_driver(&imx_reg);

->static struct uart_driver imx_reg = {
    .owner          = THIS_MODULE,
    .driver_name    = DRIVER_NAME,#define DRIVER_NAME "IMX-uart"
    .dev_name       = DEV_NAME,
    .major          = SERIAL_IMX_MAJOR,207
    .minor          = MINOR_START,16
    .nr             = ARRAY_SIZE(imx_ports),
    .cons           = IMX_CONSOLE,
};

->#define DEV_NAME        "ttymxc"    

uart_unregister_driver(&imx_reg);

_______________________________________

学习模仿probe函数

//struct imx_port {NXP自定义的
    struct uart_port    port;。。。。。。。。。}

static int serial_imx_probe(struct platform_device *pdev)
{
    struct imx_port *sport;
    void __iomem *base;
    int ret = 0;
    struct resource *res;
    int txirq, rxirq, rtsirq;

    sport = devm_kzalloc//给imx_port 申请内存

serial_imx_probe_dt//处理设备树

platform_get_resource//获取内存

devm_ioremap_resource//得到外设基地址 (可以得到所有寄存器地址)

-》uart_port    处理


    sport->port.dev = &pdev->dev;
    sport->port.mapbase = res->start;
    sport->port.membase = base;
    sport->port.type = PORT_IMX,
    sport->port.iotype = UPIO_MEM;
    sport->port.irq = rxirq;
    sport->port.fifosize = 32;
    sport->port.ops = &imx_pops;

        ret = devm_request_irq(&pdev->dev, txirq, imx_txint, 0,
                       dev_name(&pdev->dev), sport);

devm_request_irq---串口接收中断,中断处理函数中获得串口接收到的数据,然后使用tty_flip_buffer_push将其放到tty里面

static struct uart_ops imx_pops = {
    .tx_empty    = imx_tx_empty,//与寄存器相关
    .set_mctrl    = imx_set_mctrl,
    .get_mctrl    = imx_get_mctrl,
    .stop_tx    = imx_stop_tx,
    .start_tx    = imx_start_tx,
    .stop_rx    = imx_stop_rx,
    .enable_ms    = imx_enable_ms,
    .break_ctl    = imx_break_ctl,
    .startup    = imx_startup,
    .shutdown    = imx_shutdown,
    .flush_buffer    = imx_flush_buffer,
    .set_termios    = imx_set_termios,
    .type        = imx_type,
    .config_port    = imx_config_port,
    .verify_port    = imx_verify_port,
#if defined(CONFIG_CONSOLE_POLL)
    .poll_init      = imx_poll_init,
    .poll_get_char  = imx_poll_get_char,
    .poll_put_char  = imx_poll_put_char,
#endif
};

你可能感兴趣的:(p2p,网络协议,网络)