8051的多工

8051上也可以寫多工程式,但8051的task切換時間花費太多,這讓它可以跑多工卻不適合跑多工。雖然有點繞舌,不過8051就是如此的情形。儘管如此,藉著8051寫多工的程式應該有助於了解32位元多工的運作方式。能夠從小晶片去了解複雜晶片的動作原理未嘗不是一個好的學習方式。這可以幫助我們更容易進入32位元mcu的世界,並撰寫即時多工作業系統的核心。

我在下面這塊板子上實現了一隻小小的多工程式。

8051單版 8051單版

電路圖解:

8051多工

多工說明:

下圖是我從keil 8051 compiler的ide環境抓下來的畫面。在這張圖中,左邊視窗是project window,右邊視窗是edit window。

project window中,這支程式被分成五個group,main、operation system、device driver、tasks、application。
mainstartup.a51負責8051的記憶體初始化,main.c 負責多工程式的執行。
operation system多工程式的核心。我只寫了最簡單的多工,round robin的方式,沒有優先權,task一個接著一個執行,每次task的執行時間是10ms。
tasks有六個task,uart,irda,led、lcm、motor、rtc,等task。
device driver我把驅動程式和多工核心分離,故意把8051的硬體驅動程式放在同一個group中。
applicationshell.c負責接受透過rs232傳過來的指令,並執行該指令

edit window中,main.c的程式碼做了幾件事
一個delay這是為了讓板子上的電壓電流可以穩定。我們可以把整個板子想成一個大電容,為了讓這個大電容的電充飽,必須要有一個時間延遲。
8051sfr 初始化通常8051剛power on時,這些sfr就會有初始值了,只是我習慣自己去做sfr初始化。
驅動程式初始化這部份包含了timer、uart、irda的初始化。其實還有其他的,只是我把它們移到task中做初始化。
多工核心初始化這部份包含了os_core和os_task的初始化。在這份程式碼中,我的重點是tasking的實現,至於RTOS其他部份的實現要看ARM的程式碼,因為這顆8051外部ram只有1k,實在不夠用。
開六個task因為每個task都要64byte的堆疊,所以我只開六個,至於剩下來的ram要給其他程式碼使用。
開始執行OSOsCoreStart() 會把第一個task載到8051mcu裏面,然後開始執行第一個 task。其他的task會在timer的中斷中和目前正在跑的task做中斷級task切換。
8051多工

有人跟我說,他覺得程式可以從一個while(1){...}跳到另一個while(1){...} 是一件很神奇的事。很難想像程式可以從一個task跳到另一個task執行。所以我就用power point畫了這幾張圖來說明task的切換。

第一張圖說的是,當task被創造出來的時候,task的stack的內容如圖所示。此時的task只是一支尚未被執行的程式和一個資料結構。

8051多工

第二張圖說的是,當第一個task被載入執行的時候,task的stack的內容會先被複製到8051的stack中,然後用pop的方式取出給R0~R7、PSW、DPL、DPH、B、A,最後再使用ret指令(中斷級task切換要用reti)把該task的函式位址pop給pc(program counter),之後程式就在task裏面跑了,整個過程就是這樣簡單。

8051多工

第三張圖說的是,當要停止一個正在執行的task並且載入另一個準備要執行的task的時候,scheduler要把目前的task的stack內容存回,並且要把下一個要執行的task的堆疊內容載入執行。這個過程是不能被微處理器的中斷打岔的,所以必須要把中斷功能關掉。Task互換作業完成後,再把中斷功能打開,就大功告成了。

8051多工

之前我都是用小畫家抓程式,所以不能夠讓大家盡情的把我的程式碼完全看懂、完全看透。現在我使用"doxygen"製作程式文件的網頁,所以大家可以看到完整的程式碼了。
8051多工的程式碼。