基於TI-RTOS的CC2650DK開發(30)--- Swi官方示例

官方示例中有一個專門針對Swi的例子,它演示了Swi的幾種提交方法,基本針對Swi的幾種提交方法寫的程序,在讀此程序之前請先閱讀這篇日誌

先上代碼:

/* 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

下面我們來梳理下程序的運行過程:
本例程創建了兩個Swi,一個Task,一個Clock。
swi0:優先級爲2,trigger爲0
swi1:優先級爲1,trigger爲3

  • 程序運行,最先被執行的是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,請參考之前日誌。

最後來個總結吧:
Swi_Post:用於直接觸發一個函數的執行。
Swi_or:用於觸發多個函數的執行。
Swi_andn:用於多個不同事件發生後才觸發一個函數的執行。
Swi_dec:用於一個事件發生多次才能觸發一個函數的執行。
這總結,太精闢了,直擊要害啊!呵呵,慢慢體會。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章