我正在为脚控制器写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也有不同的上下文。有什么想法吗?