在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? OS_STK TaskStartStkyya[MaxStkSize]; OS_STK TaskStartStkyyb[MaxStkSize]; OS_STK TaskStartStkyyc[MaxStkSize]; OS_STK TaskStartStkyyd[MaxStkSize]; OS_STK TaskStartStkyye[MaxStkSize]; OS_STK TaskStartStkyyf[MaxStkSize]; OS_STK TaskStartStkyyg[MaxStkSize]; OS_STK TaskStartStkyyh[MaxStkSize]; OS_STK TaskStartStkyyi[MaxStkSize]; OS_STK TaskStartStkyyj[MaxStkSize]; OS_STK TaskStartStkyyk[MaxStkSize]; OS_STK TaskStartStkyyl[MaxStkSize]; OS_STK TaskStartStkyym[MaxStkSize]; void main(void) { OSInit(); InitTimer0(); InitSerial(); InitSerialBuffer(); OSTaskCreate(TaskStartyya, (void *)0, &TaskStartStkyya[0],1); OSTaskCreate(TaskStartyyb, (void *)0, &TaskStartStkyyb[0],2); OSTaskCreate(TaskStartyyc, (void *)0, &TaskStartStkyyc[0],3); OSTaskCreate(TaskStartyyd, (void *)0, &TaskStartStkyyd[0],4); OSTaskCreate(TaskStartyye, (void *)0, &TaskStartStkyye[0],5); OSTaskCreate(TaskStartyyf, (void *)0, &TaskStartStkyyf[0],6); OSTaskCreate(TaskStartyyg, (void *)0, &TaskStartStkyyg[0],7); OSTaskCreate(TaskStartyyh, (void *)0, &TaskStartStkyyh[0],8); OSTaskCreate(TaskStartyyi, (void *)0, &TaskStartStkyyi[0],9); OSTaskCreate(TaskStartyyj, (void *)0, &TaskStartStkyyj[0],10); OSTaskCreate(TaskStartyyk, (void *)0, &TaskStartStkyyk[0],11); OSTaskCreate(TaskStartyyl, (void *)0, &TaskStartStkyyl[0],14); OSTaskCreate(TaskStartyym, (void *)0, &TaskStartStkyym[0],15); OSStart(); } void TaskStartyya(void *yydata) reentrant { yydata=yydata; clrscr(); ET0=1; for(;;){ PrintStr("\t01\n"); OSTimeDly(10*OS_TICKS_PER_SEC); } } void TaskStartyyb(void *yydata) reentrant { yydata=yydata; for(;;){ PrintStr("\t02\n"); OSTimeDly(10*OS_TICKS_PER_SEC); } } void TaskStartyyc(void *yydata) reentrant { yydata=yydata; for(;;){ PrintStr("\t03\n"); OSTimeDly(10*OS_TICKS_PER_SEC); } } void TaskStartyyd(void *yydata) reentrant { yydata=yydata; for(;;){ PrintStr("\t04\n"); OSTimeDly(10*OS_TICKS_PER_SEC); } } void TaskStartyye(void *yydata) reentrant { yydata=yydata; for(;;){ PrintStr("\t05\n"); OSTimeDly(10*OS_TICKS_PER_SEC); } } void TaskStartyyf(void *yydata) reentrant { yydata=yydata; for(;;){ PrintStr("\t06\n"); OSTimeDly(20*OS_TICKS_PER_SEC); } } void TaskStartyyg(void *yydata) reentrant { yydata=yydata; for(;;){ PrintStr("\t07\n"); OSTimeDly(20*OS_TICKS_PER_SEC); } } void TaskStartyyh(void *yydata) reentrant { yydata=yydata; for(;;){ PrintStr("\t08\n"); OSTimeDly(20*OS_TICKS_PER_SEC); } } void TaskStartyyi(void *yydata) reentrant { yydata=yydata; for(;;){ PrintStr("\t09\n"); OSTimeDly(20*OS_TICKS_PER_SEC); } } void TaskStartyyj(void *yydata) reentrant { yydata=yydata; for(;;){ PrintStr("\t10\n"); OSTimeDly(20*OS_TICKS_PER_SEC); } } void TaskStartyyk(void *yydata) reentrant { yydata=yydata; for(;;){ PrintStr("\t11\n"); OSTimeDly(30*OS_TICKS_PER_SEC); } } void TaskStartyyl(void *yydata) reentrant { yydata=yydata; for(;;){ PrintStr("\t12\n"); OSTimeDly(30*OS_TICKS_PER_SEC); } } void TaskStartyym(void *yydata) reentrant { yydata=yydata; for(;;){ PrintStr("\t13\n"); OSTimeDly(30*OS_TICKS_PER_SEC); } } |
|