技术解析
问题在帖子的最后。先贴代码:
驱动的pressure.c:
/*
功能:
外部中断4接一个人体红外感应,默认感应到有人体,如果人MISS了,低电平触发外
部中断,此时nLED_2(GPB6)亮,并且打印BABY MISS !!!
*/
volatile unsigned long *gpbcon = NULL; // nLED_2(GPB6)
volatile unsigned long *gpbdat = NULL;
volatile unsigned long *gpfcon = NULL; // EINT4 ( GPF4 )
volatile unsigned long *gpfdat = NULL;
volatile unsigned long *eintmask = NULL;
volatile unsigned long *eintpend = NULL;
unsigned int val = 0;
static struct class *pressuredrv_class;
static struct class_device *pressuredrv_class_dev;
//等待队列
static DECLARE_WAIT_QUEUE_HEAD(pressure_waitq);
/* 中断事件标志, 中断服务程序将它置1,pressure_read将它清0 */
static volatile int ev_press = 0;
static irqreturn_t pressure_irq(int irq, void dev_id)
{
//((*eintpend) & (1<<4)) = 1;
val = (*eintpend) & (1<<4); //读取EINTPEND寄存器的第4位的值
while (!val); //如果标志位置1
ev_press = 1; / 表示中断发生了 /
wake_up_interruptible(&pressure_waitq); / 唤醒休眠的进程 */
return IRQ_RETVAL(IRQ_HANDLED);
}
static int pressure_open(struct inode inode, struct file *file)
{
*gpbcon &= ~(0x3<<(06*2)); / 配置GPB6为输出引脚 */
*gpbcon |= (0x1<<(06*2));
*eintmask &= ~(0x1<<4); //把EINTMASK的第4位设为0,使能中断
request_irq(IRQ_EINT4, pressure_irq, IRQT_LOW, "PRESSURE", NULL); //设置外部中断4
return 0;
}
static int pressure_read(struct file file, char __user *buf, size_t size, loff_t *ppos)
{
/*如果没有检测到外部中断4,休眠/
wait_event_interruptible(pressure_waitq, ev_press);
/*如果有外部中断,返回val值*/
copy_to_user(buf, val, 1);
ev_press = 0;
return 0;