嵌入式实时操作系统μCOS原理与实践任务控制与时间的解析
Posted 一步一个脚印
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了嵌入式实时操作系统μCOS原理与实践任务控制与时间的解析相关的知识,希望对你有一定的参考价值。
/*
*********************************************************************************************************
* uC/OS-II
* The Real-Time Kernel RTOS
*
*********************************************************************************************************
*/
/*
* 嵌入式实时操作系统μCOS原理与实践
* 王小波
* 2016于青岛大学
*/
#include "includes.h"
/*
*********************************************************************************************************
* CONSTANTS
*********************************************************************************************************
*/
//堆栈大小
#define TASK_STK_SIZE 512 /* Size of each task‘s stacks (# of WORDs) */
//开始的堆栈指针优先级
#define TaskStart_Prio 1
//任务1的优先级
#define Task1_Prio 2
//任务堆栈 二维数组
OS_STK TaskStk[OS_MAX_TASKS][TASK_STK_SIZE]; //Tasks stacks
HANDLE mainhandle; //主线程句柄
CONTEXT Context; //主线程切换上下文
BOOLEAN FlagEn = 1; //增加一个全局变量,做为是否时钟调度的标志
//任务开始函数的声明
void TaskStart(void * pParam) ;
//void Task1(void * pParam) ; /*Function prototypes of tasks
/*$PAGE*/
/*
*********************************************************************************************************
* MAIN
*********************************************************************************************************
*/
//主方法的入口
int main(int argc, char **argv)
{
int p[2],Experiment; //定义变量
p[0]=0;
p[1]=100;
//初始化vc环境
VCInit(); @@@:
@@@:
//初始化vc环境
void VCInit(void)
{
HANDLE cp,ct; //进程巨变
Context.ContextFlags = CONTEXT_CONTROL;
cp = GetCurrentProcess(); //得到当前进程句柄
ct = GetCurrentThread(); //得到当前线程伪句柄
DuplicateHandle(cp, ct, cp, &mainhandle, 0, TRUE, 2); //伪句柄转换,得到线程真句柄
}
//显示以下的内容并与操作
printf("0.没有用户任务\n");
printf("1.第一个例子,一个用户任务\n");
printf("2.第二个例子,两个任务共享CPU交替运行\n");
printf("3.第三个例子,任务的挂起和恢复\n");
printf("4.第四个例子,信号量管理\n");
printf("5.第五个例子,互斥信号量管理\n");
printf("6.第六个例子,事件标志组\n");
printf("7.第七个例子,消息邮箱\n");
printf("8.第八个例子,消息队列\n");
printf("9.第九个例子,内存管理\n");
printf("请输入序号选择例子:\n");
scanf("%d",&Experiment);
//对你输入的变量进行判断
if ((Experiment<0)||(Experiment>10))
{
printf("无效的输入!");
return(1);
}
//初始化OS(操作系统)的相关变量
OSInit(); @@@:
@@@:
//初始化OS的相关变量
void OSInit (void)
{
//钩子函数---空函数 啥也不做
OSInitHookBegin(); /* Call port specific initialization code */
//初始化全局变量
OS_InitMisc(); /* Initialize miscellaneous variables */
//初始化就绪任务
OS_InitRdyList(); /* Initialize the Ready List */
//初始化任务控制块
OS_InitTCBList(); /* Initialize the free list of OS_TCBs */
//事件控制块的初始化
OS_InitEventList(); /* Initialize the free list of OS_EVENTs */
#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
//初始化事件标志
OS_FlagInit(); /* Initialize the event flag structures */
#endif
#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u)
//初始化内存
OS_MemInit(); /* Initialize the memory manager */
#endif
#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u)
//初始化队列
OS_QInit(); /* Initialize the message queue structures */
#endif
//初始化空闲任务
OS_InitTaskIdle(); /* Create the Idle Task */
#if OS_TASK_STAT_EN > 0u
//初始化统计任务
OS_InitTaskStat(); /* Create the Statistic Task */
#endif
#if OS_TMR_EN > 0u
OSTmr_Init(); /* Initialize the Timer Manager */
#endif
//初始化钩子函数
OSInitHookEnd(); /* Call port specific init. code */
#if OS_DEBUG_EN > 0u
//初始化调式函数
OSDebugInit();
#endif
}
@@@:
#if OS_VERSION > 203
void OSInitHookBegin (void)
{
}
#endif
//初始化全局变量
static void OS_InitMisc (void)
{
#if OS_TIME_GET_SET_EN > 0u
OSTime = 0uL; /* Clear the 32-bit system clock */
#endif
//中断嵌套
OSIntNesting = 0u; /* Clear the interrupt nesting counter */
//调度锁
OSLockNesting = 0u; /* Clear the scheduling lock counter */
//任务计数
OSTaskCtr = 0u; /* Clear the number of tasks */
//是否运行状态
OSRunning = OS_FALSE; /* Indicate that multitasking not started */
//任务切换次数
OSCtxSwCtr = 0u; /* Clear the context switch counter */
//空闲计数
OSIdleCtr = 0uL; /* Clear the 32-bit idle counter */
#if OS_TASK_STAT_EN > 0u
OSIdleCtrRun = 0uL;
OSIdleCtrMax = 0uL;
OSStatRdy = OS_FALSE; /* Statistic task is not ready */
#endif
#ifdef OS_SAFETY_CRITICAL_IEC61508
OSSafetyCriticalStartFlag = OS_FALSE; /* Still allow creation of objects */
#endif
}
//初始化就绪任务
static void OS_InitRdyList (void)
{
INT8U i;
//初始化就绪组
OSRdyGrp = 0u; /* Clear the ready list */
for (i = 0u; i < OS_RDY_TBL_SIZE; i++) {
OSRdyTbl[i] = 0u;
}
//当前优先级
OSPrioCur = 0u;
//指向最高优先级的任务
OSPrioHighRdy = 0u;
//强制转化为os系统块
OSTCBHighRdy = (OS_TCB *)0;
OSTCBCur = (OS_TCB *)0;
}
//初始化任务控制块链表
static void OS_InitTCBList (void)
{
INT8U ix;
INT8U ix_next;
OS_TCB *ptcb1;
OS_TCB *ptcb2;
//先清空任务控制块
OS_MemClr((INT8U *)&OSTCBTbl[0], sizeof(OSTCBTbl)); /* Clear all the TCBs */
//清空任务优先表
OS_MemClr((INT8U *)&OSTCBPrioTbl[0], sizeof(OSTCBPrioTbl)); /* Clear the priority table */
//在初始化任务控制块
for (ix = 0u; ix < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1u); ix++) { /* Init. list of free TCBs */
ix_next = ix + 1u;
ptcb1 = &OSTCBTbl[ix];
ptcb2 = &OSTCBTbl[ix_next];
ptcb1->OSTCBNext = ptcb2;
//是否给任务控制块名
#if OS_TASK_NAME_EN > 0u
ptcb1->OSTCBTaskName = (INT8U *)(void *)"?"; /* Unknown name */
#endif
}
ptcb1 = &OSTCBTbl[ix];
ptcb1->OSTCBNext = (OS_TCB *)0; /* Last OS_TCB */
#if OS_TASK_NAME_EN > 0u
ptcb1->OSTCBTaskName = (INT8U *)(void *)"?"; /* Unknown name */
#endif
//给最后一个任务控制块指向NULL
OSTCBList = (OS_TCB *)0; /* TCB lists initializations */
//给空闲任务控制块链表指向任务控制块的首地址
OSTCBFreeList = &OSTCBTbl[0];
}
//给事件表做一个清空
void OS_MemClr (INT8U *pdest,
INT16U size)
{
while (size > 0u) {
*pdest++ = (INT8U)0;
size--;
}
}
//进行任务调度
void OS_Sched (void)
{
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
//进入临界区
OS_ENTER_CRITICAL();
//是否在存在中断
if (OSIntNesting == 0u) { /* Schedule only if all ISRs done and ... */
//是否有调度锁
if (OSLockNesting == 0u) { /* ... scheduler is not locked */
//进行任务新的调度
OS_SchedNew();
//取出任务优先级表的最高优先级任务
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
//判断是否当前运行的任务
if (OSPrioHighRdy != OSPrioCur) { /* No Ctx Sw if current task is highest rdy */
#if OS_TASK_PROFILE_EN > 0u
//进行切换任务控制的计数++
OSTCBHighRdy->OSTCBCtxSwCtr++; /* Inc. # of context switches to this task */
#endif //切换任务数+1
OSCtxSwCtr++; /* Increment context switch counter */
//进行一次任务的切换
OS_TASK_SW(); /* Perform a context switch */
}
}
}
OS_EXIT_CRITICAL();
}
//进行任务调度
static void OS_SchedNew (void)
{
//判断最低优先级是否小于63
#if OS_LOWEST_PRIO <= 63u /* See if we support up to 64 tasks */
INT8U y;
//得到优先级最高三位
//查询任务就绪表是否有高的优先级
y = OSUnMapTbl[OSRdyGrp];
//获取任务的最高优先级
OSPrioHighRdy = (INT8U)((y << 3u) + OSUnMapTbl[OSRdyTbl[y]]);
#else /* We support up to 256 tasks */
//否则就是256个任务
INT8U y;
OS_PRIO *ptbl;
if ((OSRdyGrp & 0xFFu) != 0u) {
y = OSUnMapTbl[OSRdyGrp & 0xFFu];
} else {
y = OSUnMapTbl[(OS_PRIO)(OSRdyGrp >> 8u) & 0xFFu] + 8u;
}
ptbl = &OSRdyTbl[y];
if ((*ptbl & 0xFFu) != 0u) {
OSPrioHighRdy = (INT8U)((y << 4u) + OSUnMapTbl[(*ptbl & 0xFFu)]);
} else {
OSPrioHighRdy = (INT8U)((y << 4u) + OSUnMapTbl[(OS_PRIO)(*ptbl >> 8u) & 0xFFu] + 8u);
}
#endif
}
//进行任务的切换
void OSCtxSw(void)
{
//在c中执行汇编代码
_asm{
lea eax, nextstart ;任务切换回来后从nextstart开始
push eax
pushfd ;标志寄存器的值
pushad ;保存EAX -- EDI
mov ebx, [OSTCBCur]
mov [ebx], esp ;把堆栈入口的地址保存到当前TCB结构中
}
//钩子函数
OSTaskSwHook();
//初始化当前变量
OSTCBCur = OSTCBHighRdy;
OSPrioCur = OSPrioHighRdy;
_asm{
mov ebx, [OSTCBCur]
mov esp, [ebx] ;得到OSTCBHighRdy的esp
popad ;恢复所有通用寄存器,共8个
popfd ;恢复标志寄存器
ret ;跳转到指定任务运行
}
nextstart: //任务切换回来的运行地址
return;
}
//初始化空闲任务
void OS_TaskIdle (void *p_arg)
{
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
//参数的赋值-目的就是防止编译器警告
p_arg = p_arg; /* Prevent compiler warning for not using ‘p_arg‘ */
for (;;) {
OS_ENTER_CRITICAL();//进入临界区
OSIdleCtr++; //空闲任务数++
OS_EXIT_CRITICAL(); //离开临界区
OSTaskIdleHook(); //钩子函数 /* Call user definable HOOK */
}
}
//任务控制块的初始化
INT8U OS_TCBInit (INT8U prio,//优先级
OS_STK *ptos,//栈点
OS_STK *pbos,//栈底
INT16U id,//进程id
INT32U stk_size,//堆栈大小
void *pext,//参数
INT16U opt)//选择项
{
OS_TCB *ptcb;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#if OS_TASK_REG_TBL_SIZE > 0u
INT8U i;
#endif
//移植代码
OS_ENTER_CRITICAL();
//获取空闲链表的首部
ptcb = OSTCBFreeList; /* Get a free TCB from the free TCB list */
//null
if (ptcb != (OS_TCB *)0) {
//指向下一个链表头
OSTCBFreeList = ptcb->OSTCBNext; /* Update pointer to free TCB list */
OS_EXIT_CRITICAL();
ptcb->OSTCBStkPtr = ptos; /* Load Stack pointer in TCB */
ptcb->OSTCBPrio = prio; /* Load task priority into TCB */
ptcb->OSTCBStat = OS_STAT_RDY; /* Task is ready to run */
ptcb->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */
ptcb->OSTCBDly = 0u; /* Task is not delayed */
//扩展的功能
#if OS_TASK_CREATE_EXT_EN > 0u
ptcb->OSTCBExtPtr = pext; /* Store pointer to TCB extension */
ptcb->OSTCBStkSize = stk_size; /* Store stack size */
ptcb->OSTCBStkBottom = pbos; /* Store pointer to bottom of stack */
ptcb->OSTCBOpt = opt; /* Store task options */
ptcb->OSTCBId = id; /* Store task ID */
//防止编译器警告
#else
pext = pext; /* Prevent compiler warning if not used */
stk_size = stk_size;
pbos = pbos;
opt = opt;
id = id;
#endif
//容许删除
#if OS_TASK_DEL_EN > 0u
ptcb->OSTCBDelReq = OS_ERR_NONE;
#endif
//最高任务数0
#if OS_LOWEST_PRIO <= 63u /* Pre-compute X, Y */
ptcb->OSTCBY = (INT8U)(prio >> 3u);
ptcb->OSTCBX = (INT8U)(prio & 0x07u);
//以后
#else /* Pre-compute X, Y */
ptcb->OSTCBY = (INT8U)((INT8U)(prio >> 4u) & 0xFFu);
ptcb->OSTCBX = (INT8U) (prio & 0x0Fu);
#endif
//查表 /* Pre-compute BitX and BitY */
ptcb->OSTCBBitY = (OS_PRIO)(1uL << ptcb->OSTCBY);
ptcb->OSTCBBitX = (OS_PRIO)(1uL << ptcb->OSTCBX);
//事件
#if (OS_EVENT_EN)
ptcb->OSTCBEventPtr = (OS_EVENT *)0; /* Task is not pending on an event */
#if (OS_EVENT_MULTI_EN > 0u)
ptcb->OSTCBEventMultiPtr = (OS_EVENT **)0; /* Task is not pending on any events */
#endif
#endif
#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) && (OS_TASK_DEL_EN > 0u)
ptcb->OSTCBFlagNode = (OS_FLAG_NODE *)0; /* Task is not pending on an event flag */
#endif
#if (OS_MBOX_EN > 0u) || ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u))
ptcb->OSTCBMsg = (void *)0; /* No message received */
#endif
#if OS_TASK_PROFILE_EN > 0u
ptcb->OSTCBCtxSwCtr = 0uL; /* Initialize profiling variables */
ptcb->OSTCBCyclesStart = 0uL;
ptcb->OSTCBCyclesTot = 0uL;
ptcb->OSTCBStkBase = (OS_STK *)0;
ptcb->OSTCBStkUsed = 0uL;
#endif
#if OS_TASK_NAME_EN > 0u
ptcb->OSTCBTaskName = (INT8U *)(void *)"?";
#endif
//初始化任务控制块就绪表
#if OS_TASK_REG_TBL_SIZE > 0u /* Initialize the task variables */
for (i = 0u; i < OS_TASK_REG_TBL_SIZE; i++) {
ptcb->OSTCBRegTbl[i] = 0u;
}
#endif
//钩子函数
OSTCBInitHook(ptcb);
//空函数
OSTaskCreateHook(ptcb); /* Call user defined hook */
//全局变量
OS_ENTER_CRITICAL();
//以上从空闲表拿出来但没放到就绪链表里去
OSTCBPrioTbl[prio] = ptcb;
ptcb->OSTCBNext = OSTCBList; /* Link into TCB chain */
ptcb->OSTCBPrev = (OS_TCB *)0;
if (OSTCBList != (OS_TCB *)0) {
OSTCBList->OSTCBPrev = ptcb;
}
//设置就绪表和就绪组--
OSTCBList = ptcb;
OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready to run */
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
//任务控制块的切换数++
OSTaskCtr++; /* Increment the #tasks counter */
OS_EXIT_CRITICAL();
return (OS_ERR_NONE);
}
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NO_MORE_TCB);
}
//初始化空闲任务
static void OS_InitTaskIdle (void)
{
#if OS_TASK_NAME_EN > 0u
INT8U err;
#endif
//以下是任务的扩展功能
#if OS_TASK_CREATE_EXT_EN > 0u
#if OS_STK_GROWTH == 1u
(void)OSTaskCreateExt(OS_TaskIdle,
(void *)0, /* No arguments passed to OS_TaskIdle() */
&OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1u],/* Set Top-Of-Stack */
OS_TASK_IDLE_PRIO, /* Lowest priority level */
OS_TASK_IDLE_ID,
&OSTaskIdleStk[0], /* Set Bottom-Of-Stack */
OS_TASK_IDLE_STK_SIZE,
(void *)0, /* No TCB extension */
OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack checking + clear stack */
#else
(void)OSTaskCreateExt(OS_TaskIdle,
(void *)0, /* No arguments passed to OS_TaskIdle() */
&OSTaskIdleStk[0], /* Set Top-Of-Stack */
OS_TASK_IDLE_PRIO, /* Lowest priority level */
OS_TASK_IDLE_ID,
&OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1u],/* Set Bottom-Of-Stack */
OS_TASK_IDLE_STK_SIZE,
(void *)0, /* No TCB extension */
OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack checking + clear stack */
#endif
#else
//以下是否创建任务的一般功能--创建空闲任务
#if OS_STK_GROWTH == 1u
(void)OSTaskCreate(OS_TaskIdle,
(void *)0,
&OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1u],
OS_TASK_IDLE_PRIO);
#else
(void)OSTaskCreate(OS_TaskIdle,
(void *)0,
&OSTaskIdleStk[0],
OS_TASK_IDLE_PRIO);
#endif
#endif
#if OS_TASK_NAME_EN > 0u
OSTaskNameSet(OS_TASK_IDLE_PRIO, (INT8U *)(void *)"uC/OS-II Idle", &err);
#endif
}
//任务调度锁
#if OS_SCHED_LOCK_EN > 0u
void OSSchedLock (void)
{
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
//判断是否有任务在运行
if (OSRunning == OS_TRUE) { /* Make sure multitasking is running */
OS_ENTER_CRITICAL();
//保证没有中断发生
if (OSIntNesting == 0u) { /* Can‘t call from an ISR */
//保证调度锁小于最大值
if (OSLockNesting < 255u) { /* Prevent OSLockNesting from wrapping back to 0 */
//调度锁加1
OSLockNesting++; /* Increment lock nesting level */
}
}
OS_EXIT_CRITICAL();
}
}
//给任务解锁
#if OS_SCHED_LOCK_EN > 0u
void OSSchedUnlock (void)
{
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
//判断是否有任务在运行
if (OSRunning == OS_TRUE) { /* Make sure multitasking is running */
OS_ENTER_CRITICAL();
//是否调度锁大于0
if (OSLockNesting > 0u) { /* Do not decrement if already 0 */
OSLockNesting--; /* Decrement lock nesting level */
if (OSLockNesting == 0u) { /* See if scheduler is enabled and ... */
//没有中断发生
if (OSIntNesting == 0u) { /* ... not in an ISR */
OS_EXIT_CRITICAL();
//进行一次任务的调度
OS_Sched(); /* See if a HPT is ready */
} else {
OS_EXIT_CRITICAL();
}
} else {
OS_EXIT_CRITICAL();
}
} else {
OS_EXIT_CRITICAL();
}
}
}
#endif
OSTaskCreate(TaskStart, 0, &TaskStk[1][TASK_STK_SIZE-1], TaskStart_Prio);//看到12级
switch(Experiment)
{
printf("011112");
case 1://一个任务运行
printf("0000000");
OSTaskCreate(FirstTask, 0, &TaskStk[5][TASK_STK_SIZE-1], 5);
break;
case 2://两个任务共享CPU
OSTaskCreate(E2_task1, 0, &TaskStk[5][TASK_STK_SIZE-1], 5);
OSTaskCreate(E2_task2, 0, &TaskStk[6][TASK_STK_SIZE-1], 6);
break;
case 3://任务的挂起和恢复
OSTaskCreate(E3_task0, 0, &TaskStk[5][TASK_STK_SIZE-1], 5);
OSTaskCreate(E3_task1, 0, &TaskStk[6][TASK_STK_SIZE-1], 6);
OSTaskCreate(E3_task2, 0, &TaskStk[7][TASK_STK_SIZE-1], 7);
break;
case 4://信号量管理例程
OSTaskCreate(UserTaskSemA, 0, &TaskStk[5][TASK_STK_SIZE-1], 7);
OSTaskCreate(UserTaskSemB, 0, &TaskStk[6][TASK_STK_SIZE-1], 6);
OSTaskCreate(UserTaskSemC, 0, &TaskStk[7][TASK_STK_SIZE-1], 5);
break;
case 5://互斥信号量管理例程
OSTaskCreate(TaskMutex1, 0, &TaskStk[6][TASK_STK_SIZE-1], 6);
OSTaskCreate(TaskMutex2, 0, &TaskStk[7][TASK_STK_SIZE-1], 50);
OSTaskCreate(TaskPrint, 0, &TaskStk[8][TASK_STK_SIZE-1], 30);
break;
case 6://时间标志组管理例程
OSTaskCreate(TaskDataProcess, 0, &TaskStk[5][TASK_STK_SIZE-1],5);
OSTaskCreate(TaskIO1, 0, &TaskStk[6][TASK_STK_SIZE-1], 6);
OSTaskCreate(TaskIO2, 0, &TaskStk[7][TASK_STK_SIZE-1], 7);
OSTaskCreate(TaskIO3, 0, &TaskStk[8][TASK_STK_SIZE-1], 8);
OSTaskCreate(TaskIO4, 0, &TaskStk[9][TASK_STK_SIZE-1], 9);
break;
case 7://消息邮箱
OSTaskCreate(TaskMessageSen, 0, &TaskStk[6][TASK_STK_SIZE-1], 6);
OSTaskCreate(TaskMessageRec, 0, &TaskStk[7][TASK_STK_SIZE-1], 7);
break;
case 8://消息队列
OSTaskCreate(TaskQSen, 0, &TaskStk[7][TASK_STK_SIZE-1], 5);
OSTaskCreate(TaskQRec, 0, &TaskStk[8][TASK_STK_SIZE-1], 6);
OSTaskCreate(TaskQRec, 0, &TaskStk[9][TASK_STK_SIZE-1], 7);
break;
case 9://内存管理
OSTaskCreate(TaskM, 0, &TaskStk[8][TASK_STK_SIZE-1], 6);
break;
default:
;
}
@@@
@@@
//初始化创建任务的函数;
#if OS_TASK_CREATE_EN > 0u
INT8U OSTaskCreate (void (*task)(void *p_arg),
void *p_arg,
OS_STK *ptos,
INT8U prio)
{
OS_STK *psp;
INT8U err;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL_IEC61508
if (OSSafetyCriticalStartFlag == OS_TRUE) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
//检查优先级是否有效--首先是0
#if OS_ARG_CHK_EN > 0u
if (prio > OS_LOWEST_PRIO) { /* Make sure priority is within allowable range */
return (OS_ERR_PRIO_INVALID);
}
#endif
OS_ENTER_CRITICAL();
//若是在嵌套中断函数时调用时-是不容许的
if (OSIntNesting > 0u) { /* Make sure we don‘t create the task from within an ISR */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_CREATE_ISR);
}
//查看任务优先级表的是否被占用 是 就执行以下代码
if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn‘t already exist at this priority */
//不知是哪个tcb--就先用书包占用
OSTCBPrioTbl[prio] = OS_TCB_RESERVED;/* Reserve the priority to prevent others from doing ... */
//bit /* ... the same thing until task is created. */
OS_EXIT_CRITICAL();
//任务堆栈的初始化
psp = OSTaskStkInit(task, p_arg, ptos, 0u); /* Initialize the task‘s stack */
//任务控制块的初始化
err = OS_TCBInit(prio, psp, (OS_STK *)0, 0u, 0u, (void *)0, 0u);
//若多任务已经启动就调用一次任务调度
if (err == OS_ERR_NONE) {
//若多任务的启用
if (OSRunning == OS_TRUE) { /* Find highest priority task if multitasking has started */
OS_Sched();//任务调度
}
} else {//no_tcb
OS_ENTER_CRITICAL();
//错误不能创建任务--把刚把书包的站的位置重新给优先级指针表的对应为清0
OSTCBPrioTbl[prio] = (OS_TCB *)0;/* Make this priority available to others */
OS_EXIT_CRITICAL();
}
return (err);
}
OS_EXIT_CRITICAL();
return (OS_ERR_PRIO_EXIST);//返回优先级被占用的信息
}
#endif
//初始化堆栈
OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
{
INT32U *stk; //console 下寄存器为32位宽
opt = opt; /* ‘opt‘ is not used, prevent warning */
stk = (INT32U *)ptos; /* Load stack pointer */
*--stk = (INT32U)pdata; /* Simulate call to function with argument */
//cs
*--stk = (INT32U)0X00000000;
//ip
*--stk = (INT32U)task; /* Put pointer to task on top of stack */
*--stk = (INT32U)0x00000202; /* EFL = 0X00000202 */
*--stk = (INT32U)0xAAAAAAAA; /* EAX = 0xAAAAAAAA */
*--stk = (INT32U)0xCCCCCCCC; /* ECX = 0xCCCCCCCC */
*--stk = (INT32U)0xDDDDDDDD; /* EDX = 0xDDDDDDDD */
*--stk = (INT32U)0xBBBBBBBB; /* EBX = 0xBBBBBBBB */
*--stk = (INT32U)0x00000000; /* ESP = 0x00000000 esp可以任意,因为 */
*--stk = (INT32U)0x11111111; /* EBP = 0x11111111 */
*--stk = (INT32U)0x22222222; /* ESI = 0x22222222 */
*--stk = (INT32U)0x33333333; /* EDI = 0x33333333 */
return ((OS_STK *)stk);
}
//实现任务的删除
#if OS_TASK_DEL_EN > 0u
INT8U OSTaskDel (INT8U prio)
{
#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
OS_FLAG_NODE *pnode;
#endif
OS_TCB *ptcb;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
//在中断中
if (OSIntNesting > 0u) { /* See if trying to delete from ISR */
return (OS_ERR_TASK_DEL_ISR);
}
//空闲任务
if (prio == OS_TASK_IDLE_PRIO) { /* Not allowed to delete idle task */
return (OS_ERR_TASK_DEL_IDLE);
}
//优先级
#if OS_ARG_CHK_EN > 0u
if (prio >= OS_LOWEST_PRIO) { /* Task priority valid ? */
if (prio != OS_PRIO_SELF) {
return (OS_ERR_PRIO_INVALID);
}
}
#endif
/*$PAGE*/
OS_ENTER_CRITICAL();
if (prio == OS_PRIO_SELF) { /* See if requesting to delete self */
prio = OSTCBCur->OSTCBPrio; /* Set priority to delete to current */
}
//检查优先级是否存在
ptcb = OSTCBPrioTbl[prio];
if (ptcb == (OS_TCB *)0) { /* Task to delete must exist */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NOT_EXIST);
}
//表示优先级在表中被保留
if (ptcb == OS_TCB_RESERVED) { /* Must not be assigned to Mutex */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_DEL);
}
//修改就绪表和就绪组的 标志-对就绪组和就绪表进行删除
OSRdyTbl[ptcb->OSTCBY] &= (OS_PRIO)~ptcb->OSTCBBitX;
if (OSRdyTbl[ptcb->OSTCBY] == 0u) { /* Make task not ready */
OSRdyGrp &= (OS_PRIO)~ptcb->OSTCBBitY;
}
#if (OS_EVENT_EN)
//被删除的任务是否还在等待事件的发生。是,就将从事件等待队列中删除掉,已经删除了就不需要等待了
if (ptcb->OSTCBEventPtr != (OS_EVENT *)0) {
OS_EventTaskRemove(ptcb, ptcb->OSTCBEventPtr); /* Remove this task from any event wait list */
}
#if (OS_EVENT_MULTI_EN > 0u)//os容许等待多个事件
if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) { /* Remove this task from any events‘ wait lists*/
OS_EventTaskRemoveMulti(ptcb, ptcb->OSTCBEventMultiPtr);
}
#endif
#endif
#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
pnode = ptcb->OSTCBFlagNode;
if (pnode != (OS_FLAG_NODE *)0) { /* If task is waiting on event flag */
OS_FlagUnlink(pnode); /* Remove from wait list */
}
#endif
//延时
ptcb->OSTCBDly = 0u; /* Prevent OSTimeTick() from updating */
ptcb->OSTCBStat = OS_STAT_RDY; /* Prevent task from being resumed */
ptcb->OSTCBStatPend = OS_STAT_PEND_OK;
//强行调度器上一次锁 保证不发生任务调度
if (OSLockNesting < 255u) { /* Make sure we don‘t context switch */
OSLockNesting++;
}
OS_EXIT_CRITICAL(); /* Enabling INT. ignores next instruc. */
//空闲函数
OS_Dummy(); /* ... Dummy ensures that INTs will be */
OS_ENTER_CRITICAL(); /* ... disabled HERE! */
if (OSLockNesting > 0u) { /* Remove context switch lock */
OSLockNesting--;
}
OSTaskDelHook(ptcb); /* Call user defined hook */
//任务数减一
OSTaskCtr--; /* One less task being managed */
//把优先级任务表不指向任务块了
OSTCBPrioTbl[prio] = (OS_TCB *)0; /* Clear old priority entry */
//对就绪链表 和空闲链表操作--也就是从就绪表中把摘下tcb,插进空闲链表
if (ptcb->OSTCBPrev == (OS_TCB *)0) { /* Remove from TCB chain */
ptcb->OSTCBNext->OSTCBPrev = (OS_TCB *)0;
OSTCBList = ptcb->OSTCBNext;
} else {
ptcb->OSTCBPrev->OSTCBNext = ptcb->OSTCBNext;
ptcb->OSTCBNext->OSTCBPrev = ptcb->OSTCBPrev;
}
ptcb->OSTCBNext = OSTCBFreeList; /* Return TCB to free TCB list */
OSTCBFreeList = ptcb;
#if OS_TASK_NAME_EN > 0u
ptcb->OSTCBTaskName = (INT8U *)(void *)"?";
#endif
OS_EXIT_CRITICAL();
//判断是否在多任务
if (OSRunning == OS_TRUE) {
//进行一次任务调度
OS_Sched(); /* Find new highest priority task */
}
return (OS_ERR_NONE);
}
#endif
//请求自己的删除任务
//a) notify a task to delete itself.
//b) to see if a task requested that the current task delete itself.
/*$PAGE*/
#if OS_TASK_DEL_EN > 0u
INT8U OSTaskDelReq (INT8U prio)
{
INT8U stat;
OS_TCB *ptcb;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
//各种判断--
if (prio == OS_TASK_IDLE_PRIO) { /* Not allowed to delete idle task */
return (OS_ERR_TASK_DEL_IDLE);
}
#if OS_ARG_CHK_EN > 0u
if (prio >= OS_LOWEST_PRIO) { /* Task priority valid ? */
if (prio != OS_PRIO_SELF) {
return (OS_ERR_PRIO_INVALID);
}
}
#endif
//如果删除的是自己
if (prio == OS_PRIO_SELF) { /* See if a task is requesting to ... */
OS_ENTER_CRITICAL(); /* ... this task to delete itself */
//就将自己的任务打上标记
stat = OSTCBCur->OSTCBDelReq; /* Return request status to caller */
OS_EXIT_CRITICAL();
return (stat);
}
OS_ENTER_CRITICAL();
//若是请求删除其他任务
ptcb = OSTCBPrioTbl[prio];
if (ptcb == (OS_TCB *)0) { /* Task to delete must exist */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NOT_EXIST); /* Task must already be deleted */
}
if (ptcb == OS_TCB_RESERVED) { /* Must NOT be assigned to a Mutex */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_DEL);
}
//设置请求删除任务的标志
ptcb->OSTCBDelReq = OS_ERR_TASK_DEL_REQ; /* Set flag indicating task to be DEL. */
OS_EXIT_CRITICAL();
return (OS_ERR_NONE);
}
#endif
//任务挂起
#if OS_TASK_SUSPEND_EN > 0u
INT8U OSTaskSuspend (INT8U prio)
{
BOOLEAN self;
OS_TCB *ptcb;
INT8U y;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
//检查
#if OS_ARG_CHK_EN > 0u
if (prio == OS_TASK_IDLE_PRIO) { /* Not allowed to suspend idle task */
return (OS_ERR_TASK_SUSPEND_IDLE);
}
if (prio >= OS_LOWEST_PRIO) { /* Task priority valid ? */
if (prio != OS_PRIO_SELF) {
return (OS_ERR_PRIO_INVALID);
}
}
#endif
OS_ENTER_CRITICAL();
if (prio == OS_PRIO_SELF) { /* See if suspend SELF */
//获取自己的优先级
prio = OSTCBCur->OSTCBPrio;
self = OS_TRUE;
//当前任务
} else if (prio == OSTCBCur->OSTCBPrio) { /* See if suspending self */
self = OS_TRUE;
} else {
self = OS_FALSE; /* No suspending another task */
}
ptcb = OSTCBPrioTbl[prio];
//被挂起的任务不存在?
if (ptcb == (OS_TCB *)0) { /* Task to suspend must exist */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_SUSPEND_PRIO);
}
//创建任务时--书包占位置 OS_TCB_RESERVED为1
if (ptcb == OS_TCB_RESERVED) { /* See if assigned to Mutex */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NOT_EXIST);
}
//以下代码实现就绪组 和 就绪表取消就绪标志
y = ptcb->OSTCBY;
OSRdyTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX; /* Make task not ready */
if (OSRdyTbl[y] == 0u) {
OSRdyGrp &= (OS_PRIO)~ptcb->OSTCBBitY;
}//4
//标志任务被挂起了
ptcb->OSTCBStat |= OS_STAT_SUSPEND; /* Status of task is ‘SUSPENDED‘ */
OS_EXIT_CRITICAL();
//若挂起的是自己
if (self == OS_TRUE) { /* Context switch only if SELF */
OS_Sched(); //任务调度 /* Find new highest priority task */
}
return (OS_ERR_NONE);
}
#endif
//恢复被挂起的函数
#if OS_TASK_SUSPEND_EN > 0u
INT8U OSTaskResume (INT8U prio)
{
OS_TCB *ptcb;
#if OS_CRITICAL_METHOD == 3u /* Storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
if (prio >= OS_LOWEST_PRIO) { /* Make sure task priority is valid */
return (OS_ERR_PRIO_INVALID);
}
#endif
OS_ENTER_CRITICAL();
ptcb = OSTCBPrioTbl[prio];
/* Task to suspend must exist */
if (ptcb == (OS_TCB *)0) { /* Task to suspend must exist */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_RESUME_PRIO);
}
//判断控制块是否被保留
if (ptcb == OS_TCB_RESERVED) { /* See if assigned to Mutex */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NOT_EXIST);
}
if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) != OS_STAT_RDY) { /* Task must be suspended */
//任务必须是被挂起的才可以被恢复
ptcb->OSTCBStat &= (INT8U)~(INT8U)OS_STAT_SUSPEND; /* Remove suspension */
//移除挂起标志
if (ptcb->OSTCBStat == OS_STAT_RDY) { /* See if task is now ready */
if (ptcb->OSTCBDly == 0u) {
//设置就绪表和就绪组 使任务就绪
OSRdyGrp |= ptcb->OSTCBBitY; /* Yes, Make task ready to run */
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
OS_EXIT_CRITICAL();
if (OSRunning == OS_TRUE) {
OS_Sched(); /* Find new highest priority task */
}
} else {
OS_EXIT_CRITICAL();
}
} else { /* Must be pending on event */
OS_EXIT_CRITICAL();
}
return (OS_ERR_NONE);
}
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NOT_SUSPENDED);
}
#endif
//时钟中断
void OSTimeTick (void)
{
OS_TCB *ptcb;
BOOLEAN step;
OSTimeTickHook(); /*调用用户钩子函数,默认是空函数 */
#if OS_TIME_GET_SET_EN > 0u
OS_ENTER_CRITICAL(); /* Update the 32-bit tick counter */
OSTime++; //调度计数+1
OS_EXIT_CRITICAL();
#endif
//成立表示已经启动多任务
if (OSRunning == OS_TRUE) {
#if OS_TICK_STEP_EN > 0u
switch (OSTickStepState) { /* Determine whether we need to process a tick */
case OS_TICK_STEP_DIS: /* Yes, stepping is disabled */
step = OS_TRUE;
break;
case OS_TICK_STEP_WAIT: /* No, waiting for uC/OS-View to set ... */
step = OS_FALSE; /* .. OSTickStepState to OS_TICK_STEP_ONCE */
break;
case OS_TICK_STEP_ONCE: /* Yes, process tick once and wait for next ... */
step = OS_TRUE; /* ... step command from uC/OS-View */
OSTickStepState = OS_TICK_STEP_WAIT;
break;
default: /* Invalid case, correct situation */
step = OS_TRUE;
OSTickStepState = OS_TICK_STEP_DIS;
break;
}
if (step == OS_FALSE) { /* Return if waiting for step command */
return;
}
#endif
/* Point at first TCB in TCB list */
ptcb = OSTCBList; /* Point at first TCB in TCB list */
while (ptcb->OSTCBPrio != OS_TASK_IDLE_PRIO) { /* Go through all TCBs in TCB list */
OS_ENTER_CRITICAL();
if (ptcb->OSTCBDly != 0u) { /* No, Delayed or waiting for event with TO */
ptcb->OSTCBDly--; /* Decrement nbr of ticks to end of delay */
//Check for timeout
if (ptcb->OSTCBDly == 0u) { /* Check for timeout */
//若有任务等待一事件的发生
if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) {
// Clear status flag
ptcb->OSTCBStat &= (INT8U)~(INT8U)OS_STAT_PEND_ANY; /* Yes, Clear status flag */
ptcb->OSTCBStatPend = OS_STAT_PEND_TO; /* Indicate PEND timeout */
} else {
ptcb->OSTCBStatPend = OS_STAT_PEND_OK;
}
//如果任务不是被挂起的
if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) { /* Is task suspended? */
OSRdyGrp |= ptcb->OSTCBBitY; /* No, Make ready */
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
}
}
}
// Point at next TCB in TCB list
ptcb = ptcb->OSTCBNext; /* Point at next TCB in TCB list */
OS_EXIT_CRITICAL();
}
}
}
//实现结束中断操作--OSIntNesting-1,找到优先级最高的任务来运行
void OSIntExit (void)
{
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
//是否在运行阶段
if (OSRunning == OS_TRUE) {
OS_ENTER_CRITICAL();
//是否在函数嵌套
if (OSIntNesting > 0u) { /* Prevent OSIntNesting from wrapping */
OSIntNesting--;
}
if (OSIntNesting == 0u) { /* Reschedule only if all ISRs complete ... */
//调度锁
if (OSLockNesting == 0u) { /* ... and not locked. */
OS_SchedNew();//find hight
//获取优先级的任务优先级表
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
if (OSPrioHighRdy != OSPrioCur) { /* No Ctx Sw if current task is highest rdy */
#if OS_TASK_PROFILE_EN > 0u
//给任务切换数++
OSTCBHighRdy->OSTCBCtxSwCtr++; /* Inc. # of context switches to this task */
#endif //切换任务计数++
OSCtxSwCtr++; /* Keep track of the number of ctx switches */
//实现任务的切换
OSIntCtxSw(); // /* Perform interrupt level ctx switch */
}
}
}
OS_EXIT_CRITICAL();
}
}
//实现中断级的任务切换
void OSIntCtxSw(void)
{
OS_STK *sp;
OSTaskSwHook();
sp = (OS_STK *)Context.Esp; //得到主线程当前堆栈指针
//在堆栈中保存相应寄存器。
*--sp = Context.Eip; //先保存eip
*--sp = Context.EFlags; //保存efl
*--sp = Context.Eax;
*--sp = Context.Ecx;
*--sp = Context.Edx;
*--sp = Context.Ebx;
*--sp = Context.Esp; //此时保存的esp是错误的,但OSTCBCur保存了正确的
*--sp = Context.Ebp;
*--sp = Context.Esi;
*--sp = Context.Edi;
OSTCBCur->OSTCBStkPtr = (OS_STK *)sp; //保存当前esp
OSTCBCur = OSTCBHighRdy; //得到当前就绪最高优先级任务的tcb
OSPrioCur = OSPrioHighRdy; //得到当前就绪任务最高优先级
sp = OSTCBHighRdy->OSTCBStkPtr; //得到重新执行的任务的堆栈指针
//恢复所有处理器的寄存器
Context.Edi = *sp++;
Context.Esi = *sp++;
Context.Ebp = *sp++;
Context.Esp = *sp++; //此时上下文中得到的esp是不正确的
Context.Ebx = *sp++;
Context.Edx = *sp++;
Context.Ecx = *sp++;
Context.Eax = *sp++;
Context.EFlags = *sp++;
Context.Eip = *sp++;
Context.Esp = (unsigned long)sp; //得到正确的esp
SetThreadContext(mainhandle, &Context); //保存主线程上下文
}
//多任务的开启
void OSStart (void)
{
//若os的多任务还未启动
if (OSRunning == OS_FALSE) {
//Find highest priority‘s task priority number
OS_SchedNew(); /* Find highest priority‘s task priority number */
//OSPrioHighRdy变量在OS_SchedNew已经被设置
OSPrioCur = OSPrioHighRdy;
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; /* Point to highest priority task ready to run */
OSTCBCur = OSTCBHighRdy;
OSStartHighRdy(); /* Execute target specific code to start task */
}
}
//启动高优先级任务
void OSStartHighRdy(void)
{
OSTaskSwHook();
OSRunning = TRUE; //全局变量 表示启动了多任务
_asm{
mov ebx, [OSTCBCur] ;OSTCBCur结构的第一个参数就是esp
mov esp, [ebx] ;恢复堆栈
popad ;恢复所有通用寄存器,共8个
popfd ;恢复标志寄存器
ret ;ret 指令相当于pop eip 但保护模式下不容许使用eip
;永远都不返回
}
}
//进入中断服务程序
void OSIntEnter (void)
{
if (OSRunning == OS_TRUE) {
if (OSIntNesting < 255u) {
//增加中断服务程序ISR嵌套层数
OSIntNesting++; /* Increment ISR nesting level */
}
}
}
//任务延时函数 若是100表示在100个时间片后 把该任务就绪;
void OSTimeDly (INT32U ticks)
{
//从就绪态到阻塞态
INT8U y;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
//中断服务程序不能延时
if (OSIntNesting > 0u) { /* See if trying to call from an ISR */
return;
}
//调度器上锁不能延时-因为延时后就要进行调度;
if (OSLockNesting > 0u) { /* See if called with scheduler locked */
return;
}
//若延时时间延时才回进行延时
if (ticks > 0u) { /* 0 means no delay! */
OS_ENTER_CRITICAL();
//在就绪组和就绪表中取消当前任务的就绪标志;
y = OSTCBCur->OSTCBY; /* Delay current task */
OSRdyTbl[y] &= (OS_PRIO)~OSTCBCur->OSTCBBitX;
if (OSRdyTbl[y] == 0u) {
OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY;
}
//加载给任务控制块OSTCBDly赋值延时时间
OSTCBCur->OSTCBDly = ticks; /* Load ticks in TCB */
OS_EXIT_CRITICAL();
//进行一次任务调度
OS_Sched(); /* Find next task to run! */
}
}
//任务延时以小时 分 秒
#if OS_TIME_DLY_HMSM_EN > 0u
INT8U OSTimeDlyHMSM (INT8U hours,
INT8U minutes,
INT8U seconds,
INT16U ms)
{
INT32U ticks;
//中断服务程序不能延时
if (OSIntNesting > 0u) { /* See if trying to call from an ISR */
return (OS_ERR_TIME_DLY_ISR);
}
//调度器枷锁不能延时
if (OSLockNesting > 0u) { /* See if called with scheduler locked */
return (OS_ERR_SCHED_LOCKED);
}
//进行参数的检查
#if OS_ARG_CHK_EN > 0u
if (hours == 0u) {
if (minutes == 0u) {
if (seconds == 0u) {
if (ms == 0u) {
return (OS_ERR_TIME_ZERO_DLY);
}
}
}
}
//无效分钟数
if (minutes > 59u) {
return (OS_ERR_TIME_INVALID_MINUTES); /* Validate arguments to be within range */
}
if (seconds > 59u) {
return (OS_ERR_TIME_INVALID_SECONDS);
}
if (ms > 999u) {
return (OS_ERR_TIME_INVALID_MS);
}
#endif
/* Compute the total number of clock ticks required.. */
/* .. (rounded to the nearest tick) */
//计算这些时间需要多少个时间片
ticks = ((INT32U)hours * 3600uL + (INT32U)minutes * 60uL + (INT32U)seconds) * OS_TICKS_PER_SEC
+ OS_TICKS_PER_SEC * ((INT32U)ms + 500uL / OS_TICKS_PER_SEC) / 1000uL;
OSTimeDly(ticks);
return (OS_ERR_NONE);
}
#endif
//获取时间
#if OS_TIME_GET_SET_EN > 0u
INT32U OSTimeGet (void)
{
INT32U ticks;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
OS_ENTER_CRITICAL();
ticks = OSTime;
OS_EXIT_CRITICAL();
return (ticks);
}
//设置时间
#if OS_TIME_GET_SET_EN > 0u
void OSTimeSet (INT32U ticks)
{
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
OS_ENTER_CRITICAL();
OSTime = ticks;
OS_EXIT_CRITICAL();
}
#endif
//延时恢复函数--也就是说延时没结束的时候--直接调用此函数就得以恢复
#if OS_TIME_DLY_RESUME_EN > 0u
INT8U OSTimeDlyResume (INT8U prio)
{
OS_TCB *ptcb;
#if OS_CRITICAL_METHOD == 3u /* Storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
//各种参数检查
if (prio >= OS_LOWEST_PRIO) {
return (OS_ERR_PRIO_INVALID);
}
OS_ENTER_CRITICAL();
ptcb = OSTCBPrioTbl[prio]; /* Make sure that task exist */
if (ptcb == (OS_TCB *)0) {
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NOT_EXIST); /* The task does not exist */
}
//查看优先级是否被保留
if (ptcb == OS_TCB_RESERVED) {
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NOT_EXIST); /* The task does not exist */
}
//本函数是否被延时
if (ptcb->OSTCBDly == 0u) { /* See if task is delayed */
OS_EXIT_CRITICAL();
return (OS_ERR_TIME_NOT_DLY); /* Indicate that task was not delayed */
}
//延时时间被强行设置为0
ptcb->OSTCBDly = 0u; /* Clear the time delay */
//如果任务在等待事件的发生;不让等待事件
if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) {
//取反--清0
ptcb->OSTCBStat &= ~OS_STAT_PEND_ANY; /* Yes, Clear status flag */
ptcb->OSTCBStatPend = OS_STAT_PEND_TO; /* Indicate PEND timeout */
} else {
//取消了延时
ptcb->OSTCBStatPend = OS_STAT_PEND_OK;//结束的原因 ,是时间结束了
}
//如果任务不是被挂起的-那么被挂起的任务一定要使用OSTaskResum来恢复
if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) { /* Is task suspended? */
//若没被挂起-设置就绪组合就绪表的标志-进行事件调度;
OSRdyGrp |= ptcb->OSTCBBitY; /* No, Make ready */
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
OS_EXIT_CRITICAL();
//进行一次任务调度
OS_Sched(); /* See if this is new highest priority */
} else {
//任务是被挂起 不能使用本函数恢复;
OS_EXIT_CRITICAL(); /* Task may be suspended */
}
return (OS_ERR_NONE);
}
#endif
以上是关于嵌入式实时操作系统μCOS原理与实践任务控制与时间的解析的主要内容,如果未能解决你的问题,请参考以下文章