linux的串口驱动分析

发布时间:2024-07-19  

1、串口驱动中的数据结构

• UART驱动程序结构:struct uart_driver  驱动

• UART端口结构: struct uart_port  串口

• UART相关操作函数结构: struct uart_ops   串口操作函数集

• UART状态结构: struct uart_state 串口状态

• UART信息结构: struct uart_info  串口信息

2、串口驱动程序-初始化

3、串口驱动分析-打开设备

static int s3c24xx_serial_startup(struct uart_port *port)

{

    struct s3c24xx_uart_port *ourport = to_ourport(port);

    int ret;


    dbg("s3c24xx_serial_startup: port=%p (%08lx,%p)n",

        port->mapbase, port->membase);


    rx_enabled(port) = 1;


    ret = request_irq(ourport->rx_irq, s3c24xx_serial_rx_chars, 0,

              s3c24xx_serial_portname(port), ourport);


    if (ret != 0) {

        printk(KERN_ERR "cannot get irq %dn", ourport->rx_irq);

        return ret;

    }


    ourport->rx_claimed = 1;


    dbg("requesting tx irq...n");


    tx_enabled(port) = 1;


    ret = request_irq(ourport->tx_irq, s3c24xx_serial_tx_chars, 0,

              s3c24xx_serial_portname(port), ourport);


    if (ret) {

        printk(KERN_ERR "cannot get irq %dn", ourport->tx_irq);

        goto err;

    }


    ourport->tx_claimed = 1;


    dbg("s3c24xx_serial_startup okn");


    /* the port reset code should have done the correct

     * register setup for the port controls */


    return ret;


 err:

    s3c24xx_serial_shutdown(port);

    return ret;

}


3、串口驱动程序-数据发送

static void s3c24xx_serial_start_tx(struct uart_port *port)

{

    struct s3c24xx_uart_port *ourport = to_ourport(port);

    static int a =1;//temp

    if (port->line == 3) {

//        printk("485_start_txn");


        if(a){

            s3c_gpio_cfgpin(S3C64XX_GPK(5), S3C_GPIO_SFN(1));

            a=0;

        }

        gpio_set_value(S3C64XX_GPK(5), 1);

    }

    if (!tx_enabled(port)) {

        if (port->flags & UPF_CONS_FLOW)

            s3c24xx_serial_rx_disable(port);


        enable_irq(ourport->tx_irq);

        tx_enabled(port) = 1;

    }

}


static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)

{

    struct s3c24xx_uart_port *ourport = id;

    struct uart_port *port = &ourport->port;

    struct circ_buf *xmit = &port->state->xmit;

    int count = 256;


    if (port->x_char) {

        wr_regb(port, S3C2410_UTXH, port->x_char);

        port->icount.tx++;

        port->x_char = 0;

        goto out;

    }


    /* if there isn't anything more to transmit, or the uart is now

     * stopped, disable the uart and exit

    */


    if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {

        s3c24xx_serial_stop_tx(port);

        goto out;

    }


    /* try and drain the buffer... */


    while (!uart_circ_empty(xmit) && count-- > 0) {

        if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)

            break;


        wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);

        xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);

        port->icount.tx++;

    }


    if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)

        uart_write_wakeup(port);


    if (uart_circ_empty(xmit))

        s3c24xx_serial_stop_tx(port);


 out:

    return IRQ_HANDLED;

}

4、串口驱动程序-数据接收

s3c24xx_serial_rx_chars(int irq, void *dev_id)

{

    struct s3c24xx_uart_port *ourport = dev_id;

    struct uart_port *port = &ourport->port;

    struct tty_struct *tty = port->state->port.tty;

    unsigned int ufcon, ch, flag, ufstat, uerstat;

    int max_count = 64;


    while (max_count-- > 0) {

        ufcon = rd_regl(port, S3C2410_UFCON);

        ufstat = rd_regl(port, S3C2410_UFSTAT);


        if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)

            break;


        uerstat = rd_regl(port, S3C2410_UERSTAT);

        ch = rd_regb(port, S3C2410_URXH);


        if (port->flags & UPF_CONS_FLOW) {

            int txe = s3c24xx_serial_txempty_nofifo(port);


            if (rx_enabled(port)) {

                if (!txe) {

                    rx_enabled(port) = 0;

                    continue;

                }

            } else {

                if (txe) {

                    ufcon |= S3C2410_UFCON_RESETRX;

                    wr_regl(port, S3C2410_UFCON, ufcon);

                    rx_enabled(port) = 1;

                    goto out;

                }

                continue;

            }

        }


        /* insert the character into the buffer */


        flag = TTY_NORMAL;

        port->icount.rx++;


        if (unlikely(uerstat & S3C2410_UERSTAT_ANY)) {

            dbg("rxerr: port ch=0x%02x, rxs=0x%08xn",

                ch, uerstat);


            /* check for break */

            if (uerstat & S3C2410_UERSTAT_BREAK) {

                dbg("break!n");

                port->icount.brk++;

                if (uart_handle_break(port))

                    goto ignore_char;

            }


            if (uerstat & S3C2410_UERSTAT_FRAME)

                port->icount.frame++;

            if (uerstat & S3C2410_UERSTAT_OVERRUN)

                port->icount.overrun++;


            uerstat &= port->read_status_mask;


            if (uerstat & S3C2410_UERSTAT_BREAK)

                flag = TTY_BREAK;

            else if (uerstat & S3C2410_UERSTAT_PARITY)

                flag = TTY_PARITY;

            else if (uerstat & (S3C2410_UERSTAT_FRAME |

                        S3C2410_UERSTAT_OVERRUN))

                flag = TTY_FRAME;

        }


        if (uart_handle_sysrq_char(port, ch))

            goto ignore_char;


        uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN,

                 ch, flag);


 ignore_char:

        continue;

    }

    tty_flip_buffer_push(tty);


 out:

    return IRQ_HANDLED;

}

附:linux系统中一般的流控技术


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

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

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

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

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

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

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

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