[国嵌攻略][132][串口驱动实现]

如何开发Linux驱动程序

一般情况下都会有现成的驱动程序,不需要从零开始开发驱动程序。所以Linux驱动开发主要分为两个步骤:1.读得懂驱动程序;2.写的了核心功能。

发送中断处理程序

发送中断处理函数在/drivers/serial/samsung.c的s3c24xx_serial_tx_chars

循环缓冲

struct circ_buf {

char *buf;

int head;

int tail;

};

存数据的时候移动head,取数据的时候移动tail。

static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id){
    //判断发送流控
    struct s3c24xx_uart_port *ourport = id;
    struct uart_port *port = &ourport->port;

    if(port->x_char){   //是否有发送流控字符
        //写入流控字符
        wr_regb(port, S3C2410_UTXH, port->x_char);

        //修改发送计数
        port->icount.tx++;

        //清除流控字符
        port->x_char = 0;

        return IRQ_HANDLED;   //中断处理完成
    }

    //判断数据发送
    struct circ_buf *xmit = &port->state->xmit;

    if(uart_circ_empty(xmit) || uart_tx_stopped(port)){   //是否循环缓冲为空或者串口停止发送
        s3c24xx_serial_stop_tx(port);

        return IRQ_HANDLED;   //中断处理完成
    }

    //循环发送数据
    int count = 256;

    while(!uart_circ_empty(xmit) && (count-- > 0)){   //是否循环缓冲不为空并且发送数据小于256字节
        //判断循环缓冲
        if(rd_regl(port, S3C2410_UFSTAT) & (1<<14)){   //是否循环缓冲已满
            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) < 256){   //是否循环缓冲数目小于256
        uart_write_wakeup(port);
    }

    //关闭发送使能
    if(uart_circ_empty(xmit)){   //是否循环缓冲为空
        s3c24xx_serial_stop_tx(port);
    }

    return IRQ_HANDLED;   //中断处理完成
}

接收中断处理程序

接收中断处理函数在/drivers/serial/samsung.c的s3c24xx_serial_rx_chars

static irqreturn_t s3c24xx_serial_rx_chars(int irq, void *dev_id){
    //循环接收数据
    struct s3c24xx_uart_port *ourport = dev_id;
    struct uart_port *port = &ourport->port;
    int max_count = 64;

    while((max_count--) > 0){   //是否接收数据小于64字节
        //判断接收缓冲
        unsigned int ufstat;

        ufstat = rd_regl(port, S3C2410_UFSTAT);
        if((ufstat & 0x3F) == 0){   //是否接收缓冲为空
            break;
        }

        //读取错误状态
        unsigned int uerstat;

        uerstat = rd_regl(port, S3C2410_UERSTAT);

        //读取接收数据
        unsigned int ch;

        ch = rd_regb(port, S3C2410_URXH);

        //写入接收缓冲
        uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN, ch, TTY_NORMAL);
    }

    //写入线路规程
    struct tty_struct *tty = port->state->port.tty;

    tty_flip_buffer_push(tty);

    return IRQ_HANDLED;   //中断处理完成
}
时间: 2024-09-29 20:54:16

[国嵌攻略][132][串口驱动实现]的相关文章

[国嵌攻略][131][串口驱动分析-接收]

tty数据接收流程 //tty子系统 1.tty_fops中的tty_read响应系统调用 2.tty_read调用tty_ldisc_N_TTY中的n_tty_read n_tty_read 1.设置app的状态 2.如果没有数据可读,让阻塞生效 3.如果有数据可读,从read_buf中读走数据 什么时候串口驱动会把数据送到n_tty_read的read_buf中 当串口接收到数据时会产生接收中断,然后中断处理程序会把数据送到read_buf中. 串口驱动如何收到数据 串口中断处理程序s3c2

[国嵌攻略][057][串口控制台建立]

控制台分类 1.菜单型控制台,通过选择菜单来执行命令 2.解析型控制台,通过输入命令来执行命令 printf().scanf()函数移植 1.函数采用变参 2.打印信息到串口 3.关键在于把变参转换成字符串,相关函数需要从Linux内核或标准C库中移植 va_list args; va_start(args, fmt); vsprintf(buf, fmt, args); va_end(args); /***********************************************

[国嵌攻略][117][LED驱动程序设计]

LED程序设计 1.编写内核模块 2.搭建字符驱动框架 3.实现设备方法 头文件 <linux/io.h> writel() leddev.h //设备命令 #define LED_MAGIC 'L' //LED幻数 #define LED_ON _IO(LED_MAGIC, 0) //打开LED #define LED_OFF _IO(LED_MAGIC, 1) //关闭LED leddev.c /***********************************************

[国嵌攻略][164][USB驱动程序设计]

USB驱动模型 1.USB host controller driver(主控器驱动):为USB主控制器提供驱动程序 2.USB core(USB核心):连接USB主控制器驱动和USB设备驱动 3.USB client driver:为USB外部设备提供驱动程序 USB设备模型 device(设备)->config(配置)->interface(接口)->endpoint(端点),构成了USB设备的四个层次.一个usb driver(驱动)对应的是一个interface(接口).一个接口

[国嵌攻略][061][2440LCD驱动设计]

LCD初始化 1.引脚初始化 2.时序初始化 VBPD(vertical back porch):表示在一帧图像开始时,垂直同步信号以后的无效的行数 VFBD(vertical front porch):表示在一帧图像结束后,垂直同步信号以前的无效的行数 VSPW(vertical sync pulse width):表示垂直同步脉冲的宽度,用行数计算 HBPD(horizontal back porch):表示从水平同步信号开始到一行的有效数据开始之间的VCLK的个数 HFPD(horizon

[国嵌攻略][151][nandflash驱动程序设计]

初始化 打开/drivers/mtd/nand/s3c2410.c找到nand flash驱动程序代码,找到模块初始化函数s3c_nand_init,找到platform_driver中的probe函数. 1.使能时钟 2.进行物理地址到虚拟地址转换 3.硬件纠错初始化 4.搜索nand flash 5.注册分区信息 nand flash读操作 nand flash读写函数位于通用驱动/drivers/mtd/nand/nand_base.c.nand flash的读函数位于nand_read的

[国嵌攻略][140][触摸屏驱动分析]

触摸屏驱动分析 初始化 1.使能ADC时钟 2.将物理地址转化为虚拟地址 3.让触摸屏进入等待中断模式 4.分配输入设备结构 5.设置可能上报的事件类型和按键类型 6.为TC和ADC中断注册处理函数 7.注册输入型设备 按下处理 1.判断按下或弹起 2.如果是按下情况,那么启动XY坐标的AD转换 3.进行4次ADC转换,获取4次XY坐标值 4.计算4次采集的平均值,并上报给内核

[国嵌攻略][063][电阻屏驱动程序设计]

/******************************************************************** *名称:touchscreen.c *作者:D *时间:2015.11.23 *功能: * 触摸屏驱动,由于MINI2440采用一线触控,而非四线电阻触控所以触摸屏 * 驱动无法使用. ********************************************************************/ /****************

[国嵌攻略][133][网卡驱动架构分析]

Linux网络子系统 1.系统调用接口:提供系统调用 2.协议无关接口:统一网络协议给系统调用接口使用 3.网络协议栈  :实现网络协议 4.设备无关接口:统一设备驱动程序给网络协议使用 5.设备驱动程序:实现网卡驱动 Linux驱动在内核中都有一个结构来描述,首先找到设备描述结构,然后找到设备如何注册和初始化. 网卡描述结构 在Linux内核中,每个网卡都由一个net_device结构来描述,其中一些重要成员: char name[IFNAMSIZ]   设备名,如:eth%d unsigne