前些天在中断响应(handle)函数中操作I2C的时候,发现内核会抱怨:
BUG: scheduling while atomic: samtest/0x00010000/57
Call Trace:[<c009a30>][<c009a30>][<c010f7f0>][<c010ed08>][<c010f7f0>][<c002e664>]
...
但是后面的操作依然正常,经过高手指点后发现原来通过I2C传输的时候,总线会休眠,英文说明:
* we can't acknowledge from interrupt context since the i2c
* bus controller may sleep, so we just disable the interrupt
* here and handle the acknowledge using delayed work.
查看如下代码中的说明:
http://linux.sourcearchive.com/documentation/2.6.27-1.2/migor__ts_8c-source.html
00086 static irqreturn_t migor_ts_isr(int irq, void *dev_id) 00087 { 00088 struct migor_ts_priv *priv = dev_id; 00089 00090 /* the touch screen controller chip is hooked up to the cpu 00091 * using i2c and a single interrupt line. the interrupt line 00092 * is pulled low whenever someone taps the screen. to deassert 00093 * the interrupt line we need to acknowledge the interrupt by 00094 * communicating with the controller over the slow i2c bus. 00095 * 00096 * we can't acknowledge from interrupt context since the i2c 00097 * bus controller may sleep, so we just disable the interrupt 00098 * here and handle the acknowledge using delayed work. 00099 */ 00100 00101 disable_irq_nosync(irq); 00102 schedule_delayed_work(&priv->work, HZ / 20); 00103 00104 return IRQ_HANDLED; 00105 }
所以采用先注册
/* Init the workqueue used for interrupt that have to sleep */ INIT_WORK(&dev->wq, wq_handler); void wq_handler(struct work_struct *work);
然后在中断中调用
schedule_work(&dev->wq);