软触发HW-Interrupt,Linux内核

时间:2016-05-31 19:54:03

标签: linux-kernel interrupt

我正在为脚控制器写SW。为了实现心跳功能,理想情况下,尽可能多地覆盖系统和堆栈。尽可能我试图弄清楚如何模拟按钮按下,如果可能的话直接调用GPIO相关的ISR。在Derek Molloy的tutorial之后,我的用户空间组件通过阻塞读取LKM来调用,接收按钮nr。压:

static DECLARE_WAIT_QUEUE_HEAD(wq);
static uint8_t switch_pressed_flag = 0;
static uint8_t heartbeat_const = 20;


static ssize_t dev_read(struct file *filep, char *buffer, size_t len, loff_t *offset) // called whenever device is being read from user space
{
   wait_event_interruptible(wq, switch_pressed_flag != 0);  
   switch_pressed_flag = 0;
   copy_to_user(buffer, msg_lkm_to_user, sizeof(msg_lkm_to_user));

   return 0;                                                             
}

因此读取在等待队列上,直到发生中断:

static irq_handler_t fc_irq_handler(unsigned int irq, void *dev_id, struct pt_regs *regs)
{
   uint8_t button_nr = *(uint8_t*)dev_id;

   tm_cur = jiffies_to_msecs(jiffies); // debounce
   if ( (tm_cur - tm_last[button_nr]) > 300 )
   {   
       msg_lkm_to_user[0] = button_nr; 

       switch_pressed_flag = 1;
       wake_up_interruptible(&wq);
    } 

   tm_last[button_nr] = tm_cur;

   return (irq_handler_t) IRQ_HANDLED;      // Announce that the IRQ has been handled correctly
}

对于心跳,跨越一个线程应该每隔一秒触发一次ISR:

static int heartbeat(void* arg)
{
    while(!kthread_should_stop())
    {
        set_current_state(TASK_RUNNING);

        fc_irq_handler(0, (void*)&heartbeat_const, NULL);  // 'manual' call, arbitrary button number

        set_current_state(TASK_INTERRUPTIBLE);
        msleep(1000);
    }
    return 0;
}

我所看到的是手动ISR呼叫不会唤醒读/用户线程,以某种方式排队等待直到发生真正的HW中断。

我认为线程上下文可能是一个因素,但ISR也有不同的上下文。有什么想法吗?

0 个答案:

没有答案