uC/OS-II 要點分析 ------ PendSV_Handler

来源:https://www.cnblogs.com/GyForever1004/archive/2018/01/19/8318860.html
-Advertisement-
Play Games

首先貼出今天要與大家分享的內容源碼(位於內核源碼的 os_cpu_a.asm 中):PendSV_Handler CPSID I MRS R0, PSP CBZ R0, PendSV_Handler_Nosave SUBS R0, R0, #0x20 STM R0, {R4-R11} LDR R1, ...


首先貼出今天要與大家分享的內容源碼(位於內核源碼的 os_cpu_a.asm 中):

PendSV_Handler
  CPSID I
  MRS R0, PSP
  CBZ R0, PendSV_Handler_Nosave

  SUBS R0, R0, #0x20
  STM R0, {R4-R11}

  LDR R1, =OSTCBCur
  LDR R1, [R1]
  STR R0, [R1]

PendSV_Handler_Nosave
  PUSH {R14}
  LDR R0, =OSTaskSwHook
  BLX R0
  POP {R14}

  LDR R0, =OSPrioCur
  LDR R1, =OSPrioHighRdy
  LDRB R2, [R1]
  STRB R2, [R0]

  LDR R0, =OSTCBCur
  LDR R1, =OSTCBHighRdy
  LDR R2, [R1]
  STR R2, [R0]

  LDR R0, [R2]
  LDM R0, {R4-R11}
  ADDS R0, R0, #0x20
  MSR PSP, R0
  ORR LR, LR, #0x04
  CPSIE I
  BX LR

這兩段代碼尤為重要,內核中任務的切換主要就是由它們實現的。接下來,我將逐行為大家解析其中的奧秘。

這兩段代碼是中斷服務程式(ISR),那麼由誰來觸發中斷呢?我們以OSCtxSw()這個函數為入手點。
它其實就是C程式中的OS_TASK_SW()

#define OS_TASK_SW() OSCtxSw()

開始分析OSCtxSw()

OSCtxSw
  PUSH {R4, R5}
  LDR R4, =NVIC_INT_CTRL
  LDR R5, =NVIC_PENDSVSET
  STR R5, [R4]
  POP {R4, R5}
  BX LR

1.首先進入函數,將R4,R5入棧,保護寄存器。
2.給R4,R5分別賦值,文件中這樣定義:
NVIC_INT_CTRL EQU 0xE000ED04
NVIC_PENDSVSET EQU 0x10000000
NVIC_INT_CTRL為中斷控制寄存器的地址,NVIC_PENDSVSET為PendSV中斷的觸發值
3.將觸發值寫入控制寄存器
4.彈出R4,R5


因為我們一般調用任務切換的時候,都是在臨界區調用(禁止中斷),所以不會產生中斷。之後調用OS_EXIT_CRITICAL()函數退出臨界區後,中斷才會發生,這樣就產生了PendSV異常。

接下來才是我們的重點,開始分析ISR!

CPSID I
#關中斷,防止切換任務期間被打擾

MRS R0, PSP
#取出PSP(程式棧指針)賦值給R0

CBZ R0, PendSV_Handler_Nosave
#若R0為0,則跳轉到PendSV_Handler_Nosave函數繼續執行,這裡我們講述的就是由延時導致的任務切換,PSP都是有值的,所以繼續執行

SUBS R0, R0, #0x20
#將R0 - 0x20 則R0與PSP之間空出8個單位(每個單位4個位元組)

STM R0, {R4-R11}
#將寄存器的R4-R11存入空出的8個單位

LDR R1, =OSTCBCur
#將當前TCB的地址賦給R1

LDR R1, [R1]
#取出地址處的數據(即OSTCBCur->SP的地址,因為OSTCB結構體的第一個數據就是SP)賦給R1

STR R0, [R1]
#將R0(棧頂數據的地址)賦值給OSTCBCur->SP,則OSTCBCur->SP與R0指向的位置相同

 

!!這段程式的OSTCBCur指的都是old_task的指針

這段程式的圖解:

 

 

PUSH {R14}
LDR R0, =OSTaskSwHook
BLX R0
POP {R14}
#這小段代碼就是執行OSTaskSwHook這個C的函數

LDR R0, =OSPrioCur
LDR R1, =OSPrioHighRdy
LDRB R2, [R1]
STRB R2, [R0]
#這小段代碼就將OSPrioHighRdy賦給OSPrioCur

LDR R0, =OSTCBCur
LDR R1, =OSTCBHighRdy
LDR R2, [R1]
STR R2, [R0]
#這小段代碼就將OSTCBHighRdy->SP賦給OSPrioCur->SP

LDR R0, [R2]
#將OSTCBHighRdy->SP的值(指向新任務棧中的地址,也就是新任務的棧頂)賦值給R0

LDM R0, {R4-R11}
#以R0為基址,讀出8個單位的數據給CPU的寄存器

ADDS R0, R0, #0x20
#R0地址 + 0x20,指向幾個重要的寄存器值(當前棧頂)

MSR PSP, R0
#將當前R0的值賦值給PSP

ORR LR, LR, #0x04
#確保異常返回後,新任務使用PSP指針

CPSIE I
#開啟中斷

 

!!這段程式的OSTCBCur指的都是new_task的指針

這段程式的圖解:

 

這樣也就完成了old_task到new_task的切換! 0.0

 

可能我理解不周,請謹慎參考,我會後期完善,謝謝支持!

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • PowerDesigner是一款功能非常強大的建模工具軟體,足以與Rose比肩,同樣是當今最著名的建模軟體之一。Rose是專攻UML對象模型的建模工具,之後才向資料庫建模發展,而PowerDesigner則與其正好相反,它是以資料庫建模起家,後來才發展為一款綜合全面的Case工具。 PowerDes ...
  • PowerDesigner 創建表格及導出SQL語句 目的:提高資料庫創建表格效率 測試資料庫:orcale 1.新建物理模型。 右鍵點擊workplace,new一個物理模型並指定資料庫。 2.創建表格 設置欄位屬性 新增欄位屬性(比如加欄位註釋) 3.導出sql語句及預覽 初次使用會發現orca ...
  • 轉自https://www.cnblogs.com/zuowj/archive/2015/05/04/4475663.html轉別人的,做了一點點改動 樣式類 ...
  • "返回目錄" "原文地址Java" equals() 方法總結 equals() 超類 Object 中有這個 equals() 方法,該方法主要用於比較兩個對象是否相等。該方法的源碼如下: 我們知道所有的對象都擁有標識(記憶體地址)和狀態(數據), 同時“==”比較兩個對象的的記憶體地址 ,所以說使用 ...
  • iptables規則持久化 設定防火牆規則 保存防火牆規則 設定開機自動恢復iptables規則 手動生成一些iptables規則 查看iptables規則是否生效 設定關機時自動保存iptables規則 創建關機時要執行的腳本,並且確保其有執行許可權 創建軟連接文件至rcN.d路徑下,N為運行等級 ...
  • > Vim from zero to hero - Vim 從入門到精通- 原文地址:- 原文作者:Marco Hinz- [簡介](#簡介) - [什麼是 Vim?](#什麼是-vim) - [Vim 哲學](#vim-哲學) - [入門](#入門) - [精簡的 vimrc](#精簡的-vimr... ...
  • 在應用程式中,很多時候都會調用到系統調用來完成一些操作,可是系統調用是在內核態下才能調用,用戶態下的應用程式是無法直接調用到的,那麼操作系統是怎麼處理這一過程的呢? 本文的環境是基於Linux 0.11,沒有查證現代操作系統是否有所變化,不過基本思路應該差不多。 過程: 先來看一張圖,有個大概的理解 ...
  • https://github.com/ma6174/vim-deprecated 簡易安裝方法: 打開終端,執行下麵的命令就自動安裝好了: wget -qO- https://raw.github.com/ma6174/vim/master/setup.sh | sh -x 或者自己手動安裝:(以u ...
一周排行
    -Advertisement-
    Play Games
  • 前言 在我們開發過程中基本上不可或缺的用到一些敏感機密數據,比如SQL伺服器的連接串或者是OAuth2的Secret等,這些敏感數據在代碼中是不太安全的,我們不應該在源代碼中存儲密碼和其他的敏感數據,一種推薦的方式是通過Asp.Net Core的機密管理器。 機密管理器 在 ASP.NET Core ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 順序棧的介面程式 目錄順序棧的介面程式頭文件創建順序棧入棧出棧利用棧將10進位轉16進位數驗證 頭文件 #include <stdio.h> #include <stdbool.h> #include <stdlib.h> 創建順序棧 // 指的是順序棧中的元素的數據類型,用戶可以根據需要進行修改 ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • C總結與剖析:關鍵字篇 -- <<C語言深度解剖>> 目錄C總結與剖析:關鍵字篇 -- <<C語言深度解剖>>程式的本質:二進位文件變數1.變數:記憶體上的某個位置開闢的空間2.變數的初始化3.為什麼要有變數4.局部變數與全局變數5.變數的大小由類型決定6.任何一個變數,記憶體賦值都是從低地址開始往高地 ...
  • 如果讓你來做一個有狀態流式應用的故障恢復,你會如何來做呢? 單機和多機會遇到什麼不同的問題? Flink Checkpoint 是做什麼用的?原理是什麼? ...
  • C++ 多級繼承 多級繼承是一種面向對象編程(OOP)特性,允許一個類從多個基類繼承屬性和方法。它使代碼更易於組織和維護,並促進代碼重用。 多級繼承的語法 在 C++ 中,使用 : 符號來指定繼承關係。多級繼承的語法如下: class DerivedClass : public BaseClass1 ...
  • 前言 什麼是SpringCloud? Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的開發便利性簡化了分散式系統的開發,比如服務註冊、服務發現、網關、路由、鏈路追蹤等。Spring Cloud 並不是重覆造輪子,而是將市面上開發得比較好的模塊集成進去,進行封裝,從 ...
  • class_template 類模板和函數模板的定義和使用類似,我們已經進行了介紹。有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同。類模板用於實現類所需數據的類型參數化 template<class NameType, class AgeType> class Person { publi ...
  • 目錄system v IPC簡介共用記憶體需要用到的函數介面shmget函數--獲取對象IDshmat函數--獲得映射空間shmctl函數--釋放資源共用記憶體實現思路註意 system v IPC簡介 消息隊列、共用記憶體和信號量統稱為system v IPC(進程間通信機制),V是羅馬數字5,是UNI ...