uCOS-II多任务内存资源共享

任务介绍

1、在内存空间开辟了一片区域,供 4 个任务共享读写。1 个任务在写内存时,其它任务不能读写。多个任务可以同时读该内存区域数据。键盘按键 1-4 分别是 task1、task2、task3、task4 的写控制键,键盘按键 5-8 分别是 task1、task2、task3、task4 的读控制键。每按下一次写控制键,在共享区域的数据加 1,超过 99 变为 0,显示“写倒计时“在屏幕上。按下读控制键时,对应的读任务读取共享区域的数据并显示数据。一个任务的写控制键按下且“写倒计时”未结束时,其它任务的写控制键不能写,同时所有的读控制键也不能读,如果此时有读写动作(按下相应的按键),屏幕应显示报警。--------------采用消息邮箱机制完成此实验。一次读或写任务持续时间 5 秒。


代码实现:

```c

#include "includes.h"
#define  TASK_STK_SIZE   512                         //任务堆栈长度
#define  TIME 5                                     //eat_time -> TIME - j
#define  col 10
OS_STK   StartTaskStk[TASK_STK_SIZE];               //定义任务堆栈区
OS_STK  PhilosStk[4][TASK_STK_SIZE];                //利用二维数组来创建五个任务堆栈        
INT8U  PhilosID[]={1,2,3,4};                        //用数组来存储五位哲学家的序号
INT16S   key;                                          //用于退出uCOS_II的键
INT16S   key1[] = {0x1B,0x31,0x32,0x33,0x34};  //检测输入
INT16S   key2[] = {0x1B,0x35,0x36,0x37,0x38};
INT16S   wait_ticks; 
                                        //用于循环遍历的变量
INT8U Intpart[5][4];  //3个块的分区
INT8U *IntBlkPtr; //定义内存块的指针,这是全局变量呀!
char *msg1 = "can";   //这种定义在全局变量区的可以这样定义,可以不用字符数组
char *msg2 = "can't";
OS_MBOX_DATA *p;
OS_MEM *IntBuffer;  //块的指针。
BOOLEAN getKey;                                        //用于获取键值的变量
OS_EVENT *StrBox; //创建一个消息邮箱指针
void  StartTask(void *data);
void  Task(void *data);
void  my_write(INT8U id);
void my_read(INT8U id);
/************************主函数*********************************************/
void  main (void)
{
    INT8U err;
    char temp[50];
    PC_DispClrScr(DISP_FGND_WHITE + DISP_BGND_BLACK);
    OSInit();                                          //初始化uCOS_II
    PC_DOSSaveReturn();                             //保存Dos环境
    PC_VectSet(uCOS, OSCtxSw);                         //安装uCOS_II中断
    //创建一个消息邮箱
    StrBox = OSMboxCreate(msg1);  //初始化消息是可以写
    IntBuffer = OSMemCreate(Intpart,5,4,&err);   //管理分区
    OSTaskCreate(StartTask,0,&StartTaskStk[TASK_STK_SIZE - 1],3);
    OSStart();
}

//*****************************StartTask********************************************
void  StartTask(void *pdata)
{
    char s1[100]; //必须先分配好内存,这样不会跑飞
    INT8U err1,i;
    pdata=pdata;
    OS_ENTER_CRITICAL();
    PC_VectSet(0x08, OSTickISR);
    PC_SetTickRate(OS_TICKS_PER_SEC);
    OS_EXIT_CRITICAL();
    OSStatInit();
    //请求一个内存块
    IntBlkPtr = OSMemGet(IntBuffer,&err1);  //获得一块内存
    *(IntBlkPtr+1) = 0; //首先赋初值,不用它了
    //创建4个任务
    for(i=0;i<4;i++)
    {
        OSTaskCreate(Task,(void *)&PhilosID[i],&PhilosStk[i][TASK_STK_SIZE - 1],i+6);
    }
    
    for(; ;)                                        
    {
        getKey = PC_GetKey(&key);                    //实时获取按键值
        if(key==key1[0])                            //退出程序     
        { 
            PC_DOSReturn(); 
        }
        sprintf(s1,"%x",key);
        PC_DispStr(col,0,s1,DISP_BGND_BLACK+DISP_FGND_WHITE);  //打印了键值
        OSTimeDly(1);  //为了能够实时获取按键值
    }
    
}

void  Task(void *pdata)
{
    char *s1= "write ok",*s2 = "read ok",*s3 = "wating for operation!                          ";
    char *s4 = "You can't read now!                  ";
    char *s5 = "You can't operate now!      ";
    INT8U err1,err2; //这样先分配内存不会跑飞!!!
    char *sr;
    char *sr2;
    char ss[50];
    INT8U PhID;
    PhID = *(INT8U *)pdata;  //哲学家序号
    for(;;)
    {
        
        if (key == key1[PhID]) //&& cnt ==0
        {    
            sr = OSMboxPend(StrBox,1,&err1); //我要保证一定能读取到
            if(strcmp(sr,msg1) == 0) //这是可以写
            {
                OSMboxPost(StrBox,msg2);  //马上就给它写上不能再读写了
                if(*(IntBlkPtr+1)<9)
                {
                    *(IntBlkPtr+1) += 1; 
                }
                else
                {
                    *(IntBlkPtr+1) = 0;
                }                
                my_write(PhID);
            }

            else
            {
                OSMboxPost(StrBox,msg2); //如果是不能操作的话,也要马上写上不能操作,后面的任务才能判断
                PC_DispStr(col,PhID+10,s5,DISP_BGND_BLACK+DISP_FGND_WHITE);
                OSTimeDly(200*TIME-wait_ticks);
            }
        }
        else if(key == key2[PhID])
        {
            sr2 = OSMboxPend(StrBox,1,&err2); //我要保证一定能读取到
            if(strcmp(sr2,msg1) == 0)  //这个表示可以读
            { 
                OS_ENTER_CRITICAL();
                OSMboxPost(StrBox,msg1);//马上写上可以读,告诉其他任务
                OS_EXIT_CRITICAL();
                my_read(PhID);
                
            }
            else
            {
                OSMboxPost(StrBox,msg2);  //不能读就还是写上不能读
                //if_operate = 1;
                PC_DispStr(col,PhID+10,s5,DISP_BGND_BLACK+DISP_FGND_WHITE);
                OSTimeDly(200*TIME-wait_ticks);
            }
                
        }
        else
        {
            PC_DispStr(col,PhID+10,s3,DISP_BGND_BLACK+DISP_FGND_WHITE);
            OSTimeDly(1);  //这里必须是1或者2,其他数字都是不行的!!!!
        }
        
        
    }
}

void  my_write(INT8U id)
{
    char ss[100];
    INT8U err;
    for(wait_ticks=0;wait_ticks<TIME*200;wait_ticks++)
    {
        sprintf(ss,"task_%d is writing, count down: %d               ",id,(TIME-wait_ticks/200));
        PC_DispStr(col,id+10,ss,DISP_BGND_BLACK+DISP_FGND_WHITE);
        OSTimeDly(1);
    }   
    OSMboxPend(StrBox,1,&err);  //在这里pend后,邮箱无论如何都为空,那就不用下面判断了
    OSMboxPost(StrBox,msg1);

}


void my_read(INT8U id)
{
    char ss[100];
    INT8U err;
    INT8U i;
    for(i=0;i<5;i++)
    {
        sprintf(ss,"task_%d read the number is: %d  count down: %d",id,*(IntBlkPtr+1),5-i);  //我也不知道为啥第一个内存单元不能用,它的数据总是不对
        PC_DispStr(col,id+10,ss,DISP_BGND_BLACK+DISP_FGND_WHITE);
        OSTimeDly(200);
    }
    
}

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值