⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄

📁 这是完整的ucos在51上移植的资料
💻
字号:
                                            在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 + -