SYS/BIOS簡介
創建一個SYS/BIOS項目
在項目模板中選擇SYS/BIOS項目中的Hello Example模板,點擊Next:
在RTSC(XDCtools的別稱)配置頁中選中需要的SYS/BIOS,XDCtools及其他組件的版本,Target保持默認,不需修改,如果Platform沒有自動填充,選擇與設備適用的平台。Build-profile決定程序鏈接的庫,推薦使用release,即使仍然處於創建和調試階段,點擊Finish完成創建項目。

SYS/BIOS的模塊與配置
SYS/BIOS可以用文本編輯器或者是圖像配置編輯器XGCONF來編輯,雙擊打開.cfg文件:
單擊System Overview,可以顯示程序當前使用的主模塊(帶綠色小箭頭的):
各種APIs模塊的添加這里有兩種方法,一種是直接雙擊主模板進入,然后勾選Add:
各個API模塊的作用
在項目中導入LOG模塊
LOG模塊實際上是一個實現打印信息的API。
添加LOG模塊,默認是自動添加的。
LOG模塊定義了許多比如Log_error、Log_info、Log_warning、Log_print等之類函數,這些函數的用法同printf函數的用法很相似,這些函數都可以在<xdc/runtime/Log.h>找到,其實際上是將printf的有用法分成許多不同的類(如錯誤信息、提示信息、警告信息等),LOG模塊打印的內容查看:
右下角會出現面板:
LOG中定義了許多如下的函數,比如Log_info1函數后面的數字代表函數接的變量數目,如:
Log_info1("%d",s1); Log_info2("%d, %d", s1, s2)
在項目中導入TSK任務模塊
TSK任務模塊是操作系統中最基本的模塊,其實際上反映了多線程搶占,每個任務單獨是一個線程,各個線程(任務)具有各自的優先級。
創建新任務,我們創建兩個任務task0、task1,分別對應其函數func_tsk0、func_tsk1。其優先級都為1:
編寫任務函數:
/* * ======== hello.c ======== * The hello example serves as a basic sanity check program for SYS/BIOS. It * demonstrates how to print the string "hello world" to stdout. */ #include <xdc/std.h> #include <xdc/runtime/System.h> #include <ti/sysbios/BIOS.h> #include <xdc/runtime/Log.h> #include <ti/sysbios/knl/Task.h>
/* * ======== main ======== */
void fun_task0(void); void fun_task1(void); Void main() { System_printf("hello world\n"); BIOS_start(); } void fun_task0(void) { Int count = 0; while(count<10) { Log_info1("Task0 is doing %d\n",count); Task_yield(); count++; } BIOS_exit(0); } void fun_task1(void) { Int count = 0; while(count<10) { Log_info1("Task1 is doing %d\n",count); Task_yield(); count++; } BIOS_exit(0); }

我們可以看到兩個任務是相互依次運行的,每個任務運行一次后,其優先級就會降低,此時就切換到下一個任務。
在項目中導入Swi軟件中斷模塊
不同任務有不同優先級,而軟件中斷具有比任何任務都高的優先級,而其中硬件中斷(HWI)又比軟件中斷(SWI)優先級更高。
添加軟件中斷Swi:
代碼:
/* * ======== hello.c ======== * The hello example serves as a basic sanity check program for SYS/BIOS. It * demonstrates how to print the string "hello world" to stdout. */ #include <xdc/std.h> #include <xdc/runtime/System.h> #include <ti/sysbios/BIOS.h> #include <xdc/runtime/Log.h> #include <ti/sysbios/knl/Task.h> #include <ti/sysbios/knl/Swi.h>
/* * ======== main ======== */
void fun_task0(void); void fun_task1(void); void func_swi0(void); Swi_Handle swi0; //聲明一個全局的SWI句柄
Void main() { System_printf("hello world\n"); //初始化SWI參數
Swi_Params swiParams; Swi_Params_init(&swiParams); swiParams.priority = 2; //軟件中斷優先級設置為2
swiParams.trigger = 2; //設置軟件中斷計數器
swi0 = Swi_create(func_swi0, &swiParams, NULL); //創建軟件中斷swi0,func_swi0為軟件中斷函數
BIOS_start(); } void func_swi0(void) { static Int count = 0; Log_info1("Swi0 is doing %d\n",count); count++; } /*更改軟件中斷計數器trigger,要觸發軟件中斷,首先需要讓trigger的計數為0, 這里我們可以在任務函數內增加一個trigger自減的函數,任務函數執行兩次后,將會觸發軟件中斷*/
void fun_task0(void) { Int count = 0; while(count<10) { Log_info1("Task0 is doing %d\n",count); Swi_dec(swi0); Task_yield(); count++; } BIOS_exit(0); } void fun_task1(void) { Int count = 0; while(count<10) { Log_info1("Task1 is doing %d\n",count); Swi_dec(swi0); Task_yield(); count++; } BIOS_exit(0); }
編譯調試,運行查看結果(這里我們只需要選擇單核運行就可以了):
可以看到兩個任務的每次都會使得軟件中斷計數trigger減1(通過Swi_dec函數),直到trigger的值減少到0時,執行軟件中斷,中斷后,trigger恢復到原來的值,這里的trigger初始值為2,所以執行兩次任務后就會觸發一次軟件中斷。
在項目中導入信號量Semaphore模塊

代碼:
/* * ======== hello.c ======== * The hello example serves as a basic sanity check program for SYS/BIOS. It * demonstrates how to print the string "hello world" to stdout. */ #include <xdc/std.h> #include <xdc/runtime/System.h> #include <ti/sysbios/BIOS.h> #include <xdc/runtime/Log.h> #include <ti/sysbios/knl/Task.h> #include <ti/sysbios/knl/Swi.h> #include <ti/sysbios/knl/Semaphore.h>
/* * ======== main ======== */
void fun_task0(void); void fun_task1(void); void func_swi0(void); Swi_Handle swi0; Semaphore_Handle sem0; //添加全局的信號量句柄
Void main() { System_printf("hello world\n"); Swi_Params swiParams; Swi_Params_init(&swiParams); swiParams.priority = 2; swiParams.trigger = 2; swi0 = Swi_create(func_swi0, &swiParams, NULL); sem0 = Semaphore_create(0, NULL, NULL);//創建信號量
BIOS_start(); } void func_swi0(void) { static Int count = 0; Log_info1("Swi0 is doing %d\n",count); count++; //增加一個解鎖信號量的函數
Semaphore_post(sem0); } void fun_task0(void) { Int count = 0; while(count<10) { Semaphore_pend(sem0, BIOS_WAIT_FOREVER);//在增加互斥信號量的任務函數中增加一個等待信號量為1的函數
Log_info1("Task0 is doing %d\n",count); Swi_dec(swi0); Task_yield(); count++; } BIOS_exit(0); } void fun_task1(void) { Int count = 0; while(count<10) { Log_info1("Task1 is doing %d\n",count); Swi_dec(swi0); Task_yield(); count++; } BIOS_exit(0); }
編譯調試,運行查看結果(這里我們只需要選擇單核運行就可以了):
可以看到只有當軟件中斷執行后,此時信號量才解鎖,task0才能執行,而任務執行兩次,才能觸發一次軟件中斷。
在項目中導入時鍾Clock模塊
Clocks模塊主要提供周期性執行函數,我們這里新建一個周期性執行函數,其每四個周期執行一次.
添加時鍾:
代碼:
/* * ======== hello.c ======== * The hello example serves as a basic sanity check program for SYS/BIOS. It * demonstrates how to print the string "hello world" to stdout. */ #include <xdc/std.h> #include <xdc/runtime/System.h> #include <ti/sysbios/BIOS.h> #include <xdc/runtime/Log.h> #include <ti/sysbios/knl/Task.h> #include <ti/sysbios/knl/Swi.h> #include <ti/sysbios/knl/Semaphore.h> #include <ti/sysbios/knl/Clock.h>
/* * ======== main ======== */
void fun_task0(void); void fun_task1(void); void func_swi0(void); void func_clk(UArg arg0); Swi_Handle swi0; Semaphore_Handle sem0; Void main() { System_printf("hello world\n"); Swi_Params swiParams; Swi_Params_init(&swiParams); swiParams.priority = 2; swiParams.trigger = 2; swi0 = Swi_create(func_swi0, &swiParams, NULL); Clock_Params clkParams; Clock_Params_init(&clkParams); clkParams.period = 5; // 函數執行周期
clkParams.startFlag = TRUE; // True說明時鍾立即開始計時
Clock_create(func_clk, 5, &clkParams, NULL); //創建時鍾,func_clk是周期執行的函數,這里5是開始執行的延時。
sem0 = Semaphore_create(0, NULL, NULL); BIOS_start(); } void func_swi0(void) { static Int count = 0; Log_info1("Swi0 is doing %d\n",count); count++; Semaphore_post(sem0); } void func_clk(UArg arg0) { UInt32 time; time = Clock_getTicks(); // 這里是定時器的節拍器
System_printf("System time in clk0Fxn = %lu\n", (ULong)time); if(time>20) BIOS_exit(0); } /* 因為任務的執行時間非常快,所以需要先把任務內的退出BIOS命令先刪除下,否則當任務完成后,時鍾函數還沒執行 */
void fun_task0(void) { Int count = 0; while(1) { Semaphore_pend(sem0, BIOS_WAIT_FOREVER); Log_info1("Task0 is doing %d\n",count); Swi_dec(swi0); Task_yield(); count++; } } void fun_task1(void) { Int count = 0; while(1) { Log_info1("Task1 is doing %d\n",count); Swi_dec(swi0); Task_yield(); count++; } }
編譯調試,運行查看結果(這里我們只需要選擇單核運行就可以了):
可以看到只有當周期函數func_clk每隔5個周期開始執行,開始執行時間為5。