【一】、中断底半部

1. 软中断    --->>>  执行在中断上下文  --->>>  会被中断打断,不会被软中断或进程打断  --->>> 可以完成耗时操作
    
    2. tasklet     --->>>  执行在中断上下文  --->>>  会被中断打断,不会被软中断或进程打断  --->>> 可以完成耗时操作
    
    3. 工作队列  --->>>  执行在进程上下文  --->>>  会被中断、中断底半部、进程打断   --->>> 可以完成耗时操作,同时
    
            也可以有进程调度相关的函数
            
            
            
    中断底半部实现:
    
    
        [1]. 软中断
        
            init/main.c  
            
                --->>> start_kernel
                
                    --->>> softirq_init();
                    
           /***********************************************************************
            *功能:开启(初始化)软中断
            *参数:
            *            @nr      软中断枚举值
            *            @action  中断底半部处理函数
            **********************************************************************/        
            void open_softirq(int nr, void (*action)(struct softirq_action *))
            
           /************************************************
            *功能:调度中断底半部
            *参数:
            *            @nr         软中断枚举值
            ***********************************************/
            void raise_softirq(unsigned int nr)
                    
    
        [2]. tasklet
        
            1. struct tasklet_struct  数据类型
            
            2. 定义、初始化
            
               
               /*******************************************************************************
                *功能:定义并初始化tasklet
                *参数:
                *            @name    tasklet结构体变量名
                *            @func    tasklet底半部处理函数指针
                *            @data    私有数据
                ******************************************************************************/
                #define DECLARE_TASKLET(name, func, data) \
                        struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }
                        
               /**********************************************************************************************
                *功能:初始化tasklet
                *参数:
                *            @t            tasklet结构体指针
                *            @func       tasklet底半部处理函数指针
                *            @data       私有数据
                *********************************************************************************************/        
                void tasklet_init(struct tasklet_struct *t,void (*func)(unsigned long), unsigned long data);

3. 调度tasklet底半部
               
               /********************************************************************
                *功能:调度tasklet底半部
                *参数:
                *            @t        tasklet结构体指针
                *返回值:void
                *******************************************************************/
                void tasklet_schedule(struct tasklet_struct *t)
    
    
        [3]. 工作队列
        
            <linux/workqueue.h>
            
            1. 工作队列结构体
            
                struct work_struct
            
            2. 定义、初始化
            
                typedef void (*work_func_t)(struct work_struct *work);
            
                /**********************************************************
                 *功能:定义并初始化workqueue
                 *参数:
                 *            @n    工作队列变量名
                 *            @f    工作队列底半部处理函数指针
                 *********************************************************/
                 #define DECLARE_WORK(n, f)                        \
                    struct work_struct n = __WORK_INITIALIZER(n, f)
    
                /**********************************************************
                 *功能:初始化工作队列
                 *参数:
                 *            @_work    工作队列结构体指针
                 *            @_func    工作队列底半部处理函数指针
                 *********************************************************/
                 INIT_WORK(struct work_struct * _work, _func)
                
            3. 调度工作队列
            
               /****************************************************
                *功能:调度工作队列底半部
                *参数:
                *            @work    工作队列结构体指针
                ***************************************************/
                bool schedule_work(struct work_struct *work)
    
    
【二】、定时器

<linux/timer.h>
    
    jiffies  :计数值  
    
    HZ
    
    expires = jiffies + HZ;     //定时1s
    expires - jiffies + n*HZ;   //定时ns
    
    struct timer_list {    
        unsigned long expires;             //定时器的定时时间  --->>> 计数值
        void (*function)(unsigned long);   //定时器中断处理函数指针
        unsigned long data;                   //私有数据
    };

/***************************************************************************
     *功能:定义并初始化定时器
     *参数:
     *            @_name      定时器变量名
     *            @_function  定时器中断处理函数指针
     *            @_expires   定时时间计数值
     *            @_data      私有数据
     **************************************************************************/
     #define DEFINE_TIMER(_name, _function, _expires, _data)        \
        struct timer_list _name =                \
            TIMER_INITIALIZER(_function, _expires, _data)

/**********************************
    *功能:初始化定时器
    *参数:
    *            @timer  定时器指针
    *********************************/
    init_timer(struct timer_list * timer)

/* 开启定时器 */
    void add_timer(struct timer_list *timer)
    /* 关闭定时器 */
    int del_timer(struct timer_list *timer)
    
    /************************************************************************
     *功能:修改定时器定时时间
     *参数:
     *                @timer          struct timer_list *
     *                @expires     定时时间值
     ***********************************************************************/
     int mod_timer(struct timer_list *timer, unsigned long expires)

【三】、按键消抖

采用定时器延时消抖
    
    
    延迟机制:
    
        1.  定时器
        
        2.  中断底半部
        
                软中断
                tasklet
                工作队列  
                
        3.  内核延时函数
        
            void ndelay(unsigned long x)
            mdelay(n)
        
        4.  内核睡眠函数
    
            void msleep(unsigned int msecs);
            
            unsigned long msleep_interruptible(unsigned int msecs);
            
            void ssleep(unsigned int seconds)

【四】、IIC总线

platform                      IIC                   SPI

dev            platform_device               i2c_client             spi_device
    
    drv            platform_driver               i2c_driver             spi_driver
    
    bus            bus_type

电气特性:
    
        SDA:数据线
        SCK:时钟线
        
        同步  半双工  串行
    
    
    时序(时序图):
    
        起始信号:时钟线高电平期间,数据线产生负跳变
        结束信号:时钟线高电平期间,数据线产生正跳变
    
    协议:
        
        a). signal read:
                
                
                | start signal | Device address[6:0],W[7] | slave ACK | register address[7:0] | slave ACK | --->>>
                    
                    SR | Device address[6:0],R[7] | slave ACK | Data[7:0] | MACK | SP |
                    
            b). signal write:
            
                | start signal | Device address[6:0],W[7] | slave ACK | register address[7:0] | slave ACK | --->>>
                
                    Data[7:0] | slave ACK | SP |
        
            W: write = 0
            R: read  = 1
            SR:repeated start condition
            SP:stop condition

IIC驱动:

设备驱动层:
        需要驱动工程师完成的,向应用层提供操作的接口(fops),向下层操作硬件
        
    核心层: i2c-core.c
        内核提供好的,提供设备驱动和总线驱动注册和注销的方法,还提供设备驱动和总线驱动的匹配方式
    
    总线驱动层:i2c-s3c2410.c
        内核提供好的,按照用户传递的数据和操作时序操作硬件
        
        
    
    IIC设备驱动:<linux/i2c.h>
    
    
        struct i2c_driver {
            
            int (*probe)(struct i2c_client *, const struct i2c_device_id *);
            int (*remove)(struct i2c_client *);
            
            struct device_driver driver;
            const struct i2c_device_id *id_table;   //i2c idtable表
        };
                
        struct i2c_device_id {
            char name[I2C_NAME_SIZE];     //IIC设备名
            kernel_ulong_t driver_data;      //私有数据
        };
                
        /********************************************************
         *功能:注册i2c驱动
         *参数:
         *            @driver struct i2c_driver *
         *******************************************************/    
         #define i2c_add_driver(driver) \
                i2c_register_driver(THIS_MODULE, driver)
                    
         void i2c_del_driver(struct i2c_driver *driver);
        
        
        i2c设备驱动注册过程:
            
            i2c_register_driver
            
                --->>> driver_register(&driver->driver);
                
                    --->>> bus_add_driver(drv);
                    
                        --->>> driver_attach(drv);
                        
                            --->>> bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
                            
                                --->>> __driver_attach
                                
                                    --->>> driver_match_device(drv, dev)
                                    
                                        --->>> drv->bus->match ? drv->bus->match(dev, drv) : 1
        static int i2c_device_match(struct device *dev, struct device_driver *drv)
        {
            struct i2c_client    *client = i2c_verify_client(dev);
            struct i2c_driver    *driver;

if (!client)
                return 0;

/* 设备数匹配 */
            if (of_driver_match_device(dev, drv))
                return 1;

/* Then ACPI style match */
            if (acpi_driver_match_device(dev, drv))
                return 1;

driver = to_i2c_driver(drv);
            /* idtable表匹配 */
            if (driver->id_table)
                return i2c_match_id(driver->id_table, client) != NULL;

return 0;
        }
                                        
    
        设备数匹配   >  idtable表匹配
        
        struct i2c_msg {
            __u16 addr;            /* slave address */
            __u16 flags;        /* I2C_M_RD    读数据   0  写数据 */
        
            __u16 len;            /* msg length */
            __u8 *buf;            /* pointer to msg data */
        };

/***********************************************************************************
         *功能:i2c总线数据传输
         *参数:
         *            @adap    struct i2c_adapter *
         *            @msgs    消息结构体
         *            @num     消息结构体个数
         **********************************************************************************/
         int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs,int num);
        
        
         数据收发函数的封装:
        
            [1]. 发送数据
            
                int write_reg(struct i2c_client *client,u8 reg,u8 val)
                {
                    int ret = 0;
                    u8 buf[] = {reg,val};
                    struct i2c_msg msgs[] = {
                    
                        [0] = {
                            .addr = client->addr,
                            .flags= 0,
                            .len  = 2,
                            .buf  = buf,
                        },
                    
                    };
                    ret = i2c_transfer(client->adapter,msgs,ARRAY_SIZE(msgs));
                    if(ret < 0){
                        return ret;
                    }
                    return 0;
                }
        
            [2]. 接受数据
            
                int read_reg(struct i2c_client *client,u8 reg)
                {
                    int ret = 0;
                    u8 val = 0;
                    u8 buf[] = {reg};
                    
                    struct i2c_msg msgs[] = {
                    
                        [0] = {
                            .addr = client->addr,
                            .flags= 0,
                            .len  = 1,
                            .buf  = buf,
                        },
                        
                        [1] = {
                            .addr = client->addr,
                            .flags= I2C_M_RD,
                            .len  = 1,
                            .buf  = &val,
                        },
                    
                    };
                    
                    ret = i2c_transfer(client->adapter,msgs,ARRAY_SIZE(msgs));
                    if(ret < 0){
                        return ret;
                    }
                    return (unsigned int)val;
                }

linux中断的更多相关文章

  1. linux中断与异常

    看了<深入理解linux内核>的中断与异常,简单总结了下,如果有错误,望指正! 一 什么是中断和异常 异常又叫同步中断,是当指令执行时由cpu控制单元产生的,之所以称之为异常,是因为只有在 ...

  2. 13.linux中断处理程序

    linux中断处理程序 一.中断处理流程 在linux内核代码中进入entry-armv.S目录: linux统一的入口:__irq svc. 进入了统一的入口之后,程序跳到irq_handler标号 ...

  3. Linux中断(interrupt)子系统

    Linux中断(interrupt)子系统之一:中断系统基本原理 Linux中断(interrupt)子系统之二:arch相关的硬件封装层 Linux中断(interrupt)子系统之三:中断流控处理 ...

  4. 驱动: 中断【1】linux中断流程

    通常情况下,当一个给定的中断处理程序正在执行时,所有其他的中断都是打开的,所以这些不同中断线上的其他中断都能被处理,但当前中断总是被禁止的. 将中断处理切为两个部分或两半.中断处理程序上半部(top ...

  5. Linux中断子系统:级联中断控制器驱动

    Linux中断子系统 Linux中断子系统是个很大的话题,如下面的思维导图所示,包含硬件.驱动.中断上半部.中断下半部等等.本文着眼于中断控制器(PIC),特别是级联中断控制器驱动部分,对驱动的设计和 ...

  6. Linux中断管理

    CPU和外设之间的交互,或CPU通过轮询机制查询,或外设通过中断机制主动上报. 对大部分外设中断比轮询效率高,但比如网卡驱动采取轮询比中断效率高. 这里重点关注ARM+Linux组合下中断管理,从底层 ...

  7. Linux中断管理 (1)Linux中断管理机制

    目录: <Linux中断管理> <Linux中断管理 (1)Linux中断管理机制> <Linux中断管理 (2)软中断和tasklet> <Linux中断管 ...

  8. Linux中断管理 (2)软中断和tasklet

    目录: <Linux中断管理> <Linux中断管理 (1)Linux中断管理机制> <Linux中断管理 (2)软中断和tasklet> <Linux中断管 ...

  9. Linux中断管理 (3)workqueue工作队列

    目录: <Linux中断管理> <Linux中断管理 (1)Linux中断管理机制> <Linux中断管理 (2)软中断和tasklet> <Linux中断管 ...

  10. 全志A33 lichee 开发板 Linux中断编程原理说明

    开发平台 * 芯灵思SinlinxA33开发板 淘宝店铺: https://sinlinx.taobao.com/ 嵌入式linux 开发板交流 QQ:641395230 本节实验目标实现按键触发中断 ...

随机推荐

  1. “百度杯”CTF比赛 九月场 YeserCMS

    打开题目 进入后是一个cms,但肯定的是这个cms不叫yesercms 于是我们开始随便翻翻,寻找信息,后台我也看了除了一个登陆界面,就没有其他的提示信息. 最后在文档下载的评论栏里发现,这个cms的 ...

  2. IllegalArgumentException: Unmatched braces in the pattern.

    IllegalArgumentException: Unmatched braces in the pattern. 非法参数异常. 不匹配的 吊带 在 样品 中. === 没有管.  项目一直卡在d ...

  3. python简单实现队列和栈push、pop操作

    栈: # -*- coding: utf-8 -*- #定义序列 lst=[] def pop(): if(len(lst)==0): print"栈为空","无法出栈& ...

  4. spring boot学习总结(一)-- 基础入门 Hello,spring boot!

    写在最前 SpringBoot是伴随着Spring4.0诞生的: 从字面理解,Boot是引导的意思,因此SpringBoot帮助开发者快速搭建Spring框架: SpringBoot帮助开发者快速启动 ...

  5. centos上安装elasticsearch 5.5.1 遇到的各种坑

    mac玩得好好滴,一次性启动成功,结果在centos上安装时,遇坑无数,记录一下: 一.只能localhost访问的问题修改 conf\elasticsearch.yml network.host: ...

  6. request.getRequestDispatcher("").forward()中文乱码

    即使jsp页面的编码已设为“UTF-8”,有中文的地方还是会出现乱码,但是用response.sendRedirect不会出现此问题. 解决方案一: 不使用PrintWriter out=respon ...

  7. sqlserver 2012 IDE中 Windows身份验证连接服务器报错 ,Login failed for user 'xxx\Administrator'. 原因: 找不到与提供的名称匹配的登录名。

    问题描述: 本地装了两个实例,一个是SQLEXPRESS,可以正常操作.但是另一个开发常用的实例MSSQLSERVER却连Windows身份验证都报错,报的错误也是很奇葩,怎么会找不到Administ ...

  8. JS删除String里某个字符的方法

    关于JS删除String里的字符的方法,一般使用replace()方法.但是这个方法只会删除一次,如果需要将string里的所以字符都删除就要用到正则. 1 2 3 4 var str = " ...

  9. TCP握手与socket通信细节

    http://www.jianshu.com/u/5qrPPM http://www.jianshu.com/p/f86512230707

  10. ARM 编程平台+coresight

    http://www.keil.com/product/ DS-5:http://www.cnblogs.com/njseu/p/6023081.html http://www.arm.com/pro ...