?? manual.txt
字號:
的棧底是前一個任務的棧頂,因此其個數為OS_MAX_TASKS+1。考慮到
第一個任務的棧底和最后一個任務的棧頂的值在運行時實際不會改變,
OSTsakStackBotton可以減少兩個字節空間占用,但這樣程序復雜一些。
Small RTOS的移植:
(1)在os_cpu.h中定義幾個宏(以keil c51為例):
#define OS_INT_ENTER() OSIntNesting++ /* 中斷嵌套管理 */
#define OS_ENTER_CRITICAL() EA = 0,Os_Enter_Sum++ /* 禁止中斷 */
#define OS_EXIT_CRITICAL() if (--Os_Enter_Sum==0) EA = 1 /* 允許中斷 */
#define HIGH_BYTE 0 /* uint16的高位字節 */
#define LOW_BYTE 1 /* uint16的低位字節 */
#define OS_TASK_SW() OSCtxSw() /* 任務切換函數 */
OS_ENTER_CRITICAL()、OS_EXIT_CRITICAL()分別定義為禁止和允
許中斷在特定的c編譯器的表示方法。
HIGH_BYTE、LOW_BYTE定義uint16型變量在特定的c編譯器的存儲方法,
如果高位字節的地址小于低位字節的地址(如keil c51),則
HIGH_BYTE為0,LOW_BYTE為1。否則(如8086系列),HIGH_BYTE為1,
LOW_BYTE為0。
OS_INT_ENTER則將變量OSIntNesting加1。它僅在中斷服務程序中使用。
注意:如果中斷嵌套層數可能超過255,OS_INT_ENTER要防止
OSIntNesting溢出。
OS_TASK_SW()定義非中斷中任務切換時執行的指令,可以是一條軟中斷指
令(例如在8086系列CPU上),或僅僅是函數調用(如keil c51)。
(2)定義與編譯器無關的變量類型(以keil c51為例):
typedef unsigned char uint8; /* 定義可移植的無符號8位整數關鍵字 */
typedef signed char int8; /* 定義可移植的有符號8位整數關鍵字 */
typedef unsigned int uint16; /* 定義可移植的無符號16位整數關鍵字 */
typedef signed int int16; /* 定義可移植的有符號16位整數關鍵字 */
typedef unsigned long uint32; /* 定義可移植的無符號32位整數關鍵字 */
typedef signed long int32; /* 定義可移植的有符號32位整數關鍵字 */
(3)在os_cpu_c.c和os_cpu_a.asm中定義幾個函數:
OSStart、OSIntCtxSw、OSTickISR和OS_TASK_SW()最終調用的函數
或中斷。
OSStart:初始化任務并讓ID為0的任務執行。同時允許中斷。
定義如下:
void OSStart(void)
{
初始化除ID為0以外所有任務堆棧;
OSTaskID = 0;
使堆棧指針指向ID為0的任務堆棧空間;
OS_EXIT_CRITICAL();
使程序指針指向ID為0的任務的程序首地址;
}
OSIntCtxSw:中斷中任務切換函數
定義如下:
void OSIntCtxSw(void)
{
堆棧指針調整為中斷程序調用OSIntExit前的狀態;
堆棧空間變換;
堆棧指針指向新的堆棧;
OSTaskID = OSNextTaskID;
恢復任務環境;
中斷返回指令;
}
OSIntCtxSw由OSIntExit直接調用,堆棧指針調整為中斷程序調用
OSIntExit前的狀態即為執行若干出棧指令。
堆棧空間變換可以參照keilc51目錄下Os_cpu_c.c文件中被注釋的
C_OSCtxSw函數,C_OSCtxSw還包括 堆棧指針指向新的堆棧.
OSTickISR為系統節拍中斷服務程序
定義如下:
void OSTickISR(void)
{
#if TICK_TIMER_SHARING >1
static unsigned char TickSum=0;
#endif
禁止中斷;
保存任務環境;
#if TICK_TIMER_SHARING >1
TickSum = (TickSum + 1) % TICK_TIMER_SHARING;
if (TickSum != 0)
{
允許中斷;
恢復任務環境;
return;
}
#endif
#if EN_OS_INT_ENTER >0
OS_INT_ENTER(); /* 中斷開始處理 */
#endif
允許中斷;
#if USER_TICK_TIMER_EN == 1
UserTickTimer(); /* 用戶函數 */
#endif
#if EN_TIMER_SHARING > 0
OSTimeTick(); /* 調用系統時鐘處理函數 */
#else
OSIntSendSignal(TIME_ISR_TASK_ID);
#endif
OSIntExit(); /* 中斷結束處理 */
}
其中有一些CPU的禁止中斷和保存任務環境由CPU自動處理或是自動處
理一部分。
OS_TASK_SW()最終調用的函數或中斷:非中斷中任務切換函數
定義如下:
void OS_TASK_SW(void)
{
保存任務環境;
堆棧空間變換;
堆棧指針指向新的堆棧;
OSTaskID = OSNextTaskID;
恢復任務環境;
恢復程序指針;
}
Small RTOS 51(for keil)的特殊說明:
編譯器版本需求需求
當不使用消息隊列時,需要Keil C51 V6.14以上版本。
當使用消息隊列時,需要Keil C51 V7.00以上版本。
目標系統需求
Small RTOS 51可以在沒有任何外部數據存儲器的單片8051系統上運行
但應用程序仍然可以訪問外部存儲器。Small RTOS 51可以使用C51支
持的全部存儲器模塊,選擇記憶模型僅影響應用目標的位置。一般來說
Small RTOS 51應用程序工作在小模式下。Small RTOS 51沒有按照
bank switching 程序設計,不能使用code banking程序。
可重入功能
不允許從幾個任務或中斷過程調用非可再入C語言函數。
非可再入C51函數將它們的參數和自動變量局部數據保存在靜態存儲器內
因此當重復調用函數時這些數據會被改寫。非可再入C語言函數不可第歸
調用,不可被多個任務同時調用,不可被一個或多個任務與一個或多個
中斷同時調用。Small RTOS 51系統函數不會調用任何這樣的函數。那些
僅使用寄存器作為參變量和自動變量的C語言函數總是可再入的而且可以
從不同的Small RTOS 51任務中沒有任何限制的調用。C51編譯程序也提
供可重入功能,參看“ C51 用戶手冊”以便獲得更多信息。可再入函數
將他們的參變量和局部數據變量儲存到一個可再入堆棧內并且數據是被
保護的以預防多重呼叫。然而如果你在你的應用程序中使用可再入函數
你必須保證這些功能不呼叫任何Small RTOS 51系統函數。而且那些可再
入函數不會被Small RTOS 51任務調度所中斷。特別注意一點,可再入堆
棧不得放在內部RAM中。
C51庫函數
全部的可再入 C51 庫函數可以沒有任何限制的用于全部任務。非可再入
c51庫函數與非可再入C語言函數在應用時有著同樣的限制。
多數據指針和數學單元的用法
c51 編譯程序允許你使用8051派生類型的多數據指針和數學單元。因為
Small RTOS 51不包括任何對這些硬件的管理,最好你不要與Small
RTOS 51 一起使用這些器件。如果你可以保證在使用這些派生硬件的程
序執行期間不會被任務調度中斷的話你可以使用多數據指針和數學單元。
寄存器段
Small RTOS 51分配全部任務到寄存器段0。因此全部的任務函數必須用
c51的默認設置registerbank 0 編譯。不需要Small RTOS 51管理的
中斷函數可以使用剩余的寄存器段。
局部變量
keil c51采用變量覆蓋的方法分配局部變量,而不是把局部變量分配到
堆棧中,當在keil c51使用Small RTOS時,編譯系統會把各個任務的局
部變量分配在同一塊內存,造成程序運行錯誤。因此,最多只能允一個
任務函數與?CO?OS_CPU_C進行覆蓋分析,禁止任務函數與?CO?OS_CPU_C
進行覆蓋分析的方法如下:
在Progect->BL51 Misc->Overlay里填"?CO?OS_CPU_C~任務函數名,"
每一項禁止一個任務函數。
如果任務(包括任務調用的函數)沒有局部變量,可以不進行以上處理。
注意參數也是局部變量。
另外,用戶函數被多個任務或和中斷調用且不可重入(程序保證各個任
務和中斷不同時調用此函數),它的局部變量不能與任何任務的局部變
量覆蓋,應該禁止所有調用它的任務與之進行覆蓋分析,方法與上面一
樣:
在Progect->BL51 Misc->Overlay里填"任務函數名~用戶函數名,"。
在進行以上處理后,會出現多條類似如下的警告:
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
SEGMENT: ?PR?XXXX?XXX
不用理會它.
注意,以上最后一項不需要逗號。
關于軟非屏蔽中斷
當某個中斷對時間要求非常嚴格的時候,用戶可以使用軟非屏蔽中斷,使
之不受Small RTOS 51關中斷的影響,但它也不再受OS管理。設置方法
如下:
(1)將這個中斷設置為最高優先級中斷,其它受OS管理的中斷優先級
必須比它低。因此,標準51系列單片機就不需要中斷嵌套管理了。有些
51單片機有超過2個中斷優先級,它們還需要中斷嵌套管理。
(2)將OS_CPU.h中EN_SP2定義為1
(3)將OS_CPU.h中宏OS_ENTER_CRITICAL()定義為類似
IE = IE & (~0x30)
形式,其中0x30根據程序要求取值,為1的位為程序運行時需要打開且
受OS管理的中斷。
(4)將OS_CPU.h中宏OS_ENTER_CRITICAL()定義為類似
IE = IE | 0xb0
形式,其中0xb0根據程序要求取值,為1的位為程序運行時需要打開且
受OS管理的中斷。
(5)將OS_CPU.h中Sp2Space定義合適大小(ISR使用堆棧最大值+2)。
(6)將OS_CPU.h中宏SET_EA定義為類似
orl IE,#0b0h
形式,其中0b0h根據程序要求取值,以允許程序運行時受OS管理的中斷
可以中斷CPU。
(7)在合適的時候允許或軟非屏蔽中斷。
(8)軟非屏蔽中斷不允許調用OS_INT_ENTER()和OSIntExit(),因此,
如果在軟非屏蔽中斷中調用OSIntSendSignal()使高優先級任務就緒,
OS也不進行任務切換。作者不推薦在軟非屏蔽中斷中調用
OSIntSendSignal()。
其它注意事項
1、通過調用系統函數進行任務切換,保存任務環境需要RAM空間為(2+到
OSSched時的調用層次*2)字節。通過中斷進行任務切換保存任務環境
需要RAM空間為(中斷發生時堆棧使用量+15)字節,這15字節包括
R0~R7,ACC,B,PSW,DPH和DPL。而8051系列idata小(51只有128字節,
52只有256字節),因此,當任務較多時,應該避免過多的通過中斷進
行任務切換。
2、OS_CPU.H 中的IDATA_RAM_SIZE應當與實際的idata相同。
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -