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

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

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

RT-Thread啟動(dòng)進(jìn)入就緒態(tài)最高優(yōu)先級線程的全過程與棧幀分析(上)

冬至子 ? 來源:lchnu ? 作者:lchnu ? 2023-11-08 12:47 ? 次閱讀

本文簡單討論RT-Thread在啟動(dòng)后,逐步進(jìn)入到處于就緒態(tài)最高優(yōu)先級main線程的全過程。部分內(nèi)容涉及到匯編指令,但通俗易懂。通過簡化工程,配合Debug過程,逐步觀察寄存器的變化、繪制棧幀結(jié)構(gòu)、繪制線程控制塊和rt_interrupt_from_thread、rt_interrupt_to_thread等典型變量取值(指向,雖然是rt_uint32_t類型,但實(shí)際在匯編中是作為指針使用),能有效幫助理解RTOS的線程棧的恢復(fù)與啟動(dòng)過程。

通過本文對線程啟動(dòng)過程的了解,對于兩個(gè)線程/多個(gè)線程之間的互相切換能奠定堅(jiān)實(shí)的基礎(chǔ),化繁為簡,結(jié)合論壇關(guān)于上下文切換的代碼注釋,能幫助快速抓住主線。

使用的軟硬件環(huán)境如下:

IDE工具 - RT-Thread Studio 2.2.6
硬件 - STM32L431RCT6,Cortex M4內(nèi)核
軟件 - RT-Thread 4.0.5版本
配置 - 僅使能main線程和tidle0線程

一、工程設(shè)置

Step 1. 新建名稱為EVBMX_RTThread405_Switch的4.0.5版本工程

1.jpg

Step 2. 不使能軟件定時(shí)器,使能線程狀態(tài)更改的調(diào)試

關(guān)閉軟件定時(shí)器線程,避免干擾。

1.jpg

Step 3. 關(guān)閉msh shell,禁用Finsh

關(guān)閉tshell線程,避免干擾。僅僅保留main線程和tidle0線程。

1.jpg

Step 4. 修改main函數(shù)

修改main函數(shù)后,線程進(jìn)入一次,休眠且切換1次,再次切回且return,然后徹底退出,只留下tidle0線程。

#include
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include
int main(void)
{
rt_thread_mdelay(1000);
return RT_EOK;
}

Step 5. 下載程序,觀察輸出結(jié)果

讀完全文后,對下方輸出結(jié)果的每一行語句所代表的含義和發(fā)生時(shí)刻,能有更深刻體會(huì)。

1.jpg

二、調(diào)試運(yùn)行

Step 6. 在component.c中257行按F9設(shè)置斷點(diǎn);F5全速運(yùn)行到此處后,再按F9關(guān)閉此處斷點(diǎn)。

1.jpg

Step 7. 依次進(jìn)入rt_thread_create, _thread_init, 停留在thread.c的164行。

將變量thread添加到表達(dá)式窗口,可以查看各個(gè)成員的值,其中,thread->stack_addr = 0x20001138, thread->stack_size = 0x800,分別表示棧底位置和??臻g大小。

164行的函數(shù)rt_hw_stack_init對于理解線程切換是一個(gè)相當(dāng)重要的函數(shù),其形參分別為:

線程入口函數(shù):main_thread_entry

線程參數(shù)RT_NULL:

線程棧棧頂?shù)刂罚簍hread->stack_addr + thread->stack_size - 4 = 0x20001138 + 0x800 - 4 = 0x20001934

1.jpg

Step 8. 單步進(jìn)入到rt_hw_stack_init函數(shù)內(nèi)部,開展分析

149行,由于傳遞進(jìn)來的stack_addr = 0x20001934,執(zhí)行完畢后,stk為0x20001938。從0x20001138(含)到0x20001934(含),合計(jì)是0x800 = 2048字節(jié)。STM32使用的滿遞減棧,所以此處的stk是0x20001938。

150行,此處設(shè)置8字節(jié)對齊。由于0x20001938 = (536877368)Decimal,該數(shù)據(jù)除8等于67109671,能被8整除,該語句執(zhí)行棧對齊操作后,stk依然為0x20001938。

1.jpg

Step 9. 繼續(xù)了解rt_hw_stack_init函數(shù)。

151行,更新stk的值,減去struct stack_frame結(jié)構(gòu)體的大小。執(zhí)行完畢后,stk = 0x200018F4。
153行,stack_frame指針指向0x200018F4。
156至159行,通過for循環(huán)將0x200018F4至0x20001938的所有內(nèi)存變成0xdeadbeaf魔法字。
161行至168行,將stack_frame成員的exception_stack_frame中的r0~psr共8個(gè)寄存器分別設(shè)置為:線程參數(shù),4個(gè)0,線程返回地址,線程入口地址,0x01000000。
175行,返回stk的值,此時(shí)變成0x200018F4。這個(gè)值在初始化線程時(shí),將返回給thread->sp,即線程棧的臨時(shí)棧頂指針。
依次將線程的形參、r1-r3, r12, 線程返回地址、線程入口地址,線程的xPSR寫入異常棧幀結(jié)構(gòu)中。
在初入門時(shí),這里是難點(diǎn)。C語言中使用結(jié)構(gòu)體定義的棧結(jié)構(gòu),如何和實(shí)際寄存器的順序進(jìn)行一一對應(yīng)?,后文會(huì)通過逐步Debug揭示這個(gè)問題答案。

1.jpg

至此,main線程創(chuàng)建完畢后,線程結(jié)構(gòu)體和線程??臻g如下所示。

1.jpg

Step 10. 繼續(xù)單步到rt_system_scheduler_start函數(shù)處,并單獨(dú)跟蹤進(jìn)入到該函數(shù)內(nèi)部。

期間,RT-Thread會(huì)調(diào)用rt_thread_idle_init函數(shù),在該函數(shù)中使用靜態(tài)創(chuàng)建方式初始化tidle0線程??梢园凑丈鲜鲞^程記錄tidle0線程的棧空間。

1.jpg

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

    關(guān)注

    31

    文章

    5356

    瀏覽量

    120572
  • STM32
    +關(guān)注

    關(guān)注

    2270

    文章

    10904

    瀏覽量

    356445
  • C語言
    +關(guān)注

    關(guān)注

    180

    文章

    7605

    瀏覽量

    137049
  • Shell
    +關(guān)注

    關(guān)注

    1

    文章

    366

    瀏覽量

    23404
  • RT-Thread
    +關(guān)注

    關(guān)注

    31

    文章

    1293

    瀏覽量

    40217
收藏 人收藏

    評論

    相關(guān)推薦

    RT-Thread啟動(dòng)進(jìn)入就緒態(tài)最高優(yōu)先級線程全過程分析(下)

    Step 11. 繼續(xù)單步到rt_hw_context_switch_to函數(shù)處。
    的頭像 發(fā)表于 11-08 12:53 ?1440次閱讀
    <b class='flag-5'>RT-Thread</b><b class='flag-5'>啟動(dòng)</b><b class='flag-5'>進(jìn)入</b><b class='flag-5'>就緒</b><b class='flag-5'>態(tài)</b><b class='flag-5'>最高</b><b class='flag-5'>優(yōu)先級</b><b class='flag-5'>線程</b>的<b class='flag-5'>全過程</b>與<b class='flag-5'>棧</b><b class='flag-5'>幀</b><b class='flag-5'>分析</b>(下)

    靈動(dòng)微課堂 (第135講) | 基于MM32 MCU的OS移植與應(yīng)用——RT-Thread 線程管理

    的屬性,如線程控制塊、線程、入口函數(shù)等。圖 1 對象容器與線程對象線程的調(diào)度RT-Thread
    發(fā)表于 09-03 17:40

    什么是RT-Thread線程管理看完你就懂了

    ,每個(gè)線程都有重要的屬性,如線程控制塊、線程、入口函數(shù)等。RT-Thread線程調(diào)度器是搶
    發(fā)表于 03-29 06:16

    【每日一練】RT-Thread Nano-線程創(chuàng)建1(第五節(jié)學(xué)習(xí)視頻)

    )A、256.0 B、32.32 C、512.0D、256.2562、rt_thread_create()函數(shù)有哪幾個(gè)參數(shù)?請說明(問答)3、啟動(dòng)線程后,線程會(huì)
    發(fā)表于 05-21 10:04

    RT-Thread基于優(yōu)先級的全搶占式調(diào)度算法的實(shí)現(xiàn)

    thread2,當(dāng)它們都進(jìn)入就緒狀態(tài)等待調(diào)度時(shí),效果如下:此時(shí)問題來了,當(dāng)任務(wù)們都進(jìn)入就緒狀態(tài),掛載在這個(gè)
    發(fā)表于 04-20 14:17

    基于STM32L475VET5的RT-Thread線程管理學(xué)習(xí)

    調(diào)度。此狀態(tài)在 RT-Thread 中的宏定義為 RT_THREAD_INIT。(2)就緒狀態(tài):在就緒狀態(tài)下,線程按照
    發(fā)表于 04-22 15:00

    RT-Thread代碼啟動(dòng)線程切換過程的實(shí)現(xiàn)

    就緒列表里面, 表示線程已經(jīng)就緒,系統(tǒng)隨時(shí)可以調(diào)度。2.1.1. 實(shí)現(xiàn)就緒列表就緒列表實(shí)際就是
    發(fā)表于 04-25 11:38

    RT-Thread嵌入式操作系統(tǒng)線程優(yōu)先級該怎樣去實(shí)現(xiàn)呢

    就緒列表RT-Thread 要支持多優(yōu)先級,需要靠就緒列表的支持,從代碼看,就緒列表由兩個(gè)在
    發(fā)表于 05-09 14:32

    rt-thread優(yōu)先級線程可以調(diào)度執(zhí)行嗎?

    請教下,在rt-thread中,如果低優(yōu)先級線程中用while(1){}直接死循環(huán),是不是高優(yōu)先級線程也無法調(diào)度執(zhí)行了?如果高
    發(fā)表于 05-13 10:51

    RT-Thread線程優(yōu)先級鏈表與位圖算法的介紹

    隊(duì)列為當(dāng)前系統(tǒng)最高優(yōu)先級,則調(diào)用rt_list_insert_before(&(rt_thread_priority_table[thread
    發(fā)表于 05-13 15:38

    RT-Thread系統(tǒng)線程調(diào)度器的設(shè)計(jì)實(shí)現(xiàn)

    就將演變?yōu)樵?b class='flag-5'>優(yōu)先級數(shù)組中尋找具有最高優(yōu)先級線程的非空鏈表。RT-Thread內(nèi)核中采用了基于位圖的優(yōu)先級
    發(fā)表于 08-23 15:24

    RT-Thread實(shí)時(shí)操作系統(tǒng)中的五種狀態(tài)之間是如何變換的

    線程由于申請一個(gè)資源(例如使用rt_sem_take),而可能進(jìn)入掛起態(tài)。又例如因?yàn)橐粋€(gè)外部中斷發(fā)生了,系統(tǒng)轉(zhuǎn)入中斷服務(wù)例程,在中斷服務(wù)例程中釋放了相應(yīng)的資源,導(dǎo)致把等待在這個(gè)資源
    發(fā)表于 08-24 16:15

    RT-Thread線程管理手冊指南

    _resume (rt_thread_t thread)使線程恢復(fù)運(yùn)行詳細(xì)描述線程管理接口RT-Thread操作系統(tǒng)是基于
    發(fā)表于 08-26 16:22

    RT-Thread實(shí)時(shí)系統(tǒng)的線程設(shè)計(jì)應(yīng)該注意什么要點(diǎn)

    key線程來處理按鍵。線程的狀態(tài)躍遷這里說的狀態(tài)躍遷指的是線程運(yùn)行中狀態(tài)的變化,從就緒態(tài)過渡到掛起態(tài)
    發(fā)表于 09-14 15:45

    如何去處理RT-Thread線程優(yōu)先級的問題呢

    RT-Thread優(yōu)先級問題,官方文檔互斥量一節(jié),線程2的優(yōu)先級線程1高,但在線程2runni
    發(fā)表于 12-05 11:51