獲得線程:rt_thread_t rt_thread_self(void);
一 線程的創建和刪除:
rt_thread_create()創建的句柄,對應的刪除rt_thread_delete(),注意線程的刪除只是將線程的狀態該為close,進入空閑任務才刪除。
rt_thread_init()函數對應的是rt_thread_detach()
二 線程的就緒和掛起:RTT只能是講一個已經就緒的線程掛起,而不能對已經掛起(調用系統延時函數)的任務再執行掛起操作用suspend!
rt_thread_startup(taskn):使當前線程就緒;
rt_err_t rt_thread_suspend (rt_thread_t thread)使當前線程掛起但很少用,除非在調用該函數后立刻調用rt_schedule()進行調度;
對應的恢復就緒rt_err_t rt_thread_resume (rt_thread_t thread)后也緊跟調用rt_schedule();
yield主動切出掛起;rt_thread_yield()
函數和rt_schedule()
函數的區別:前者從當前線程中切出,插入到本優先級列表尾端,然后轉到同優先級的其它線程執行;而后者當前線程不一定切出,只是從調度器重新檢查一遍最高優先級就緒任務並執行;
三線程的休眠:
rt_err_t rt_thread_sleep(rt_tick_t tick); rt_err_t rt_thread_delay(rt_tick_t tick);
rt_err_t rt_thread_mdelay(rt_int32_t ms);
四線程控制:rt_err_t rt_thread_control(rt_thread_t thread, rt_uint8_t cmd, void* arg);使之就緒、刪除、或更改優先級
五空閑線程:
void rt_thread_idle_init(void);
void rt_thread_idle_sethook(void (*hook)(void));
rt_err_t rt_thread_idle_delhook(void (*hook)(void));設置的鈎子函數必須保證空閑線程在任何時刻都不會處於掛起狀態,主要用於設置狀態指示(因不能調用系統延時函數,等待信號所以用處不大,最多只能用條件判斷的指示燈)。低功耗模式。刪除的線程資源回收。
void rt_scheduler_sethook(void (*hook)(struct rt_thread* from, struct rt_thread* to)調度器鈎子用以確定在某個時刻發生了什么線程切換。
六 線程設計:
1 需要知道什么時候讓線程進入非就緒態,如果一直就緒,低優先級線程就可能得不到執行的機會。
2 需要確定線程的運行周期、運行時間(task1的響應時間(周期)有要求,則要求其它高優先級任務taskn的執行時間不能超過task1的周期)、優先級的因素
3線程創建步驟:
3.0系統啟動流程架構:在rt_application_init()中創建main線程($super$$main必須成對使用,這里是讓擴展了Main之后返回到用戶main,然后刪除自己。硬件初始化,系統初始化,
RT-Thread通過擴展main函數的方式都在component.c里面實現,所以在主main中只有用戶自己創建的線程。main線程執行到最后,通過LR寄存器指定的鏈接地址退出,在
創建main線程的時候,線程棧對應LR寄存器的內容是rt_thread_exit()函數,在
rt_thread_exit里面會把main線程占用的內存空間都釋放掉
3.1 創建線程函數,執行什么功能;定義線程堆棧和線程控制塊(ID:)
3.2用rt_thread_init()初始化線程任務,任務進入初始化態,調用rt_thread_startup(&led1_thread); 后參與線程調度
#define LED1_StackSize 1024
static rt_uint8_t rt_led1_thread_stack[LED1_StackSize];
static struct rt_thread led1_thread;
rt_thread_init(&led1_thread, /* 線程控制塊 */ (1)
"led1", /* 線程名字 */ (2)
led1_thread_entry, /* 線程入口函數 */ (3)
RT_NULL, /* 線程入口函數參數 */ (4)
&rt_led1_thread_stack[0], /* 線程棧起始地址 */ (5)
sizeof(rt_led1_thread_stack), /* 線程棧大小 */ (6)
3, /* 線程的優先級 */ (7)
20); /* 線程時間片,相同優先級才起作用,對只有一個線程時那么該參數不起作用 */
,
線程的棧、控制塊用的若靜態內存(由編譯器負責分配),必須由用戶手動預先定義,但這種方法我們在使用RT-Thread的時候用的比較少,通常的方法是在線程創建的時候動態
的分配線程棧和線程控制塊的內存空間,即推薦使用動態法創建線程(堆棧大小、優先級、時間片最好宏定義給出增加靈活性)。接下來我們講解下“創建單線程—SRAM動態內存”的方法(堆),在board.c
static rt_thread_t led1_thread = RT_NULL;
led1_thread = /* 線程控制塊指針 */ (1)
rt_thread_create( "led1", /* 線程名字 */ (2)
led1_thread_entry, /* 線程入口函數 */ (3)
512, /* 線程棧大小 不用指定起始地址*/ (5)
3, /* 線程的優先級 */ (6)
20); /* 線程時間片 */ (7)
RT_NULL, /* 線程入口函數參數 */ (4)
if (led1_thread != RT_NULL)
rt_thread_startup(led1_thread); /* 啟動線程,開啟調度 */
else
return -1;
線程的管理:
RT-Thread內核中采用了基於位圖的優先級算法(時間復雜度O(1),即與就緒線程的多少無關)。
在系統中除了中斷處理函數、調度器上鎖部分的代碼和禁止中斷的代碼是不可搶占的之外,系統的其他部分都是可以搶占的,包括線程調度器自身。
時間片輪轉調度僅在當前系統中無更高優先級就緒線程存在的情況下才有效,也可以是一個任務的2個副本。