【一】、中断底半部

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. Android `AsyncTask`简要分析

    AsyncTask简要分析 经典异步任务:AsyncTask,使用场景有:批量下载,批量拷贝等.官方文档就直接给出了一个批量下载的示例. private class DownloadFilesTask ...

  2. 学习ABP遇到的问题汇总

    1,在abp官网下载的模板(asp.net+ef)写Application层的时候需要使用AutoMapper.结果ObjectMapper一直为null 解决:需要在当前项目的Module依赖Abp ...

  3. Android Intent Service

    Android Intent Service 学习自 Android 官方文档 https://blog.csdn.net/iromkoear/article/details/63252665 Ove ...

  4. InvokeRepeating重复定时器

    JS // Starting in 2 seconds.// a projectile will be launched every 0.3 secondsvar projectile : Rigid ...

  5. Codeforces.566F.Clique in the Divisibility Graph(DP)

    题目链接 \(Description\) 给定集合\(S=\{a_1,a_2,\ldots,a_n\}\),集合中两点之间有边当且仅当\(a_i|a_j\)或\(a_j|a_i\). 求\(S\)最大 ...

  6. Codeforces Round #371 (Div. 2) B. Filya and Homework 水题

    B. Filya and Homework 题目连接: http://codeforces.com/contest/714/problem/B Description Today, hedgehog ...

  7. Codeforces Round #281 (Div. 2) A. Vasya and Football 模拟

    A. Vasya and Football 题目连接: http://codeforces.com/contest/493/problem/A Description Vasya has starte ...

  8. Gym 100646 You’ll be Working on the Railroad dfs

    You'll be Working on the Railroad 题目连接: http://codeforces.com/gym/100646/attachments Description Con ...

  9. 深入理解webpack

    什么是Webpack WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并 ...

  10. FireDAC 下的 Sqlite [1] - 前言

    很长时间没静下心来写博客了, 现在回来, 是 Delphi 不断地进步让我感动.振奋. Delphi XE5 并入了 FireDAC, 第一印象非常好, 恐怕 dbExpress 等等都要靠边站了. ...