??
字號:
在OSStart前開中斷引起的莫名其妙錯誤
巨龍公司VPN部 楊屹 asdjf@163.com 2004/03/09
2004/03/07網友方呂ladderls來電詢問以下問題:
你的ucos-ii在51的移植為啥不能超過11個應用任務?更改任務數量設置無用。
我在keil v623軟環境下模擬,建立的任務與您的三個范例任務類同,修改配制文件的最大任務數和最小優先級數,超過11個任務即死機。不知還要修改那些配制?
經檢查是ucos51的BUG。我的OS_EXIT_CRITICAL()宏定義為EA=1;,上電后51自動關中斷(EA=0,ET0=0),因為在系統調用OSInit()時會自動創建一個優先級最低的系統任務,創建過程中會調用OS_EXIT_CRITICAL()打開EA。而我在InitTimer0函數里使能了T0中斷,這個函數在OSStart()前執行,導致在OSStart()前產生中斷,致使系統崩潰。
按照我在《關于keilc51入出臨界區的內嵌匯編》一文里的方法改正,可以解決這個問題。
或者這樣改:(ucos51V2最終采用這種方法)
//OS_CPU_C.C
//初始化定時器0
void InitTimer0(void) reentrant
{
TMOD=TMOD&0xF0;
TMOD=TMOD|0x01; //模式1(16位定時器),僅受TR0控制
TH0=0x70; //定義Tick=50次/秒(即0.02秒/次)
TL0=0x00; //OS_CPU_A.ASM 和 OS_TICKS_PER_SEC
//ET0=1; //允許T0中斷,此時EA=0(51上電缺省值),中斷還不會發生,滿足在OSStart()前不產生中斷的要求。
TR0=1;
}
注釋掉InitTimer0函數里的ET0=1,保證在OSStart()前不開時鐘中斷。
在最高優先級任務里開T0中斷:(切記是最高優先級任務)
void TaskStartyya(void *yydata) reentrant
{
yydata=yydata;
//注意!在最高優先級任務循環前打開定時器中斷,以滿足在OSStart()前不產生中斷的要求。
//在系統調用OSInit()時會自動創建一個優先級最低的系統任務,創建過程中會調用OS_EXIT_CRITICAL()打開EA。
//若在InitTimer0()里打開T0中斷,則違反了在OSStart()前不產生中斷的要求。
//切記將ET0=1;放在最高優先級任務里,OSStart()將調用OSStartHighRdy()第一個運行最高優先級任務,這樣ET0=1總能被第一個執行。
ET0=1;
for(;;){
PrintStr("\t01\n");
OSTimeDly(10*OS_TICKS_PER_SEC);
}
}
具體到ladderls網友的問題,因為在OSStart()前開了中斷,不符合作者要求,會導致系統崩潰。在創建12個以下任務時,時機上的巧合,不會出問題,這些創建函數在12個以下數量時所用時間恰好在T0時鐘中斷前完成,不會引起崩潰。
改動后的程序如下:
#include <includes.h>
void TaskStartyya(void *yydata) reentrant;
void TaskStartyyb(void *yydata) reentrant;
void TaskStartyyc(void *yydata) reentrant;
void TaskStartyyd(void *yydata) reentrant;
void TaskStartyye(void *yydata) reentrant;
void TaskStartyyf(void *yydata) reentrant;
void TaskStartyyg(void *yydata) reentrant;
void TaskStartyyh(void *yydata) reentrant;
void TaskStartyyi(void *yydata) reentrant;
void TaskStartyyj(void *yydata) reentrant;
void TaskStartyyk(void *yydata) reentrant;
void TaskStartyyl(void *yydata) reentrant;
void TaskStartyym(void *yydata) reentrant;
//注意:我在ASM文件中設置?STACK空間為40H
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -