先上代碼:
/* XDC module Headers */
#include <xdc/std.h>
#include <xdc/runtime/System.h>
/* BIOS module Headers */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Swi.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Semaphore.h>
/* Example/Board Header files */
#include "Board.h"
#define TASKSTACKSIZE 512
Task_Struct task0Struct;
Char task0Stack[TASKSTACKSIZE];
Swi_Struct swi0Struct, swi1Struct;
Swi_Handle swi0Handle, swi1Handle;
Clock_Struct clk0Struct;
Semaphore_Struct sem0Struct;
Semaphore_Handle sem0Handle;
/*
* ======== swi0Fxn =======
*/
Void swi0Fxn(UArg arg0, UArg arg1)
{
System_printf("Enter swi0Fxn, a0 = %d, a1 = %d\n", (Int)arg0, (Int)arg1);
System_printf("swi0 trigger = %d\n", Swi_getTrigger());
System_printf("swi0 pri = %d\n", Swi_getPri(swi0Handle));
System_printf("Exit swi0Fxn\n");
}
/*
* ======== swi1Fxn =======
*/
Void swi1Fxn(UArg arg0, UArg arg1)
{
System_printf("Enter swi1Fxn, a0 = %d, a1 = %d\n", (Int)arg0, (Int)arg1);
System_printf("swi1 trigger = %d\n", Swi_getTrigger());
System_printf("swi1 pri = %d\n", Swi_getPri(swi1Handle));
System_printf("Exit swi1Fxn\n");
}
/*
* ======== clk0Fxn =======
*/
Void clk0Fxn(UArg arg0)
{
Swi_post(swi0Handle);
Swi_post(swi1Handle);
Semaphore_post(sem0Handle);
}
/*
* ======== task0Fxn =======
*/
Void task0Fxn(UArg arg0, UArg arg1)
{
UInt key;
/* wait for swis to be posted from Clock function */
Semaphore_pend(sem0Handle, BIOS_WAIT_FOREVER);
System_printf("Running tsk0Fxn\n");
key = Swi_disable(); /* swis are disabled */
Swi_inc(swi0Handle); /* swi0 trigger = 1 */
Swi_inc(swi0Handle); /* swi0 trigger = 2 */
Swi_restore(key); /* swi0 runs */
Swi_or(swi1Handle, 0x100); /* swi1 runs with trigger = 0x103 */
Swi_andn(swi1Handle, 0x1); /* swi1 trigger = 0x02 */
Swi_andn(swi1Handle, 0x2); /* swi1 runs with trigger = 0x00 */
Swi_dec(swi1Handle); /* swi1 trigger = 2 */
Swi_dec(swi1Handle); /* swi1 trigger = 1 */
Swi_dec(swi1Handle); /* swi1 runs with trigger = 0 */
System_printf("Calling BIOS_exit\n");
BIOS_exit(0);
}
/*
* ======== main ========
*/
Int main()
{
/* Construct BIOS objects */
Task_Params taskParams;
Swi_Params swiParams;
Semaphore_Params semParams;
Clock_Params clkParams;
/* Call board init functions */
Board_initGeneral();
Task_Params_init(&taskParams);
taskParams.stackSize = TASKSTACKSIZE;
taskParams.priority = 1;
taskParams.stack = &task0Stack;
Task_construct(&task0Struct, (Task_FuncPtr)task0Fxn, &taskParams, NULL);
Swi_Params_init(&swiParams);
swiParams.arg0 = 1;
swiParams.arg1 = 0;
swiParams.priority = 2;
swiParams.trigger = 0;
Swi_construct(&swi0Struct, (Swi_FuncPtr)swi0Fxn, &swiParams, NULL);
swi0Handle = Swi_handle(&swi0Struct);
swiParams.arg0 = 2;
swiParams.arg1 = 0;
swiParams.priority = 1;
swiParams.trigger = 3;
Swi_construct(&swi1Struct, (Swi_FuncPtr)swi1Fxn, &swiParams, NULL);
swi1Handle = Swi_handle(&swi1Struct);
/* Construct a Semaphore object to be used as a resource lock, inital count 0 */
Semaphore_Params_init(&semParams);
Semaphore_construct(&sem0Struct, 0, &semParams);
/* Obtain instance handle */
sem0Handle = Semaphore_handle(&sem0Struct);
Clock_Params_init(&clkParams);
clkParams.startFlag = TRUE;
/* Construct a periodic Clock Instance with period = 2 system time units */
Clock_construct(&clk0Struct, (Clock_FuncPtr)clk0Fxn,
2, &clkParams);
BIOS_start(); /* Does not return */
return(0);
}
運行結果:
Enter swi0Fxn, a0 = 1, a1 = 0
swi0 trigger = 0
swi0 pri = 2
Exit swi0Fxn
Enter swi1Fxn, a0 = 2, a1 = 0
swi1 trigger = 3
swi1 pri = 1
Exit swi1Fxn
Running tsk0Fxn
Enter swi0Fxn, a0 = 1, a1 = 0
swi0 trigger = 2
swi0 pri = 2
Exit swi0Fxn
Enter swi1Fxn, a0 = 2, a1 = 0
swi1 trigger = 259
swi1 pri = 1
Exit swi1Fxn
Enter swi1Fxn, a0 = 2, a1 = 0
swi1 trigger = 0
swi1 pri = 1
Exit swi1Fxn
Enter swi1Fxn, a0 = 2, a1 = 0
swi1 trigger = 0
swi1 pri = 1
Exit swi1Fxn
Calling BIOS_exit
- 程序運行,最先被執行的是clk0Fxn,它提交了兩個swi,併發送一個信號量給task0Fxn。由於Clock是最高優先級的Swi,所以兩個Swi和一個task只是被提交到Post列表等待執行。
- 接下來由於swi0的優先級更高,所以先執行它,然後執行swi1。這裏需要注意,Swi_post是無條件提交swi到post列表,跟trigger沒任何關係,也不會更改trigger的值。
- 接下來執行task0Fxn的Semaphore_pend之後的內容。
key = Swi_disable(); /* swis are disabled */
Swi_inc(swi0Handle); /* swi0 trigger = 1 */
Swi_inc(swi0Handle); /* swi0 trigger = 2 */
Swi_restore(key); /* swi0 runs */
這裏先關閉了Swi,然後調用兩次Swi_inc,從而將swi0的trigger值由1增加至2。本來Swi_inc會導致swi被提交,但由於關閉了Swi,所以swi0不會運行,直到最後一句Swi_restore使得swi重新執行後,swi0被執行。
- 接下來執行了以下語句:
Swi_or(swi1Handle, 0x100);
首先swi1的trigger會變爲0x103(參數0x100跟trigger原值0x003進行或運算得出的結果)。然後swi執行(Swi_or無條件提交swi),執行完後加上去的0x100會被摳掉,trigger又變回0x03。
- 接下來執行了以下語句:
Swi_andn(swi1Handle, 0x1); /* swi1 trigger = 0x02 */
Swi_andn(swi1Handle, 0x2); /* swi1 runs with trigger = 0x00 */
第一句的參數0x01會把trigger值0x03變成0x02(兩值進行異或操作),不提交swi。
第一句的參數0x02會把trigger值0x02變成0x00(兩值進行異或操作),對於Swi_andn來說,如果trigger變0則提交swi,使得swi1被執行。
注意:swi提交完後,trigger會恢復原值0x03,這一點請參考之前日誌中有關Swi_andn那一段。
- 最後執行了以下語句:
Swi_dec(swi1Handle); /* swi1 trigger = 2 */
Swi_dec(swi1Handle); /* swi1 trigger = 1 */
Swi_dec(swi1Handle); /* swi1 runs with trigger = 0 */
最後來個總結吧:每一句都是trigger值減1,當減到0時,swi1被提交併運行。注意:swi提交完後,trigger會恢復原值0x03,請參考之前日誌。