在我们的数据处理系统中,需要实现CPU和FPGA之间的通讯,CPU与FPGA(或其它外设)的通讯方式主要有两种,查询和中断。据说以前的数据处理系统中由于使用了很多中断,造成系统不稳定,容易死机,所以搞得现在大家对使用中断比较害怕。我觉得这个问题主要是由两个原因引起的:
第一,以前使用的操作系统是DOS,是单任务操作系统。它要响应外部事件必须使用中断,并且在中断处理程序(ISR)中完成该事件的全部处理。处理器在执行ISR时,如果有更高优先级的中断进入,则进行中断嵌套(当然是在允许中断嵌套的前提下),处理器响应更高优先级的任务;如果有低优先级的中断进入,则处理器不能响应,该低优先级的中断就pending在那儿,等高优先级的中断处理程序执行完了,才能响应该低优先级中断。
第二,如果所有的的ISR都写得短小精悍,执行起来时间都很短,那问题也不大,但如果有某些ISR又臭又长,优先级又贼高,这就大大影响了CPU对较低优先级中断的响应时间,造成“死机”。
而我们的数据处理使用的是VxWorks,号称最牛X的多任务实时操作系统,它可以从根本上解决上述两个问题,使得其对中断的响应飞快(在PC104平台下,我测下来大概3~5us)。
首先,VxWorks是多任务操作系统,它可以把应用分割成不同的任务(Task),任务之间根据设定的优先级竞争使用CPU(如果有多个CPU的话任务可以并发执行)。在VxWorks中ISR不属于任务的范畴,ISR是专门用来响应中断的,而对中断事务的处理可以交给Task来完成。ISR的优先级高于所有Task。最经典的中断处理任务是这么写的:
void intHandler(void)
{
初始化;
while(1) {
semTake(intSem , WAIT_FOREVER);
中断事务处理;
}
}
void intISR(int val)
{
semGive(intSem);
}
也就是说VxWorks中对中断的处理可由两部分组成:ISR和Task。Task执行intHandler函数,它的主体是个死循环,在该循环内它一直在等待intSem这个信号量(VxWorks中用来进行任务间或任务和中断间同步,或资源互斥的东东),所以平时这个任务是阻塞起来的,并不占用CPU时间,一旦intSem信号量来了,这个任务就被唤醒,来执行中断处理事务,而intISR这个中断处理程序正是给Task提供该信号量的。intISR如此简洁,执行起来当然不花时间,这样中断资源就被有效利用,当然能又快又好地响应很多很多中断。
再来说一下查询。VxWorks中要实现查询可以利用其提供的WatchDog Timer机制,该机制可以使得任何一个C函数以固定的速率重复执行。这实际上是利用了系统时间中断,该C函数也是被当作ISR来运行的,VxWorks中所有对ISR的限制也同样对之起作用。既然大家都是ISR,那反应时间应该差不多,但查询需要精确地配合好读写时序,做到这点比较麻烦。
也可以用任务(Task)来实现查询,优点是不受ISR的种种限制,但不同的任务之间是可以抢占的,要是一个查询任务要执行时,来了一个更高优先级的任务,那么这个查询任务就要延迟执行,这样就不能精确地保证查询任务按时执行了。
综上,我还是比较倾向于使用中断的方式使得CPU与FPGA通讯。