ucoslll和ucos2,ucos任務調度函數 OSSched()函數分析 ,任務切換函數

 2023-11-19 阅读 19 评论 0

摘要:OS_Sched()分析 ?????????在uc/os中總是運行優先級最高的就緒任務,確定哪個任務優先級最高,該由哪個優先級人物運行了,這一工作是由任務調度器完成的,(而具體的任務切換,是任務調度器在調用其他函數來完成)。

OS_Sched()分析

?????????在uc/os中總是運行優先級最高的就緒任務,確定哪個任務優先級最高,該由哪個優先級人物運行了,這一工作是由任務調度器完成的,(而具體的任務切換,是任務調度器在調用其他函數來完成)。其中任務級的調度由函數OS_Sched()來完成,中斷級的調度由OSIntExt()來完成的。

OS_Sched()函數分析

ucoslll和ucos2,?

?

void OSSched (void)
{

ucos用的多嗎,?

  INT8U y;

  OS_ENTER_CRITICAL();

?

正點原子ucos。    if ((OSLockNesting | OSIntNesting) == 0)
   { //判斷是否滿足調度條件,在uc/os中任務級調度的調用不允許來自中斷服務子程序(OSIntNesting) == 0),此外當調度器上鎖時,任務調度函數將直接退出,不做任務調度

?

      y = OSUnMapTbl[OSRdyGrp];

freertos 任務調度。?      OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);//這兩行代碼是獲得進入就緒態且優先級最高的任務

?      if (OSPrioHighRdy != OSPrioCur)?

      {?//檢驗優先級最高的任務是否是當前正在運行的任務。以避免不必要的的任務調度,畢竟任務調度是需要時間滴。

crop函數??        OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];//通過當前最高優先級OSPrioHighRdy,從任務控制塊優先級表中OSTCBPrioTbl[]獲得當前最高優優先級任務控制塊

?        OSCtxSwCtr++;//該全局變量(32位)用于記錄任務切換的次數,

?        OS_TASK_SW();最后調用OS_TASK_SW宏來完成實際上的任務切換,該宏是一個軟中斷

ucoslll,?      }

?

    }

?

OS_EXIT_CRITICAL();
}

?

?

OS_TASK_SW()函數分析
任務切換的內容其實是很簡單的:將被掛起任務的寄存器壓入堆棧,然后將高優先級的寄存器從棧中恢復到CPU的寄存器中。該過程使用軟中斷來實現。
SoftwareInterrupt
  LDR SP, StackSvc ; 重新設置堆棧指針,在LPC2200開發板中軟中斷觸發后,開發板處于管理模式
  STMFD SP!, {R0-R3, R12, LR} //壓棧,在下面過程中使用到了以下以下的寄存器,故需要將這些寄存器壓入管理模式堆棧,來實現原始寄存器的保存。
  MOV R1, SP //R1指向參數存儲位置

  MRS R3, SPSR /在ARM處理器中,只有MRS指令可以讀取狀態寄存器
  TST R3, #T_bit //中斷前是否是Thumb狀態
  LDRNEH R0, [LR,#-2] //是: 取得Thumb狀態SWI號
  BICNE R0, R0, #0xff00
  LDREQ R0, [LR,#-4] //否: 取得arm狀態SWI號
  BICEQ R0, R0, #0xFF000000
  // r0 = SWI號,R1指向參數存儲位置
  CMP R0, #1//比較軟中斷號,確立軟中斷的服務程序
  LDRLO PC, =OSIntCtxSw//0號軟中斷用于任務級切換
  LDREQ PC, =__OSStartHighRdy ; SWI 0x01為第一次任務切換

  BL SWI_Exception//跳轉到軟中斷服務子程序

  LDMFD SP!, {R0-R3, R12, PC}^//SWI異常中斷返回
StackSvc DCD (SvcStackSpace + SVC_STACK_LEGTH * 4 - 4)
對于SWI中斷來說,其格式是SWI{cond} immed_24;后面的24位數字就是軟中斷號,故在SWI異常中斷出路程序中,取出SWI中斷號的方法是首先確定軟中斷SWI指令是ARM指令還是THUMB指令(通過訪問SPSR獲得),然后取得該指令的地址,可通過LR獲得,接著讀出指令,分解出立即數,該立即數就是軟中斷號。
在軟中斷觸發后,處理器應進入管理模式,故需要從新設置堆棧指針。
在軟中斷觸發后,SoftwareInterrupt相當于是一個判斷程序,只是簡單的取出中斷號,具體的實現是調用其他函數完成的。
在SoftwareInterrupt中,進行了一次壓棧,是因為在獲得軟中斷號的過程中使用了R0,R1,R2,R3故需要將這些寄存器壓棧,而使用的SP是管理模式下的寄存器,其于用戶模式下的SP寄存器不是一個寄存器,故不需要進行壓棧。

?

?該函數調用所需要的時間是常量,于實際的任務數無?

?

?

任務級調度 OSIntCtxsw
OSIntCtxSw
  //下面為保存任務環境
  LDR R2, [SP, #20] //此時處理器仍處于管理模式,從管理模式堆棧中獲得PC保存到R2中
  LDR R12, [SP, #16] //從堆棧中獲取R12,更新CPU寄存器
  MRS R0, CPSR //保存當前狀態寄存器,用于模式之間的切換

  MSR CPSR_c, #(NoInt | SYS32Mode)//進入系統模式,且關中斷
  MOV R1, LR //獲得系統模式下的LR保存到R1中,該LR就是原始任務的LR
  STMFD SP!, {R1-R2} //此時處理器處于系統模式,故SP是原始任務的堆棧指針,故原始任務的LR,PC壓入原始任務堆棧
  STMFD SP!, {R4-R12} //由于R4-R11寄存器未改變,故其內容是原始任務的內容,直接壓入原始任務堆棧即可。

  MSR CPSR_c, R0 //此時切換回管理模式
  LDMFD SP!, {R4-R7} //從管理模式堆棧中獲得前面保存的原是任務的RO-R3,保存到CPU的R4-R7
  ADD SP, SP, #8 //忽略掉R12,PC,使堆棧指針回到初始位置,使得下次繼續使用

  MSR CPSR_c, #(NoInt | SYS32Mode)//進入系統模式
  STMFD SP!, {R4-R7} //原始任務的R0-R3入棧保存

  LDR R1, =OsEnterSum //獲取OsEnterSum
  LDR R2, [R1]
  STMFD SP!, {R2, R3} //從上面知道R3的內容為原始任務的CPSR,故該指令保存CPSR,OsEnterSum

  LDR R1, =OSTCBCur //獲得原始任務的TCB地址
  LDR R1, [R1]//該地址的內容是原始任務的SP值
  STR SP, [R1] //保存原始任務堆棧指針到原始任務的TCB

  BL OSTaskSwHook //調用鉤子函數
  ;OSPrioCur <= OSPrioHighRdy將當前優先級切換為最高優先級(優先級的切換)
  LDR R4, =OSPrioCur//當前TCB結構體首地址
  LDR R5, =OSPrioHighRdy//最高優先級TCB結構體首地址
  LDRB R6, [R5]
  STRB R6, [R4]//更新當前TCB指向最高優先級TCB
  ;OSTCBCur <= OSTCBHighRdy將當前TCB切換為最高優先級的TCB(TCB的切換)
  LDR R6, =OSTCBHighRdy
  LDR R6, [R6]
  LDR R4, =OSTCBCur
  STR R6, [R4]
OSIntCtxSw_1
  ;獲取新任務堆棧指針
  LDR R4, [R6]//R6為新任務的TCB地址,其內容是新任務的堆棧指針
  ADD SP, R4, #68 //;17寄存器CPSR,OsEnterSum,R0-R12,LR,SP,移動新任務堆棧的SP,指向棧底
  LDR LR, [SP, #-8]//新任務LR進入CPU寄存器
  MSR CPSR_c, #(NoInt | SVC32Mode) //進入管理模式
  MOV SP, R4 //設置堆棧指針

  LDMFD SP!, {R4, R5} //CPSR,OsEnterSum
  //恢復新任務的OsEnterSum
  LDR R3, =OsEnterSum
  STR R4, [R3]

  MSR SPSR_cxsf, R5 //恢復CPSR
  LDMFD SP!, {R0-R12, LR, PC }^ ;新任務RO-R12,LR,PC出棧,運行新任務

  該函數執行前的數據結構:OSTCBCur指向原始任務(低優先級任務)、CPU的SP指向原始任務的棧頂、OSTCBHighRdy指向新任務的TCB
  【轉】msr cpsr_cxsf,r1 ;這里的cxsf表示從低到高分別占用的4個8bit的數據域
  指令中有時還有出現cpsr_cf, cpsr_all, cpsr_c等,這里:

?

c 指 CPSR中的control field ( PSR[7:0])
f 指 flag field (PSR[31:24])
x 指 extend field (PSR[15:8])
s 指 status field ( PSR[23:16])
其中cpsr的位表示為:
31 30 29 28 --- 7 6 - 4 3 2 1 0
N Z C V I F M4 M3 M2 M1 M0

?

0 0 0 0 0 User26 模式
0 0 0 0 1 FIQ26 模式
0 0 0 1 0 IRQ26 模式
0 0 0 1 1 SVC26 模式
1 0 0 0 0 User 模式
1 0 0 0 1 FIQ 模式
1 0 0 1 0 IRQ 模式
1 0 0 1 1 SVC 模式
1 0 1 1 1 ABT 模式
1 1 0 1 1 UND 模式
深入分析:
對于MSR(寄存器到狀態寄存器)的指令,
MSR CPSR, r0
MSR CPSR_all, r0
MSR CPSR_flg, r0
都是已經過時的表示方法。
對于MRS(狀態寄存器到寄存器)的指令,
MRS R0, CPSR 等同于MRS R0, CPSR_cxsf
MRS R0, CPSR_all 會有waring
MRS R0, CPSR_flg 會有錯誤
在ADS中使用c,f,x,s表示cpsr的各個部分是推薦的。從指令來說:
MSR CPSR_f, r0機器碼為0xe128f000
MSR CPSR_c, r0機器碼為0xe121f000
MSR CPSR_x, r0機器碼為0xe122f000
MSR CPSR_s, r0機器碼為0xe124f000
可見機器碼中用bit[29:16]4bit表示是f,c,x,s的。所以能夠在機器執行的時候,
給予不同的執行結果。為了代碼向后兼容性,建議使用f,c,x,s尾綴

?

轉載于:https://www.cnblogs.com/tureno/articles/7910793.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/3/181439.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息