SylixOS armv7 任務切換

SylixOS 操作系統下,任務切換可以分為兩種

  • 中斷退出時,執行的任務切換(_ScheduleInt)
  • 內核退出時,執行的任務切換(_Schedule)

下面分別講講這兩種任務切換

1、中斷退出時任務切換

關于 ARM 架構下,棧空間,推薦這篇文章:ARM 棧和函數調用

;/*********************************************************************************************************
;  中斷入口
;*********************************************************************************************************/FUNC_DEF(archIntEntry);/* 在 IRQ 模式下,LR(R14_irq)存儲的是 當前執行地址 + 4,所以需要 減 4 調整回正確的返回地址 */SUB     LR , LR, #4                                                 ;/*  調整用于中斷返回的 PC 值    */;/* 保存 REG 到 IRQ 模式棧空間(中斷上下文保存)*/STMFD   SP!, {LR}                                                   ;/*  保存返回地址                */STMFD   SP!, {R0-R12}                                               ;/*  保存寄存器                  */;/* 將當前 IRQ 模式的棧指針 SP_irq 存入 R1(用于后續保存 SYS 模式寄存器)*/MOV     R1 , SPMSR     CPSR_c, #(DIS_INT | SYS32_MODE)                             ;/*  回到 SYS 模式               */;/* 將 SYS 模式的棧指針 SP_sys 存入 R1 指向的內存(保存任務棧)*/STMFD   R1!, {SP}                                                   ;/*  保存 SP_sys                 */;/* 將 SYS 模式的鏈接寄存器 LR_sys 存入 R1 指向的內存(保存任務返回地址) */STMFD   R1 , {LR}                                                   ;/*  保存 LR_sys                 */MSR     CPSR_c, #(DIS_INT | IRQ32_MODE)                             ;/*  回到 IRQ 模式               */SUB     SP , SP , #(2 * 4)                                          ;/*  調整 SP_irq                 */;/* 讀取 SPSR_irq(保存了被中斷任務的 CPSR_sys) */MRS     R2 , SPSR;/* 將 SPSR_irq(即原 CPSR_sys)壓入 IRQ 模式棧(保存任務狀態) */STMFD   SP!, {R2}                                                   ;/*  保存 CPSR_sys               */;/*; * API_InterEnter(SP_irq), 如果是第一次中斷, 會將 IRQ 模式棧空間的 ARCH_REG_CTX; * 拷貝到當前任務 TCB 的 ARCH_REG_CTX 里; */MOV     R0 , SPLDR     R1 , =API_InterEnterMOV     LR , PCBX      R1;/*; * 如果不是第一次進入中斷, 那么上一次中斷(工作在 SYS 模式)已經設置 SP_sys, 只需要回到 SYS 模式; */CMP     R0 , #1BNE     1f;/*; * 第一次進入中斷: 因為已經將 IRQ 模式棧空間的 ARCH_REG_CTX 拷貝到當前任務 TCB 的 ARCH_REG_CTX 里; * 調整 SP_irq; */ADD     SP , SP , #(ARCH_REG_CTX_SIZE);/*; * 第一次進入中斷: 獲得當前 CPU 中斷堆棧棧頂, 并回到 SYS 模式, 并設置 SP_sys; */LDR     R0 , =API_InterStackBaseGetMOV     LR , PCBX      R0MSR     CPSR_c, #(DIS_INT | SYS32_MODE)                             ;/*  回到 SYS 模式               */MOV     SP , R0                                                     ;/*  設置 SP_sys                 */1:MSR     CPSR_c, #(DIS_INT | SYS32_MODE)                             ;/*  回到 SYS 模式(不是多余的)   */;/*; * bspIntHandle(); */LDR     R1 , =bspIntHandleMOV     LR , PCBX      R1;/*; * API_InterExit(); * 如果沒有發生中斷嵌套, 則 API_InterExit 會調用 archIntCtxLoad 函數, SP_irq 在上面已經調整好; */LDR     R1 , =API_InterExitMOV     LR , PCBX      R1

??這里有一個很重要的點,API_InterStackBaseGet函數。因為 ARM 異常棧通常不會很大,而我們后面調用的 bspIntHandle 是一個 C 函數,需要用到堆棧。所以這里調用 API_InterStackBaseGet 函數設置了一個操作系統給每個 CPU 分配的中斷堆棧。

LW_API
ULONG    API_InterEnter (ARCH_REG_T  reg0,ARCH_REG_T  reg1,ARCH_REG_T  reg2,ARCH_REG_T  reg3)
{PLW_CLASS_CPU  pcpu;pcpu = LW_CPU_GET_CUR();pcpu->CPU_ulInterNesting++;#if !defined(__SYLIXOS_ARM_ARCH_M__) || (LW_CFG_CORTEX_M_SVC_SWITCH > 0)archIntCtxSaveReg(pcpu, reg0, reg1, reg2, reg3);
#endif	......
}

這里要注意,中斷上下文的保存,不僅僅需要保存到 ARM 架構的異常棧中,同時也需要保存一份,到當前任務 TCB 中。因為中斷退出時(API_InterExit),會進行調度(_ScheduleInt)。所以無法保證中斷結束后,一定運行的是之前被中斷的任務,也有可能是其它高優先級任務。之前被中斷的任務的上下文現場,必須要保存一份到它自己的 TCB 中!用于后面恢復!

??API_InterExit 函數中的 __KERNEL_SCHED_INT 會進行一系列判斷,查找到需要切換的任務(不一定是之前被打斷的任務),獲得任務的 TCB 控制塊。然后使用 archIntCtxLoad 函數進行任務上下文切換。

LW_API
VOID    API_InterExit (VOID)
{......__KERNEL_SCHED_INT(pcpu);											/*  中斷中的調度                */......
#if !defined(__SYLIXOS_ARM_ARCH_M__) || (LW_CFG_CORTEX_M_SVC_SWITCH > 0)archIntCtxLoad(pcpu);                                               /*  中斷返回 (當前任務 CTX 加載)*/
#endif......
}
FUNC_DEF(archTaskCtxStart)LDR     R0 , [R0]                                                   ;/*  獲取當前 TCB 的 REG_CTX 地址*/LINE_LABEL(archTaskCtxLoad)LDMIA   R0!, {R2-R4}                                                ;/*  讀取 CPSR LR SP             */MSR     CPSR_c , #(DIS_INT | SYS32_MODE)                            ;/*  進入 SYS 模式, 關中斷       */MOV     SP , R4                                                     ;/*  恢復 SP_sys                 */MOV     LR , R3                                                     ;/*  恢復 LR_sys                 */MSR     CPSR_c, #(DIS_INT | SVC32_MODE)                             ;/*  進入 SVC 模式, 關中斷       */MSR     SPSR_cxsf , R2                                              ;/*  CPSR_sys -> SPSR_svc        */LDMIA   R0 , {R0-R12, PC}^                                          ;/*  恢復包括 PC 的所有寄存器,   */;/*  同時更新 CPSR               */FUNC_END()FUNC_DEF(archIntCtxLoad)B       archTaskCtxStartFUNC_END()

2、內核退出時任務切換

??在內核退出時最終會調用 archTaskCtxSwitch 函數進行任務切換。

INT  _Schedule (VOID)
{....../* 前面的調度已經找到了一個最適合在當前核上運行的任務,下面就是將該任務加載到當前 CPU 核的寄存器中 */archTaskCtxSwitch(pcpuCur);  ......
}
/*********************************************************************************************************
** 函數名稱: __kernelExit
** 功能描述: 退出內核狀態
** 輸 入  : NONE
** 輸 出  : 調度器返回值
** 全局變量: 
** 調用模塊: 
*********************************************************************************************************/
INT  __kernelExit (VOID)
{......iRetVal = _Schedule();                                      /*  嘗試調度                    */......
}

??首先是保存當前上下文,和進入中斷時一樣,保存當前 TCB 上下文。這里有一個很重要的點,_SchedSafeStack函數。因為是任務調度,所以使用的棧還是當前 TCB 的棧。因為我們下面需要調用 _SchedSwp C 函數,會用到棧,可能會破壞之前 TCB 的棧空間。所以我們需要調用 _SchedSafeStack函數來獲取一個額外的堆棧空間。

??然后調用 _SchedSwp 程序進行切換當前 CPU 控制塊的當前 TCB,然后進行上下文恢復。

;/*********************************************************************************************************
;  線程切換 
;  參數為當前 CPU 控制塊, 即 R0 為當前 CPU 控制塊指針
;*********************************************************************************************************/FUNC_DEF(archTaskCtxSwitch)LDR     R1 , [R0]                                                   ;/*  獲取當前 TCB                */ADD     R1 , R1 , #(ARCH_REG_CTX_SIZE)                              ;/*  當前 TCB 的 REG_CTX 頂端地址*//* 保存當前 TCB 的上下文,保存到當前 TCB 中 */STMFD   R1!, {LR}                                                   ;/*  保存返回地址                */STMFD   R1 , {R0-R12}                                               ;/*  保存寄存器                  */SUB     R1 , R1 , #(13 * 4)                                         ;/*  調整 R1                     */STMFD   R1!, {SP}                                                   ;/*  保存 SP                     */STMFD   R1!, {LR}                                                   ;/*  保存 LR                     */MRS     R2 , CPSR                                                   ;/*  保存 CPSR                   */STMFD   R1!, {R2}MOV     R9 , R0                                                     ;/*  備份 R0                     */
#if LW_CFG_SMP_EN > 0LDR     R1 , =_SchedSafeStack                                       ;/*  _SchedSafeStack();          */MOV     LR , PCBX      R1MOV     SP , R0                                                     ;/*  設置 SP                     */MOV     R0 , R9                                                     ;/*  恢復 R0                     */
#endif;/* 這里會去切換當前 CPU 控制塊的當前 TCB */LDR     R1 , =_SchedSwp                                             ;/*  _SchedSwp();                */MOV     LR , PCBX      R1MOV     R0 , R9                                                     ;/*  恢復 R0                     */;/* 因為剛剛已經切換過,這里直接恢復切換后的 TCB 上下文 */B       archTaskCtxStartFUNC_END()

archTaskCtxStart 這里和中斷退出時恢復寄存器一樣。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/84210.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/84210.shtml
英文地址,請注明出處:http://en.pswp.cn/web/84210.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java 自定義異常:如何優雅地處理程序中的“業務病”?

🔥「炎碼工坊」技術彈藥已裝填! 點擊關注 → 解鎖工業級干貨【工具實測|項目避坑|源碼燃燒指南】 一、從一個真實場景開始:銀行轉賬系統的困境 假設你正在開發一個銀行轉賬系統,當用戶嘗試轉賬時可能出現以下問題: 轉…

【JAVA】【Stream流】

1. filter操作 filter()方法用于根據給定的條件過濾列表中的元素&#xff0c;僅保留滿足條件的項。 List<Integer> list Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);List<Integer> res list.stream().filter(a -> a % 2 0).collect(Collectors.toList());for(I…

四、Redis實現限流

簡介&#xff1a; 限流算法在分布式領域是一個經常被提起的話題&#xff0c;當系統的處理能力有限時&#xff0c;如何阻止計劃外的請求繼續對系統施壓。 系統要限定用戶的某個行為在指定的時間里只能允許發生 N 次&#xff0c;如何使用 Redis 的數據結構來實現這個限流的功能&a…

基于Geotools的兩條道路相交并根據交點形成新路線實戰-以OSM數據為例

目錄 前言 一、需求場景及分解 1、需求場景 2、需求應用 二、需求實現 1、加載路網數據 2、獲取道路信息 3、相交點求解 4、生成新道路 5、結果可視化 三、總結 前言 在當今數字化迅速發展的時代&#xff0c;地理空間數據的處理與分析已成為眾多領域不可或缺的關鍵技…

goland有基礎速通(需要其它編程語言基礎)

tip: 無論是變量、方法還是struct的訪問權限控制都是通過命名控制的&#xff0c;命名的首字母是大寫就相當于java中的public&#xff0c;小寫的話就是private&#xff0c;&#xff08;private只有本包可以訪問&#xff09; 1 go的變量聲明 普通變量 特點&#xff1a; 變量類…

量化面試綠皮書:19. 相關系數

文中內容僅限技術學習與代碼實踐參考&#xff0c;市場存在不確定性&#xff0c;技術分析需謹慎驗證&#xff0c;不構成任何投資建議。 19. 相關系數 假設有三個隨機變量x、y和z。 x與y之間的相關系數為0.8&#xff0c;x與z之間的相關系數也是0.8。 Q: 那么y與z之間的最大相關…

新生活的開啟:從 Trae AI 離開后的三個月

很久沒有寫文章了&#xff0c;想借著入職新公司一個月的機會&#xff0c;和大家嘮嘮嗑。 離職 今年2月份我從字節離職了&#xff0c;結束了四年的經歷&#xff0c;當時離開的核心原因是覺得加班時間太長了&#xff0c;平均每天都要工作15&#xff0c;16個小時&#xff0c;周末…

LLM部署之vllm vs deepspeed

部署大語言模型(如 Qwen/LLaMA 等)時,vLLM 與 DeepSpeed 是當前主流的兩種高性能推理引擎。它們各自專注于不同方向,部署流程也有明顯區別。 vLLM 提供極致吞吐、低延遲的推理服務,適用于在線部署;DeepSpeed 更側重訓練與推理混合優化,支持模型并行,適用于推理 + 微調/…

Git(二):基本操作

文章目錄 Git(二)&#xff1a;基本操作添加文件修改文件版本回退撤銷修改情況一&#xff1a;工作區的代碼還沒有 add情況?&#xff1a;已經 add 但沒有 commit情況三&#xff1a;已經 add 并且也 commit 刪除文件 Git(二)&#xff1a;基本操作 添加文件 首先我們先來學習一個…

nginx + ffmpeg 實現 rtsp視頻實時播放和歷史播放

nginx和ffmpeg 的安裝請參考我的另一篇文章 Nginxrtmpffmpeg搭建視頻轉碼服務_nginx-rtmp-module-master-CSDN博客 目錄 1、整體方案設計如圖 2、nginx下目錄創建和配置文件創建 3、創建視頻流生成腳本 4、修改nginx配置 5、管理界面 (video.html) 6、ffmpeg后臺啟動 …

全國產!瑞芯微 RK3576 ARM 八核 2.2GHz 工業核心板—硬件說明書

前 言 本文為創龍科技 SOM-TL3576 工業核心板硬件說明書,主要提供 SOM-TL3576 工業 核心板的產品功能特點、技術參數、引腳定義等內容,以及為用戶提供相關電路設計指導。 為便于閱讀,下表對文檔出現的部分術語進行解釋;對于廣泛認同釋義的術語,在此不做注釋。 硬件參考…

web3 瀏覽器注入 (如 MetaMask)

以下是關于 瀏覽器注入方式(如 MetaMask) 的完整詳解,包括原理、使用方法、安全注意事項及常見問題解決方案: 1. 核心原理 當用戶安裝 MetaMask 等以太坊錢包擴展時,錢包會向瀏覽器的 window 對象注入一個全局變量 window.ethereum,這個對象遵循 EIP-1193 標準,提供與區…

解密提示詞工程師:AI 時代的新興職業

大家好!在人工智能飛速發展的當下&#xff0c;有一個新興職業正悄然崛起——提示詞工程師。他們雖不如數據科學家般廣為人知&#xff0c;卻在 AI 應用領域發揮著獨特且關鍵的作用。 何為提示詞工程師&#xff1f; 提示詞工程師專注于設計和優化與 AI 模型進行交互的提示詞&…

linux 下 jenkins 構建 uniapp node-sass 報錯

背景: jenkins 中構建 uniapp 應用 配置: 1. 將windows HbuilderX 插件目錄下的 uniapp-cli 文件夾復制到 服務器 /var/jenkins_home/uniapp-cli 2. jenkins 構建步驟增加 執行 shell ,內容如下 echo ">> 構建中..."# 打包前端 export LANGen_US.UTF-8…

QT常見問題(1)

QT常見問題&#xff08;1&#xff09; 1.問題描述 Qt在編譯器中直接運行沒有任何問題&#xff0c;但是進入exe生成目錄直接雙擊運行就報錯&#xff1a;文件無法定位程序輸入點_zn10qarraydata10deallocateepsyy于動態鏈接庫。 2.問題原因 這個錯誤通常是由于程序運行時找不…

『大模型筆記』第2篇:并發請求中的 Prefill 與 Decode:優化大語言模型性能

『大模型筆記』并發請求中的 Prefill 與 Decode:優化大語言模型性能 文章目錄 一. Token 生成的兩個階段:Prefill 和 Decode1.1. 指標分析1.2. 資源利用率分析二. 并發處理機制2.1. 靜態批處理 vs 持續批處理(Static Batching vs. Continuous Batching)2.2. Prefill 優先策略…

JVM(7)——詳解標記-整理算法

核心思想 標記-整理算法同樣分為兩個主要階段&#xff0c;但第二個階段有所不同&#xff1a; 標記階段&#xff1a; 與標記-清除算法完全一致。遍歷所有可達對象&#xff08;從 GC Roots 開始&#xff09;&#xff0c;標記它們為“存活”。 整理階段&#xff1a; 不再簡單地清…

進程虛擬地址空間

1. 程序地址空間回顧 我們在學習語言層面時&#xff0c;會了解到這樣的空間布局圖&#xff0c;我們先對他進行分區了解&#xff1a; 如果以靜態static修飾的變量就會當成已初始化全局變量來看待&#xff0c;存放在已初始化數據區和未初始化數據區之前。 如果不用static修飾test…

C語言學習day17-----位運算

目錄 1.位運算 1.1基礎知識 1.1.1定義 1.1.2用途 1.1.3軟件控制硬件 1.2運算符 1.2.1與 & 1.2.2或 | 1.2.3非 ~ 1.2.4異或 ^ 1.2.5左移 << 1.2.6右移 >> 1.2.7代碼實現 1.2.8置0 1.2.9置1 1.2.10不借助第三方變量&#xff0c;實現兩個數的交換…

【linux】簡單的shell腳本練習

簡單易學 解釋性語言&#xff0c;不需要編譯即可執行 對于一個合格的系統管理員來說&#xff0c;學習和掌握Shell編程是非常重要的&#xff0c;通過shell程序&#xff0c;可以在很大程度上簡化日常的維護工作&#xff0c;使得管理員從簡單的重復勞動中解脫出來 用戶輸入任意兩…