(多核DSP快速入門)SYS/BIOS入門


 

(多核DSP快速入門)SYS/BIOS入門

                                         
原創文章

轉載請注冊來源http://blog.csdn.net/tostq

系列教程目錄:http://blog.csdn.net/tostq/article/details/51245979   

       SYS/BIOS是一個可擴展的實時內核(或者說是操作系統),其提供了許多模塊化的APIs(應用程序接口),支持搶占式多線程,硬件抽象,實時分析和配置工具,其設計目的是為了最大限度地減少對內存和CPU的要求。其擁有很多實時嵌入式操作系統的功能,如任務的調度,任務間的同步和通信,內存管理,實時時鍾管理,中斷服務管理等。有了它,用戶可以編寫復雜的多線程程序,並且會占用更少的CPU和內存資源。
       SYS/BIOS的早期版本是DSP/BIOS,更名的原因,是因為SYS/BIOS不僅可以用於DSP,而且也可以嵌入到ARM等其他SoC中去。SYS/BIOS是一個可用於實時調度、同步,主機和目標機通信,以及實時分析系統上的一個可裁減實時內核,它提供了搶占式的多任務調度,對硬件的及時反應,實時分析和配置工具等。同時也提供標准的API接口,易於使用。它是TI的eXpressDSP實時軟件技術的的一個關鍵部分。
       CCS中集成安裝了SYS/BIOS,能夠大大方便用戶編寫多任務應用程序。另一方面,SYS/BIOS可以在XDCtools中使用配置技術,極大地方便了SYS/BIOS的開發流程。
       本節主要是通過一些簡單的SYS/BIOS的例子來介紹相關APIs組件的作用,這里主要包括了時鍾Clock模塊、任務Tsk模塊、軟件中斷Swi模塊、信號量Sem模塊及日志Log模塊五類簡單模塊的使用。
 
一、新建SYS/BIOS項目
(1)在項目模板中選擇SYS/BIOS項目中的Hello Example模板,點擊Next
(2)在RTSC(XDCtools的別稱)配置頁中選中需要的SYS/BIOS,XDCtools及其他組件的版本,Target保持默認,不需修改,如果Platform沒有自動填充,選擇與設備適用的平台。Build-profile決定程序鏈接的庫,推薦使用release,即使仍然處於創建和調試階段,點擊完成創建項目。
Tips:當我們開始使用SYS/BIOS時,是不能指定自己添加的鏈接命令文件.cmd。因為.cmd會在構建工程的時候由SYS/BIOS自動創建並使用。
(3)點擊編譯
(4)導入target文件后,點擊調試,運行得到結果
 
二、SYS/BIOS的模塊與配置
(1)SYS/BIOS可以用文本編輯器或者是圖像配置編輯器XGCONF來編輯,雙擊打開.cfg文件如下
       單擊System Overview,可以顯示程序當前使用的主模塊(帶綠色小箭頭的)
(2)各種APIs模塊的添加這里有兩種方法,一種是直接雙擊主模板進入,然后勾選Add
       另一種方法是在Available Products中右擊選中的模塊,選擇Use
(3)各個API模塊的作用
       CLK:片內定時器模塊,主要控制片內定時器並提供高精度的32位實時邏輯時鍾,它能控制中斷的速度,使之最快達到單指令周期時間。
       HST:主機輸入/輸出模塊,管理主機通過對象,它允許應用程序在目標系統和主機之間交流數據,主機通道通過靜態配置為輸入或輸出。
       HWI:硬件中斷模塊,提供對硬件中斷服務例程的支持,可在配置文件中指定當硬件中斷發生時需要啟動的函數
       IDL:休眠功能模塊,管理休眠函數在目標系統程序沒有更高優先權的函數運行時啟動
       LOG:日志模塊,管理LOG對象,LOG對象在目標系統程序執行時實時捕捉事件,開發者可以使用系統日志或定義自己的日志,並在CCS中利用它實時瀏覽信息。
       MEM:存儲器模塊允許指定存放目標程序的代碼和數據所需的存儲器段
       PIP:數據通道模塊管理數據通道,它用來緩存輸入和輸出數據流,這此數據通道提供一致性的軟件數據結構,可以使用它們驅動DSP和其他實時外圍設備之間的I/O通道
       PRD:周期函數模塊,管理周期對象,它觸發應用程序的周期性執行。
       RTDX:實時數據交換允許數據在主機和目標系統之間實時交換,在主機上使用自動OLE的客戶都可對數據進行實時顯示和分析。
       STS:統計模塊,管理統計累積器,在程序運行時,它存儲關鍵統計數據並能通過CCS瀏覽這此統計數據
       SWI:軟件中斷模塊管理軟件中斷。
       TRC:跟蹤模塊,管理一套跟蹤控制比特,它們通過事件日志和統計累積器控制程序信息的實時捕捉。
 
三、在項目中導入LOG模塊
       LOG模塊實際上是一個實現打印信息的API
       (1)添加LOG模塊
       (2)LOG模塊的使用
       LOG模塊定義了許多比如Log_error、Log_info、Log_warning、Log_print等之類函數,這些函數的用法同printf函數的用法很相似,這些函數都可以在<xdc/runtime/Log.h>找到,其實際上是將printf的有用法分成許多不同的類(如錯誤信息、提示信息、警告信息等),LOG模塊打印的內容可以在Tools/RTA/PrintfLogs中看到。
       Tips:LOG中定義了許多如下的函數,i比如Log_info1函數后面的數字代表函數接的變量數目
       如Log_info1("%d",s1)、Log_info2("%d, %d", s1, s2)
 
 
四、在項目中導入TSK任務模塊
       TSK任務模塊是操作系統中最基本的模塊,其實際上反映了多線程搶占,每個任務單獨是一個線程,各個線程(任務)具有各自的優先級
       (1)新建任務,首先選擇Use TSK,確定TSK模擬是否導入
       然后創建新任務New Task
       這里我們創建兩個任務task0、task1,分別對應其函數func_tsk0、func_tsk1。其優先級都為1
       (2)編寫任務函數
       a). 這里我們在主函數中BIOS_start()函數,說明任務開始執行了
       b). 任務執行完后調用BIOS_exit(0)退出
       c). Task_yield()是個優先級調度函數,其作用就是如果有相同優先級的任務,則調度到同優先級的其它任務執行!
       d). Log_info1()的作用是打印日志信息
       e). while和count循環的目標是讓任務執行較長的時間,而不是只執行一次就退出了。
       f). 最后別忘了在增加相關頭文件和函數的聲明!
       (3)編譯調試,運行查看結果(這里我們只需要選擇單核運行就可以了)
       從下面的分析,我們可以看到兩個任務是相互依次運行的,每個任務運行一次后,其優先級就會降低,此時就切換到下一個任務
 
五、在項目中導入Swi軟件中斷模塊
       前面我們已經知道了不同任務有不同優先級,而軟件中斷具有比任何任務都高的優先級,而其中硬件中斷(HWI)又比軟件中斷(SWI)優先級更高。
       (1)添加軟件中斷Swi,這里方法同前面添加TSK的方法不一樣,似乎不能用圖形界面方式去添加(我沒有成功=_=||)
       這里我選擇通過直接在源代碼中添加相關代碼:
       a). 首先需要添加一個全局的Swi句柄:Swi_Handle swi0;
       b). 初始化Swi參數:
            Swi_Params swiParams;        
            Swi_Params_init(&swiParams);
            swiParams.priority = 2;        // 軟件中斷的優先級
            swiParams.trigger = 2;         // 軟件中斷的計數器
       c). 創建軟件中斷:
            swi0 = Swi_create(func_swi0, &swiParams, NULL);  // swi0是中斷名,func_swi0是中斷函數
       d). 編寫中斷函數:
              void func_swi0(void)
              {
                   static Int count = 0;
                   Log_info1("Swi0 is doing %d\n",count);
                   count++;
              }
       e). 更改軟件中斷計數器trigger,要觸發軟件中斷,首先需要讓trigger的計數為0,這里我們可以在任務函數內增加一個trigger自減的函數,任務函數執行兩次后,將會觸發軟件中斷。
       void func_tsk0(void)
       {
            Int count = 0;
            while(count<10){
                Log_info1("Task0 is doing %d\n",count);
                Swi_dec(swi0);
                Task_yield();
                count++;
            }
            BIOS_exit(0);
       }
       (2)一些Swi APIs 函數
       Swi_inc Swi.trigger自增函數,每次增加1
       Swi_dec Swi.trigger自減函數,每次減少1
       Swi_or 將trigger的值與模板求或操作
       Swi_and 將trigger的值與模板求和操作
       (3)編譯調試,運行查看結果(這里我們只需要選擇單核運行就可以了)
       從下面的分析,我們可以看到兩個任務的每次都會使得軟件中斷計數trigger減1(通過Swi_dec函數),直到trigger的值減少到0時,執行軟件中斷,中斷后,trigger恢復到原來的值,這里的trigger初始值為2,所以執行兩次任務后就會觸發一次軟件中斷
 
六、在項目中導入信號量Semaphore模塊
       信號量是在多線程環境下使用的一種設施,是可以用來保證兩個或多個關鍵代碼段不被並發調用,對於多個任務來說,使用信號量可以防止多個任務同時執行。
       信號量可分互斥信號量和計數信號量,互斥信號量只有兩種狀態:1和0,為1時說明可用,否則不可用。而計數信號量通過設置一個計數值,如果計數值大於0,則任務請求該信號量時是可用。
       這里例子是我們給task0任務中增加一個互斥信號量,當信號量狀態為1時,task0才能繼續執行。通過軟件中斷來達到信號量歸1。
       (1)添加信號量
              a). 首先需要添加一個全局的信號量句柄:Semaphore_Handle sem0;
              b). 創建信號量:sem0 = Semaphore_create(0, NULL, NULL);
              c). 在增加互斥信號量的任務函數中增加一個等待信號量為1的函數
                     Semaphore_pend(sem0, BIOS_WAIT_FOREVER);  // BIOS_WAIT_FOREVER表示一直等待,直到信號量為1
              d). 在軟件中斷函數中增加一個解鎖信號量的函數
                     Semaphore_post(sem0);
              e). 最后別忘了添加Semaphore模塊的頭文件
                     #include <ti/sysbios/knl/Semaphore.h>
              f). 如果.cfg文件中沒有添加信號量模塊,記得一定要添加,否則雖然不會報錯,但信號量不會工作
       (2)編譯調試,運行查看結果(這里我們只需要選擇單核運行就可以了)
       從下面的分析,我們可以看到只有當軟件中斷執行后,此時信號量才解鎖,task0才能執行,而任務執行兩次,才能觸發一次軟件中斷。
 
七、在項目中導入時鍾Clock模塊
       Clocks模塊主要提供周期性執行函數,我們這里新建一個周期性執行函數,其每四個周期執行一次。
       (1)添加信號量
              a). 首先初始化時鍾參數:
                   Clock_Params clkParams;
                   Clock_Params_init(&clkParams);
                   clkParams.period = 5; // 函數執行周期
                   clkParams.startFlag = TRUE; // True說明時鍾立即開始計時
              b). 創建時鍾:Clock_create(func_clk, 5, &clkParams, NULL); //創建時鍾,func_clk是周期執行的函數,這里5是開始執行的延時。
              c).  編寫周期執行的時鍾函數
                     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);
                     }
              d). 因為任務的執行時間非常快,所以需要先把任務內的退出BIOS命令先刪除下,否則當任務完成后,時鍾函數還沒執行
                     void func_tsk1(void)
                     {
                         Int count = 0;
                         while(1){
                          //while(count<10){
                              Log_info1("Task1 is doing %d\n",count);
                              Swi_dec(swi0);
                              Task_yield();
                             count++;
                          }
                          //BIOS_exit(0);
                     }
             e). 最后別忘了添加時鍾模塊的頭文件
             #include <ti/sysbios/knl/Clock.h>
             f). 如果.cfg文件中沒有添加時鍾Clock模塊,記得一定要添加,否則雖然不會報錯,但時鍾模塊不會工作
       (2)編譯調試,運行查看結果(這里我們只需要選擇單核運行就可以了)
       從下面的分析,我們可以看到只有當周期函數func_clk每隔5個周期開始執行,開始執行時間為5。
 
項目代碼下載:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM