我们继续来看看相关用到的函数:
10,使用pps_register_source 注册PPS
xtrxdev->pps = pps_register_source(&xtrx_pps_info,
PPS_CAPTUREASSERT | PPS_OFFSETASSERT);
if (!xtrxdev->pps) {
dev_err(&pdev->dev, "Failed to register 1PPS source.\n");
}
这里看到xtrx_pps_info这个结构体:
static struct pps_source_info xtrx_pps_info = {
.name = "xtrx_pps",
.path = "",
.mode = PPS_CAPTUREASSERT|PPS_OFFSETASSERT|PPS_ECHOASSERT|
PPS_CANWAIT|PPS_TSFMT_TSPEC,
.owner = THIS_MODULE,
};
这里看到了只是一些标志和名称用来传递一些信息,没有实际的回调函数。关于PPS的注册这里先留个疑问。
11,init_waitqueue_head 这里队列操作:
init_waitqueue_head是初始化一个队列。这种队列是实现不同线程之间同步。从字面意思上看是等待队列,我们看看人工智能给出了的例子:这里来回拷贝非常麻烦,我就直接截图;
上面这里子就用到了相关的三个函数:
init_waitqueue_head(&wait_queue);//初始化一个队列
wake_up_interruptible(&wait_queue);//唤醒一个队列
wait_event_interruptible(wait_queue, cond)//等待一个队列,第二个参数是条件,不满足再等待队列,满足的话就不等待队列了
我们在这个xtrx这驱动里面找到的关于等待函数是wait_event_interruptible_timeout()。
#define wait_event_interruptible_timeout(wq, condition, timeout) \
({ \
long __ret = schedule_timeout_interruptible(timeout); \
if (!(condition)) \
__ret = 0; \
__ret; \
})
这个函数多了第三个参数就是等待时间,也就是等待若干时间后不满足也返回,如果需要返回的时刻还没有满足condition就返回0。(这里的condition应该是动态变化的才有意义,静态看的话可以理解为强制返回为0).如下图:
这里我们看到有一个atomic_开头的是原子操作。
12,atomic_开头的原子操作:简单说就是不被中断的原子操作。
在上面截图代码里面我们看到,atomic_read,atomic_xchg,另外也可以看到atomic_inc。这些操作很简单,主要分析要达到什么目的。
上面代码判断中atomic_read返回数不等于0作为condition,我们按照静态来看,就是说将atomic_read的操作的对象在调用wait_event_interruptible_timeout之前就要初始化成非0数值,否则是0的话(0!=0)的条件为假,所以这里wait_event_interruptible_timeout就一直返回为0.
我们继续搜可以看到在中断里面唤醒了对应的等待队列。在使用wake_up_interrupt之前首先调用了atomic_inc将对应的变量设置成了非0数值。(而在中断处理后,被设置成了0). 这里可能有什么还没体会明白的门道,需要以后继续体会一下。