嵌入式系統不只是ARM+Linux,不是隻有安卓,凡是電子產品都可稱為嵌入式系統。物聯網行業的興起,也提升了FreeRTOS市場佔有率。
01
在大學裡一般電子資訊專業的最後大部分都進入嵌入式這個領域,入門首先接觸的是微控制器程式設計,尤其是C51微控制器,基礎的微控制器程式設計通常都是指裸機程式設計,即不加入任何 RTOS(Real Time Operating System 即時作業系統)。
常用的有國外的FreeRTOS、μC/OS、RTX 和國內的 RT-thread、Huawei LiteOS 和 AliOS-Things 等,其中開源且免費的 FreeRTOS 的市場佔有率極高。在工作中用的最多的就是FreeRTOS,免費也沒有版權誰不喜歡用呢?
02
1、輪詢系統
輪詢系統即是在裸機程式設計的時候,先初始化好相關的硬體,然後讓主程式在一個死迴圈裡面不斷迴圈,順序地做各種事情。裸機系統通常分成輪詢系統和前後臺系統。
intmain(void)
{
/* 硬體相關初始化 */
HardWareInit();
/* 無限迴圈 */
for
(;;) {
/* 處理事情 1 */
DoSomething1();
/* 處理事情 2 */
DoSomethingg2();
/* 處理事情 3 */
DoSomethingg3();
}
}
輪詢系統是一種非常簡單的軟體結構,通常只適用於那些只需要順序執行程式碼且不需要外部事件來驅動的就能完成的事情。在程式碼清單中,如果只是實現LED翻轉,序列埠輸出,液晶顯示等這些操作,那麼使用輪詢系統將會非常完美。
但是,如果加入了按鍵操作等需要檢測外部訊號的事件,用來模擬緊急報警,那麼整個系統的即時響應能力就不會那麼好了。
假設
DoSomethingg3
是按鍵掃描,當外部按鍵被按下,相當於一個警報,這個時候,需要立馬響應 , 並做緊急處理 , 而這個時候程式剛好執行到DoSomethingg1
, 要命的是DoSomethingg1
需要執行的時間比較久,久到按鍵釋放之後都沒有執行完畢,那麼當執行到DoSomethingg3
的時候就會丟失掉一次事件。足見,輪詢系統只適合順序執行的功能程式碼,當有外部事件驅動時,即時性就會降低。
2、前後臺系統
在裸機系統中,所有的操作都是在一個無限的大迴圈裡面實現,支援中斷檢測。外部中斷緊急事件在中斷裡面標記或者響應,中斷服務稱為前臺,main 函數里面的while(1)無限迴圈稱為後臺,按順序處理業務功能,以及中斷標記的可執行的事件。小型的電子產品用的都是裸機系統,而且也能夠滿足需求。
int
flag1 =
0
;
int
flag2 =
0
;
int
flag3 =
0
;
intmain(void)
{
/* 硬體相關初始化 */
HardWareInit();
/* 無限迴圈 */
for
(;;) {
if
(flag1) {
/* 處理事情 1 */
DoSomething1();
}
if
(flag2) {
/* 處理事情 2 */
DoSomethingg2();
}
if
(flag3) {
/* 處理事情 3 */
DoSomethingg3();
}
}
}
voidISR1(void)
{
/* 置位標誌位 */
flag1 =
1
;
/* 如果事件處理時間很短,則在中斷裡面處理
如果事件處理時間比較長,在回到後臺處理 */
DoSomething1();
}
voidISR2(void)
{
/* 置位標誌位 */
flag2 =
2
;
/* 如果事件處理時間很短,則在中斷裡面處理
如果事件處理時間比較長,在回到後臺處理 */
DoSomething2();
}
voidISR3(void)
{
/* 置位標誌位 */
flag3 =
1
;
/* 如果事件處理時間很短,則在中斷裡面處理
如果事件處理時間比較長,在回到後臺處理 */
DoSomething3();
}
在順序執行後臺程式的時候,如果有中斷來臨,那麼中斷會打斷後臺程式的正常執行流,轉而去執行中斷服務程式,在中斷服務程式裡面標記事件,如果事件要處理的事情很簡短,則可在中斷服務程式裡面處理,如果事件要處理的事情比較多,則返回到後臺程式裡面處理。
雖然事件的響應和處理是分開了,但事件的處理還是在後臺裡面順序執行的,但相比輪詢系統,前後臺系統確保了事件不會丟失,再加上中斷具有可巢狀的功能,這可以大大的提高程式的即時響應能力。在大多數的中小型專案中,前後臺系統運用的好,堪稱有作業系統的效果。
一般來說:如果的專案裡面沒有使用RTOS,則一般使用的都是這種前後臺系統。
03
相比前後臺系統,多執行緒系統的事件響應也是在中斷中完成的,但事件的處理是線上程中完成的。在多執行緒系統中,執行緒跟中斷一樣,也具有優先順序,優先順序高的執行緒會被優先執行。
當一個緊急的事件在中斷被標記之後,如果事件對應的執行緒的優先順序足夠高,就會立馬得到響應。相比前後臺系統,多執行緒系統的即時性又被提高了。
多執行緒系統大概的虛擬碼具體見程式碼清單所示:
int
flag1 =
0
;
int
flag2 =
0
;
int
flag3 =
0
;
intmain(void)
{
/* 硬體相關初始化 */
HardWareInit();
/* OS 初始化 */
RTOSInit();
/* OS 啟動,開始多執行緒排程,不再返回 */
RTOSStart();
while
(
1
);
/* 程式不會執行到這裡 */
}
voidISR1(void)
{
/* 置位標誌位 */
flag1 =
1
;
}
voidISR2(void)
{
/* 置位標誌位 */
flag2 =
2
;
}
voidISR3(void)
{
/* 置位標誌位 */
flag3 =
1
;
}
voidDoSomething1(void)
{
/* 無限迴圈,不能返回 */
for
(;;) {
/* 執行緒實體 */
if
(flag1) {
}
}
}
voidDoSomething2(void)
{
/* 無限迴圈,不能返回 */
for
(;;) {
/* 執行緒實體 */
if
(flag2) {
}
}
}
voidDoSomething3(void)
{
/* 無限迴圈,不能返回 */
for
(;;) {
/* 執行緒實體 */
if
(flag3) {
}
}
}
相比前後臺系統中後臺順序執行的程式主體,在多執行緒系統中,根據程式的功能,我們把這個程式主體分割成一個個獨立的,無限迴圈且不能返回的小程式,這個小程式我們稱之為執行緒。
每個執行緒都是獨立的,互不干擾的,且具備自身的優先順序,它由作業系統排程管理。加入作業系統後,我們在程式設計的時候不需要精心地去設計程式的執行流,不用擔心每個功能模組之間是否存在干擾。
加入了作業系統,我們的程式設計反而變得簡單了。整個系統隨之帶來的額外開銷就是作業系統佔據的那一丁點的
FLASH
和RAM
。現如今,微控制器的 FLASH和RAM是越來越大,完全足以抵擋RTOS那點開銷。04
學習RTOS,一是專案需要,隨著產品要實現的功能越來越多,單純的裸機系統已經不能完美地解決問題,反而會使程式設計變得更加複雜,如果想降低程式設計的難度,就必須引入RTOS實現多工管理。
二是技能需要,掌握作業系統,和基於RTOS的程式設計,實現更好的職業規劃,對個人發展尤其是“錢途”是必不可少的。
大家可能一直覺得學作業系統就必須是linux,實際每個系統都有其應用場景,對於物聯網行業,殺雞焉用牛刀,小而美,且應用廣泛的FreeRTOS 是首選。
有一個作業系統的基礎,即使後續基於其他系統開發軟體,也可觸類旁通,對新技術快速入門。
關鍵詞
程式碼
時候
功能
優先順序
嵌入式