• disable_irq与disable_irq_nosync使用场景


    disable_irq与disable_irq_nosync使用场景
        Linux设备驱动,关于中断屏蔽有两个接口:disable_irq和disable_irq_nosync,该两接口使用场景如下:
     
        1、disable_irq:在非中断处理函数中使用,会阻塞;
        2、disable_irq_nosync:在中断处理函数中使用,不会阻塞;用于屏蔽相应中断;
     
     一、为什么要屏蔽中断?  
        使能中断后,一旦触发中断,系统会进入中断处理函数;如果下一个中断触发的时候,前一个中断处理函数已经完成,这是理想状态,不会发生异常;如果前一个中断处理函数还未完成,那么就会导致中断嵌套。为了不出现中断嵌套,必须在中断处理函数中屏蔽中断,待中断处理完成后,再主动使能中断
     
     
    二、disable_irq不能放在中断处理函数中
        如果在中断处理函数中使用disable_irq屏蔽相应中断,系统将会出现死锁状态,最后死机,然后重启。(已验证)
     
    三、enable_irq配套使用
        当中断处理函数已经完成所有工作,在返回之前需要主动调用接口enable_irq使能中断,否则该中断将一直被屏蔽。(已验证)
     
     
    四、附上距离传感器中断处理处理函数
     
    //PS中断处理
    static irqreturn_t ltr559_irq_handler(int irq, void *arg)
    {
    struct ltr559_data *data = (struct ltr559_data *)arg;


    //printk("%s ",__func__);
    if (NULL == data)
    return IRQ_HANDLED;


    //后面必须有使能中断
    disable_irq_nosync(data->irq); //屏蔽中断,不会造成死锁
    schedule_delayed_work(&data->ps_work, 0); //调用延时工作队列
    return IRQ_HANDLED;
    }
     
     

    //PS工作任务
    //重要接口
    static void ltr559_ps_work_func(struct work_struct *work)
    {
    struct ltr559_data *data = container_of(work, struct ltr559_data, ps_work.work);
    struct i2c_client *client=data->client;
    int als_ps_status;
    int psval_lo, psval_hi, psdata;
    static u32 ps_state_last = 2; //Far as default.


    mutex_lock(&data->op_lock);


    als_ps_status = i2c_smbus_read_byte_data(client, LTR559_ALS_PS_STATUS);
    //printk("%s ps_open_state=%d, als_ps_status=0x%x ",__func__,data->ps_open_state,als_ps_status);
    if (als_ps_status < 0)
    goto workout;
    /* Here should check data status,ignore interrupt status. */
    /* Bit 0: PS Data
    * Bit 1: PS interrupt
    * Bit 2: ASL Data
    * Bit 3: ASL interrupt
    * Bit 4: ASL Gain 0: ALS measurement data is in dynamic range 2 (2 to 64k lux)
    *                 1: ALS measurement data is in dynamic range 1 (0.01 to 320 lux)
    */

    //使能情况
    if ((data->ps_open_state == 1) && (als_ps_status & 0x02)) {
    psval_lo = i2c_smbus_read_byte_data(client, LTR559_PS_DATA_0);
    if (psval_lo < 0) {
    psdata = psval_lo;
    goto workout;
    }
    psval_hi = i2c_smbus_read_byte_data(client, LTR559_PS_DATA_1);
    if (psval_hi < 0) {
    psdata = psval_hi;
    goto workout;
    }
    psdata = ((psval_hi & 7) << 8) | psval_lo;
    printk("%s: psdata=%d(0x%x), near_thrd=%u, far_thrd=%u, dynamic_noise=%u ",
      __func__, psdata, (u32)psdata, data->platform_data->prox_threshold,
      data->platform_data->prox_hsyteresis_threshold, data->dynamic_noise);


    if(psdata >= data->platform_data->prox_threshold){
    data->ps_state = 0; //near
    ltr559_set_ps_threshold(client, LTR559_PS_THRES_LOW_0, data->platform_data->prox_hsyteresis_threshold);
    ltr559_set_ps_threshold(client, LTR559_PS_THRES_UP_0, 0x07ff);
    printk("%s: near, update near_thrd=%u, far_thrd=%u ",
      __func__, 0x7ff, data->platform_data->prox_hsyteresis_threshold);
    } else if (psdata <= data->platform_data->prox_hsyteresis_threshold){
    data->ps_state = 1; //far




    //该宏已经定义
    #if defined(CONFIG_PICCOLO_COMMON)
      if (data->dynamic_noise > 20 && psdata < (data->dynamic_noise - 50) ) {
     data->dynamic_noise = psdata;
     if(psdata < 100) {
     }else if(psdata < 200){
     data->platform_data->prox_threshold = psdata+230;
     data->platform_data->prox_hsyteresis_threshold = psdata+180;
     }else if(psdata < 500){
     data->platform_data->prox_threshold = psdata+280;
     data->platform_data->prox_hsyteresis_threshold = psdata+230;
     }else if(psdata < 1500){
     data->platform_data->prox_threshold = psdata+420;
     data->platform_data->prox_hsyteresis_threshold = psdata+350;
     }else{  
     data->platform_data->prox_threshold= 1800;
     data->platform_data->prox_hsyteresis_threshold= 1700;
     pr_err("ltr559 the proximity sensor rubber or structure is error! ");
     }
     printk("%s: NEW prox_threshold=%u, prox_hsyteresis_threshold=%u !!! ",
    __func__, data->platform_data->prox_threshold,
        data->platform_data->prox_hsyteresis_threshold);
      }
    #endif

    ltr559_set_ps_threshold(client, LTR559_PS_THRES_LOW_0, 0);
    ltr559_set_ps_threshold(client, LTR559_PS_THRES_UP_0, data->platform_data->prox_threshold);
    printk("%s: far, update near_thrd=%u, far_thrd=0 ",
      __func__, data->platform_data->prox_threshold);
    } else {
    data->ps_state = ps_state_last;
    }


    printk("%s: ps_state_last = %u, ps_state = %u ", __func__, ps_state_last, data->ps_state);
    if((ps_state_last != data->ps_state) || (data->ps_state == 0)) //need report the input event constant when near 
    {
    //上报数据
    input_report_abs(data->input_dev_ps, ABS_DISTANCE, data->ps_state);
    input_sync(data->input_dev_ps);
    printk("%s: report ABS_DISTANCE=%s ",__func__, data->ps_state ? "far" : "near");

    ps_state_last = data->ps_state;  //Report ABS value only if the state changed.
    }
    else
    printk("%s: ps_state still %s ", __func__, data->ps_state ? "far" : "near");
    }
    workout:
    enable_irq(data->irq); //使能 irq
    mutex_unlock(&data->op_lock); //解锁
    }
  • 相关阅读:
    Solution -「ARC 126F」Affine Sort
    Solution -「ABC 219H」Candles
    Solution -「LOCAL」二进制的世界
    Solution Set -「ABC 217」
    Java 封装
    Java 对象和类
    Java 继承
    牛客网MySQL在线编程
    Linux uniq命令
    Linux 单引号、双引号、反引号
  • 原文地址:https://www.cnblogs.com/Ph-one/p/6229709.html
Copyright © 2020-2023  润新知