一、认识任务管理的函数:
1、建立任务:OSTaskCreate()
2、堆栈检验:OSTaskStkChk()
3、删除任务:OSTaskDel()
4、改变任务优先级:OSTaskChangePrio()
5、挂起任务:OSTaskSuspend()
6、恢复任务:OSTaskResume()
????????任务可以是一个无限的循环,也可以是在一次执行完毕后被删除掉。这里要注意的是,任务代码并不是被真正的删除了,而只是操作系统不再理会该任务代码,所以该任务代码不会再运行。任务从来不会返回,所以任务的类型都是Void型。
二、建立任务
? ? ? ? 任务可以在多任务开始前被建立,即OSStart()函数执行前。也可以在其他任务的执行过程中被创建,但在多任务调度开始前必须建立至少一个任务,但千万不要在中断服务函数中建立任务。我们可以使用OSTaskCreate与OSTaskCreateExt这两个函数来建立任务。
void OSTaskCreate (OS_TCB *p_tcb,指向任务的TCB指针
CPU_CHAR *p_name,用于为任务提供名称
OS_TASK_PTR p_task,指向任务的代码
void *p_arg,为任务传递参数
OS_PRIO prio,任务优先级,数字越小优先级越高
CPU_STK *p_stk_base,指向任务的堆栈基址指针
CPU_STK_SIZE stk_limit,限制堆栈元素数
CPU_STK_SIZE stk_size,堆栈大小
OS_MSG_QTY q_size,可以发送到任务的最大消息数
OS_TICK time_quanta,时间片
void *p_ext,
OS_OPT opt,任务行为信息
OS_ERR *p_err)错误返回值
{
CPU_STK_SIZE i;
#if OS_CFG_TASK_REG_TBL_SIZE > 0u
OS_REG_ID reg_nbr;
#endif
#if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
OS_TLS_ID id;
#endif
CPU_STK *p_sp;
CPU_STK *p_stk_limit;
CPU_SR_ALLOC();
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return;
}
#endif
#ifdef OS_SAFETY_CRITICAL_IEC61508
if (OSSafetyCriticalStartFlag == DEF_TRUE) {
*p_err = OS_ERR_ILLEGAL_CREATE_RUN_TIME;
return;
}
#endif
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* ---------- CANNOT CREATE A TASK FROM AN ISR ---------- */
*p_err = OS_ERR_TASK_CREATE_ISR;
return;
}
#endif
#if OS_CFG_ARG_CHK_EN > 0u /* ---------------- VALIDATE ARGUMENTS ------------------ */
if (p_tcb == (OS_TCB *)0) { /* User must supply a valid OS_TCB */
*p_err = OS_ERR_TCB_INVALID;
return;
}
if (p_task == (OS_TASK_PTR)0) { /* User must supply a valid task */
*p_err = OS_ERR_TASK_INVALID;
return;
}
if (p_stk_base == (CPU_STK *)0) { /* User must supply a valid stack base address */
*p_err = OS_ERR_STK_INVALID;
return;
}
if (stk_size < OSCfg_StkSizeMin) { /* User must supply a valid minimum stack size */
*p_err = OS_ERR_STK_SIZE_INVALID;
return;
}
if (stk_limit >= stk_size) { /* User must supply a valid stack limit */
*p_err = OS_ERR_STK_LIMIT_INVALID;
return;
}
if (prio >= OS_CFG_PRIO_MAX) { /* Priority must be within 0 and OS_CFG_PRIO_MAX-1 */
*p_err = OS_ERR_PRIO_INVALID;
return;
}
#endif
#if OS_CFG_ISR_POST_DEFERRED_EN > 0u
if (prio == (OS_PRIO)0) {
if (p_tcb != &OSIntQTaskTCB) {
*p_err = OS_ERR_PRIO_INVALID; /* Not allowed to use priority 0 */
return;
}
}
#endif
if (prio == (OS_CFG_PRIO_MAX - 1u)) {
if (p_tcb != &OSIdleTaskTCB) {
*p_err = OS_ERR_PRIO_INVALID; /* Not allowed to use same priority as idle task */
return;
}
}
OS_TaskInitTCB(p_tcb); /* Initialize the TCB to default values */
*p_err = OS_ERR_NONE;
/* --------------- CLEAR THE TASK'S STACK --------------- */
if ((opt & OS_OPT_TASK_STK_CHK) != (OS_OPT)0) { /* See if stack checking has been enabled */
if ((opt & OS_OPT_TASK_STK_CLR) != (OS_OPT)0) { /* See if stack needs to be cleared */
p_sp = p_stk_base;
for (i = 0u; i < stk_size; i++) { /* Stack grows from HIGH to LOW memory */
*p_sp = (CPU_STK)0; /* Clear from bottom of stack and up! */
p_sp++;
}
}
}
/* ------- INITIALIZE THE STACK FRAME OF THE TASK ------- */
#if (CPU_CFG_STK_GROWTH == CPU_STK_GROWTH_HI_TO_LO)
p_stk_limit = p_stk_base + stk_limit;
#else
p_stk_limit = p_stk_base + (stk_size - 1u) - stk_limit;
#endif
p_sp = OSTaskStkInit(p_task,
p_arg,
p_stk_base,
p_stk_limit,
stk_size,
opt);
/* -------------- INITIALIZE THE TCB FIELDS ------------- */
p_tcb->TaskEntryAddr = p_task; /* Save task entry point address */
p_tcb->TaskEntryArg = p_arg; /* Save task entry argument */
p_tcb->NamePtr = p_name; /* Save task name */
p_tcb->Prio = prio; /* Save the task's priority */
p_tcb->StkPtr = p_sp; /* Save the new top-of-stack pointer */
p_tcb->StkLimitPtr = p_stk_limit; /* Save the stack limit pointer */
p_tcb->TimeQuanta = time_quanta; /* Save the #ticks for time slice (0 means not sliced) */
#if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u
if (time_quanta == (OS_TICK)0) {
p_tcb->TimeQuantaCtr = OSSchedRoundRobinDfltTimeQuanta;
} else {
p_tcb->TimeQuantaCtr = time_quanta;
}
#endif
p_tcb->ExtPtr = p_ext; /* Save pointer to TCB extension */
p_tcb->StkBasePtr = p_stk_base; /* Save pointer to the base address of the stack */
p_tcb->StkSize = stk_size; /* Save the stack size (in number of CPU_STK elements) */
p_tcb->Opt = opt; /* Save task options */
#if OS_CFG_TASK_REG_TBL_SIZE > 0u
for (reg_nbr = 0u; reg_nbr < OS_CFG_TASK_REG_TBL_SIZE; reg_nbr++) {
p_tcb->RegTbl[reg_nbr] = (OS_REG)0;
}
#endif
#if OS_CFG_TASK_Q_EN > 0u
OS_MsgQInit(&p_tcb->MsgQ, /* Initialize the task's message queue */
q_size);
#else
(void)&q_size;
#endif
OSTaskCreateHook(p_tcb); /* Call user defined hook */
#if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
for (id = 0u; id < OS_CFG_TLS_TBL_SIZE; id++) {
p_tcb->TLS_Tbl[id] = (OS_TLS)0;
}
OS_TLS_TaskCreate(p_tcb); /* Call TLS hook */
#endif
/* --------------- ADD TASK TO READY LIST --------------- */
OS_CRITICAL_ENTER();
OS_PrioInsert(p_tcb->Prio);
OS_RdyListInsertTail(p_tcb);
#if OS_CFG_DBG_EN > 0u
OS_TaskDbgListAdd(p_tcb);
#endif
OSTaskQty++; /* Increment the #tasks counter */
if (OSRunning != OS_STATE_OS_RUNNING) { /* Return if multitasking has not started */
OS_CRITICAL_EXIT();
return;
}
OS_CRITICAL_EXIT_NO_SCHED();
OSSched();
}
????????OSTaskCreate函数的大致流程为:判断是否可以创建任务,导致创建失败的原因有,在中断中创建、用户没有为任务传输相关参数、占用已使用特定任务的优先级。之后进行TCB的初始化,调用的是OSTaskInitTCB函数。再判断传入的堆栈位置是否可用,是否需要初始化。确定堆栈的生长方向,再调用OSTaskStkInit进行堆栈初始化。之后判断是否打开了轮循调度、确定任务的时间片大小,将TCB的各项初始为传入的参数,初始化任务的消息队列,设置任务的钩子函数,呼叫钩子函数,进入临界区后将任务插入就绪队列,任务数变量自加一,如果轮循调度开启退出临界区进行任务调度。创建好的任务在内存形式如下:
?三、OSTaskDel(OS_TCB ?*p_tcb, ? ? ? ? ? ? ? ? ?OS_ERR ?*p_err)
? ? ? ? 该函数函数可以通过指定NULL来删除自己。?删除一个任务。根据任务状态,将p_tcb从RdyList,TickList,PendList中删除,释放Queue中的所有OS_MSG,调用钩子函数,清空TCB, p_tcb->TaskState = (OS_STATE)OS_TASK_STATE_DEL;,启动调度。
void OSTaskDel (OS_TCB *p_tcb,
OS_ERR *p_err)
{
CPU_SR_ALLOC();
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return;
}
#endif
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if trying to delete from ISR */
*p_err = OS_ERR_TASK_DEL_ISR;
return;
}
#endif
if (p_tcb == &OSIdleTaskTCB) { /* Not allowed to delete the idle task */
*p_err = OS_ERR_TASK_DEL_IDLE;
return;
}
#if OS_CFG_ISR_POST_DEFERRED_EN > 0u
if (p_tcb == &OSIntQTaskTCB) { /* Cannot delete the ISR handler task */
*p_err = OS_ERR_TASK_DEL_INVALID;
return;
}
#endif
if (p_tcb == (OS_TCB *)0) { /* Delete 'Self'? */
CPU_CRITICAL_ENTER();
p_tcb = OSTCBCurPtr; /* Yes. */
CPU_CRITICAL_EXIT();
}
OS_CRITICAL_ENTER();
switch (p_tcb->TaskState) {
case OS_TASK_STATE_RDY:
OS_RdyListRemove(p_tcb);
break;
case OS_TASK_STATE_SUSPENDED:
break;
case OS_TASK_STATE_DLY: /* Task is only delayed, not on any wait list */
case OS_TASK_STATE_DLY_SUSPENDED:
OS_TickListRemove(p_tcb);
break;
case OS_TASK_STATE_PEND:
case OS_TASK_STATE_PEND_SUSPENDED:
case OS_TASK_STATE_PEND_TIMEOUT:
case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:
OS_TickListRemove(p_tcb);
switch (p_tcb->PendOn) { /* See what we are pending on */
case OS_TASK_PEND_ON_NOTHING:
case OS_TASK_PEND_ON_TASK_Q: /* There is no wait list for these two */
case OS_TASK_PEND_ON_TASK_SEM:
break;
case OS_TASK_PEND_ON_FLAG: /* Remove from wait list */
case OS_TASK_PEND_ON_MULTI:
case OS_TASK_PEND_ON_MUTEX:
case OS_TASK_PEND_ON_Q:
case OS_TASK_PEND_ON_SEM:
OS_PendListRemove(p_tcb);
break;
default:
break;
}
break;
default:
OS_CRITICAL_EXIT();
*p_err = OS_ERR_STATE_INVALID;
return;
}
#if OS_CFG_TASK_Q_EN > 0u
(void)OS_MsgQFreeAll(&p_tcb->MsgQ); /* Free task's message queue messages */
#endif
OSTaskDelHook(p_tcb); /* Call user defined hook */
#if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
OS_TLS_TaskDel(p_tcb); /* Call TLS hook */
#endif
#if OS_CFG_DBG_EN > 0u
OS_TaskDbgListRemove(p_tcb);
#endif
OSTaskQty--; /* One less task being managed */
OS_TaskInitTCB(p_tcb); /* Initialize the TCB to default values */
p_tcb->TaskState = (OS_STATE)OS_TASK_STATE_DEL; /* Indicate that the task was deleted */
OS_CRITICAL_EXIT_NO_SCHED();
*p_err = OS_ERR_NONE; /* See Note #1. */
OSSched(); /* Find new highest priority task */
}
四、OSTaskSuspend (OS_TCB ?*p_tcb, ? ? ? ? ? ? ? ? ? ? ? OS_ERR ?*p_err)
? ? ? ? 调用该函数可以暂停任务,p_tcb为NULL时可以暂停自己,最前面的是安全认证相关不用理会。中断中不可调用、不可暂停空闲函数、不可暂停中断服务函数、转到函数OS_TaskSuspend 中。
void OSTaskSuspend (OS_TCB *p_tcb,
OS_ERR *p_err)
{
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return;
}
#endif
#if (OS_CFG_ISR_POST_DEFERRED_EN == 0u) && \
(OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u)
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to call from an ISR */
*p_err = OS_ERR_TASK_SUSPEND_ISR;
return;
}
#endif
if (p_tcb == &OSIdleTaskTCB) { /* Make sure not suspending the idle task */
*p_err = OS_ERR_TASK_SUSPEND_IDLE;
return;
}
#if OS_CFG_ISR_POST_DEFERRED_EN > 0u
if (p_tcb == &OSIntQTaskTCB) { /* Not allowed to suspend the ISR handler task */
*p_err = OS_ERR_TASK_SUSPEND_INT_HANDLER;
return;
}
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if called from an ISR */
OS_IntQPost((OS_OBJ_TYPE)OS_OBJ_TYPE_TASK_SUSPEND, /* Post to ISR queue */
(void *)p_tcb,
(void *)0,
(OS_MSG_SIZE)0,
(OS_FLAGS )0,
(OS_OPT )0,
(CPU_TS )0,
(OS_ERR *)p_err);
return;
}
#endif
OS_TaskSuspend(p_tcb, p_err);
}
?进入临界区,如果传入指针为NULL则将指针指向当前任务TCB指针,如果调度器上锁了不可以调度,根据任务所处的状态处理任务。开启调度。如果成功挂起任务,任务状态会变为暂停态,把他从就绪队列中移除,并设置暂停计数器为1,挂起一次累加一次。
void OS_TaskSuspend (OS_TCB *p_tcb,
OS_ERR *p_err)
{
CPU_SR_ALLOC();
CPU_CRITICAL_ENTER();
if (p_tcb == (OS_TCB *)0) { /* See if specified to suspend self */
p_tcb = OSTCBCurPtr;
}
if (p_tcb == OSTCBCurPtr) {
if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* Can't suspend when the scheduler is locked */
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_SCHED_LOCKED;
return;
}
}
*p_err = OS_ERR_NONE;
switch (p_tcb->TaskState) {
case OS_TASK_STATE_RDY:
OS_CRITICAL_ENTER_CPU_EXIT();
p_tcb->TaskState = OS_TASK_STATE_SUSPENDED;
p_tcb->SuspendCtr = (OS_NESTING_CTR)1;
OS_RdyListRemove(p_tcb);
OS_CRITICAL_EXIT_NO_SCHED();
break;
case OS_TASK_STATE_DLY:
p_tcb->TaskState = OS_TASK_STATE_DLY_SUSPENDED;
p_tcb->SuspendCtr = (OS_NESTING_CTR)1;
CPU_CRITICAL_EXIT();
break;
case OS_TASK_STATE_PEND:
p_tcb->TaskState = OS_TASK_STATE_PEND_SUSPENDED;
p_tcb->SuspendCtr = (OS_NESTING_CTR)1;
CPU_CRITICAL_EXIT();
break;
case OS_TASK_STATE_PEND_TIMEOUT:
p_tcb->TaskState = OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED;
p_tcb->SuspendCtr = (OS_NESTING_CTR)1;
CPU_CRITICAL_EXIT();
break;
case OS_TASK_STATE_SUSPENDED:
case OS_TASK_STATE_DLY_SUSPENDED:
case OS_TASK_STATE_PEND_SUSPENDED:
case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:
p_tcb->SuspendCtr++;
CPU_CRITICAL_EXIT();
break;
default:
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_STATE_INVALID;
return;
}
OSSched();
}
五、OSTaskResume (OS_TCB ?*p_tcb, ? ? ? ? ? ? ? ? ? ? OS_ERR ?*p_err)
? ? ? ? 调用函数可以恢复暂停的,函数首先判断是否在中断中、是否是自己调用。执行函数?OS_TaskResume(p_tcb, p_err);我们看这个函数足以。首先进入临界区、根据恢复暂停的任务状态来执行操作。状态为OS_TASK_STATE_SUSPENDED时暂停计数器减一,如果计数器减为0才可以将状态改为就绪态,将其放入就绪队列中。执行任务调度。
void OS_TaskResume (OS_TCB *p_tcb,
OS_ERR *p_err)
{
CPU_SR_ALLOC();
CPU_CRITICAL_ENTER();
*p_err = OS_ERR_NONE;
switch (p_tcb->TaskState) {
case OS_TASK_STATE_RDY:
case OS_TASK_STATE_DLY:
case OS_TASK_STATE_PEND:
case OS_TASK_STATE_PEND_TIMEOUT:
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_TASK_NOT_SUSPENDED;
break;
case OS_TASK_STATE_SUSPENDED:
OS_CRITICAL_ENTER_CPU_EXIT();
p_tcb->SuspendCtr--;
if (p_tcb->SuspendCtr == (OS_NESTING_CTR)0) {
p_tcb->TaskState = OS_TASK_STATE_RDY;
OS_TaskRdy(p_tcb);
}
OS_CRITICAL_EXIT_NO_SCHED();
break;
case OS_TASK_STATE_DLY_SUSPENDED:
p_tcb->SuspendCtr--;
if (p_tcb->SuspendCtr == (OS_NESTING_CTR)0) {
p_tcb->TaskState = OS_TASK_STATE_DLY;
}
CPU_CRITICAL_EXIT();
break;
case OS_TASK_STATE_PEND_SUSPENDED:
p_tcb->SuspendCtr--;
if (p_tcb->SuspendCtr == (OS_NESTING_CTR)0) {
p_tcb->TaskState = OS_TASK_STATE_PEND;
}
CPU_CRITICAL_EXIT();
break;
case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:
p_tcb->SuspendCtr--;
if (p_tcb->SuspendCtr == (OS_NESTING_CTR)0) {
p_tcb->TaskState = OS_TASK_STATE_PEND_TIMEOUT;
}
CPU_CRITICAL_EXIT();
break;
default:
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_STATE_INVALID;
return;
}
OSSched();
}
六、OSTaskStkChk()
? ? ? ? 检查p_tcb堆栈的使用量和剩余量,为了适应系统以后的升级和扩展,用户应该多分配10%-100%的堆栈空间。在堆栈检验中,用户所得到的只是一个大致的堆栈使用情况,并不能说明堆栈使用的全部实际情况。函数主要功能是不能在中断中检测、判断地址是否可用,进入临界区,p_tcb==NULL则为查询自身的,查看传入任务是否存在,查看查看堆栈的选项是否开启,判断完后退出临界区。根据栈的生长方式计算出空闲区域的大小,用栈的总量减去刚得出空闲区域的大小为已使用区域的大小。具体示意如图所示:
?
void OSTaskStkChk (OS_TCB *p_tcb,
CPU_STK_SIZE *p_free,
CPU_STK_SIZE *p_used,
OS_ERR *p_err)
{
CPU_STK_SIZE free_stk;
CPU_STK *p_stk;
CPU_SR_ALLOC();
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return;
}
#endif
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if trying to check stack from ISR */
*p_err = OS_ERR_TASK_STK_CHK_ISR;
return;
}
#endif
#if OS_CFG_ARG_CHK_EN > 0u
if (p_free == (CPU_STK_SIZE*)0) { /* User must specify valid destinations for the sizes */
*p_err = OS_ERR_PTR_INVALID;
return;
}
if (p_used == (CPU_STK_SIZE*)0) {
*p_err = OS_ERR_PTR_INVALID;
return;
}
#endif
CPU_CRITICAL_ENTER();
if (p_tcb == (OS_TCB *)0) { /* Check the stack of the current task? */
p_tcb = OSTCBCurPtr; /* Yes */
}
if (p_tcb->StkPtr == (CPU_STK*)0) { /* Make sure task exist */
CPU_CRITICAL_EXIT();
*p_free = (CPU_STK_SIZE)0;
*p_used = (CPU_STK_SIZE)0;
*p_err = OS_ERR_TASK_NOT_EXIST;
return;
}
if ((p_tcb->Opt & OS_OPT_TASK_STK_CHK) == (OS_OPT)0) { /* Make sure stack checking option is set */
CPU_CRITICAL_EXIT();
*p_free = (CPU_STK_SIZE)0;
*p_used = (CPU_STK_SIZE)0;
*p_err = OS_ERR_TASK_OPT;
return;
}
CPU_CRITICAL_EXIT();
free_stk = 0u;
#if CPU_CFG_STK_GROWTH == CPU_STK_GROWTH_HI_TO_LO
p_stk = p_tcb->StkBasePtr; /* Start at the lowest memory and go up */
while (*p_stk == (CPU_STK)0) { /* Compute the number of zero entries on the stk */
p_stk++;
free_stk++;
}
#else
p_stk = p_tcb->StkBasePtr + p_tcb->StkSize - 1u; /* Start at the highest memory and go down */
while (*p_stk == (CPU_STK)0) {
free_stk++;
p_stk--;
}
#endif
*p_free = free_stk;
*p_used = (p_tcb->StkSize - free_stk); /* Compute number of entries used on the stack */
*p_err = OS_ERR_NONE;
}
七、OSTaskChangePrio()
? ? ? ? 使用该函数可以动态的设置任务的优先级,优先级必须可用。根据状态对任务进行处理,当任务处于就绪状态时,将任务从就绪列表上移除,改变其优先级,再将他插入回就绪队列。若为暂停状态则直接改变优先级。执行调度。
void OSTaskChangePrio (OS_TCB *p_tcb,
OS_PRIO prio_new,
OS_ERR *p_err)
{
CPU_BOOLEAN self;
CPU_SR_ALLOC();
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return;
}
#endif
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* ---------- CANNOT CREATE A TASK FROM AN ISR ---------- */
*p_err = OS_ERR_TASK_CHANGE_PRIO_ISR;
return;
}
#endif
#if OS_CFG_ISR_POST_DEFERRED_EN > 0u
if (prio_new == 0) { /* Cannot set to IntQueue Task priority */
*p_err = OS_ERR_PRIO_INVALID;
return;
}
#endif
if (prio_new >= (OS_CFG_PRIO_MAX - 1u)) { /* Cannot set to Idle Task priority */
*p_err = OS_ERR_PRIO_INVALID;
return;
}
if (p_tcb == (OS_TCB *)0) { /* See if want to change priority of 'self' */
CPU_CRITICAL_ENTER();
p_tcb = OSTCBCurPtr;
CPU_CRITICAL_EXIT();
self = DEF_TRUE;
} else {
self = DEF_FALSE;
}
OS_CRITICAL_ENTER();
switch (p_tcb->TaskState) {
case OS_TASK_STATE_RDY:
OS_RdyListRemove(p_tcb); /* Remove from current priority */
p_tcb->Prio = prio_new; /* Set new task priority */
OS_PrioInsert(p_tcb->Prio);
if (self == DEF_TRUE) {
OS_RdyListInsertHead(p_tcb);
} else {
OS_RdyListInsertTail(p_tcb);
}
break;
case OS_TASK_STATE_DLY: /* Nothing to do except change the priority in the OS_TCB */
case OS_TASK_STATE_SUSPENDED:
case OS_TASK_STATE_DLY_SUSPENDED:
p_tcb->Prio = prio_new; /* Set new task priority */
break;
case OS_TASK_STATE_PEND:
case OS_TASK_STATE_PEND_TIMEOUT:
case OS_TASK_STATE_PEND_SUSPENDED:
case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:
switch (p_tcb->PendOn) { /* What to do depends on what we are pending on */
case OS_TASK_PEND_ON_TASK_Q: /* Nothing to do except change the priority in the OS_TCB */
case OS_TASK_PEND_ON_TASK_SEM:
case OS_TASK_PEND_ON_FLAG:
p_tcb->Prio = prio_new; /* Set new task priority */
break;
case OS_TASK_PEND_ON_MUTEX:
case OS_TASK_PEND_ON_MULTI:
case OS_TASK_PEND_ON_Q:
case OS_TASK_PEND_ON_SEM:
OS_PendListChangePrio(p_tcb,
prio_new);
break;
default:
break;
}
break;
default:
OS_CRITICAL_EXIT();
*p_err = OS_ERR_STATE_INVALID;
return;
}
OS_CRITICAL_EXIT_NO_SCHED();
OSSched(); /* Run highest priority task ready */
*p_err = OS_ERR_NONE;
}
|