软件中断仿照I硬件ISRs。SYS/BIOS的Swi模块提供了软件中断的能力。软件中断通过调用SYS/BIOS的API(诸如Swi_post())来以程序的方式触发软件中断。软件中断的优先级高于tasks,但低于硬件中断。请参考 video introducing Swis进行一个概览。
注意:不应将Swi模块跟现存于很多处理器的SWI指令混淆。SYS/BIOS Swi 模块独立于任意指定目标/设备的软件中断功能。
软件中断适合于处理那些相对于Hwis触发速率更慢或者实时期限不太严格的应用任务。 可通过以下SYS/BIOS APIs来触发或提交一个Swi:
- Swi_andn()
- Swi_dec()
- Swi_inc()
- Swi_or()
- Swi_post()
Swi管理器控制着所有Swi函数的执行。当程序调用以上某个APIs时,Swi管理器安排指定Swi所对应的函数运行。Swi管理器通过使用Swi对象来处理Swi函数。
如果提交了一个Swi,它只会在所有等待中的Hwis都完成之后才会运行。Swi函数在运行过程中可在任意时间被Hwi所抢占;Hwi会在Swi函数重新执行之前完成。另一方面,Swi函数总是抢占tasks。所有等待中的Swi都会在甚至是最高优先级的task被允许执行前运行。实际上,Swi更象比于所有普通tasks拥有更高优先权的task。
注意:谨记有关Swi函数的两件事:
一个Swi会运行至结束,除非它被Hwi中断或更高优先级的Swi抢占。
任何触发或提交Swi的硬件ISR都必须已经被Hwi调度器调用(对于不支持Hwi调度器的平台,由中断存根产生,如MSP430)。这意味着,Swi必须由Hwi对象所调用的函数触发。
3.5.1 创建Swi对象 和很多其它SYS/BIOS对象一样,你即可以通过调用Swi_create()动态地创建Swi对象,也可以在配置文件中静态创建Swi对象。动态创建的Swis在程序运行期间也可以被删除。
为在配置中添加一个新的Swi,可在配置脚本中创建一个新的Swi对象。为每个Swi配置function属性,当应用程序触发对象时,即可运行对应的函数。也可以为每个Swi函数配置两个参数。
对于所有带实例的模块,你可以决定Swi对象在哪个内存段分配。Swis被提交或安排执行时,由Swi管理器访问Swi对象。 关于完整的Swi API、配置和对象参考信息,请参照在线文档“ti.sysbios.knl”包的Swi模块。(运行在线帮助的相关信息,请参考1.6.1节,23页—Using the API Reference Help System)
动态创建一个Swi对象,使用如下语法进行调用:
Swi_Handle swi0; Swi_Params swiParams; Error_Block eb; Error_init(&eb); Swi_Params_init(&swiParams); swi0 = Swi_create(swiFunc, &swiParams, &eb); if (swi0 == NULL) { System_abort( “Swi create failed”); } |
其中,swi0是所创建的Swi对象句柄,swiFunc是Swi所关联函数的名称,swiParams是Swi_Params结构体,它包含了Swi实例参数(priority,arg0,arg1等等)。如果传递的是NULL而不是实际的Swi_Params结构体指针,则使用默认的参数集。“eb”是一个错误块,你可以通过它处理Swi对象创建期间所发生的错误。
注意:Swi_create()不能在Hwi或其它Swi线程上下文中调用。应用程序要动态创建Swi线程,必须从main()函数或Task线程上下文中创建。
在配置文件中创建Swi对象,使用如下语法:
var Swi = xdc.useModule( ‘ti.sysbios.knl.Swi’); var swiParams = new Swi.Params(); program.global.swi0 = Swi.create(swiParams); |
3.5.2 设置软件中断优先权 Swi的优先级分为不同级别。你可在内存限制所允许的范围内为每个优先级创建尽可能多的Swis。你可以为拥有更短实时期限线程的Swi选择一个更高的优先级(更大的优先级序 ),也可以为Swi分配一个更低的优先级,用于处理那些拥有不太关键执行期限的线程。
应用程序中Swi优先级分为32个等级。MSP430和C28x的优先级分为16个等级。默认优先级为16。最低优先级为0,因此最高优先级为15。 你无法对同一优先级的Swis进行排序,它们根据提交顺序依次运行。
3.5.3 软件中断优先权和系统栈尺寸 当提交了一个Swi,将会使用系统栈调用它相关的Swi函数。当你为某些目标设置了所有32个级别的Swi优先级,请记住在最坏的情况下,每个Swi优先级都可能变成一个嵌套的Swi调度函数(也就是说,最低优先级Swi被下一优先级抢占,转而下一优先级又被更高一级优先级抢占……)。这将增加每个在用的Swi优先级增加其栈尺寸需求。因此,就栈使用尺寸而言,给Swi分配相同优先级比分配不同优先级更具效率。
默认系统栈尺寸是4096字节。你可以在配置脚本中使用如下代码来设置系统栈尺寸:
Program.stack = yourStackSize; |
注意:Clock模块创建并使用最大优先级的Swi(也就是说,如果有16个Swi优先级,Clock Swi使用序 为15的优先级)。
下表显示了在最坏Swi中断嵌套情况下所需要的系统栈尺寸。第一列数字是某目标的首个优先级系统栈尺寸。第二列数字显示的是每个之后的优先级所使用的系统栈的尺寸。
如果Swis可用,Swi管理器会对比提交的Swi对象的优先权和当前运行线程的优先权。如果当前运行线程是后台Idle Loop、一个Task、或低优先级Swi,Swi管理器将从Swis posted列表删除Swi,将CPU控制权从当前线程切换至提交的Swi函数,并开始运行。
如果当前运行的线程是相同或更高优先级的Swi,Swi管理器会返回控制当前线程,所提交的线程直到之前提交的所有相同或更高优先级线程都执行完毕后才会执行。
当多个相同优先级的Swis被提交,它们会按照提交顺序依次执行。 关于Swi有两个重要的事情:
- 当Swi开始执行,它必须无阻塞地执行完毕。
- 当从硬件ISR中被调用,任何触发或提交Swi的函数的代码必须已经被Hwi调度器调用(对于不支持Hwi调度器的平台,由中断存根产生,如MSP430)。这意味着,Swi必须由Hwi对象所调用的函数触发。
Swi函数可被拥有更高优先级的线程所抢占(如Hwi或更高优先级的Swi)。然后Swi函数又不能被阻塞。你无法挂起一个Swi让它象一个设备一样处于准备状态。
如果Swi在Swi管理器将其从posted列表中删除之前提交过多次,它的Swi函数仅会执行一次。这很像Hwi,在CPU清除中断标志寄存器中相应的中断标志位前,如果Hwi被触发多次,最终它只会执行一次。(参考3.5.5节,获取更多关于如何处理Swi在执行前多次被提交的问题)
应用程序对相同优先权的Swi函数的执行顺序不应做任何假设,尽管Swi函数可安全地自行提交(或由其它中断提交)。如果超过一个Swi函数处于等待状态,所有的Swi函数都会在所有task运行前被调用。
3.5.5 使用Swi对象的触发器变量 每个Swi对象都拥有相关联的触发器变量,C6x目标为32bit触发器变量,C5x、C28x和MSP430目标为16bit触发器变量。它即可用于决定是否提交Swi,也可用于在Swi函数中提供可评估的值。
Swi_post()、Swi_or()、and Swi_inc() 用于无条件地提交Swi对象:
- 当Swi_post()用于提交Swi时,不会改变Swi对象触发器的值。
- Swi_or()设置由作为参数传递过来的掩码决定的触发器的标志位,然后提交Swi。
- Swi_inc()在提交Swi对象前将Swi的触发器值加1。
- Swi_andn()和Swidec()仅在Swi对象的触发器值变为0时提交它。
- Swi_andn()将作为参数传递过来的掩码决定的触发器的标志位清0。
- Swi_dec()将触发器值减1。
表3-6展示了这些函数之间的区别:
记住,任何阻塞的Task被允许运行前,都必须先完成Swi函数。
3.5.7 Swi函数 同步 在Idle、Task或Swi函数中,可以通过调用Swi_disable()来临时阻止更高优先级的Swi的抢占,这会禁止所有的Swi抢占。重新使能Swi抢占,调用Swi_restore()。Swis可作为一个组整体使能或禁用,单独的Swi无法自已使能或禁用。
当SYS/BIOS在第一个task被调用前完成初始化时,Swis已经被使能。如果应用程序希望禁用Swis,可调用Swi_disable():
key = Swi_disable(); |
相应地,使能函数为Swi_restore(),其中key值是由Swi模块使用,用于决定是否Swi_disable()已经被调用多次。
Swi_restore(key); |
允许嵌套调用Swi_disable() / Swi_restore() ,因为仅有最外层Swi_restore()才实际使能Swis。就是说,task可在不知道Swi_disable()是否已在别处被调用的情况下直接禁止或使能Swis。
当Swis被禁用,一个提交的Swi函数无法立即运行。当Swis可用,并且它的最高优先级线程正准备运行,则中断是锁定在软件中运行的。
使用Swi_delete()来删除一个动态创建的Swi,此时分配给Swi将会释放。Swi_delete()仅能在task中被调用。
3.5.8 Swi Hooks Swi模块支持以下Hook函数集:
- Register:在所静态创建Swis前被调用,用于在运行时进行初始化。register hook在main()前的中断使能前被调用。
- Create:在创建一个Swi时被调用。包括静态创建和使用Swi_create()进行动态创建。
- Ready:在任何Swi准备运行前调用。
- Begin:在运行一个Swi函数前调用。
- End:Swi函数返回前被调用。
- Delete:在运行时使用Swi_delete()删除一个Swi时调用。
下面的Swi_HookSet结构体类型囊括了Swi模块所支持的hook函数:
typedef struct Swi_HookSet { Void (*registerFxn)(Int); /* 声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!
软件英文术语缩写大全
上一篇
2016年11月10日
做软件项目经理需要具备的品质和素质
下一篇
2016年11月11日
|