参考自:http://hi.baidu.com/greatren518/blog/item/25b349c7126e8fd9d10060b1.html
最近在做一个有关USB CAMERA的项目,发现我们的MUSB控制器驱动在收到一个完整的URB之后会回调UVC驱动去拷贝urb缓冲区的32个包的数据做后续处理。只是在我们的平台上,在进行urb切换的时候开销比较大,会造成在1ms之内未发出请求包,导致ISO类型的camera数据丢失一个包,导致图片出错。
单纯为解决这个开销问题,可以将原UVC驱动着数据拷贝的代码从中断函数中挪到中断底半部中执行。当然,原UVC驱动之所以这么设计应该是为了保证数据的实时性,并且是建立在一定的系统性能上的,实测这套代码在mini2440的板子上是可以顺畅跑QVGA-30fs的。
特此对中断底半部的机制之一tasklet做一个简要的描述,虽简单,参考网上的文章,做个记录。以下为转载:
一个有关于定时的内核设施是 tasklet。它类似内核定时器:在中断时间运行且运行同一个 CPU 上, 并接收一个 unsigned long 参数。不同的是:无法要求在一个指定的时间执行函数,只能简单地要求它在以后的一个由内核选择的时间执行。它对于中断处理特别有用:硬件中断必须尽快处理, 但大部分的数据管理可以延后到以后安全的时间执行。 实际上, 一个 tasket, 就象一个内核定时器, 在一个"软中断"的上下文中执行(以原子模式)。软件中断是在使能硬件中断时执行异步任务的一个内核机制。
tasklet 以一个数据结构形式存在,使用前必须被初始化。初始化能够通过调用一个特定函数或者通过使用某些宏定义声明结构:
#include <linux/interrupt.h> |
tasklet 的特点:
(1)一个 tasklet 能够被禁止并且之后被重新使能; 它不会执行,直到它被使能与被禁止相同的的次数;
(2)如同定时器, 一个 tasklet 可以注册它自己;
(3)一个 tasklet 能被调度来执行以正常的优先级或者高优先级;
(4) 如果系统不在重负载下,taslet 可能立刻运行, 但是从不会晚于下一个时钟嘀哒;
(5)一个 tasklet 可能和其他 tasklet 并发, 但是它自己是严格地串行的 ,且tasklet 从不同时运行在不同处理器上,通常在调度它的同一个 CPU 上运行。
当然,这个机制在实时性要求很高的USB的ISO传输(1ms一次中断)的背景下,会造成图片数据的少许延时,是否应该可以考虑使用void tasklet_hi_schedule(struct tasklet_struct *t),按照上述的描述,可能效果有限,毕竟这个1ms一次的中断是很频繁的。