zhliao2

风雨兼程,一路向北-------fpga (Keep a quiet heart study)
时间片轮询多任务操作系统( TinyOS51 V1.3 )

选自<<项目驱动-单片机应用设计基础>>

 

//注意了:
//1,消息邮箱中仅能保存一条消息.  
//2,当初始值消息邮箱时,一定要给消息邮箱赋初值,并将等待消息邮箱的任务列表清空



//任务标志( tiny_os_51_core.c )
#define __TN_TASK_FLG_DEL        0x00        //任务被删除标志
#define __TN_TASK_FLG_RDY        0x01        //任务就绪标志
#define __TN_TASK_FLG_DLY        0x02        //任务延时标志
#define __TN_TASK_FLG_SEM        0x04        //任务获得信号量 标志
#define __TN_TASK_FLG_MSG         0x08         //任务等待消息邮箱标志

struct tn_os_tcb
{
    jmp_buf                  jbTaskContext;        //用于存储上下文信息
    unsigned char            ucTaskStat;           //任务状态
    unsigned int              uiTicks;              //任务延时时间
    data void                  *pvEvent;               //指向等待事件的指针
};
typedef struct tn_os_tcb         TN_OS_TCB;        //TN_OS_TCB等效于struct tn_os_tcb

static data TN_OS_TCB        __GtcbTasks[ TN_OS_MAS_TASKS ];        //任务控制块的结构体数组




//消息邮箱的定义( tiny_os_51_core.h )
//消息邮箱变量中不包括等待任务列表,消息邮箱只包含消息
struct tn_os_msg
{
    unsigned int uiMsg;            //定义用于保存消息的成员
};
typedef struct tn_os_msg    TN_OS_MSG;        //定义消息邮箱


//消息邮箱的存储空间既可以有操作系统分配,也可以有用户分配
//用户分配的消息邮箱
static TN_OS_MSG        __GomMsg;                //定义消息邮箱





//创建信号量tnOsMsgGreate()函数( tiny_os_51.c )
data tnOsMsgGreate ( 
            data TN_OS_MSG *posMsg,                //指向消息邮箱的指针
            char uiMsg                            //声明传递消息邮箱的参数变量

)
{
    if ( posMsg == ( data TN_OS_SEM * )0 )
    {
        return TN_OS_PAR_ERR;            //如果posMsg指针为空指针,则返回参数错误
    }

    EA = 0;
    posMsg->uiMsg = uiMsg;            //将消息邮箱置初始值
    EA = 1;
    return TN_OS_OK;                    //若消息邮箱创建成功,则返回正确
}





//获得消息邮箱tnOsMsgPend()函数( tiny_os_51.c )
char tnOsMsgPend (
             data TN_OS_SEM *posSem,            //指向消息邮箱变量的指针
             unsigned int uiDlyTicks            //等待时限 
             
)    
{
    unsigned int uiMsg;            //定义传递消息邮箱的参数变量

    if ( posMsg == ( data TN_OS_MSG * )0 )
    {
        return 0;                    //如果posMsg为空指针,返回0表明未获得消息
    }

    EA = 0;
    if ( posMsg->uiMsg > 0 )
    {
        uiMsg = posMsg->uiMsg;           //取出消息邮箱并保存
        posMsg->uiMsg = 0;                 //接着将信息邮箱清空
        EA = 1;
        return uiMsg;                    //返回消息邮箱计退出之后,则继续维持运行状态
    }


    //如果邮箱没有消息,则当前进入等待状态,说明任务处于等待消息的状态
    __GtcbTasks[ __GthTaskCur ].uiTicks = uiDlyTicks;            //等待多少时间
    __GtcbTasks[ __GthTaskCur ].ucTaskStat = __TN_TASK_FLG_MSG;        //任务正在等待消息
    __GtcbTasks[ __GthTaskCur ].pvEvent = ( data void * )posMsg;    //任务在等待这个消息

    
    EA = 1;
    __tnOsSched();            //任务切换
    EA = 0;


    if ( __GtcbTasks[ __GthTaskCur ].ucTaskStat == __TN_TASK_FLG_RDY )
    {
        uiMsg = posMsg->uiMsg;            //取出消息并保存
        posMsg->uiMSG = 0;                  //接着将消息邮箱清空
        EA = 1;
        return uiMsg;                        //返回消息退出之后,则继续维持运行状态
    }


    //没有等到消息
    __GtcbTasks[ __GthTask ].ucTaskStat = __TN_TASK_FLG_RDY;        //任务就绪
    __GtcbTasks[ __GthTask ].pvEvent = ( data void * )0;            //无等待事件
    EA = 1;
    return 0; 
}




//发送消息tnOsMsgPost(函数( tiny_os_51_core.c )
char tnOsMsgPost ( 
        data TN_OS_SMG *posMsg,                //指向消息邮箱的指针
        unsigned int uiMsg                    //声明传递消息的参数变量 

)
{
    TN_OS_TASK_HANDLE    tnTask;            //操作的任务

    if ( posMsg == ( data TN_OS_MSG * )0 )
    {
        return TN_OS_PAR_ERR;            //如果posMsg指针为空指针,则返回参数错误
    }


    if ( uiMsg == 0 )
    {
        return TN_OS_PAR_ERR;        //uiMsg为0,说明程序异常,返回参数错误
    } 



    EA = 0;

    if ( posMsg->uiMsg != 0 )            //说明了有消息
    {
        EA = 1;
        return TN_OS_EVENT_FULL;        //返回消息已满
    }
    posMsg->uiMsg = uiMsg;            //将消息保存到消息邮箱



    //查找等待消息的任务,判断一个任务是否等待这个消息邮箱的方法如下:
    //任务必须处于等待消息状态,即任务控制块的成员ucTaskStat的值为__TN_TASK_FLG_MSG
    //等待的必须是这个消息状态,即任务控制块的成员pvEvent与posMsg同时指向变量__GomMSG
    for ( thTask = 0; thTask < TN_OS_MAX_TASKS; thTask ++ )
    {
        if ( __GtcbTasks[ thTask ].ucTaskStat == __TN_TASK_FLG_MSG )
        {
            if ( __GtcbTasks[ thTask ].pvEvent == ( data void * )posMsg )
            {
                break;
            }
        }
    }


    if ( thTask >= 0 && thTask < TN_OS_MAX_TASKS )
    {
        //激活等待消息的任务
        __GtcbTasks[ thTask ].ucTaskStat = __TN_TASK_FLG_RDY;        //任务就绪
        __GtcbTasks[ thTask ].pvEvent = ( data void * )0;            //无等待的事件
    }

    EA = 1;
    
    return TN_OS_OK;    
}

 

举例:

static idata unsigned char         __GucTaskStks[2][32];        //分配任务堆栈

static unsigned char     __GucTask0;        //任务0测试变量
static unsigned char     __GucTask1;        //任务1测试变量
static TN_OS_MSG        __GomMsg;            //定义消息邮箱

void task0 ( void )
{
    TMOD = ( TMOD & 0xF0 ) | 0x01;                //时钟节拍中断的初始化
    TL0 = 0x00;
    TH0 = 0x00;
    TR0 = 1;
    ET0 = 1;
    TF0 = 0;
                            //允许time0中断


    tnOsMsgGreate ( &__GosMsg, 0 );
    while ( 1 )
    {
        __GucTask0 = tnOsMsgPend ( &__GomMsg, 0 );
    }
}

void task1 ( void )
{
    while ( 1 )
    {
        __GucTask1 ++;
        tnOsMsgPost ( &__GomMsg, __GucTask1 );
        tnOsTimeDly ( 10 );
    }
}

void timer0ISR( void ) __interrupt 1        //时钟节拍中断服务程序
{
    tnOSTimeTick();                            //时钟节拍处理程序
}

void main ( void )
{
    tnOsInit ();
    tnOsTaskGreate ( task0, __GucTaskStks[0] );
    tnOsTaskGreate ( task1, __GucTaskStks[1] );
    tnOsStart ();
}

 

 

 

posted on 2012-08-12 22:05  zhliao  阅读(1194)  评论(1)    收藏  举报