本模块主要介绍软件中断(SWI);软件中断通过调用SYS/BIOS中断API接口函数如Swi_post()来触发中断程序。SWI优先级高于任务,低于HWI。
同以下API函数可以触发或者发起一个SWI:
- Swi_andn():当触发器值变为0时,发出(post)一个Swi对象
- Swi_dec():当触发器值变为0时,发出(post)一个Swi对象
- Swi_inc():在发出一个Swi对象时,Swi触发器值增加一
- Swi_or():根据作为参数传递的一个掩码设置触发变量相应的位
- Swi_post():发布一个Swi,并且不修改Swi对象触发变量的值
当程序调用以上中的一个函数时,SWI管理器会规划相应的SWI函数执行。
创建SWI可以动态或者静态创建SWI
动态创建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实例的参数。eb为错误块,通过它处理在执行Swi对象创建时发生的错误。
静态创建Swi对象在cfg文件中:
var Swi = xdc.useModule('ti.sysbios.knl.Swi');
var swiParams = new Swi.Params();
program.global.swi0 = Swi.create(swiParams);
SWI的中断优先级共计16个,最低优先级为0,最高优先级为15。
Swi钩子函数:
typedef struct Swi_HookSet {
Void (*registerFxn)(Int); /* Register Hook */
Void (*createFxn)(Handle, Error.Block *); /* Create Hook */
Void (*readyFxn)(Handle); /* Ready Hook */
Void (*beginFxn)(Handle); /* Begin Hook */
Void (*endFxn)(Handle); /* End Hook */
Void (*deleteFxn)(Handle); /* Delete Hook */
};
- registerFxn:寄存器函数,任何静态创建的Swi在运行时被初始化前调用的一个函数,在main函数之前,中断使能前,该函数被调用。
- createFxn:当一个Swi被创建,包括静态或者动态创建时调用的一个函数。
- readyFxn:任何Swi准备运行时调用的一个函数。
- beginFxn:正要运行一个Swi函数前调用的一个函数。
- endFxn:刚刚从一个Swi函数返回之后调用的一个函数。
- deleteFxn:在一个Swi运行时被Swi_delete删除后调用的一个函数。
例子:
/* ======== SwiHookExample.c ========
* This example demonstrates basic Swi hook usage */
#include <xdc/std.h>
#include <xdc/runtime/Error.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/Timestamp.h>
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/hal/Timer.h>
#include <ti/sysbios/knl/Swi.h>
Swi_Handle mySwi;
Int myHookSetId1, myHookSetId2;
/* HookSet 1 functions */
/* ======== myRegister1 ========
* invoked during Swi module startup before main
* for each HookSet */
Void myRegister1(Int hookSetId)//由registerFxn创建,在main之前被调用
{
System_printf("myRegister1: assigned hookSet Id = %d\n", hookSetId);
myHookSetId1 = hookSetId;
}
/* ======== myCreate1 ========
* invoked during Swi_create for dynamically created Swis */
Void myCreate1(Swi_Handle swi, Error_Block *eb)//由createFxn创建,创建swi的时候被调用
{
Ptr pEnv;
pEnv = Swi_getHookContext(swi, myHookSetId1);
/* pEnv should be 0 at this point. If not, there's a bug. */
System_printf("myCreate1: pEnv = 0x%x, time = %d\n", pEnv, Timestamp_get32());
Swi_setHookContext(swi, myHookSetId1, (Ptr)0xdead1);
}
//* ======== myReady1 ========
/* invoked when Swi is posted */
Void myReady1(Swi_Handle swi)//当swi准备运行时执行,由readyFxn创建
{
Ptr pEnv;
pEnv = Swi_getHookContext(swi, myHookSetId1);
System_printf("myReady1: pEnv = 0x%x, time = %d\n", pEnv, Timestamp_get32());
Swi_setHookContext(swi, myHookSetId1, (Ptr)0xbeef1);
}
/* ======== myBegin1 ========
* invoked just before Swi func is run */
Void myBegin1(Swi_Handle swi)//由myBegin1创建
{
Ptr pEnv;
pEnv = Swi_getHookContext(swi, myHookSetId1);
System_printf("myBegin1: pEnv = 0x%x, time = %d\n", pEnv, Timestamp_get32());
Swi_setHookContext(swi, myHookSetId1, (Ptr)0xfeeb1);
}
/* ======== myEnd1 ========
* invoked after Swi func returns */
Void myEnd1(Swi_Handle swi)//endFxn创建
{
Ptr pEnv;
pEnv = Swi_getHookContext(swi, myHookSetId1);
System_printf("myEnd1: pEnv = 0x%x, time = %d\n", pEnv, Timestamp_get32());
Swi_setHookContext(swi, myHookSetId1, (Ptr)0xc0de1);
}
/* ======== myDelete1 ========
* invoked upon Swi deletion */
Void myDelete1(Swi_Handle swi)//由deleteFxn创建
{
Ptr pEnv;
pEnv = Swi_getHookContext(swi, myHookSetId1);
System_printf("myDelete1: pEnv = 0x%x, time = %d\n", pEnv, Timestamp_get32());
}
/* HookSet 2 functions */
/* ======== myRegister2 ========
* invoked during Swi module startup before main
* for each HookSet */
Void myRegister2(Int hookSetId)
{
System_printf("myRegister2: assigned hookSet Id = %d\n", hookSetId);
myHookSetId2 = hookSetId;
}
/* ======== myCreate2 ========
* invoked during Swi_create for dynamically created Swis */
Void myCreate2(Swi_Handle swi, Error_Block *eb)
{
Ptr pEnv;
pEnv = Swi_getHookContext(swi, myHookSetId2);
/* pEnv should be 0 at this point. If not, there's a bug. */
System_printf("myCreate2: pEnv = 0x%x, time = %d\n", pEnv, Timestamp_get32());
Swi_setHookContext(swi, myHookSetId2, (Ptr)0xdead2);
}
/* ======== myReady2 ========
* invoked when Swi is posted */
Void myReady2(Swi_Handle swi)
{
Ptr pEnv;
pEnv = Swi_getHookContext(swi, myHookSetId2);
System_printf("myReady2: pEnv = 0x%x, time = %d\n", pEnv, Timestamp_get32());
Swi_setHookContext(swi, myHookSetId2, (Ptr)0xbeef2);
}
/* ======== myBegin2 ========
* invoked just before Swi func is run */
Void myBegin2(Swi_Handle swi)
{
Ptr pEnv;
pEnv = Swi_getHookContext(swi, myHookSetId2);
System_printf("myBegin2: pEnv = 0x%x, time = %d\n", pEnv, Timestamp_get32());
Swi_setHookContext(swi, myHookSetId2, (Ptr)0xfeeb2);
}
/* ======== myEnd2 ========
* invoked after Swi func returns */
Void myEnd2(Swi_Handle swi)
{
Ptr pEnv;
pEnv = Swi_getHookContext(swi, myHookSetId2);
System_printf("myEnd2: pEnv = 0x%x, time = %d\n", pEnv, Timestamp_get32());
Swi_setHookContext(swi, myHookSetId2, (Ptr)0xc0de2);
}
/* ======== myDelete2 ========
* invoked upon Swi deletion */
Void myDelete2(Swi_Handle swi)
{
Ptr pEnv;
pEnv = Swi_getHookContext(swi, myHookSetId2);
System_printf("myDelete2: pEnv = 0x%x, time = %d\n", pEnv, Timestamp_get32());
}
/* ======== mySwiFunc ======== */
Void mySwiFunc(UArg arg0, UArg arg1)
{
System_printf("Entering mySwi.\n");//swi函数。即软件中断处理函数
}
/* ======== myTaskFunc ======== */
Void myTaskFunc(UArg arg0, UArg arg1)
{
System_printf("Entering myTask.\n");//在此之前没有中断触发因此执行任务函数
System_printf("Posting mySwi.\n");
Swi_post(mySwi); //启动软件中断
System_printf("Deleting mySwi.\n");
Swi_delete(&mySwi); //删除swi
System_printf("myTask exiting ...\n");
}
/* ======== myIdleFunc ======== */
Void myIdleFunc()
{
System_printf("Entering myIdleFunc().\n");//空闲函数,在所有中断完成后才执行
System_exit(0);
}
/* ======== main ======== */
Int main(Int argc, Char* argv[])
{
Error_Block eb;
Error_init(&eb);
System_printf("Starting SwiHookExample...\n");//main之前执行registerFxn
/* Create mySwi with default params
* to exercise Swi Hook Functions */
mySwi = Swi_create(mySwiFunc, NULL, &eb);//创建swi对象
if (mySwi == NULL) {
System_abort("Swi create failed");
}
BIOS_start();
return (0);
}
CFG配置文件:
/* pull in Timestamp to print time in hook functions */
xdc.useModule('xdc.runtime.Timestamp');
/* Disable Clock so that ours is the only Swi in the application */
var BIOS = xdc.useModule('ti.sysbios.BIOS');
BIOS.clockEnabled = false;
var Idle = xdc.useModule('ti.sysbios.knl.Idle');
Idle.addFunc('&myIdleFunc');
/* Create myTask with default task params */
var Task = xdc.useModule('ti.sysbios.knl.Task');
var taskParams = new Task.Params();
Program.global.myTask = Task.create('&myTaskFunc', taskParams);
/* Define and add two Swi Hook Sets */
var Swi = xdc.useModule("ti.sysbios.knl.Swi");
/* Hook Set 1 */
Swi.addHookSet({
registerFxn: '&myRegister1', //寄存器钩子函数,在main函数前,中断使能前被调用
createFxn: '&myCreate1',
readyFxn: '&myReady1', //当post一个swi后,任何SWI准备运行时调用的函数
beginFxn: '&myBegin1', //在正要运行一个swi函数前调用
endFxn: '&myEnd1', //执行完swi创建的函数后执行该函数
deleteFxn: '&myDelete1' //执行完swi_delete后执行
});
/* Hook Set 2 */
Swi.addHookSet({
registerFxn: '&myRegister2',
createFxn: '&myCreate2',
readyFxn: '&myReady2',
beginFxn: '&myBegin2',
endFxn: '&myEnd2',
deleteFxn: '&myDelete2'
});
运行结果:
结果分析:
- 程序启动后,首先执行registerFxn创建的myRegister1和myRegister2函数,ID分别为1,2。
- 接着执行main函数中的System_printf函数。
- 执行Swi_create函数,创建myswi对象。执行由createFxn创建的myCreate1和myCreate2函数。createFxn创建的函数是在创建swi对象前被调用,执行后才会执行Swi_create(mySwiFunc, NULL, &eb)中的mySwiFunc函数。
- 此时没有发布SWI,因此执行较低优先级的任务函数,由Task.create创建的myTaskFunc函数中断内容。
- myTaskFunc函数中通过Swi_post(mySwi)发布了一个swi中断,便执行由readyFxn创建的myReady1和myReady2函数。该函数是在发布了swi后,当swi准备执行时所运行的函数。
- 在执行完readyFxn创建后的函数后,执行由beginFxn创建的myBegin1和myBegin2函数。
- 这里正式执行swi软件中断函数,即swi中断处理函数是在beginFxn后执行。
- 中断处理函数执行完后,执行由endFxn创建的myEnd1和myEnd2函数。该函数是在执行完swi创建的中断函数后执行。
- 返回myTaskFunc中继续执行System_printf("Deleting mySwi.\n")。
- 在myTaskFunc中执行Swi_delete(&mySwi);执行后执行由deleteFxn创建的myDelete1和myDelete2函数。
- 返回myTaskFunc中继续执行System_printf("myTask exiting ...\n")。
- 所有中断执行完后,执行空闲进程中断的函数即myIdleFunc。