【一】、中断底半部

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. 表达式树(Expression Tree)

    饮水思源 本文并非原创而是下面网址的一个学习笔记 https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/e ...

  2. 以管理员身份运行CMD

    To complete these procedures, you must be a member of the Administrators group. To start a command p ...

  3. Codeforces.838D.Airplane Arrangements(思路)

    题目链接 \(Description\) 飞机上有n个位置.有m个乘客入座,每个人会从前门(1)或后门(n)先走到其票上写的位置.若该位置没人,则在这坐下:若该位置有人,则按原方向向前走直到找到空座坐 ...

  4. [AHOI2013]作业

    [AHOI2013]作业 题目大意: 给定一个长度为\(n(n\le10^5)\)的数列\(A(1\le A_i\le n)\).\(m(m\le10^6)\)次询问,每次询问区间\([l,r]\)内 ...

  5. KVM源代码解读:linux-3.17.4\arch\x86\include\asm\kvm_host.h

    /* * Kernel-based Virtual Machine driver for Linux * * This header defines architecture specific int ...

  6. Codeforces Round #374 (Div. 2) B. Passwords 贪心

    B. Passwords 题目连接: http://codeforces.com/contest/721/problem/B Description Vanya is managed to enter ...

  7. LPC-Link2 CMSIS-DAP firmware source

    LPC-Link2 CMSIS-DAP firmware source Hi, I'm using the CMSIS-DAP firmware with the LPC-Link2. I'd lik ...

  8. windows和linux 下将tomcat注册为服务

    参考文献: tomcat注册成windows服务 背景 当前项目需要运行两个Tomcat,每次启动系统以后都要手动进入到tomcat目录执行startup.bat,非常烦,所以想将这两个tomcat直 ...

  9. [Go] 判断 文件/文件夹 是否存在?

    Golang 判断文件是否存在有点怪异,是根据在操作文件时返回的错误信息来判断的,而不能直接根据路径判断 版本1: func IsExists(path string) (bool, error) { ...

  10. POJ 3076 SUKODU [Dangcing Links DLX精准覆盖]

    和3074仅仅有数目的不同,3074是9×9.本来想直接用3074的.然后MLE,,,就差那么20M的空间,,. 从这里学习到了解法: http://www.cnblogs.com/ylfdrib/a ...