免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
Cortex-M3 的SVC、PendSV異常,與操作系統(tǒng)(ucos實時系統(tǒng))

SVC和PendSV

SVC(系統(tǒng)服務(wù)調(diào)用,亦簡稱系統(tǒng)調(diào)用)和PendSV(可懸起系統(tǒng)調(diào)用),它們多用于在操作系統(tǒng)之上的軟件開發(fā)中。

SVC:

SVC 用于產(chǎn)生系統(tǒng)函數(shù)的調(diào)用請求。
例如,操作系統(tǒng)不讓用戶程序直接訪問硬件,而是通過提供一些系統(tǒng)服務(wù)函數(shù),用戶程序使用SVC 發(fā)出對系統(tǒng)服務(wù)函數(shù)的呼叫請求,以這種方法調(diào)用它們來間接訪問硬件。
因此,
當(dāng)用戶程序想要控制特定的硬件時,它就會產(chǎn)生一個SVC 異常,
然后操作系統(tǒng)提供的SVC 異常服務(wù)例程得到執(zhí)行,
它再調(diào)用相關(guān)的操作系統(tǒng)函數(shù),
后者完成用戶程序請求的服務(wù)。
這種“提出要求——得到滿足”的方式,很好、很強大、很方便、很靈活、很能可持續(xù)發(fā)展。
首先,它使用戶程序從控制硬件的繁文縟節(jié)中解脫出來,而是由操作系統(tǒng) 負(fù)責(zé)控制具體的硬件。
第二,操作系統(tǒng)的代碼可以經(jīng)過充分的測試,從而能使系統(tǒng)更加健壯和可靠。
第三,它使用戶程序無需在特權(quán)級下執(zhí)行,用戶程序無需承擔(dān)因誤操作而癱瘓整個系統(tǒng)的風(fēng)險。
第四,通過SVC 的機制,還讓用戶程序變得與硬件無關(guān),因此在開發(fā)應(yīng)用程序時無需了解硬件的操作細(xì)節(jié),從而簡化了開發(fā)的難度和繁瑣度,并且使應(yīng)用程序跨硬件平臺移植成為可能。開發(fā)應(yīng)用程序唯一需要知道的就是操作系統(tǒng)提供的應(yīng)用編程接口(API),并且了解各個請求代號和參數(shù)表,然后就可以使用SVC 來提出要求了(事實上,為使用方便,操作系統(tǒng)往往會提供一層封皮,以使系統(tǒng)調(diào)用的形式看起來和普通的函數(shù)調(diào)用一致。各封皮函數(shù)會正確使用SVC指令來執(zhí)行系統(tǒng)調(diào)用——譯者注)。
其實,嚴(yán)格地講,操作硬件的工作是由設(shè)備驅(qū)動程序完成的,只是對應(yīng)用程序來說,它們也是操作系統(tǒng)的一部分。如圖7.14 所示


SVC 異常通過執(zhí)行”SVC”指令來產(chǎn)生。該指令需要一個立即數(shù),充當(dāng)系統(tǒng)調(diào)用代號。SVC異常服務(wù)例程稍后會提取出此代號,從而解釋本次調(diào)用的具體要求,再調(diào)用相應(yīng)的服務(wù)函數(shù)。例如,

SVC 0x3 ; 調(diào)用3 號系統(tǒng)服務(wù)

在SVC 服務(wù)例程執(zhí)行后,上次執(zhí)行的SVC 指令地址可以根據(jù)自動入棧的返回地址計算出。找到了SVC 指令后,就可以讀取該SVC 指令的機器碼,從機器碼中萃取出立即數(shù),就獲知了請求執(zhí)行的功能代號。如果用戶程序使用的是PSP,服務(wù)例程還需要先執(zhí)行

MRS Rn,PSP

指令來獲取應(yīng)用程序的堆棧指針。通過分析LR 的值,可以獲知在SVC 指令執(zhí)行時,正在使用哪個堆棧。
由CM3 的中斷優(yōu)先級模型可知,你不能在SVC 服務(wù)例程中嵌套使用SVC 指令(事實上這樣做也沒意義),因為同優(yōu)先級的異常不能搶占自身。這種作法會產(chǎn)生一個用法fault。同理,在NMI 服務(wù)例程中也不得使用SVC,否則將觸發(fā)硬fault。

PendSV:

另一個相關(guān)的異常是PendSV(可懸起的系統(tǒng)調(diào)用),它和SVC 協(xié)同使用。
一方面,SVC異常是必須立即得到響應(yīng)的(若因優(yōu)先級不比當(dāng)前正處理的高,或是其它原因使之無法立即響應(yīng),將上訪成硬fault——譯者注),應(yīng)用程序執(zhí)行SVC 時都是希望所需的請求立即得到響應(yīng)。
另一方面,PendSV 則不同,它是可以像普通的中斷一樣被搶占掛起的(不像SVC 那樣會上訪)。
操作系統(tǒng) 可以利用它“緩期執(zhí)行”一個異?!钡狡渌匾娜蝿?wù)完成后才執(zhí)行動作。

PendSV是什么?
根據(jù) 權(quán)威指南。PendSV是為系統(tǒng)設(shè)備而設(shè)的“可懸掛請求”(pendable request)。

  • 上下文切換 不能在中斷中進行,會導(dǎo)致中斷延期。為了解決這個問題,使用 PendSV。PendSV可以掛起,也就是等到別的 ISR結(jié)束后緩期執(zhí)行。

  • 為了實現(xiàn)緩期執(zhí)行PendSV,PendSV一定要被設(shè)置為最低優(yōu)先級的異常。

掛起PendSV 的方法是:軟件實現(xiàn)OSIntCtxSw()函數(shù),向NVIC 的PendSV 懸起寄存器中寫1。

NVIC_INT_CTRL  EQU    0xE000ED04   ; Interrupt control state register.
NVIC_PENDSVSET EQU    0x10000000   ; Value to trigger PendSV exception.
OSIntCtxSw
    LDR   R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch)
    LDR   R1, =NVIC_PENDSVSET
    STR   R1, [R0]
    BX   LR

掛起后,如果優(yōu)先級不夠高,則將緩期等待執(zhí)行。
PendSV 的典型使用場合是在上下文切換時(在不同任務(wù)之間切換)。

操作系統(tǒng),上下文切換 實例:

場景假設(shè):一個系統(tǒng)(按時間片輪轉(zhuǎn)調(diào)度的系統(tǒng))中有兩個就緒的任務(wù)(A任務(wù)、B任務(wù)),
上下文切換被觸發(fā)的場合可以是:

  • 執(zhí)行一個系統(tǒng)調(diào)用

  • 系統(tǒng)滴答定時器(SYSTICK)中斷,(輪轉(zhuǎn)調(diào)度中需要)

A、B兩個就緒任務(wù),通過SysTick 異常啟動上下文切換。如圖7.15 所示。


上圖是兩個任務(wù)輪轉(zhuǎn)調(diào)度的示意圖。
但若在產(chǎn)生SysTick 異常時正在響應(yīng)一個中斷,則SysTick 異常會搶占其ISR。
在這種情況下,操作系統(tǒng) 不可以執(zhí)行上下文切換,否則將使中斷請求被延遲,
而且在真實系統(tǒng)中延遲時間還往往不可預(yù)知——任何有一丁點實時要求的系統(tǒng)都決不能容忍這種事。
因此,在CM3 中也是嚴(yán)禁沒商量——如果操作系統(tǒng) 在某中斷活躍時嘗試切入線程模式,將觸犯用法fault 異常。

為解決此問題,早期的操作系統(tǒng) 大多會在SysTick 異常中 檢測當(dāng)前是否有中斷在活躍中,只有沒有任何中斷需要響應(yīng)時,才執(zhí)行上下文切換(切換期間無法響應(yīng)中斷)。
然而,這種方法的弊端在于,
它可能把任務(wù)切換動作拖延很久(因為如果搶占了IRQ,則本次SysTick 在執(zhí)行后不得作上下文切換,只能等待下一次SysTick 異常),尤其是當(dāng)某中斷源的頻率和SysTick 異常的頻率比較接近時,會發(fā)生“共振”。
現(xiàn)在好了,PendSV 來完美解決這個問題了(產(chǎn)生SysTick 異常時正在響應(yīng)一個中斷,SysTick 異常會搶占其ISR。此時,操作系統(tǒng) 不可以執(zhí)行上下文切換,否則將使中斷請求被延遲):
把PendSV 編程為最低優(yōu)先級的異常,PendSV 異常會自動延遲上下文切換的請求,直到其它的ISR 都完成了處理后才放行。
如果操作系統(tǒng) 檢測到某IRQ 正在活動并且被SysTick 搶占,它將懸起一個PendSV 異常,以便緩期執(zhí)行上下文切換。如圖7.17 所示

流水賬記錄如下:
1. 任務(wù) A 呼叫SVC 來請求任務(wù)切換(例如,等待某些工作完成)
2. OS 接收到請求,做好上下文切換的準(zhǔn)備,并且pend 一個PendSV 異常。
3. 當(dāng) CPU 退出SVC 后,它立即進入PendSV,從而執(zhí)行上下文切換。
4. 當(dāng) PendSV 執(zhí)行完畢后,將返回到任務(wù)B,同時進入線程模式。
5. 發(fā)生了一個中斷,并且中斷服務(wù)程序開始執(zhí)行
6. 在 ISR 執(zhí)行過程中,發(fā)生SysTick 異常,并且搶占了該ISR。
7. OS 執(zhí)行必要的操作,然后pend 起PendSV 異常以作好上下文切換的準(zhǔn)備。
8. 當(dāng) SysTick 退出后,回到先前被搶占的ISR 中,ISR 繼續(xù)執(zhí)行
9. ISR 執(zhí)行完畢并退出后,PendSV 服務(wù)例程開始執(zhí)行,并且在里面執(zhí)行上下文切換
10. 當(dāng) PendSV 執(zhí)行完畢后,回到任務(wù)A,同時系統(tǒng)再次進入線程模式。

其實,ucos中的實現(xiàn),于此有些差異,但從結(jié)果上看,是一致的(如果systick搶占了其他ISRs,不會在其中執(zhí)行上下文切換。會等到全部的ISRs執(zhí)行完畢后(期間一定是無任務(wù)調(diào)度的),才執(zhí)行pendsv異常,完成上下文的切換。==差別在于生成pendsv異常的時機。)

ucos 關(guān)于 PendSV 異常的應(yīng)用(上下文切換時機、怎樣滿足實時性):

在systick異常中,執(zhí)行必要的任務(wù)維護更新工作,在退出時,考慮生成pensv異常。
當(dāng)且僅當(dāng)無中斷被搶占時,生成pensv異常,并于pendsv異常中,完成上下文切換工作;
當(dāng)每一個中斷/異常處理函數(shù)中,均在退出時考慮生成pensv異常,則最終無中斷可執(zhí)行時,pensv異常一定會生成,并且期間無任務(wù)調(diào)度。

這可能與上邊描述的不一致,但結(jié)果上來看,是一致的。
下邊以ucos系統(tǒng)的源碼,進行大概的講解:

中斷/異常處理通用模板:

    OS_CPU_SR  cpu_sr;
    OS_ENTER_CRITICAL(); /* Tell uC/OS-II that we are starting an ISR */
    OSIntNesting++;
    OS_EXIT_CRITICAL();
    用戶處理代碼;
    void  OSIntExit (void);//OSIntNesting--;以及可能的調(diào)度

systick異常實現(xiàn)(ucos心臟):

void  OS_CPU_SysTickHandler (void)
{
    OS_CPU_SR  cpu_sr;
    OS_ENTER_CRITICAL(); /* Tell uC/OS-II that we are starting an ISR */
    OSIntNesting++;
    OS_EXIT_CRITICAL();
    OSTimeTick();  /* Call uC/OS-II's OSTimeTick()       */

    OSIntExit();  /* Tell uC/OS-II that we are leaving the ISR */
}

void OSTimeTick (void)

void  OSTimeTick (void){更新系統(tǒng)時間,OSTime++;遍歷OSTCBList 任務(wù)控制塊鏈表(已經(jīng)建立的任務(wù)),    如果任務(wù)控制塊OSTCBDly非零,則減一;    如果等于零,更新OSTCBStat(任務(wù)狀態(tài))、OSTCBStatPend(任務(wù)掛起狀態(tài))成員;    如果OSTCBStat等于OS_STAT_RDY(就緒狀態(tài)),則將任務(wù)放入就緒表中。}

OSIntExit

/*$PAGE*/
/**********************************************************************************
*                                               EXIT ISR
*
* Description: This function is used to notify uC/OS-II that you have completed serviving an ISR. When the last nested ISR has completed, uC/OS-II will call the scheduler to determine whether a new, high-priority task, is ready to run.
*
* Arguments  : none
*
* Returns   : none
*
* Notes    : 1) You MUST invoke OSIntEnter() and OSIntExit() in pair.  In other words, for every call to OSIntEnter() at the beginning of the ISR you MUST have a call to OSIntExit() at the end of the ISR.
*        2) Rescheduling is prevented when the scheduler is locked (see OS_SchedLock())
**********************************************************************************/

void  OSIntExit (void)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
    OS_CPU_SR  cpu_sr = 0;
#endif

  if (OSRunning == OS_TRUE) {
     OS_ENTER_CRITICAL();
     if (OSIntNesting > 0) { /* Prevent OSIntNesting from wrapping */
         OSIntNesting--;
     }
     if (OSIntNesting == 0) { /* Reschedule only if all ISRs complete */
        if (OSLockNesting == 0) { /* ... and not locked. */
             OS_SchedNew();
             OSTCBHighRdy  = OSTCBPrioTbl[OSPrioHighRdy];
             if (OSPrioHighRdy != OSPrioCur) { /* No Ctx Sw if current task is highest rdy */

#if OS_TASK_PROFILE_EN > 0
                 OSTCBHighRdy->OSTCBCtxSwCtr++; /* Inc. # of context switches to this task  */
#endif
                 OSCtxSwCtr++; /* Keep track of the number of ctx switches */
                 OSIntCtxSw(); /* Perform interrupt level ctx switch */
             }
         }
     }
     OS_EXIT_CRITICAL();
  }
}

我們在進入systick異常時,有執(zhí)行OSIntNesting++;準(zhǔn)備出來時,自然需要OSIntNesting–;
如果OSIntNesting不等于零,退出systick異常。
只有OSIntNesting等于零(無其他異常/中斷發(fā)生)并且OSLockNesting等于零(無任務(wù)調(diào)度鎖),才執(zhí)行OS_SchedNew()查就任務(wù)緒表中最高優(yōu)先級并返回,比較返回的優(yōu)先級是否為當(dāng)前運行任務(wù)的優(yōu)先級,
僅不相等時,執(zhí)行OSIntCtxSw()函數(shù),生成pendsv異常。OSIntCtxSw()函數(shù)的實現(xiàn)見上邊篇幅。
pendsv異常OS_CPU_PendSVHandler,實現(xiàn)上下文的切換。這里不做解釋。

ucos中,systick的優(yōu)先級?

PENDSV和SYSTICK屬于系統(tǒng)異常;
定時器中斷,串口中斷這些屬于外部中斷。
PENDSV和SYSTICK的中斷優(yōu)先級可以編程,
一般要把PENDSV的優(yōu)先級設(shè)置成最低(沒什么好說的)。
但SYSTICK異常的優(yōu)先級:

  • 一般無需設(shè)置(高于外部中斷的優(yōu)先級),畢竟這是系統(tǒng)的時鐘源(ucos心臟);

  • 當(dāng)然,也可根據(jù)項目需要(有些外部中斷,項目上要求務(wù)必實時),將SYSTICK優(yōu)先級設(shè)置與合適的位置。

  • 確實存在的普遍現(xiàn)象是,很多項目對于實時沒有很高的要求,干脆將PENDSV和SYSTICK的優(yōu)先級都設(shè)置成OxFF。

都是最低優(yōu)先級,此時因為PENDSV在中斷向量表中排在SYSTICK前面,所以如果PENDSV,SYSTICK同時產(chǎn)生中斷,PENDSV優(yōu)先中斷。

本文有些地方表述的確實有些怪異,見諒。
歡迎各位指正。

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
關(guān)于PendSV異常和SVC異常
構(gòu)建RTOS Kernel指南 (上)
如何從零開始寫一個簡單的操作系統(tǒng)?
cortexM3權(quán)威指南上下文切換圖的問題?
FreeRTOS高級篇3
實時操作系統(tǒng)的任務(wù)調(diào)度示例之時間片
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服