DSP

纯新手DSP编程--5.30--DSP/BIOS线程

2019-07-13 09:33发布

DSP/BIOS中的线程和电脑中的线程有很大区别。关于DSP/BIOS的详细介绍请参考TMS320 DSP/BIOS User's Guide。下面简单地介绍一下DSP/BIOS的线程。 在DSP/BIOS中采用广义的定义,即DSP执行的所有独立的指令流。一个线程是一个单独的控制点,它可能包含一个子程序,一个宏或者一个函数调用。
为了让DSP能够同时处理多个任务,DSP/BIOS提供了如下几种类型的线程。
HWI(硬件中断),SWI(软件中断),TSK(任务),IDL(空闲线程)。 优先级等级数:HWI(有具体DSP型号决定) >SWI(15个,其中PRD周期函数的优先级与PRD_swi软件中断对象的优先级一致,TSK任务调度软件中断优先级最低)  > TSK(16) > idl(只有一个优先级)   HWI 其实就是中断服务。当硬件中断产生之后,DSP/BIOS就会调用相应的HWI函数。如果把HWI设置为Dispatch的话,则会在调用HWI函数的前 后自动调用HWI_enter和HWI_exit。在HWI函数的执行时,若有其他的硬件中断产生,当前的HWI会被新的中断抢占,也就是说DSP会先去 执行新的HWI。如果希望当前的HWI在不被其他的HWI打断的话,可以在不能被打断的代码前后调用HWI_disable和HWI_enable。 HWI的优先级是硬件级别的优先级(固定的),若同时有多个中断向DSP请求的话,它决定DSP先响应哪个中断。而中断所对应的HWI则是可以被任何其他 的HWI抢占。
SWI有15级优先级,高优先级的SWI可以抢占低优先级的SWI。一般通过SWI_post(或者类似的函数)来启动它。SWI和HWI一样都是不能被阻塞(blocking)的线程。也就是说一旦它们被运行,就要运行到终点为止,除非被其它的线程抢占。TSK可以中断自己的执行,IDL,不应该组撒,会阻止PC主机获取DSP目标系统的信息。   HWI和SWI都使用系统堆栈,而每个TSK都有自己的堆栈。可以在TSK线程之间随意地互相切换,切换时DSP/BIOS将自动地更新堆栈寄存器,因此TSK线程可以被阻塞。这样TSK就可以写成一个死循环: While(1){
   Do_some_task();
   Yield_to_other_task();
} Do_some_task 做这个TSK所要做的事情,Yield_to_other_task则把控制权转给其他的TSK。例如如果是把控制权转给同样优先级的其他TSK,则可以 调用TSK_yield函数。如果是要把控制权转给低优先级的TSK,则可以调用TSK_sleep函数让自己休眠一段时间,或者调用SEM_pend函 数等待。除非TSK中调用了HWI_disable或者SWI_disable,否则它在任何时候都可以被HWI或者SWI抢占。
TSK和电脑上的线程有些类似,而HWI和SWI则不一样。下面举一个例子说明一下:假设有线程SWI1,SWI2,TSK1,TSK2。SWI1的优先级大于SWI2,TSK1的优先级大于TSK2。
则:
若 在SWI2运行当中,SWI1被post了的话,DSP马上转到SWI1运行,并且直到SWI1运行结束之后再继续SWI2的运行。这就是说SWI只能被 抢占,不能被阻塞。这是因为所有的SWI和HWI都公用系统堆栈,一旦SWI1运行,堆栈的最上层就变成了SWI1的环境,除非SWI1运行结束,是无法 切换回到SWI2的环境中去的。 若在TSK2运行当中,TSK1进入ready状态的话,DSP马上转到TSK1运行。稍后如果TSK1被阻塞的 话,DSP再继续TSK2运行,当TSK1所等待的信号就绪之后,再转入TSK1运行,如此反复。也就是说DSP可以在TSK之间相互切换。这正是因为每 个TSK都有自己独立的堆栈可以保存自己的运行环境。   线程选择的一些原则: 1 严格的实时性  如果线程的执行需要严格的实时性,而线程执行需要的时间又很少时,可以使用硬件中断或者时钟函数来完成,CLK时钟函数也是在硬件中断中执行的。 因为硬件中断具有很短的处理时间间隔,同时,具有极小的中断潜伏期。所谓中断潜伏期,就是指从中断处罚到中断服务子程序的第一条指令开始执行之间的时间。它越小,则表示响应时间越及时。  由于其他低优先级的中断要在硬件中断执行结束后执行,所以HWI函数应尽量很小,另外,在DSP响应硬件中断后自动屏蔽所有中断,因此可以通过设置调用HWI_enter的参数开放一些中断,允许这些中断抢先执行。 2 部分实时性   通用做法是,增加SWI中断或者TSK任务线程来完成一些非实时性的处理任务,而严格要求实时性的处理有HWI中断完成,这样没有减少中断潜伏期,提高响应实时性请求的能力。   这些SWI或TSK有两个特点:  能完成实时处理任务,但允许处理时间相对较长  允许被其他线程抢占  到底选取SWI还是TSK,根据情况判断 选TSK的情况: 处理函数需要等待某些资源(例如数据,上位机的信号等),以便继续运行 处理函数与其他线程之间有复杂的联系或数据共享 希望处理函数有自己的堆栈,还不是系统共用的堆栈 处理函数中用到CLK,MBX或SEM这几个内核模块 希望在线程创建,删除,退出,切换就绪时调用钩子函数 上面任何一个存在,建议TSK,相反,当没有上面的一种情况,选SWI TSK和SWI区别: TSK可以被阻塞,SWI不行 TSK具有通信和同步的数据结构,包括邮箱,锁,旗语。SWI没有 TSK拥有自己的堆栈,SWI共用系统堆栈。因此SWI使用更少的存储器 TSK可以调用钩子函数   SWI适合处理一些发送速率较低的任务,或者对实时性要求不苛刻的任务,它往往伴随着HWI产生而触发。它通常帮助HWI中断函数将一些非严格实时性的处理放到低优先级的线程中,以减少HWI的响应时间。   3 周期性服务   周期性地或在固定的时间间隔内完成处理任务,建议使用DSP/BIOS内核提供的PRD周期函数完成。  所有的周期函数具有同样的SWI优先级,因此不能抢先。为了保证所有PRD函数的正常执行,除了尽量减少周期函数本身的处理时间外,还需要提高整个PRD周期函数的优先级去。 4 不需要实时性   只需要在后台进行一些无关紧要的处理,如收集统计数据等等,建议IDL线程。