DSP

SYs_BIOS swi中断

2019-07-13 15:19发布

一、SWI模块概述
        在SYS/BIOS内核中,系统管理并运行的线程分为四个等级:硬件中断服务程序、软件中断服务程序、任务和后台空闲函数,优先级依次降低。每个软件中断服务程序都对应一个函数,当然,每个软件中断也可以单独设置优先级。高优先级的软件中断会抢占正在执行的低优先级的软件中断          
        所有软件中断都是通过SYS/BIOS内核的API调用来启动。一旦启动了一个SWI对象,此时,系统将为该SWI对象中的函数创建一个运行时间表。因此,当一个软件中断被启动后,其对象函数不一定会立即执行,而是会按照时间表在执行队列中根据优先级排队等候运行。DSP/BIOS根据软件中断优先级来判断是否要暂停当前运行的线程。
        中断线程(包括硬件中断和软件中断)都是使用相同的堆栈来执行的。当中断发生时,新的线程就会添加到栈顶,系统会执行一次任务切换(Context Switch)。由于高优先级软件中断会打断低优先级的软件中断的运行,所以SWI模块在运行高优先级软件中断前会自动保存寄存器中的内容。在高优先级软件中断运行完成后,寄存器会恢复原来的内容,以便继续运行原来的低优先级中断。如果没有启动其他高优先级的软件中断,低优先级的软件中断就会运行。SYS/BIOS内核虽然具有抢占的特点,但如果没有导致任务切换的API函数调用,系统则不会主动切换道其他线程去执行的。(理解这点在实际应用中很重要,即如果现在运行的是低优先级软中断对应的函数,如果你不在函数中调用如SWI_post()启动更高优先级的软件中断或启动了比自身低的优先级中断,则当前软中断就不会被打断,执行直到退出)。
      个人经验:尽量不要在一个软中断对应的函数中去启动另一个比其本身优先级高的软件中断,因为根据抢占原则,其本身将被打断,从而CPU转去执行高优先级软中断对应的函数,低优先级的实时性将得不到保证,当有多级优先级及系统复杂情况下甚至引起系统瘫痪。也不要设置很多的优先级。当然这也不是绝对的,如果系统规划的好,利用好软中断的基于优先级抢占式的特点会大大简化你的设计。

二、SWI的执行
     通过调用SWI_andn,SWI_sec,SWI_inc,SWI_or,SWI_post可以使软件中断被调度执行。这些函数本身可以在程序的任何地方调用------中断服务程序ISR中,周期函数中,空闲函数中或其他软件中断函数中。
     当一个SWI对象被触发时,SWI管理器将该软件中断添加到一个被触发软件中断的列表中等待,然后SWI管理器检查软件中断当前是否被使能。如果使能,SWI管理器将该SWI对象的优先级和当前运行线程的优先级进行比较。若当前运行线程是后台空闲循环IDL或是一个更低优先级的SWI,那么SWI管理器将这个SWI对象从被触发SWI对象列表中移除,并将CPU控制权从当前线程交给SWI对象,开始执行SWI函数。
       Note:1.当一个SWI开始执行后,必须无阻塞地运行到结束;
              2.当在HWI中调用时,调用任何会触发软件中断的SWI函数的代码必须包装在一个HWI_enter/HWI_exit宏调用中,或者由HWI调度程序调用;
               3.如果一个软件中断在SWI管理器将其从被触发SWI对象列表中移除之前,被触发多次,其SWI函数只会执行一次。这个类似硬件中断的特征:即在CPU清除中断标志寄存器中相应的中断标志为之前,如果该硬件中断触发多次,对应的HWI只会执行一次。

三、SWI对象的触发值
       每个SWI对象有一个触发值,可以决定是否触发该中断。用于触发SWI的API函数可以对触发值作不同的操作,并根据不同的限制条件触发SWI对象。其中SWI_post,SWI_or,SWI_inc无条件的触发。
       要访问一个SWI对象的触发值,可以在该SWI函数调用SWI_getTrigger,这个函数只能在SWI函数中调用,其返回值是该SWI对象从被触发SWI对象队列中移除之前的触发值大小。当SWI管理器从被触发对象列表中移除一个SWI对象时,其触发值被复位为其初始值。如果在SWI函数执行的时候该SWI对象又一次被触发,其触发值也会被相应的更新,然而这些都不会影响SWI函数执行时调用SWI_getTrigger返回的值,该值在SWI对象被从被触发SWI队列中移除那一刻锁存起来。

       1.SWI_inc:一个SWI对象在被移除队列之前,如果被多次触发。一般情况下,SWI管理器只会调度其函数执行一次,然而,如果应用程序需要该SWI函数在这种情况下执行多次,可以利用SWI_inc来触发该SWI对象。如果使用SWI_inc触发一个SWI对象,一旦SWI管理器调用并执行对应的SWI函数,就可以在函数中访问该对象的触发值,获知SWI在运行之前被触发了几次,然后可以将相同的一段程序执行同样的次数来满足应用程序的需求。

       2.SWI_andn:如果一个软件中断必须在多个事件都发生的条件下才能被触发,应该使用SWI_andn。例如一个软家中断在执行之前必须等待两个不同设备的输入数据,其邮箱应该配置有两个被置1的比特位。

      3.SWI_or:在某些情况下,SWI函数需要根据触发事件的不同来调用不同的函数,这是可以用SWI_or。

      4.SWI_dec:如果应用程序需要同一个事件必须发生多次之后才触发一个SWI,可以使用SWI_dec。