0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

揭秘RTOS任務入口函數(shù)執(zhí)行完之后去哪里了

strongerHuang ? 來源:Mculover666 ? 作者:mculover666 ? 2021-11-05 14:20 ? 次閱讀

1. 說明

在工作過程中,我發(fā)現(xiàn)在實際使用RTOS完成項目時,理解這些知識僅能達到會用RTOS的水平,要想用好RTOS,還需要了解一些比較細節(jié)的機制,否則容易掉坑進去,花大量時間定位問題。

本文結(jié)合TencentOS-Tiny實時操作系統(tǒng)給大家講述一下相關內(nèi)容。

2. 任務的通常寫法

遵循“不使用就讓出”的原則,任務通常有兩種寫法。

「阻塞等待」某個事件處理,等待到之后處理:

voidtask1_entry(void*arg)
{
//init...

while(1){
//1.waitsomekernelobject...
//eg.tos_sem_pend,tos_mutex_pend,tos_event_pend.

//2.waitsuccess,handle!
}
}

這種寫法中,在沒有事件發(fā)生的時候,任務會因為等待某個內(nèi)核對象而被掛起,讓出CPU不參與調(diào)度。

② 定時執(zhí)行

voidtask1_entry(void*arg)
{
//init...

while(1){
//1.dosomething...

//2.sleep!
//eg.tos_task_delay,tos_sleep_ms.
}
}

這種寫法中,任務在干完活之后,會主動進入睡眠狀態(tài),讓出CPU不參與調(diào)度。

3. 一次性任務

上面兩種寫法的共性是都有主循環(huán),不需要考慮任務入口函數(shù)退出的情況,但在一些場景中任務只需要執(zhí)行一次即可:

voidtask1_entry(void*arg)
{
//init...

//dosomething...

//exit?
}

「這個時候就要思考一個問題:任務入口函數(shù)執(zhí)行完畢之后去了哪里?」

4. 尋找答案

首先,「任務入口函數(shù)本質(zhì)上是一個函數(shù)」,跳轉(zhuǎn)函數(shù)的指令是BL,CPU在執(zhí)行該指令跳轉(zhuǎn)到某個函數(shù)執(zhí)行時,會將當前PC地址作為函數(shù)返回地址、加載到LR寄存器中、保證函數(shù)執(zhí)行完可以返回到這兒繼續(xù)執(zhí)行,再將函數(shù)地址加載到PC寄存器、程序接著執(zhí)行就到了函數(shù)中。

6cdb8e6e-3dfd-11ec-82a9-dac502259ad0.png

那么,任務入口函數(shù)沒有被別的函數(shù)主動調(diào)用,是如何被拉起來執(zhí)行的呢?

任務切換分為兩步:保存上文、切換下文。切換下文就是指將保存在任務棧中的CPU寄存器組的值、加載到CPU中。

「所以,當任務棧中初始保存的CPU寄存器組的值中、PC寄存器值為該任務的任務入口函數(shù)地址時,切換下文加載之后,由于PC指向任務入口函數(shù),所以CPU接著運行就到了任務入口函數(shù)中,也就是該任務在運行?!?/strong>

同樣的道理,「任務棧中初始保存的CPU寄存器組的值中、LR寄存器的值決定了、任務入口函數(shù)退出時候返回到哪里?!?/strong>

由于不同CPU架構(gòu)的CPU寄存器組不同,所以初始化任務棧的代碼與架構(gòu)強相關,在arch目錄下都有不同架構(gòu)對應的實現(xiàn)。

這里我們以ARM Cortex-M4為例(Arm-v7m)看看代碼如何實現(xiàn):

6d302d48-3dfd-11ec-82a9-dac502259ad0.png

從代碼里可以看到,TencentOS-Tiny默認退出函數(shù)為exit參數(shù)指定的值,接下來我們看看退出函數(shù)~

5. 任務退出函數(shù)

在創(chuàng)建任務的API tos_task_create 中,初始化任務棧的過程中會指定退出函數(shù)為 task_exit

task->sp=cpu_task_stk_init((void*)entry,arg,(void*)task_exit,stk_base,stk_size);

task_exit 函數(shù)主要完成銷毀自身的工作,具體實現(xiàn)如下:

__STATIC__voidtask_exit(void)
{
tos_task_destroy(K_NULL);
}

該銷毀函數(shù)傳入的參數(shù)為NULL表示銷毀自身,如果是靜態(tài)任務則按以下步驟銷毀(動態(tài)任務銷毀值得用一篇文章去講述):

  • 將任務從就緒列表移除
  • 將任務從等待列表移除
  • 將任務從統(tǒng)計列表移除
  • 任務狀態(tài)置為K_TASK_STATE_DELETED

6. 總結(jié)

本文講述了任務的兩種常規(guī)寫法,以及任務函數(shù)執(zhí)行完畢之后去了哪里?

當任務函數(shù)執(zhí)行完畢退出時,會執(zhí)行到哪里由任務棧初始化時LR寄存器的值決定,RTOS內(nèi)核都會提供一個默認退出函數(shù),TencentOS-Tiny提供的任務退出函數(shù)中,會自動銷毀任務自身。

所以在編寫一次性任務時,就不需要主動調(diào)用銷毀API銷毀自身啦~

編輯:jq
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 寄存器
    +關注

    關注

    31

    文章

    5304

    瀏覽量

    119876
  • API
    API
    +關注

    關注

    2

    文章

    1477

    瀏覽量

    61764
  • 函數(shù)
    +關注

    關注

    3

    文章

    4290

    瀏覽量

    62342
  • RTOS
    +關注

    關注

    21

    文章

    809

    瀏覽量

    119373

原文標題:RTOS 任務入口函數(shù)執(zhí)行完之后去哪里了?

文章出處:【微信號:strongerHuang,微信公眾號:strongerHuang】歡迎添加關注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關推薦

    MaXim96717 VPG功能啟用之后去哪里查看圖像

    MaXim96717 VPG功能啟用之后去哪里查看圖像
    發(fā)表于 11-01 10:42

    freertos和rtos區(qū)別是什么

    (Real-Time Operating System,實時操作系統(tǒng))是一種特殊的操作系統(tǒng),它能夠為實時任務提供確定性的響應時間。RTOS 通常用于嵌入式系統(tǒng),如工業(yè)自動化、汽車電子、醫(yī)療設備等領域
    的頭像 發(fā)表于 09-02 14:18 ?864次閱讀

    SPI數(shù)據(jù)速率影響定時器中斷,問題出在哪里?

    就會發(fā)送到 RTOS 隊列。 此時會執(zhí)行一個任務,在該任務中會執(zhí)行一個記錄到終端的日志函數(shù)。 現(xiàn)
    發(fā)表于 07-23 07:07

    請問從哪里獲得ESP8266 RTOS SDK的SPI驅(qū)動程序?

    我計劃將ESP8266用作SPI從設備,它可以根據(jù)功能從某些SPI主設備進行操作。我已經(jīng)檢查 NON OS SDK 中有 SPI 驅(qū)動程序ESP8266但 RTOS SDK ESP8266沒有任何源。 那么,有沒有人知道我可以從哪里
    發(fā)表于 07-12 07:28

    請問CMSIS-RTOS RTX的任務調(diào)度鎖在哪里?

    請問一下,CMSIS-RTOS RTX的任務調(diào)度鎖在哪里?謝謝!
    發(fā)表于 05-13 08:28

    鴻蒙TypeScript入門學習第8天:【TypeScript 函數(shù)

    函數(shù)是一組一起執(zhí)行一個任務的語句。 您可以把代碼劃分到不同的函數(shù)中。如何劃分代碼到不同的函數(shù)中是由您來決定的,但在邏輯上,劃分通常是根
    的頭像 發(fā)表于 04-03 14:54 ?379次閱讀
    鴻蒙TypeScript入門學習第8天:【TypeScript <b class='flag-5'>函數(shù)</b>】

    請問RTOS USBSetuPcb回調(diào)函數(shù)是在中斷還是單獨線程中處理的?

    UART 通信)和異步 USB Setup 請求回調(diào)處理程序函數(shù)之間的 Uart 訪問之間存在競爭條件。 -> 在執(zhí)行主循環(huán)UART功能的同時,正在執(zhí)行USB消息處理UART功能。 要
    發(fā)表于 02-23 06:10

    verilog中函數(shù)任務對比

    在verilog中,函數(shù)任務均用來描述共同的代碼段,并且在模式內(nèi)任意位置被調(diào)用,提高代碼效率,讓代碼更加的直觀,提高代碼可讀性。但是在實際使用的過程中,函數(shù)任務也存在諸多的不同,下
    的頭像 發(fā)表于 02-12 18:43 ?837次閱讀

    GD32 MCU是如何進入中斷函數(shù)

    用過GD32 MCU的小伙伴們都知道,程序是順序執(zhí)行的,但當有中斷來的時候程序會跳轉(zhuǎn)到中斷函數(shù),執(zhí)行中斷函數(shù)后程序又繼續(xù)回到原來的位置繼續(xù)
    的頭像 發(fā)表于 01-30 09:45 ?961次閱讀
    GD32 MCU是如何進入中斷<b class='flag-5'>函數(shù)</b>的

    GD32 MCU啟動后如何運行到main函數(shù)

    GD32 MCU啟動后如何運行到main函數(shù)入口?你是否也有這樣的疑慮。在執(zhí)行到main函數(shù)之前MCU干了哪些事情呢?下面為大家解答。
    的頭像 發(fā)表于 01-15 10:00 ?1008次閱讀
    GD32 MCU啟動后如何運行到main<b class='flag-5'>函數(shù)</b>

    bootm命令的執(zhí)行流程

    Bootm命令用來從memory啟動內(nèi)核,bootm命令的執(zhí)行流程如下圖所示。 在串口終端輸入bootm命令后,執(zhí)行do_bootm函數(shù)來完成相應的功能。Do_bootm函數(shù)首先
    的頭像 發(fā)表于 12-04 17:33 ?1086次閱讀
    bootm命令的<b class='flag-5'>執(zhí)行</b>流程

    RTOS內(nèi)功修煉記(一)— 任務到底應該怎么寫?

    本篇文章講述任務的三大元素:任務控制塊、任務棧、任務入口
    的頭像 發(fā)表于 12-01 16:36 ?699次閱讀
    <b class='flag-5'>RTOS</b>內(nèi)功修煉記(一)— <b class='flag-5'>任務</b>到底應該怎么寫?

    怎么讓python執(zhí)行后再執(zhí)行

    在Python中,可以使用一些技術來確保程序執(zhí)行完畢后再執(zhí)行其他任務。下面將詳細介紹幾種方法。 一、使用阻塞方式執(zhí)行程序 阻塞方式是最簡單的方法之一,它要求程序在
    的頭像 發(fā)表于 11-29 15:09 ?3365次閱讀

    c語言源程序main函數(shù)的位置

    C語言源程序中的main函數(shù)是程序的入口點,它被認為是C語言程序的起點。在執(zhí)行程序時,操作系統(tǒng)將首先定位到main函數(shù),并從該函數(shù)開始
    的頭像 發(fā)表于 11-24 10:23 ?2271次閱讀

    新手必看的RTOS基礎知識

    時間片調(diào)度保證每個線程都有一個要執(zhí)行的槽。這種類型的調(diào)度通常不利于實時應用。如果需要,TI-RTOS內(nèi)核支持使用任務進行時間切片調(diào)度。
    的頭像 發(fā)表于 11-20 16:06 ?2321次閱讀
    新手必看的<b class='flag-5'>RTOS</b>基礎知識