女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

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

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

3天內不再提示

深度剖析 RT-Thread 線程調度流程

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

掃碼添加小助手

加入工程師交流群

RT-Thread 調度第一個線程的主要流程分如下:

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

rtthread_startup:RTT的啟動函數,主要負責板級驅動,調度器,系統線程初始化,啟動調度的工作

rt_system_scheduler_start:調度系統第一個線程

rt_hw_context_switch_to:初始化上下文切換環境,觸發 PendSV 異常

first_thread:系統中優先級最高的線程的入口函數

???

rt_hw_context_switch_to

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


加載目標線程的堆棧狀態,使CPU開始執行目標線程的代碼

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

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

函數原型:

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 指向的地址

此時rt_interrupt_to_thread地址存儲的是目標線程SP的地址,通過內存窗口查看0x2000113c地址中內容,內容即為0x2000198C

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

接下來設置rt_interrupt_from_thread的值為0,表示啟動第一次線程切換:

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

設置中斷標志位rt_thread_switch_interrupt_flag的值為1,因為 Cortex-M 是通過 PendSV 異常進行線程切換的,所以這里置位表示要進行切換,稍后會用到。

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 的當前值到 r2ORR r1, r1, r2 ; 將 r1 和 r2 的值進行按位或操作,保持其他位不變STR r1, [r0] ; 將修改后的值寫回 NVIC_SYSPRI2,更新 PendSV 和 SysTick 的優先級

接下來分別將PendSVSysTick異常的優先級設置為最低優先級(0xFFFF0000)

最低優先級的意義:

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

避免搶占:在 RTOS 中,上下文切換是一個相對耗時的操作(涉及保存/恢復寄存器、棧操作等)。將 PendSV 設置為最低優先級,確保它不會搶占其他關鍵中斷(如定時器、外部設備中斷),從而提高系統的實時性和穩定性。

;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值,手動的觸發 PendSV 異常。觸發后,處理器會在當前中斷或異常處理完成后調用PendSV_Handler,執行線程上下文切換。



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

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

作用是重置主堆棧指針(MSP)到系統啟動時的初始狀態,通常用于初始化或上下文切換的場景,確保處理器在特權模式下使用正確的堆棧。

芯片啟動時(Reset_Handler),MSP的數值為:0x200010E0

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

我們可以發現當執行完206行后

MSP 的數值已經恢復成初值了(0x200010E0)

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


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

CPSIE I:

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

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

背景

PRIMASK 是一個特殊寄存器,用于控制中斷的屏蔽狀態。當 PRIMASK = 1 時,除 NMI 和 HardFault 外的所有中斷被禁用。

因此到了這里代表即將要觸發 PendSV 中斷來進行線程切換


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

作用:

在觸發 PendSV 異常后,清除 BASEPRI 確保不會因為之前的優先級屏蔽設置而阻止任何中斷的觸發。

這是初始化線程環境的一部分,確保目標線程運行時,處理器能夠響應所有可屏蔽中斷。


???

PendSV_Handler

PendSV_Handler PROCEXPORT PendSV_Handler; disable interrupt to protect contextswitchMRS r2, PRIMASK ; 將 PRIMASK 寄存器的值讀取到 r2CPSID I ; 禁用中斷(設置 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,跳轉到 pendsv_exit

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

保護上下文切換:

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

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

檢查切換請求:

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


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

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

如果 r1 為 0,說明無需保存上下文,直接跳轉到switch_to_thread加載目標線程的上下文。

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

聯系上文,rt_interrupt_from_thread在系統啟動時在函數rt_hw_context_switch_to中已經置為0,所以此時應該切換到switch_to_thread函數


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

作用:

rt_interrupt_to_thread存儲目標線程的堆棧指針地址(rt_hw_context_switch_to函數傳入的第一個參數)。

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

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

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

通過上述步驟,獲取目標線程的堆棧指針,為后續從堆棧中恢復上下文做準備。


針對棧幀的處理:

IF{FPU} !="SoftVFP"LDMFDr1!, {r3} ; 彈出 FPU 使用標志到 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<

作用:

如果處理器支持硬件浮點單元,從目標線程的堆棧中彈出 FPU 使用標志。

從目標線程的堆棧中彈出寄存器 r4 到 r11 的值,恢復目標線程的通用寄存器狀態。

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

可見壓棧的順序和cpuport.c中的線程棧幀是完全對應的,見下圖:

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

???

Pendsv_Exit


作用:

恢復中斷狀態

通過MSR PRIMASK, r2,恢復進入 PendSV 異常前的中斷狀態(使能或禁用),確保系統中斷配置不受影響。

設置異常返回堆棧

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

完成異常退出

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

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

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

當執行完成pendsv_exit函數后,進入main_thread_entry線程入口函數,可以看到PC指向的地址是移植的,至此已經完成了 RT-Thread 的第一個線程切換。

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

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 調度
    +關注

    關注

    0

    文章

    54

    瀏覽量

    10926
  • 線程
    +關注

    關注

    0

    文章

    508

    瀏覽量

    20127
  • RT-Thread
    +關注

    關注

    32

    文章

    1384

    瀏覽量

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

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

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

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

    RT-Thread記錄(二、RT-Thread內核啟動流程

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

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

    RT-Thread 中,與上述子任務對應的程序實體就是線程線程是實現任務的載體,它是 RT-Thread 中最基本的調度單位,它描述了一
    發表于 03-29 06:16

    RT-Thread內核簡介

    RT-Thread 內核簡介前言1、RT-Thread 的架構2、RT-Thread 的內核3、RT-Thread 內核功能部分線程
    發表于 08-06 07:44

    RT-Thread線程簡介

    RT-Thread線程簡介線程thread)是系統能夠進行調度的最小單位,在linux中也是這樣定義的,但是和我們RTOS中的
    發表于 08-24 07:56

    RT-Thread系統線程調度器的設計實現

    線程調度RT-Thread中提供的線程調度器是基于優先級的全搶占式調度:在系統中除了中斷處理函
    發表于 08-23 15:24

    RT-Thread線程管理手冊指南

    _resume (rt_thread_t thread)使線程恢復運行詳細描述線程管理接口RT-Thread操作系統是基于
    發表于 08-26 16:22

    RT-Thread學習筆記 --(6)RT-Thread線程間通信學習過程總結

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

    RTthread線程調度詳解

    系統調度就是在就緒列表中尋找優先級最高的就緒線程,然后去執行該線程。但是目前我們還不支持優先級, 僅實現兩個線程輪流切換,系統調度函數
    的頭像 發表于 05-19 17:07 ?2855次閱讀

    大佬帶你理解RT-Thread內核并上手實踐

    RT-Thread內核的相關概念和基礎知識,然后了解RT-Thread系統的啟動流程、內存分布情況以及內核的配置方法。內核處于硬件層之上,包括了內核庫和實時內核的實現,而實時內核又包括:對象管理、
    發表于 06-30 17:10 ?1578次閱讀

    RT-Thread學習筆記 RT-Thread的架構概述

    聯網操作系統。 RT-Thread 概述 RT-Thread,全稱是 Real Time-Thread,顧名思義,它是一個嵌入式實時多線程
    的頭像 發表于 07-09 11:27 ?4961次閱讀
    <b class='flag-5'>RT-Thread</b>學習筆記 <b class='flag-5'>RT-Thread</b>的架構概述

    RT-Thread文檔_線程管理

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

    RT-Thread文檔_線程間同步

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

    RT-Thread文檔_線程間通信

    RT-Thread文檔_線程間通信
    發表于 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 介紹與移植
    發表于 02-22 18:31 ?9次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> SMP 介紹與移植