📄 os_task.c
字号:
/*
************************************************************************************************************************
* uC/OS-III
* The Real-Time Kernel
*
* (c) Copyright 2009-2011; Micrium, Inc.; Weston, FL
* All rights reserved. Protected by international copyright laws.
*
* TASK MANAGEMENT
*
* File : OS_TASK.C
* By : JJL
* Version : V3.02.00
*
* LICENSING TERMS:
* ---------------
* uC/OS-III is provided in source form for FREE short-term evaluation, for educational use or
* for peaceful research. If you plan or intend to use uC/OS-III in a commercial application/
* product then, you need to contact Micrium to properly license uC/OS-III for its use in your
* application/product. We provide ALL the source code for your convenience and to help you
* experience uC/OS-III. The fact that the source is provided does NOT mean that you can use
* it commercially without paying a licensing fee.
*
* Knowledge of the source code may NOT be used to develop a similar product.
*
* Please help us continue to provide the embedded community with the finest software available.
* Your honesty is greatly appreciated.
*
* You can contact us at www.micrium.com, or by phone at +1 (954) 217-2036.
************************************************************************************************************************
*/
#include <os.h>
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
const CPU_CHAR *os_task__c = "$Id: $";
#endif
/*
************************************************************************************************************************
* CHANGE PRIORITY OF A TASK
*
* Description: This function allows you to change the priority of a task dynamically. Note that the new
* priority MUST be available.
*
* Arguments : p_tcb is the TCB of the tack to change the priority for
*
* prio_new is the new priority
*
* p_err is a pointer to an error code returned by this function:
*
* OS_ERR_NONE is the call was successful
* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed
* (i.e. >= (OS_CFG_PRIO_MAX-1))
* OS_ERR_STATE_INVALID if the task is in an invalid state
* OS_ERR_TASK_CHANGE_PRIO_ISR if you tried to change the task's priority from an ISR
************************************************************************************************************************
*/
#if OS_CFG_TASK_CHANGE_PRIO_EN > 0u
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 (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;
}
#endif
/*$PAGE*/
/*
************************************************************************************************************************
* CREATE A TASK
*
* Description: This function is used to have uC/OS-III manage the execution of a task. Tasks can either be created
* prior to the start of multitasking or by a running task. A task cannot be created by an ISR.
*
* Arguments : p_tcb is a pointer to the task's TCB
*
* p_name is a pointer to an ASCII string to provide a name to the task.
*
* p_task is a pointer to the task's code
*
* p_arg is a pointer to an optional data area which can be used to pass parameters to
* the task when the task first executes. Where the task is concerned it thinks
* it was invoked and passed the argument 'p_arg' as follows:
*
* void Task (void *p_arg)
* {
* for (;;) {
* Task code;
* }
* }
*
* prio is the task's priority. A unique priority MUST be assigned to each task and the
* lower the number, the higher the priority.
*
* p_stk_base is a pointer to the base address of the stack (i.e. low address).
*
* stk_limit is the number of stack elements to set as 'watermark' limit for the stack. This value
* represents the number of CPU_STK entries left before the stack is full. For example,
* specifying 10% of the 'stk_size' value indicates that the stack limit will be reached
* when the stack reaches 90% full.
*
* stk_size is the size of the stack in number of elements. If CPU_STK is set to CPU_INT08U,
* 'stk_size' corresponds to the number of bytes available. If CPU_STK is set to
* CPU_INT16U, 'stk_size' contains the number of 16-bit entries available. Finally, if
* CPU_STK is set to CPU_INT32U, 'stk_size' contains the number of 32-bit entries
* available on the stack.
*
* q_size is the maximum number of messages that can be sent to the task
*
* time_quanta amount of time (in ticks) for time slice when round-robin between tasks. Specify 0 to use
* the default.
*
* p_ext is a pointer to a user supplied memory location which is used as a TCB extension.
* For example, this user memory can hold the contents of floating-point registers
* during a context switch, the time each task takes to execute, the number of times
* the task has been switched-in, etc.
*
* opt contains additional information (or options) about the behavior of the task.
* See OS_OPT_TASK_xxx in OS.H. Current choices are:
*
* OS_OPT_TASK_NONE No option selected
* OS_OPT_TASK_STK_CHK Stack checking to be allowed for the task
* OS_OPT_TASK_STK_CLR Clear the stack when the task is created
* OS_OPT_TASK_SAVE_FP If the CPU has floating-point registers, save them
* during a context switch.
*
* p_err is a pointer to an error code that will be set during this call. The value pointer
* to by 'p_err' can be:
*
* OS_ERR_NONE if the function was successful.
* OS_ERR_ILLEGAL_CREATE_RUN_TIME if you are trying to create the task after you called
* OSSafetyCriticalStart().
* OS_ERR_NAME if 'p_name' is a NULL pointer
* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum
* allowed (i.e. >= OS_CFG_PRIO_MAX-1) or,
* if OS_CFG_ISR_POST_DEFERRED_EN is set to 1 and you tried
* to use priority 0 which is reserved.
* OS_ERR_STK_INVALID if you specified a NULL pointer for 'p_stk_base'
* OS_ERR_STK_SIZE_INVALID if you specified zero for the 'stk_size'
* OS_ERR_STK_LIMIT_INVALID if you specified a 'stk_limit' greater than or equal
* to 'stk_size'
* OS_ERR_TASK_CREATE_ISR if you tried to create a task from an ISR.
* OS_ERR_TASK_INVALID if you specified a NULL pointer for 'p_task'
* OS_ERR_TCB_INVALID if you specified a NULL pointer for 'p_tcb'
*
* Returns : A pointer to the TCB of the task created. This pointer must be used as an ID (i.e handle) to the task.
************************************************************************************************************************
*/
/*$PAGE*/
void OSTaskCreate (OS_TCB *p_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_OBJ_QTY reg_nbr;
#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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -