• [国嵌攻略][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;   //中断处理完成
    }
  • 相关阅读:
    各种读取速度
    索引倒排
    清空mysql数据
    java随机读取文件
    移动文件
    输出字符串数组
    背包问题
    使用bloomfilter
    使用hash拆分文件
    判断文件的编码格式
  • 原文地址:https://www.cnblogs.com/d442130165/p/5265703.html
Copyright © 2020-2023  润新知