原创 菜鸟学uC/OS_II(8)

2008-9-12 10:10 3134 7 7 分类: MCU/ 嵌入式

菜鸟学uC/OS_II(8)<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


By <?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />Norman


2008-7-15


 


实验<>


 


实验四:


 


实验内容:消息邮箱的使用


源程序及分析:


实验使用消息邮箱,任务2给任务1发送递增的数值,任务1接收到就显示出来。


这个实验是昨天晚上写好的,但是由于中间调试没有达到预期结果,任务1不是接收到多条重复信息,就是一条都接不到,所以拖到今天。最后发现的问题是:发送缓冲区必须是一个局部变量,否则接受任务就会永远挂起;具体原因(若有大虾看到,帮小弟分析一把),我想不太明白,反正做成局部变量就可以了。


#include "includes.h"


 


#define TASK_STK_SIZE 1024     /*按照一般的流程将所需要的数据结构定义、初始化等*/


 


OS_STK TaskStartStk[TASK_STK_SIZE];


OS_STK Task_1_Stk[TASK_STK_SIZE];


OS_STK Task_2_Stk[TASK_STK_SIZE];


 


INT16S key;


INT16U i="0";


 


INT16U y1 = 6,y2 = 6;


OS_EVENT *MB_Str; /*声明*/


 


void taskStart(void* pdata);


void task_1(void* pdata);


void task_2(void* pdata);


 


static  void  TaskStartDispInit(void);


 


void main(void)    /*main函数的一般结构*/


{


OSInit();


 


PC_DOSSaveReturn();


PC_VectSet(uCOS,OSCtxSw);



MB_Str = OSMboxCreate((void*)0);     /*创建工作一般都放在这里*/


OSTaskCreate(taskStart,(void*)0,&TaskStartStk[TASK_STK_SIZE-1],0);



OSStart();  /*开始多任务*/


}


 


void taskStart(void* pdata)    /*第一个任务必须创建,做创建其他任务、初始化等工作*/


{


#if OS_CRITICAL_METHOD == 3


           OS_CPU_SR cpu_sr;


#endif



pdata = pdata;



TaskStartDispInit();



OS_ENTER_CRITICAL();


PC_VectSet(0x08,OSTickISR);


PC_SetTickRate(OS_TICKS_PER_SEC);


OS_EXIT_CRITICAL();



OSStatInit();



OSTaskCreate(task_1,pdata,&Task_1_Stk[TASK_STK_SIZE-1],5);


OSTaskCreate(task_2,pdata,&Task_2_Stk[TASK_STK_SIZE-1],6);




for(;;)         /*作返回判断工作*/


{


           if(PC_GetKey(&key) == TRUE)


           {


                    if(key == 0x1B)


                    {


                             PC_DOSReturn();


                    }


           }


           OSTimeDly(10);


}


}


 


void task_1(void* pdata)


{


INT8U* err;


char* msg;


char* str = "Task_1 gets a msg:";


pdata = pdata;


for(;;)


{


           msg = OSMboxPend(MB_Str,0,err);       /*等待消息,这里需要一个局部变量msg*/


 


           if(y2 > 20 || y1 > 20)


           {


                    y1 = 6;


                    y2 = 6;


                    TaskStartDispInit();


           }


          


           y1++;


           PC_DispStr(0,y1,str,DISP_BGND_LIGHT_GRAY+DISP_FGND_RED);


           PC_DispStr(18,y1,msg,DISP_BGND_LIGHT_GRAY+DISP_FGND_RED);


 


           OSTimeDly(20);


}


}


 


 


void task_2(void* pdata)


{


INT8U* err;


char* str = "Task_2 sends a msg:";


char* send;


pdata = pdata;


for(;;)


{


           sprintf(send,"%d",i++);


           OSMboxPost(MB_Str,send);         /*发送一个消息,也需要一个局部变量*/


           if(y2 > 20 || y1 > 20)


           {


                    y1 = 6;


                    y2 = 6;


                    TaskStartDispInit();


           }


          


           y2++;


           PC_DispStr(40,y2,str,DISP_BGND_LIGHT_GRAY+DISP_FGND_BLUE);


           PC_DispStr(59,y2,send,DISP_BGND_LIGHT_GRAY+DISP_FGND_BLUE);


 


           OSTimeDly(400);


}


}


 


static  void  TaskStartDispInit(void)<>


 


 


实验五:


 


实验内容:利用消息队列进行任务间通信


源程序及分析:


本程序设计三个任务:taskServe作为消息队列服务器,向消息队列发送递增数据;task_1task_2两个任务从消息队列中读取数据并作显示。


taskServe任务向消息队列发送消息比较快,而两个消费者读取消息比较慢,所以理论上可以观测FIFOLILO方式的不同结果。


但是:


疑惑:为什么使用OSQPost()OSQPostFront()效果是一样的?郁闷,OS_CFG中也没有做特殊配置嘛!为什么就不行呢?难道说2.52版本没有FIFO?结果都是LILO嘛!


 


#include "includes.h"


 


#define TASK_STK_SIZE 1024     /*按照一般的流程将所需要的数据结构定义、初始化等*/


#define N_MSGS 32     /**/


 


OS_STK TaskStartStk[TASK_STK_SIZE];


OS_STK Task_S_Stk[TASK_STK_SIZE];


OS_STK Task_1_Stk[TASK_STK_SIZE];


OS_STK Task_2_Stk[TASK_STK_SIZE];


 


INT16S key;


INT16U i="0";


 


void* MsgQGrp[N_MSGS]; /*消息队列需要一个消息数组,其实是分配存储空间*/


INT16U y1 = 6,y2 = 6;


OS_EVENT *MQ_Str; /*声明*/


 


 


void taskStart(void* pdata);


void taskServe(void* pdata);


void task_1(void* pdata);


void task_2(void* pdata);


 


static  void  TaskStartDispInit(void);


 


void main(void)    /*main函数的一般结构*/


{


OSInit();


 


PC_DOSSaveReturn();


PC_VectSet(uCOS,OSCtxSw);



MQ_Str = OSQCreate(&MsgQGrp[0],N_MSGS);  /*创建工作一般都放在这里*/


OSTaskCreate(taskStart,(void*)0,&TaskStartStk[TASK_STK_SIZE-1],0);



OSStart();  /*开始多任务*/


}


 


void taskStart(void* pdata)    /*第一个任务必须创建,做创建其他任务、初始化等工作*/


{


#if OS_CRITICAL_METHOD == 3


           OS_CPU_SR cpu_sr;


#endif



pdata = pdata;



TaskStartDispInit();



OS_ENTER_CRITICAL();


PC_VectSet(0x08,OSTickISR);


PC_SetTickRate(OS_TICKS_PER_SEC);


OS_EXIT_CRITICAL();



OSStatInit();



OSTaskCreate(taskServe,pdata,&Task_S_Stk[TASK_STK_SIZE-1],4);


OSTaskCreate(task_1,pdata,&Task_1_Stk[TASK_STK_SIZE-1],5);


OSTaskCreate(task_2,pdata,&Task_2_Stk[TASK_STK_SIZE-1],6);




for(;;)         /*作返回判断工作*/


{


           if(PC_GetKey(&key) == TRUE)


           {


                    if(key == 0x1B)


                    {


                             PC_DOSReturn();


                    }


           }


           OSTimeDly(10);


}


}


 


void taskServe(void* pdata)


{


char* send;


OS_Q_DATA* Q_Data;



for(;;)


{


           sprintf(send,"%d",i++);


           OSQPostOpt(MQ_Str,send,OS_POST_OPT_NONE);    /*消息队列服务器???*/


          


           OSQQuery(MQ_Str,Q_Data);


           if(Q_Data->OSNMsgs == 32)


           {


                    OSQFlush(MQ_Str);


                    i = 0;


           }


           OSTimeDly(50);


}


}


 


void task_1(void* pdata)


{


INT8U* err;


char* msg;


char* str = "Task_1 gets a msg:";


pdata = pdata;


for(;;)


{


           msg = OSQPend(MQ_Str,0,err);    /**/


 


           if(y2 > 20 || y1 > 20)


           {


                    y1 = 6;


                    y2 = 6;


                    TaskStartDispInit();


           }


          


           y1++;


           PC_DispStr(0,y1,str,DISP_BGND_LIGHT_GRAY+DISP_FGND_RED);


           PC_DispStr(18,y1,msg,DISP_BGND_LIGHT_GRAY+DISP_FGND_RED);


 


           OSTimeDly(200);


}


}


 


 


void task_2(void* pdata)


{


INT8U* err;


char* str = "Task_2 gets a msg:";


char* msg;


pdata = pdata;


for(;;)


{



           msg = OSQPend(MQ_Str,0,err);    /**/


          


           if(y2 > 20 || y1 > 20)


           {


                    y1 = 6;


                    y2 = 6;


                    TaskStartDispInit();


           }


          


           y2++;


           PC_DispStr(40,y2,str,DISP_BGND_LIGHT_GRAY+DISP_FGND_BLUE);


           PC_DispStr(59,y2,msg,DISP_BGND_LIGHT_GRAY+DISP_FGND_BLUE);


 


           OSTimeDly(200);


}


}


 


static  void  TaskStartDispInit(void)<>


 


实验结果:


改了很多地方:发送方式,等待时间,延迟时间等等,不行就是不行,这个FIFO默认都不行……


 


 


实验六:


 


实验内容:互斥信号量的使用——创建三个任务,三个任务都要访问同一个资源,创建互斥信号量来保护这个资源。


源程序:


#include "includes.h"


#define TASK_STK_SIZE 1024     /*按照一般的流程将所需要的数据结构定义、初始化等*/


OS_STK TaskStartStk[TASK_STK_SIZE];


OS_STK Task_1_Stk[TASK_STK_SIZE];


OS_STK Task_2_Stk[TASK_STK_SIZE];


OS_STK Task_3_Stk[TASK_STK_SIZE];


 


INT16S key;


 


INT16U y = 6;


OS_EVENT *Mutex_Str;       /*声明*/


 


 


void taskStart(void* pdata);


void task_1(void* pdata);


void task_2(void* pdata);


void task_3(void* pdata);


 


static  void  TaskStartDispInit(void);


 


void main(void)    /*main函数的一般结构*/


{


INT8U* err;


OSInit();


 


PC_DOSSaveReturn();


PC_VectSet(uCOS,OSCtxSw);



Mutex_Str = OSMutexCreate(4,err);       /*创建工作一般都放在这里*/


OSTaskCreate(taskStart,(void*)0,&TaskStartStk[TASK_STK_SIZE-1],0);



OSStart();  /*开始多任务*/


}


 


void taskStart(void* pdata)    /*第一个任务必须创建,做创建其他任务、初始化等工作*/


{


#if OS_CRITICAL_METHOD == 3


           OS_CPU_SR cpu_sr;


#endif



pdata = pdata;



TaskStartDispInit();



OS_ENTER_CRITICAL();


PC_VectSet(0x08,OSTickISR);


PC_SetTickRate(OS_TICKS_PER_SEC);


OS_EXIT_CRITICAL();



OSStatInit();



OSTaskCreate(task_1,pdata,&Task_1_Stk[TASK_STK_SIZE-1],5);


OSTaskCreate(task_2,pdata,&Task_2_Stk[TASK_STK_SIZE-1],6);


OSTaskCreate(task_3,pdata,&Task_3_Stk[TASK_STK_SIZE-1],7);




for(;;)         /*作返回判断工作*/


{


           if(PC_GetKey(&key) == TRUE)


           {


                    if(key == 0x1B)


                    {


                             PC_DOSReturn();


                    }


           }


           OSTimeDly(10);


}


}


 


void task_1(void* pdata)


{


INT8U* err;


char* str;


pdata = pdata;


for(;;)


{


           str = "Task_1 asks for mutex!";


           y++;


           PC_DispStr(0,y,str,DISP_BGND_LIGHT_GRAY+DISP_FGND_RED);


          


           OSMutexPend(Mutex_Str,0,err);   /**/


                   


           if(y > 20)


           {


                    y = 6;


                    TaskStartDispInit();


           }


           str = "Task_1 is running!";


           y++;


           PC_DispStr(0,y,str,DISP_BGND_LIGHT_GRAY+DISP_FGND_RED);


          


           OSTimeDly(150);


          


           str = "Task_1 release mutex!";


           y++;


           PC_DispStr(0,y,str,DISP_BGND_LIGHT_GRAY+DISP_FGND_RED);


           OSMutexPost(Mutex_Str);


          


           OSTimeDly(10);


          


}


}


 


void task_2(void* pdata)


{


INT8U* err;


char* str;


pdata = pdata;


for(;;)


{


           str = "Task_2 asks for mutex!";


           y++;


           PC_DispStr(25,y,str,DISP_BGND_LIGHT_GRAY+DISP_FGND_RED);


          


           OSMutexPend(Mutex_Str,0,err);   /**/


          


           if(y > 20)


           {


                    y = 6;


                    TaskStartDispInit();


           }


           str = "Task_2 is running!";


           y++;


           PC_DispStr(25,y,str,DISP_BGND_LIGHT_GRAY+DISP_FGND_RED);


 


           OSTimeDly(200);


 


           str = "Task_2 release mutex!";


           y++;


           PC_DispStr(25,y,str,DISP_BGND_LIGHT_GRAY+DISP_FGND_RED);


           OSMutexPost(Mutex_Str);


 


           OSTimeDly(10);


 


}


}


 


 


void task_3(void* pdata)


{


INT8U* err;


char* str;


pdata = pdata;


for(;;)


{


           str = "Task_3 asks for mutex!";


           y++;


           PC_DispStr(50,y,str,DISP_BGND_LIGHT_GRAY+DISP_FGND_RED);


          


           OSMutexPend(Mutex_Str,0,err);   /**/


          


           if(y > 20)


           {


                    y = 6;


                    TaskStartDispInit();


           }


           str = "Task_3 is running!";


           y++;


           PC_DispStr(50,y,str,DISP_BGND_LIGHT_GRAY+DISP_FGND_RED);


 


           OSTimeDly(250);


 


           str = "Task_3 release mutex!";


           y++;


           PC_DispStr(50,y,str,DISP_BGND_LIGHT_GRAY+DISP_FGND_RED);


           OSMutexPost(Mutex_Str);


 


           OSTimeDly(10);


}


}


 


static  void  TaskStartDispInit(void)


实验结果及分析:


1


点击看大图


点击看大图


没有任务释放后没有添加延时模拟。但任务3饿死了……


“饥饿”就是由于在占先式内核中,高优先级任务一直不释放OS的使用权,致使低优先级的任务一直由于得不到使用权而无法运行。


那么,在程序中加入一个延时在释放信号量之后。


这里加了一个10ticks的延时。


 


2


点击看大图


点击看大图


添加延时模拟之后更清楚,但是任务3还是饿死了……


难道是我加的延时太少了?少也能够交出OS了撒!


我生气了,加就加吧——我一口气给加到500ticks——


结果……


任务3真有东西吃了……


500ticks内,任务可能全部都在延迟,任务3就很有机会得到这个资源了。


 


3


点击看大图


点击看大图


具体的时间是:首先根据任务优先级和任务运行时间的关系:任务1运行时间最短,因此需要高优先级;任务3运行时间最长,赋给最低的优先级。对于任务1,延迟300ticks;任务2延迟200ticks;任务3延迟100ticks


这样的话,任务运行的时间也看得比较清楚:任务1运行次数多;任务3运行次数少。


如果延迟相同的时间,150ticks是最低值,否则任务3还是会饿死。


这难道是和任务运行时间有关系?任务1运行时间设置为150ticks的;不会吧?如果要这样才能够交出OS,那效率如何提高?OS作者本意该不会是这样的!


再次研究程序,我发现只要任务2延时150ticks以上任务3就不会饿死了……


分析起来是这样的:三个任务一开始都回去请求信号量。任务1优先级高,首先运行;任务1释放信号量的时候,任务2不请求,那么任务3就得以运行。


我看很多演示程序中都只建立了两个任务去请求一个共享资源。这样不好啊……


各位大虾拯救我吧……


 


实验七:


 


实验内容:事件标志的使用


源程序:


 


/*******************************************************************************/


/*********************************事件标志组实验********************************/


/************************************By Norman**********************************/


/************************************2008-7-15**********************************/


/****************该程序创建4个任务,任务1等待事件标志FlagsPtr发生***************/


 


#include "includes.h"


 


#define TASK_STK_SIZE 1024     /*按照一般的流程将所需要的数据结构定义、初始化等*/


 


OS_STK TaskStartStk[TASK_STK_SIZE];


OS_STK Task_1_Stk[TASK_STK_SIZE];


OS_STK Task_2_Stk[TASK_STK_SIZE];


OS_STK Task_3_Stk[TASK_STK_SIZE];


OS_STK Task_4_Stk[TASK_STK_SIZE];


 


INT16S key;


 


INT16U y = 6;


OS_FLAG_GRP *FlagsPtr;   /*声明*/


 


void taskStart(void* pdata);


void task_1(void* pdata);


void task_2(void* pdata);


void task_3(void* pdata);


void task_4(void* pdata);


 


static  void  TaskStartDispInit(void);


 


void main(void)    /*main函数的一般结构*/


{


INT8U* err;


OSInit();


 


PC_DOSSaveReturn();


PC_VectSet(uCOS,OSCtxSw);



FlagsPtr = OSFlagCreate((OS_FLAGS)0,err);  /*创建工作一般都放在这里*/


OSTaskCreate(taskStart,(void*)0,&TaskStartStk[TASK_STK_SIZE-1],0);



OSStart();  /*开始多任务*/


}


 


void taskStart(void* pdata)    /*第一个任务必须创建,做创建其他任务、初始化等工作*/


{


#if OS_CRITICAL_METHOD == 3


           OS_CPU_SR cpu_sr;


#endif



pdata = pdata;



TaskStartDispInit();



OS_ENTER_CRITICAL();


PC_VectSet(0x08,OSTickISR);


PC_SetTickRate(OS_TICKS_PER_SEC);


OS_EXIT_CRITICAL();


OSStatInit();


OSTaskCreate(task_1,pdata,&Task_1_Stk[TASK_STK_SIZE-1],5);


OSTaskCreate(task_2,pdata,&Task_2_Stk[TASK_STK_SIZE-1],6);


OSTaskCreate(task_3,pdata,&Task_3_Stk[TASK_STK_SIZE-1],7);


OSTaskCreate(task_4,pdata,&Task_4_Stk[TASK_STK_SIZE-1],8);



for(;;)         /*作返回判断工作*/


{


           if(PC_GetKey(&key) == TRUE)


           {


                    if(key == 0x1B)


                    {


                             PC_DOSReturn();


                    }


           }


           OSTimeDly(10);


}


}


 


void task_1(void* pdata)


{


INT8U* err;


char* str;


pdata = pdata;


for(;;)


{


           str = "Task_1 asks is waiting!";


           y++;


           PC_DispStr(0,y,str,DISP_BGND_LIGHT_GRAY+DISP_FGND_RED);


          


           OSFlagPend(FlagsPtr,(OS_FLAGS)0x26,


                    OS_FLAG_WAIT_SET_ALL + OS_FLAG_CONSUME,0,err);         /*等待事件标志组,注意OS_FLAG_CONSUME*/


                   


           if(y > 20)


           {


                    y = 6;


                    TaskStartDispInit();


           }


           str = "Task_1 is running!";


           y++;


           PC_DispStr(0,y,str,DISP_BGND_LIGHT_GRAY+DISP_FGND_RED);


          


           OSTimeDly(10);


          


}


}


 


void task_2(void* pdata)


{


INT8U* err;


char* str;


pdata = pdata;


for(;;)


{      


           str = "Task_2 is running!";


          


           if(y > 20)


           {


                    y = 6;


                    TaskStartDispInit();


           }


           y++;


           PC_DispStr(40,y,str,DISP_BGND_LIGHT_GRAY+DISP_FGND_RED);


 


           OSTimeDly(200);


          


           str = "Task_2 sets 0x02!";


           y++;


           PC_DispStr(40,y,str,DISP_BGND_LIGHT_GRAY+DISP_FGND_RED);


          


           OSFlagPost(FlagsPtr,(OS_FLAGS)0x02,OS_FLAG_SET,err);   /**/


          


           OSTimeDly(200);


 


}


}


 


 


void task_3(void* pdata)


{


INT8U* err;


char* str;


pdata = pdata;


for(;;)


{


           str = "Task_3 is running!";


           if(y > 20)


           {


                   y = 6;


                    TaskStartDispInit();


           }


           y++;


           PC_DispStr(40,y,str,DISP_BGND_LIGHT_GRAY+DISP_FGND_RED);


 


           OSTimeDly(500);


          


           str = "Task_3 sets 0x04!";


           y++;


           PC_DispStr(40,y,str,DISP_BGND_LIGHT_GRAY+DISP_FGND_RED);


          


           OSFlagPost(FlagsPtr,(OS_FLAGS)0x04,OS_FLAG_SET,err);   /**/


          


           OSTimeDly(200);


 


}


}


 


void task_4(void* pdata)


{


INT8U* err;


char* str;


pdata = pdata;


for(;;)


{


           str = "Task_4 is running!";


          


           if(y > 20)


           {


                    y = 6;


                    TaskStartDispInit();


           }


           y++;


           PC_DispStr(40,y,str,DISP_BGND_LIGHT_GRAY+DISP_FGND_RED);


           OSTimeDly(800);


           str = "Task_4 sets 0x20!";


           y++;


           PC_DispStr(40,y,str,DISP_BGND_LIGHT_GRAY+DISP_FGND_RED);


          


           OSFlagPost(FlagsPtr,(OS_FLAGS)0x20,OS_FLAG_SET,err);   /**/


                             OSTimeDly(200);


}


}


 


static  void  TaskStartDispInit(void)<>


 


 


实验结果及分析:


1FLAG_WAIT_SET_ALL + OS_FLAG_CONSUME


点击看大图


点击看大图


2FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME


点击看大图


点击看大图


看起来实验结果同预期的效果是一样的。


注意到OS_FLAG_CONSUME这个选项,有了这个选项,任务1可以不停等待一个事件标志发生;如果任务只是等待这个事件标志发生一次,然后被遵循被唤醒之类的机制后一直运行,不加这个选项就可以了。


 


总结:


1)总的来说,熟悉了uC/OS_II的功能函数等的使用。下一步就是对其他处理器的移植和一些驱动程序的开发了。这些应该比前面学到要难,一步步来吧。


2)我在程序中没有做错误信息处理,这应该是一个很不好的习惯;在程序中,对于一些内核函数的调用应该处理其错误信息!


如:


err = OSTaskCreate(myTask,(void*)0,&myTask_Stk[Task_Stk_Size-1],7);


if(err = ?????)


{


       err handler;


}


这样的程序才能够避免不必要的麻烦。


3)实验中有些问题需要解决。


 


唉,不写了,王小妹儿扭着要打牌,升级去了^_^


 


<待续>

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
7
关闭 站长推荐上一条 /3 下一条