一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

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

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

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

深度剖析 RT-Thread 線程調(diào)度流程

RT-Thread官方賬號(hào) ? 2025-06-25 18:24 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

RT-Thread 調(diào)度第一個(gè)線程的主要流程分如下:

97b0dbf8-51ae-11f0-986f-92fbcf53809c.png

rtthread_startup:RTT的啟動(dòng)函數(shù),主要負(fù)責(zé)板級(jí)驅(qū)動(dòng),調(diào)度器,系統(tǒng)線程初始化,啟動(dòng)調(diào)度的工作

rt_system_scheduler_start:調(diào)度系統(tǒng)第一個(gè)線程

rt_hw_context_switch_to:初始化上下文切換環(huán)境,觸發(fā) PendSV 異常

first_thread:系統(tǒng)中優(yōu)先級(jí)最高的線程的入口函數(shù)

???

rt_hw_context_switch_to

rt_hw_context_switch_to((rt_uintptr_t)&to_thread->sp):


加載目標(biāo)線程的堆棧狀態(tài),使CPU開始執(zhí)行目標(biāo)線程的代碼

(rt_uintptr_t)&to_thread->sp表示目標(biāo)線程的堆棧指針地址;to_thread->sp是目標(biāo)線程的堆棧指針,此時(shí)SP=0x2000198C

97c078f6-51ae-11f0-986f-92fbcf53809c.png

函數(shù)原型:

rt_hw_context_switch_to PROC EXPORT rt_hw_context_switch_to ; set to thread LDR r1, =rt_interrupt_to_thread STR r0, [r1]

這段匯編可以類比為C語言寫法:

rt_uintptr_tr0 = (rt_uintptr_t)&to_thread->sp;// r0 傳入的棧指針地址rt_uintptr_t*r1 = &rt_interrupt_to_thread;// r1 加載 rt_interrupt_to_thread 的地址*r1 = r0;// 將 r0 的值賦給 r1 指向的地址

此時(shí)rt_interrupt_to_thread地址存儲(chǔ)的是目標(biāo)線程SP的地址,通過內(nèi)存窗口查看0x2000113c地址中內(nèi)容,內(nèi)容即為0x2000198C

97d77920-51ae-11f0-986f-92fbcf53809c.png97f1dc2a-51ae-11f0-986f-92fbcf53809c.png

接下來設(shè)置rt_interrupt_from_thread的值為0,表示啟動(dòng)第一次線程切換:

980c80d4-51ae-11f0-986f-92fbcf53809c.png

設(shè)置中斷標(biāo)志位rt_thread_switch_interrupt_flag的值為1,因?yàn)?Cortex-M 是通過 PendSV 異常進(jìn)行線程切換的,所以這里置位表示要進(jìn)行切換,稍后會(huì)用到。

98219514-51ae-11f0-986f-92fbcf53809c.png

NVIC_SYSPRI2 EQU0xE000ED20;system priorityregister(2)NVIC_PENDSV_PRI EQU 0xFFFF0000 ;PendSVandSysTick priorityvalue(lowest);setthe PendSVandSysTick exception priorityLDR r0, =NVIC_SYSPRI2 ; 將 NVIC_SYSPRI2 的地址加載到 r0LDR r1, =NVIC_PENDSV_PRI ; 將 NVIC_PENDSV_PRI 的值加載到 r1LDR.W r2, [r0,#0x00] ; 讀取 NVIC_SYSPRI2 的當(dāng)前值到 r2ORR r1, r1, r2 ; 將 r1 和 r2 的值進(jìn)行按位或操作,保持其他位不變STR r1, [r0] ; 將修改后的值寫回 NVIC_SYSPRI2,更新 PendSV 和 SysTick 的優(yōu)先級(jí)

接下來分別將PendSVSysTick異常的優(yōu)先級(jí)設(shè)置為最低優(yōu)先級(jí)(0xFFFF0000)

最低優(yōu)先級(jí)的意義:

延遲上下文切換:通過將 PendSV 的優(yōu)先級(jí)設(shè)置為最低(0xFF),確保它在所有其他中斷(例如硬件中斷或更高優(yōu)先級(jí)的異常)處理完成后才會(huì)執(zhí)行。這避免了上下文切換被高優(yōu)先級(jí)中斷打斷,保證了中斷處理程序的實(shí)時(shí)性。

避免搶占:在 RTOS 中,上下文切換是一個(gè)相對(duì)耗時(shí)的操作(涉及保存/恢復(fù)寄存器、棧操作等)。將 PendSV 設(shè)置為最低優(yōu)先級(jí),確保它不會(huì)搶占其他關(guān)鍵中斷(如定時(shí)器、外部設(shè)備中斷),從而提高系統(tǒng)的實(shí)時(shí)性和穩(wěn)定性。

;trigger the PendSVexception(causes contextswitch)LDR r0, =NVIC_INT_CTRL ; 將 NVIC_INT_CTRL 的地址加載到 r0LDR r1, =NVIC_PENDSVSET ; 將 NVIC_PENDSVSET 的值加載到 r1STR r1, [r0] ; 將 r1 的值寫入 NVIC_INT_CTRL 寄存器

這段代碼通過向 NVIC 的 ICSR 寄存器寫入NVIC_PENDSVSET值,手動(dòng)的觸發(fā) PendSV 異常。觸發(fā)后,處理器會(huì)在當(dāng)前中斷或異常處理完成后調(diào)用PendSV_Handler,執(zhí)行線程上下文切換。



SCB_VTOR EQU0xE000ED08; VectorTableOffsetRegisterLDR r0,=SCB_VTOR ; 將 SCB_VTOR 的地址加載到 r0LDR r0, [r0] ; 從 SCB_VTOR 地址讀取向量表地址到 r0LDR r0, [r0] ; 從向量表起始地址讀取初始 MSP 值到 r0MSR msp, r0 ; 將 r0 的值寫入 MSP 寄存器

這段代碼從向量表中提取初始主堆棧指針(MSP)的值,并將其恢復(fù)到 MSP 寄存器。

作用是重置主堆棧指針(MSP)到系統(tǒng)啟動(dòng)時(shí)的初始狀態(tài),通常用于初始化或上下文切換的場(chǎng)景,確保處理器在特權(quán)模式下使用正確的堆棧。

芯片啟動(dòng)時(shí)(Reset_Handler),MSP的數(shù)值為:0x200010E0

98329738-51ae-11f0-986f-92fbcf53809c.png

我們可以發(fā)現(xiàn)當(dāng)執(zhí)行完206行后

MSP 的數(shù)值已經(jīng)恢復(fù)成初值了(0x200010E0)

984779aa-51ae-11f0-986f-92fbcf53809c.png


CPSIE F ; 啟用故障異常(Fault)CPSIEI; 啟用中斷(Interrupt)

CPSIE I:

指令含義:CPSIE I 用于啟用中斷。

作用:該指令清除PRIMASK寄存器的值(將其置為 0),從而啟用所有配置為可屏蔽的中斷(包括外部中斷和系統(tǒng)異常)。

背景

PRIMASK 是一個(gè)特殊寄存器,用于控制中斷的屏蔽狀態(tài)。當(dāng) PRIMASK = 1 時(shí),除 NMI 和 HardFault 外的所有中斷被禁用。

因此到了這里代表即將要觸發(fā) PendSV 中斷來進(jìn)行線程切換


; clear the BASEPRI register todisablemasking priorityMOV r0,#0x00 ; 將 r0 設(shè)置為 0MSR BASEPRI, r0 ; 將 r0 的值(0)寫入 BASEPRI 寄存器

作用:

在觸發(fā) PendSV 異常后,清除 BASEPRI 確保不會(huì)因?yàn)橹暗膬?yōu)先級(jí)屏蔽設(shè)置而阻止任何中斷的觸發(fā)。

這是初始化線程環(huán)境的一部分,確保目標(biāo)線程運(yùn)行時(shí),處理器能夠響應(yīng)所有可屏蔽中斷。


???

PendSV_Handler

PendSV_Handler PROCEXPORT PendSV_Handler; disable interrupt to protect contextswitchMRS r2, PRIMASK ; 將 PRIMASK 寄存器的值讀取到 r2CPSID I ; 禁用中斷(設(shè)置 PRIMASK =1);getrt_thread_switch_interrupt_flagLDR r0, =rt_thread_switch_interrupt_flag ; 將 rt_thread_switch_interrupt_flag 的地址加載到 r0LDR r1, [r0] ; 從該地址讀取值到 r1CBZ r1, pendsv_exit ; 如果 r1 為0,跳轉(zhuǎn)到 pendsv_exit

985c8796-51ae-11f0-986f-92fbcf53809c.png

保護(hù)上下文切換:

通過CPSID I禁用中斷,確保上下文切換過程不被其他中斷打斷。

保存PRIMASK(通過 MRS r2, PRIMASK)允許在切換完成后恢復(fù)原始中斷狀態(tài),避免影響系統(tǒng)的中斷配置。

檢查切換請(qǐng)求:

通過讀取rt_thread_switch_interrupt_flag,檢查是否需要執(zhí)行上下文切換。如果標(biāo)志為 0,說明無需切換,直接退出,減少不必要的開銷。


LDR r0, =rt_interrupt_from_thread ; 將 rt_interrupt_from_thread 的地址加載到 r0LDR r1, [r0] ; 從該地址讀取值到 r1CBZ r1, switch_to_thread ; 如果 r1 為 0,跳轉(zhuǎn)到 switch_to_thread

這段代碼檢查rt_interrupt_from_thread是否為 0,以決定是否需要保存當(dāng)前線程的上下文。

如果 r1 為 0,說明無需保存上下文,直接跳轉(zhuǎn)到switch_to_thread加載目標(biāo)線程的上下文。

如果 r1 非零,說明有來源線程需要保存上下文,代碼會(huì)繼續(xù)執(zhí)行后續(xù)的寄存器保存操作(如保存 r4-r11 和 FPU 寄存器)。

聯(lián)系上文,rt_interrupt_from_thread在系統(tǒng)啟動(dòng)時(shí)在函數(shù)rt_hw_context_switch_to中已經(jīng)置為0,所以此時(shí)應(yīng)該切換到switch_to_thread函數(shù)


switch_to_threadLDR r1, =rt_interrupt_to_thread ; 將 rt_interrupt_to_thread 的地址加載到 r1LDR r1, [r1] ; 從該地址讀取值到 r1LDR r1, [r1] ; 從該值指向的地址讀取線程堆棧指針到 r1

作用:

rt_interrupt_to_thread存儲(chǔ)目標(biāo)線程的堆棧指針地址(rt_hw_context_switch_to函數(shù)傳入的第一個(gè)參數(shù))。

第一次 LDR r1, [r1] 從rt_interrupt_to_thread讀取目標(biāo)線程的堆棧指針地址(例如,&to_thread->sp)。

第二次 LDR r1, [r1] 從該地址讀取實(shí)際的堆棧指針值(to_thread->sp),即目標(biāo)線程的當(dāng)前堆棧頂部。

9871eadc-51ae-11f0-986f-92fbcf53809c.png

通過上述步驟,獲取目標(biāo)線程的堆棧指針,為后續(xù)從堆棧中恢復(fù)上下文做準(zhǔn)備。


針對(duì)棧幀的處理:

IF{FPU} !="SoftVFP"LDMFDr1!, {r3} ; 彈出 FPU 使用標(biāo)志到 r3ENDIFLDMFDr1!, {r4 - r11} ; 彈出 r4 - r11 寄存器IF{FPU} !="SoftVFP"CMPr3, #0; 如果 flag_r3 !=0VLDMFDNEr1!, {d8 - d15} ; 彈出 FPU 寄存器 s16~s31ENDIFMSRpsp, r1 ; 更新堆棧指針到 PSPIF{FPU} !="SoftVFP"ORRlr, lr, #0x10 ; lr |= (1<

作用:

如果處理器支持硬件浮點(diǎn)單元,從目標(biāo)線程的堆棧中彈出 FPU 使用標(biāo)志。

從目標(biāo)線程的堆棧中彈出寄存器 r4 到 r11 的值,恢復(fù)目標(biāo)線程的通用寄存器狀態(tài)。

r4-r11 是 ARM 架構(gòu)中需要手動(dòng)保存的寄存器,r0-r3 和 r12 等由硬件自動(dòng)壓棧

可見壓棧的順序和cpuport.c中的線程棧幀是完全對(duì)應(yīng)的,見下圖:

98896554-51ae-11f0-986f-92fbcf53809c.png

???

Pendsv_Exit


作用:

恢復(fù)中斷狀態(tài)

通過MSR PRIMASK, r2,恢復(fù)進(jìn)入 PendSV 異常前的中斷狀態(tài)(使能或禁用),確保系統(tǒng)中斷配置不受影響。

設(shè)置異常返回堆棧

通過ORR lr, lr, #0x04,設(shè)置 EXC_RETURN[2] = 1,確保異常返回時(shí)使用PSP,切換到目標(biāo)線程的堆棧。(線程模式使用 PSP,特權(quán)模式使用 MSP)。

完成異常退出

通過BX lr,觸發(fā)異常返回,處理器切換到線程模式,恢復(fù)目標(biāo)線程的執(zhí)行上下文(包括 PC、寄存器和堆棧)。

通過調(diào)試我們可以查看要切換的第一個(gè)線程(main)的入口地址是:0x080050A1

989fbba6-51ae-11f0-986f-92fbcf53809c.png

當(dāng)執(zhí)行完成pendsv_exit函數(shù)后,進(jìn)入main_thread_entry線程入口函數(shù),可以看到PC指向的地址是移植的,至此已經(jīng)完成了 RT-Thread 的第一個(gè)線程切換。

98b699e8-51ae-11f0-986f-92fbcf53809c.png

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

    關(guān)注

    0

    文章

    54

    瀏覽量

    10930
  • 線程
    +關(guān)注

    關(guān)注

    0

    文章

    508

    瀏覽量

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

    關(guān)注

    32

    文章

    1385

    瀏覽量

    41669
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    RT-Thread記錄(三、RT-Thread線程操作函數(shù))

    講完了RT-Thread開發(fā)環(huán)境,啟動(dòng)流程,啟動(dòng)以后當(dāng)然是開始跑線程了,那么自然我們得學(xué)會(huì)如何創(chuàng)建線程以及線程的有關(guān)操作。
    的頭像 發(fā)表于 06-20 00:31 ?7756次閱讀
    <b class='flag-5'>RT-Thread</b>記錄(三、<b class='flag-5'>RT-Thread</b><b class='flag-5'>線程</b>操作函數(shù))

    RT-Thread記錄(二、RT-Thread內(nèi)核啟動(dòng)流程

    在前面我們RT-Thread Studio工程基礎(chǔ)之上講一講RT-Thread內(nèi)核啟動(dòng)流程.
    的頭像 發(fā)表于 06-20 00:30 ?5593次閱讀
    <b class='flag-5'>RT-Thread</b>記錄(二、<b class='flag-5'>RT-Thread</b>內(nèi)核啟動(dòng)<b class='flag-5'>流程</b>)

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

    RT-Thread 中,與上述子任務(wù)對(duì)應(yīng)的程序?qū)嶓w就是線程,線程是實(shí)現(xiàn)任務(wù)的載體,它是 RT-Thread 中最基本的調(diào)度單位,它描述了一
    發(fā)表于 03-29 06:16

    RT-Thread內(nèi)核簡(jiǎn)介

    RT-Thread 內(nèi)核簡(jiǎn)介前言1、RT-Thread 的架構(gòu)2、RT-Thread 的內(nèi)核3、RT-Thread 內(nèi)核功能部分線程
    發(fā)表于 08-06 07:44

    RT-Thread線程簡(jiǎn)介

    。RT-Thread線程簡(jiǎn)介線程thread)是系統(tǒng)能夠進(jìn)行調(diào)度的最小單位,在linux中也是這樣定義的,但是和我們RTOS中的
    發(fā)表于 08-24 07:56

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

    線程調(diào)度RT-Thread中提供的線程調(diào)度器是基于優(yōu)先級(jí)的全搶占式調(diào)度:在系統(tǒng)中除了中斷處理函
    發(fā)表于 08-23 15:24

    RT-Thread線程管理手冊(cè)指南

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

    RT-Thread學(xué)習(xí)筆記 --(6)RT-Thread線程間通信學(xué)習(xí)過程總結(jié)

    前兩篇文章總結(jié)了RT-Thread線程以及多線程同步的學(xué)習(xí)過程,關(guān)于前兩篇學(xué)習(xí)總結(jié),可以查看之前的文章。
    發(fā)表于 01-25 18:50 ?7次下載
    <b class='flag-5'>RT-Thread</b>學(xué)習(xí)筆記 --(6)<b class='flag-5'>RT-Thread</b><b class='flag-5'>線程</b>間通信學(xué)習(xí)過程總結(jié)

    RTthread線程調(diào)度詳解

    系統(tǒng)調(diào)度就是在就緒列表中尋找優(yōu)先級(jí)最高的就緒線程,然后去執(zhí)行該線程。但是目前我們還不支持優(yōu)先級(jí), 僅實(shí)現(xiàn)兩個(gè)線程輪流切換,系統(tǒng)調(diào)度函數(shù)
    的頭像 發(fā)表于 05-19 17:07 ?2864次閱讀

    大佬帶你理解RT-Thread內(nèi)核并上手實(shí)踐

    RT-Thread內(nèi)核的相關(guān)概念和基礎(chǔ)知識(shí),然后了解RT-Thread系統(tǒng)的啟動(dòng)流程、內(nèi)存分布情況以及內(nèi)核的配置方法。內(nèi)核處于硬件層之上,包括了內(nèi)核庫和實(shí)時(shí)內(nèi)核的實(shí)現(xiàn),而實(shí)時(shí)內(nèi)核又包括:對(duì)象管理、
    發(fā)表于 06-30 17:10 ?1579次閱讀

    RT-Thread學(xué)習(xí)筆記 RT-Thread的架構(gòu)概述

    聯(lián)網(wǎng)操作系統(tǒng)。 RT-Thread 概述 RT-Thread,全稱是 Real Time-Thread,顧名思義,它是一個(gè)嵌入式實(shí)時(shí)多線程
    的頭像 發(fā)表于 07-09 11:27 ?4968次閱讀
    <b class='flag-5'>RT-Thread</b>學(xué)習(xí)筆記 <b class='flag-5'>RT-Thread</b>的架構(gòu)概述

    RT-Thread文檔_線程管理

    RT-Thread文檔_線程管理
    發(fā)表于 02-22 18:28 ?0次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>線程</b>管理

    RT-Thread文檔_線程間同步

    RT-Thread文檔_線程間同步
    發(fā)表于 02-22 18:29 ?1次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>線程</b>間同步

    RT-Thread文檔_線程間通信

    RT-Thread文檔_線程間通信
    發(fā)表于 02-22 18:29 ?0次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>線程</b>間通信

    RT-Thread文檔_RT-Thread SMP 介紹與移植

    RT-Thread文檔_RT-Thread SMP 介紹與移植
    發(fā)表于 02-22 18:31 ?9次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> SMP 介紹與移植