如转发,请标明出处!
编写ISR最基本的原则就是:尽可能短。代码少是一方面,更重要的是ISR里不能调用可能阻塞或延迟的操作。
因为ISR不在常规任务上下文中运行,并且没有TCB,而是所有ISR共享一个栈(ISR_STACK_SIZE)。因此,ISR不能调用可能阻塞的函数。例如,它们不能申请信号量,因为信号量不可用时,内核会尝试将申请者切换到阻塞状态;不过,ISR可以释放信号量。另外,内存机制malloc()和free()会使用信号量,所以ISR里也不能调用这些函数,以及任何Create或Delete机制。ISR也不能通过VxWorks驱动程序执行I/O操作。尽管在I/O系统中没有固定的限制,但大多数设备驱动程序需要任务上下文,因为它们可能会等待设备的反馈。一个重要的例外是VxWorks的管道机制(Pipe),ISR可以使用Pipe进行写操作。ISR还可以调用VxWorks的一些机制来将消息打印到系统控制台:logMsg()、kprintf()和kputs()。
ISR不能调用使用浮点协处理器的机制。这是因为在VxWorks中,由intConnect()创建的中断驱动程序代码不保存和恢复浮点寄存器。如果ISR必须要使用浮点指令,则需要使用fppArchLib中的函数显式保存和还原浮点协处理器的寄存器。
ISR中调用C++语句时要特别小心。intConnect()机制要求在发生中断时执行函数的地址,但不能使用非静态成员函数的地址,因此必须实现静态成员函数。而且不能在ISR代码中实例化或删除对象。ISR中执行的C++代码应该限制为嵌入式C++,不应使用exception或RTTI (Run-Time Type Identification)。
ISR不应该直接访问共享数据区(shared data region)。ISR继承它抢占的任务的内存上下文,如果该任务没有映射该共享数据区,则它无法访问该内存,并导致异常。为了可靠地访问共享数据区,ISR可以将相关操作交给映射了该共享数据区的任务。
那么ISR中可以调用哪些机制或函数呢
bLib | 所有函数 |
---|---|
errnoLib | errnoGet(), errnoSet() |
eventLib | eventSend() |
fppArchLib | fppSave(), fppRestore() |
intLib | intContext(), intCount(), intVecSet(), intVecGet() |
intArchLib | intLock(), intUnlock() |
logLib | logMsg() |
lstLib | 除lstFree(),所有函数 |
mathALib | 使用fppSave()/fppRestore()时,所有函数 |
msgQLib | msgQSend() |
rngLib | 除rngCreate()/rngDelete(),所有函数 |
pipeDrv | write() |
selectLib | selWakeup(), selWakeupAll() |
semLib | semFlush(),非互斥信号量的semGive() |
semPxLib | sem_post() |
sigLib | kill() |
taskLib | taskSuspend(), taskResume(), taskPrioritySet(), taskPriorityGet(), taskIdVerify(), taskIdDefault(), taskIsReady(), taskIsSuspended(), taskIsPended(), taskIsDelayed(), taskTcb() |
tickLib | tickAnnounce(), tickSet(), tickGet() |
tyLib | tyIRd(), tyITx() |
vxLib | vxTas(), vxMemProbe() |
wdLib | wdStart(), wdCancel() |
中断到任务的通信机制
这正是:
ISR,限制多,尽快执行别阻塞。
诸多机制仍可用,任务通信不耽搁。
我是泰山,专注VX 15年!
一起学习,共同进步!