linux的串口驱动分析

发布者:乡村乐园最新更新时间:2024-07-19 来源: cnblogs关键字:linux  串口驱动  初始化 手机看文章 扫描二维码
随时随地手机看文章

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系统中一般的流控技术


关键字:linux  串口驱动  初始化 引用地址:linux的串口驱动分析

上一篇:linux MTD系统解析,
下一篇:ok6410 3.0.1内核调用V4L接口出错解决方法

推荐阅读最新更新时间:2026-03-10 05:37

ARM-Linux S5PV210 UART驱动(4)----串口驱动初始化过程
对于S5PV210 UART驱动来说,主要关心的就是drivers/serial下的samsung.c和s5pv210.c连个文件。 由drivers/serial/Kconfig:   config SERIAL_SAMSUNG     depends on ARM && PLAT_SAMSUNG   config SERIAL_S5PV210     depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_S5P6442) && SERIAL_SAMSUNG_CONSOLE 可以看出模块的依赖关系,先加载samsung.ko,然后再加载s5pv210.ko。 所以串
[单片机]
ARM-<font color='red'>Linux</font> S5PV210 UART驱动(4)----<font color='red'>串口驱动</font><font color='red'>初始化</font>过程
专题3-串口驱动程序设计-第2课串口驱动分析-初始化
1、概述 (1)串口驱动程序结构 (2)串口驱动中的重要数据结构体 用户态发生write时- VFS中的sys_write,先经过file_operation中的tty_write,这个tty_fops是在哪里注册的? 2、回溯-初始化分析 两个重要的文件: samsung.c:注册串口驱动程序 s5pv210.c (2)串口驱动中重要的数据结构: uart驱动程序结构:struct uart_driver --对应串口驱动 使用场景实例: static uart_driver s3c24xx_uart_ddrv = {   .owner = THIS_MODULE,   .dev_name= s3c2440_s
[单片机]
专题3-<font color='red'>串口驱动</font>程序设计-第2课<font color='red'>串口驱动</font>分析-<font color='red'>初始化</font>
迅为4412开发板Linux驱动教程之GPIO的初始化
视频下载地址: http://pan.baidu.com/s/1c06oiti GPIO的初始化 • 在内核源码目录下使用命令“ls drivers/gpio/*.o”,可以看到“gpio-exynos4”被编译进了内核 – 生成.o文件代表最终被编译进了内核 – 除了menuconfig配置文件,还可以通过.o文件来判定该文件是否编译进了 内核 • 在“gpio-exynos4.c”文件最下面一行 – core_initcall(exynos4_gpiolib_init); – core_initcall代表在linux初始化过程中会调用 – 初始化函数是在源码目录下“include/linux/init.h”文件中定义
[单片机]
迅为4412开发板<font color='red'>Linux</font>驱动教程之GPIO的<font color='red'>初始化</font>
浅谈分析Arm linux 内核移植及系统初始化的过程二
4.1. 处理器、设备4.2. 描述 设备描述主要两个结构体完成:struct resource和struct platform_device。 先来看看着两个结构体的定义: struct resource { resource_size_t start; resource_size_t end; const char *name; unsigned long flags; struct resource *parent, *sibling, *child; }; Resource结构体主要是描述了设备在系统中的起止地址、名称、标志以及为了链式描述方便指向本结构体类型的指针。Resource定义的实例将被添加到platform_d
[单片机]
STM8单片机串口驱动的深度解析
串口是单片机最重要的外设之一,在很多项目开发中都有应用,Lora模块的外部通讯方式就是串口。 本节简单的和大家解析一下串口通讯及驱动代码的编程。 STM8L101F3单片机支持一路串口通讯。我们先看一下Lora模块的硬件接口,如下图所示: 串口的硬件接口是PC2 和PC3两个脚位。 下面开始讲解软件部分,这块我们无际单片机编程也有这个项目全部视频教程,下面是文字版。 软件驱动 STM8打开标准库文件夹,打开串口USART例程: 2.如上图所示,是标准库中串口通讯的的例程,并选择第一个例程。 3.我们按照之前的方式,把USART_HyperTerminalInterrupt文件复制到ProjectSTM8
[单片机]
STM8单片机<font color='red'>串口驱动</font>的深度解析
STM32 串口驱动,分层通信
以前在使用串口的时候都是直接使用中断,每收发一个字节都要进一次中断,然后直接在中断进行封包,现在做了一个简单的分层设计,其实这个设计还是驱动设计,后期将逻辑层划分再细致一点,争取做到和linux的shell类似的分层。 软件分层如下 驱动层:串口、DMA、初始化,串口只开启接收空闲中断,DMA中断不开启。 缓冲区:利用malloc和free函数创建的链表,缓冲区管理有两个,一个是接收缓冲区,每次进入接收空闲中断就把数据扔到接收缓冲队列里面去;另一个是发送缓冲区,发送缓冲区无逻辑,这只是一个数据结构。 示意图中的数据指针实际上用的是uint8 数组,当然,第一个数据完全可以塞到第二个数据里面,但是如果使用的是M0芯
[单片机]
STM32 <font color='red'>串口驱动</font>,分层通信
STM32F746 利用HAL库编写串口驱动程序
之前用hal库的时候都是用一些简单的,例如初始化一个IO用作LED指示,今天写的代码需要串口的例子,说真的看了官方的demo也没看出啥名堂,反而觉得用hal写串口驱动太麻烦了. 回顾下之前常见的串口写法,发送用的是阻塞式发送,一般都是发送一些调试信息,接收肯定用的是中断; 为了编程的方便,发送一般是跟printf绑定的,但是对于hal库这些我们又怎么来编写呢? 接下来我把我刚刚学习到的东西分享下,如果有错误请指教。 我的开发板是STM32F746G-DISCO,参考的是UART_TwoBoards_ComIT例子。 首先我们看看中断发送的例子: /* Buffer used for transmission */ u
[单片机]
用单片机的串口驱动74LS164
  8051单片机串行接口是一个可编程的全双工串行通信接口。它可用作异步通信方式(UART),与串行传送信息的外部设备相连接,或用于通过标准异步通信协议进行全双工的8051多机系统也能通过同步方式,使用TTL或 CMOS 移位寄存器来扩充I/O口。   串口工作在模式0,只是作为同步移位寄存器。RXD(P3.0)用于串行数据输出,TXD(P3.1)用于移位时钟输出,P1.7用来控制74LS164的工作状态。   单片机串口驱动74LS164的程序主要包括函数声明管脚定义部分、串口初始化函数以及数据发送函数。   (1)函数声明管脚定义。   函数声明管脚定义部分主要完成程序所涉及的库函数的声明及有关引脚的定义,一般置于程序的开
[单片机]
用单片机的<font color='red'>串口驱动</font>74LS164
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved