1
裸機與RTOS的理解
首先這里只針對單核CPU架構的芯片展開討論,大部分是MCU吧,而多核CPU的討論相對比較復雜,暫不涉及~玩RTOS的朋友都知道,裸機與OS的最大區別就是實現多任務的并發,其實你說裸機就不能實現任務的并發嗎 ? 這個需要看所站的角度吧,只是說RTOS并發的粒度可以更加細,因為你把裸機的任務拆分成多塊運行,其實也是一種并發方式。從宏觀上雖然RTOS的每個任務都是在并發執行,其實微觀上還是一條一條指令在順序執行著。
而對于目前主流的RTOS,如UCOS或者FreeRTOS,所實現的都是多任務,更多的是一種多線程的并發執行而非多進程,所以對應到Linux平臺上稱他們為thread。
2
并發帶來的問題
并發的好處就是能夠在更細的粒度來盡可能的提高CPU的利用率,這里不能說使用了多線程就一定能提高,這與你所設計的任務劃分和處理有著直接的關系,只能說多線程相比裸機更有這個能力。
而任何事物都有其利弊,多個任務在沒有同步處理的情況下,任務之間是無序運行的,無序也就意味著狀態的多樣性和復雜度。
當然bug菌這里所說的無序是一個相對的過程,比如對于CPU而言,它就是順序的去執行一條一條的指令,所以在這個層面它是有序的、確定的。
而我們把過程放大,比如執行一條C語言語句,一般它是由多條匯編指令組成,對于目前的搶占式內核,在一段時間內其多個任務就有可能指令交替執行,當這些指令都去操作同一塊內存,那么內存的最終結果由于順序不同而不同,最終難以確定。
狀態的不確定就有可能造成異常行為,也就是大家經常遇到的:“怎么跑著跑著就有問題,還沒啥規律~”,“這段代碼怎么看也沒問題呀~”
所以對比看來RTOS確實會帶來編程上的難度~
3
臨界區
既然有難度,我們就要解決,把不確定性部分通過一些手段來變得確定,而造成這些不確定因素的動力是什么呢?是中斷~
bug菌一直覺得,其實對于裸機而言,如果把中斷服務函數看成一個更高優先級的搶占式任務,其實裸機主任務與中斷任務就形成了一種兩任務的并發,所以中斷與任務之間也是有共享問題需要類似處理的。
為了解決這些不確定因素,我們只需要在這段代碼區域限制中斷的發生即可,這一段區域就是臨界區,說得直白點 : 關中斷與開中斷。
1ENTER_CRITICAL();//進入臨界區23//臨界區代碼45EXIT_CRITICAL();//退出臨界區
4
臨界區嵌套
臨界區的使用沒啥可說的,但是在你的代碼中怎么加臨界區確實一門技巧,可是說很多3~5年的工程師也并不一定處理得好,本文暫不展開,后面bug菌整理以后再分享給大家,今天只聊聊臨界區嵌套使用的問題,畢竟很多朋友在這里掉過坑~
參考偽代碼:
1/********************************************* 2 * Function: Fuction1 3 * Description:功能函數
4 * Author: bug菌 5 ********************************************/ 6void Fuction1(void)7{ 8 ENTER_CRITICAL();//進入臨界區 910 //do something~1112 EXIT_CRITICAL();//退出臨界區
13} 14/********************************************* 15 * Function: Fuction2 16 * Description: 功能函數 17 * Author: bug菌 18 ********************************************/19void Fuction2(void) 20{ 21 ENTER_CRITICAL();//進入臨界區2223... 24 Fuction1(); 2526. 27 //do something~2829 EXIT_CRITICAL();//退出臨界區30}
這種臨界區的使用是很多朋友常犯的錯誤,當然這里的臨界區操作僅僅只是開關中斷,許多自己公司寫的,或者裁剪的都是這種簡約開關中斷版本,所以當調用Function1函數以后,后面的代碼就不在臨界區內了,此時就有可能會存在共享問題。
當然目前的開源OS都會提供一種把相關嵌套標記保存在局部變量中的處理方式,如下代碼所示:
1//來源于ucos源碼 2#define OS_ENTER_CRITICAL() (cpu_sr = OSCPUSaveSR()) 3#define OS_EXIT_CRITICAL()
(OSCPURestoreSR(cpu_sr)) 4 5/*********************************************6 * Function: Fuction1 7 * Description:功能函數 8 * Author: bug菌 9 ********************************************/10void Fuction1(void) 11{ 12 int cpu_sr; 1314 OS_ENTER_CRITICAL();//進入臨界區
1516 //do something~1718 OS_EXIT_CRITICAL();//退出臨界區
19} 2021/********************************************* 22 * Function: Fuction2 23 * Description: 功能函數 24 * Author: bug菌
25 ********************************************/26void Fuction2(void) 27{ 28 int cpu_sr; 2930 OS_ENTER_CRITICAL();//進入臨界區3132 Fuction1(void); 3334 OS_EXIT_CRITICAL();//退出臨界區
3536}
為了更好的理解,我寫了一下下面的偽代碼,供大家參數~
1//中斷寄存器register原本是1, 向register寫0關中斷,向register寫1開中斷 2 3void Fuction2(void) 4{ 5 int cpu_sr1 = 0; 6 7 cpu_sr1 = register; 8 register = 0;
//register == 0;
cpu_sr1 == 1; 910 void Fuction1(void) 11 { 12 int cpu_sr1 = 0; 1314 cpu_sr2 = register; 15 register = 0; //register == 0;cpu_sr2 == 0;
161718 register = cpu_sr2; 19 cpu_sr2 = 0;//register == 0;
cpu_sr2 == 0;20 } 2122 register = cpu_sr1; 23 cpu_sr1 = 0;//register == 1;cpu_sr1 == 0;2425}
不同的OS可能具體實現有所差異,大體上都一樣~
原文標題:同事在RTOS“臨界區嵌套使用”栽了跟頭~
文章出處:【微信公眾號:嵌入式ARM】歡迎添加關注!文章轉載請注明出處。
責任編輯:haq
-
cpu
+關注
關注
68文章
10863瀏覽量
211765 -
RTOS
+關注
關注
22文章
813瀏覽量
119636 -
裸機程序
+關注
關注
0文章
5瀏覽量
6989
原文標題:同事在RTOS"臨界區嵌套使用"栽了跟頭~
文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論