时间片轮询多任务操作系统( 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 (); }
浙公网安备 33010602011771号