BL,CPU在執(zhí)行該指令跳轉到某個函數執(zhí)行時,會將當前PC地址作為函數返回地址、加載到LR寄存器中、保證函數執(zhí)行完可以返回到這兒繼續(xù)執(zhí)行,再將函數地址加載到PC寄存器、程序接著執(zhí)行就到了函數中。那么,任務入口函數沒有被別的函數主動調用,是如何被拉起來執(zhí)行的呢?
任務切換分為兩步:保存上文、切換下文。切換下文就是指將保存在任務棧中的CPU寄存器組的值、加載到CPU中。
「所以,當任務棧中初始保存的CPU寄存器組的值中、PC寄存器值為該任務的任務入口函數地址時,切換下文加載之后,由于PC指向任務入口函數,所以CPU接著運行就到了任務入口函數中,也就是該任務在運行?!?
同樣的道理,「任務棧中初始保存的CPU寄存器組的值中、LR寄存器的值決定了、任務入口函數退出時候返回到哪里。」
由于不同CPU架構的CPU寄存器組不同,所以初始化任務棧的代碼與架構強相關,在arch目錄下都有不同架構對應的實現(xiàn)。
這里我們以ARM Cortex-M4為例(Arm-v7m)看看代碼如何實現(xiàn):
從代碼里可以看到,TencentOS-Tiny默認退出函數為exit參數指定的值,接下來我們看看退出函數~
5. 任務退出函數
在創(chuàng)建任務的API tos_task_create中,初始化任務棧的過程中會指定退出函數為 task_exit:
task->sp = cpu_task_stk_init((void *)entry, arg, (void *)task_exit, stk_base, stk_size);
task_exit 函數主要完成銷毀自身的工作,具體實現(xiàn)如下:
__STATIC__ void task_exit(void)
{
tos_task_destroy(K_NULL);
}
該銷毀函數傳入的參數為NULL表示銷毀自身,如果是靜態(tài)任務則按以下步驟銷毀(動態(tài)任務銷毀值得用一篇文章去講述):
-
將任務從就緒列表移除
-
將任務從等待列表移除
-
將任務從統(tǒng)計列表移除
-
任務狀態(tài)置為K_TASK_STATE_DELETED
6. 總結
本文講述了任務的兩種常規(guī)寫法,以及任務函數執(zhí)行完畢之后去了哪里?
當任務函數執(zhí)行完畢退出時,會執(zhí)行到哪里由任務棧初始化時LR寄存器的值決定,RTOS內核都會提供一個默認退出函數,TencentOS-Tiny提供的任務退出函數中,會自動銷毀任務自身。
所以在編寫一次性任務時,就不需要主動調用銷毀API銷毀自身啦~
------------ END ------------