[轉]關於嵌入式實時操作系統的實時性 - yanhc - 博客園



 

嵌入式實時操作系統RTOS里實時的衡量指標到底是什么呢?1s肯定達不到實時,那需要多快呢?100ms,10ms,1ms,還是100us,10us?

還有這些指標是如何測量的呢?

一個關於1553B總線消息周期實時性指標的例子

一篇論文中關於1553B總線消息周期實時性的指標,從這個例子中可以看出,對於windows這種非實時操作系統而言,10ms的精度也很難保證。因此,實時性指標要求任務需要至少滿足10ms的指標,甚至更高。

韓春慧,王煜,黃書華,許權,張珅,魯月林. 基於BM3803的1553B總線通信軟件設計 [J]. 中國空間科學技術, 2019,39(234), 05 65-72.

論文中需要完成的1553總線測試終端的消息的周期數值偏差較為嚴格,

對於任務1廣播時間碼,周期為1s,周期偏差不能超過100us,

對於任務7系統同步,周期為2s,周期偏差不能超過10 000us=10ms,如下圖所示。

如果使用傳統的windows+1553B-PCI板卡方案的話,不能保證以上的精度;所以,論文使用了嵌入式實時操作系統的方案,BM3803+uCOS+61580,該系統可以滿足上圖的精度。

下表為實際測試結果,對於任務1,采用嵌入式實時操作系統方案,周期精確度偏差平均為8us,而采用windows方案則高達13ms,超過了100us=0.1ms的精度要求。

其它任務的周期精度要求均為10ms以內,對於嵌入式實時操作系統方案,周期精度平均1.5ms,而windows則為15ms,超過了精度要求。

論文

鏈接:https://pan.baidu.com/s/15P6VCZqdieAlSH9Mq8anmg
提取碼:o1vq

關於實時性都有哪些指標

expresslogic有一個文檔Measuring RTOS Real-Time Performance,其中描述了實時性的各種指標,最后,介紹了其RTOS實時性測量軟件。

https://rtos.com/wp-content/uploads/2017/10/EL_Measuring_RTOS_Real-Time_Performance.pdf

主要分為兩部分,

一是中斷處理實時性,主要包括以下步驟:

(1)中斷當前正在執行的任務,

(2)保存當前任務上下文,

(3)開始執行中斷服務程序ISR,

(4)ISR中進行一些處理,以確定需要采取的動作,

(5)保存一些中斷相關的關鍵數據,

(6)設置一些必須的輸出,

(7)確定該執行哪個任務(一般中斷到來之后,需要的處理會比較多,一般中斷中會處理必須的事情,剩下的處理由某個任務來處理)

(8)清除中斷狀態寄存器,

(9)將控制轉移到要執行的任務。

二是系統服務實時性,包括

(1)在某個事件發生時調度一個任務執行,

(2)任務之間傳遞消息(消息隊列),

(3)申明公共資源三方面(信號量等)。

 

TNKernel-RX/Thread-Metric/,某個操作系統使用了Thread Metric

源代碼:https://github.com/msalau/TNKernel-RX/tree/master/Thread-Metric

pdf鏈接:https://pan.baidu.com/s/1pJH2azMJb8QNmYZwXUQpFA
提取碼:t421

用戶程序需要做到什么

以上都是對於RTOS來說的,那么對於用戶程序需要做到什么呢?

RTOS內核里一般都會有一些關鍵區域critical section,在這些區域是需要關中斷的,中斷都屏蔽了,那么響應外界中斷自然會帶來延時,影響系統的實時性。

因此,對於用戶程序也可以這么說,用戶程序關中斷的時間不超過內核關中斷的時間,就能保證用戶程序不會使內核實時性變差。

這里有一個文檔Interrupts-II-Bringing Organization to our Code (the shared-data problem) Reference An Embedded Software Primer By David E. Simon,其中有描述內核關鍵區關中斷的時間會影響系統的實時性。

鏈接:https://pan.baidu.com/s/1M3f1rdl2DHsMMpLJ1Ptb0Q
提取碼:dbno

對於FreeRTOS而言,如何選擇保護關鍵區的方式 

https://forums.freertos.org/t/how-to-choose-a-critical-section-protecton-approach-taskenter-critical-or-vtasksuspendall-or-mutex/9500

View Code

(1)taskENTER_CRITICAL,會關中斷,同時支持嵌套nesting,操作方便

(2)vTaskSuspendAll,不關中斷,會關調度器,操作復雜

(3)mutex,不關中斷,不關調度器

對於FreeRTOS內核來說,因為(3)Mutex是可選配置項,因此,內核是不能夠使用mutex的。

所以,對於FreeRTOS內核來說,只有選擇(1)和(2)。

而對於(1)和(2),按照richard-damon的回復,用(1)需要保證關鍵區執行時間在幾微秒以內(strictly bounded execution time,in small number of microseconds at most)。

而如果無法保證執行時間短且有界的,則需要使用(2)(FreeRTOS uses suspending the scheduler if the time period isn’t both strictly bounded and short.)。且在使用(2)時需要保證被保護的關鍵區不會阻塞(inside the section you can’t do anything that might block)。

 

關於這句話的進一步核實:when you suspend the schedule it sets a flag to tell the ISRs not to modify the main task lists

下面vTaskSuspendAll的時候,會對uxSchedulerSuspended+1。(這里的注釋比較有意思,就是因為變量的類型是基礎類型,因此不用設置關鍵區,為什么呢?因為是基礎類型,所以不用兩次move?但是++也會ldr,inc,str需要3條指令,也可能被打斷呢?

1 void vTaskSuspendAll( void )2 {3     /* A critical section is not required as the variable is of type4  portBASE_TYPE. */5     ++uxSchedulerSuspended;6 }

uxSchedulerSuspended != 0的話,那么,上下文切換vTaskSwitchContext就不會執行。

1 void vTaskSwitchContext( void )2 {3     if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE )4     {5         /* The scheduler is currently suspended - do not allow a context6         switch. */7         xMissedYield = pdTRUE;8     }9     else

同時,注意到在xTaskResumeFromISR用到了這個調度器掛起變量,如果調度器掛起,那么,不能操作就緒任務列表(為什么呢?),因此,將任務放在即將就緒列表上。

 1 portBASE_TYPE xTaskResumeFromISR( xTaskHandle pxTaskToResume ) 2     { 3     portBASE_TYPE xYieldRequired = pdFALSE; 4     tskTCB *pxTCB; 5     unsigned portBASE_TYPE uxSavedInterruptStatus; 6  7         configASSERT( pxTaskToResume ); 8  9         pxTCB = ( tskTCB * ) pxTaskToResume;10 11         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();12         {13             if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE )14             {15                 traceTASK_RESUME_FROM_ISR( pxTCB );16 17                 if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )18                 {19                     xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority );20                     uxListRemove(  &( pxTCB->xGenericListItem ) );21                     prvAddTaskToReadyQueue( pxTCB );22                 }23                 else24                 {25                     /* We cannot access the delayed or ready lists, so will hold this26  task pending until the scheduler is resumed, at which point a27  yield will be performed if necessary. */28                     vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );29                 }30             }31         }32         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );33 34         return xYieldRequired;35     }

同時,在vTaskIncrementTick時,也會判斷調度器是否掛起,若掛起,則記錄丟失的tick數,在調取器繼續時,補償丟失的tick數。

 1 void vTaskIncrementTick( void ) 2 { 3 tskTCB * pxTCB; 4  5     /* Called by the portable layer each time a tick interrupt occurs. 6     Increments the tick then checks to see if the new tick value will cause any 7     tasks to be unblocked. */ 8     traceTASK_INCREMENT_TICK( xTickCount ); 9     if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )10     {11         ++xTickCount;12 13     }14     else15     {16         ++uxMissedTicks;17 18         /* The tick hook gets called at regular intervals, even if the19         scheduler is locked. */20         #if ( configUSE_TICK_HOOK == 1 )21         {22             vApplicationTickHook();23         }24         #endif25     }26 }

在xTaskResumeAll時,補償丟失的tick數。

 1 signed portBASE_TYPE xTaskResumeAll( void ) 2 { 3  4     /* It is possible that an ISR caused a task(只有ISR會引起) to be removed from an event 5  list while the scheduler was suspended. If this was the case then the 6  removed task will have been added to the xPendingReadyList.  Once the 7     scheduler has been resumed it is safe(?) to move all the pending ready 8     tasks from this list into their appropriate ready list. */ 9     taskENTER_CRITICAL();10     {11         --uxSchedulerSuspended;12 13         if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )14         {15             if( uxCurrentNumberOfTasks > ( unsigned portBASE_TYPE ) 0U )16             {17                 portBASE_TYPE xYieldRequired = pdFALSE;18 19                 /* If any ticks occurred while the scheduler was suspended then20  they should be processed now. This ensures the tick count does not21  slip, and that any delayed tasks are resumed at the correct time. */22                 if( uxMissedTicks > ( unsigned portBASE_TYPE ) 0U )23                 {24                     while( uxMissedTicks > ( unsigned portBASE_TYPE ) 0U )25                     {26  vTaskIncrementTick();27                         --uxMissedTicks;28                     }29                 }31             }32         }33     }34     taskEXIT_CRITICAL();35 36     return xAlreadyYielded;37 }

 


---------------------
作者:yanhc
來源:CNBLOGS
原文:https://www.cnblogs.com/yanhc/p/12594768.html
版權聲明:本文為作者原創文章,轉載請附上博文鏈接!
內容解析By:CSDN,CNBLOG博客文章一鍵轉載插件


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM