disable_irq与disable_irq_nosync使用场景

Posted 柒月

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n",__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\n",__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\n",
  __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\n",
  __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!\n");
 }
 printk("%s: NEW prox_threshold=%u, prox_hsyteresis_threshold=%u !!!\n",
__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\n",
  __func__, data->platform_data->prox_threshold);
} else {
data->ps_state = ps_state_last;
}


printk("%s: ps_state_last = %u, ps_state = %u\n", __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\n",__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\n", __func__, data->ps_state ? "far" : "near");
}
workout:
enable_irq(data->irq); //使能 irq
mutex_unlock(&data->op_lock); //解锁
}

以上是关于disable_irq与disable_irq_nosync使用场景的主要内容,如果未能解决你的问题,请参考以下文章

求教stm32f030 HAL库,怎么关闭和打开所有中断

使用keil5编译stm32,头文件core_cmFunc.h中,是预定义__CC_ARM,还是__GNUC__?

LDAP 与 MYSQL .. JA-SIG CAS 与 LDAP 与 CAS 与 MySQL

python网络编程基础(线程与进程并行与并发同步与异步)

=与==&与&&| 与 || 的区别

与 0 进行比较与与某个值进行比较是不是更快?