《uCOS51移植心得》---七年前之《快快乐乐跟我学51单片机操作系统和IP栈》 第九部分在OSStart前开中断引起的莫名其妙错误
来源:互联网 发布:二分法查找c语言 编辑:程序博客网 时间:2024/05/17 07:59
在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);
}
}
巨龙公司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);
}
}
- 《uCOS51移植心得》---七年前之《快快乐乐跟我学51单片机操作系统和IP栈》 第九部分在OSStart前开中断引起的莫名其妙错误
- 《uCOS51移植心得》---七年前之《快快乐乐跟我学51单片机操作系统和IP栈》 第四部分在51单片机上固化uCOS51的说明
- 《uCOS51移植心得》---七年前之《快快乐乐跟我学51单片机操作系统和IP栈》 第八部分.printf在uCOS51上的移植和浮点数显示
- 《uCOS51移植心得》---七年前之《快快乐乐跟我学51单片机操作系统和IP栈》
- 《uCOS51移植心得》---七年前之《快快乐乐跟我学51单片机操作系统和IP栈》
- 《uCOS51移植心得》---七年前之《快快乐乐跟我学51单片机操作系统和IP栈》第二部分
- 《uCOS51移植心得》---七年前之《快快乐乐跟我学51单片机操作系统和IP栈》第三部分为uCOS51增加Shell界面
- 《uCOS51移植心得》---七年前之《快快乐乐跟我学51单片机操作系统和IP栈》 第七部分一个简单Ping的实现
- 《uCOS51移植心得》---七年前之《快快乐乐跟我学51单片机操作系统和IP栈》 第五部分.NE2000网卡芯片驱动程序
- 《uCOS51移植心得》---七年前之《快快乐乐跟我学51单片机操作系统和IP栈》 第六部分ARP协议实现原理
- 七年前的Google
- uCOS51移植心得
- uCOS51移植心得
- 前向声明和其引起的错误提示
- 【51单片机学习过程记录】13中断 之串口中断应用前的了解过程(较详细)
- 51单片机学uCosII 跟我一起看书和实践
- 七年前的Google什么样?
- 【51单片机学习过程记录】7 中断之 定时计数器0 操作前理解过程
- 《uCOS51移植心得》---七年前之《快快乐乐跟我学51单片机操作系统和IP栈》 第七部分一个简单Ping的实现
- 迷茫之后....
- Java Software Websites
- 《uCOS51移植心得》---七年前之《快快乐乐跟我学51单片机操作系统和IP栈》 第八部分.printf在uCOS51上的移植和浮点数显示
- -bash: yum: command not found 问题解决 .
- 《uCOS51移植心得》---七年前之《快快乐乐跟我学51单片机操作系统和IP栈》 第九部分在OSStart前开中断引起的莫名其妙错误
- POJ 1016 Numbers That Count
- 驱动程序学习(四)并发控制(3):阻塞与非阻塞
- cocos2d对动画的各种操作
- simon手册翻译_part1
- 必须知道的.NET
- Func<T, TResult> 委托
- hibernate 数据库死锁
- 进入2000,标识一下