📄 ar_task.c
字号:
/*----------------------------------------------------------------------------
* A R T X - K e r n e l
*----------------------------------------------------------------------------
* Name: AR_TASK.C
* Purpose: Task functions and system start up.
* Rev.: V2.00 / 19-oct-2005
*----------------------------------------------------------------------------
* This code is part of the ARTX-ARM kernel package of Keil Software.
* Copyright (c) 2004-2005 Keil Software. All rights reserved.
*---------------------------------------------------------------------------*/
#include "Kernel\ARTX_Config.h"
#include "Kernel\AR_List.h"
#include "Kernel\AR_Task.h"
/* AR_Resource.c */
extern P_TCB os_runtask;
extern struct OS_TCB os_idle_TCB;
extern struct OS_TCB os_clock_TCB;
extern struct OS_XCB os_dly;
/* AR_List.c */
extern U16 os_psq_first;
extern U16 os_psq_last;
/* ARTX_Config.c */
extern U16 const os_maxtaskrun;
extern P_TCB os_active_TCB[];
/*----------------------------------------------------------------------------
* Local Functions
*---------------------------------------------------------------------------*/
OS_TID os_get_TID (P_TCB task) {
U32 tid;
for (tid = 1; tid <= os_maxtaskrun; tid++) {
if (os_active_TCB[tid-1] == task) {
return ((OS_TID)tid);
}
}
return (0);
} /* end of os_get_TID */
/*--------------------------- os_dispatch -----------------------------------*/
void os_dispatch (P_TCB next_TCB) {
/* Dispatch next task if any identified or dispatch highest ready task */
/* "next_TCB" identifies a task to run or has value NULL (=no next task) */
if (next_TCB == NULL) {
/* Running task was blocked: continue with highest ready task */
next_TCB = os_get_first (&os_rdy);
os_switch_tasks (next_TCB);
}
else {
/* Check which task continues */
if (next_TCB->prio > os_runtask->prio) {
/* preempt running task */
os_put_rdy_first (os_runtask);
os_runtask->state = READY;
os_switch_tasks (next_TCB);
}
else {
/* put next task into ready list, no task switch takes place */
next_TCB->state = READY;
os_put_prio (&os_rdy, next_TCB);
};
};
} /* end of os_dispatch */
/*--------------------------- os_block --------------------------------------*/
OS_RESULT os_block (U16 timeout, U8 block_state) {
/* Block running task and choose next ready task. */
/* "timeout" sets a time-out value or is 0xffff (=no time-out). */
/* "block_state" defines the appropriate task state */
P_TCB next_TCB;
if (timeout) {
if (timeout < 0xffff) {
os_put_dly (os_runtask, timeout);
};
os_runtask->state = block_state;
next_TCB = os_get_first (&os_rdy);
os_switch_tasks (next_TCB);
return (os_runtask->ret_val);
}
else {
return (OS_R_TMO);
}
} /* end of os_block */
/*--------------------------- os_tsk_pass -----------------------------------*/
void os_tsk_pass (void) {
/* Allow tasks of same priority level to run cooperatively.*/
P_TCB p_new;
tsk_lock();
p_new = os_get_same_rdy_prio();
if (p_new != NULL) {
os_put_prio ((P_XCB)&os_rdy, os_runtask);
os_runtask->state = READY;
os_switch_tasks (p_new);
};
tsk_unlock();
} /* end of os_tsk_pass */
/*--------------------------- os_tsk_self -----------------------------------*/
OS_TID os_tsk_self (void) {
/* Return own task identifier value. */
return (os_get_TID(os_runtask));
} /* end of os_tsk_self */
/*--------------------------- os_tsk_prio -----------------------------------*/
OS_RESULT os_tsk_prio (OS_TID task_id, U8 new_prio) {
/* Change execution priority of a task to "new_prio". */
P_TCB task_context;
tsk_lock();
if (task_id == 0) {
/* Change execution priority of calling task. */
os_runtask->prio = new_prio;
run_t:if (os_rdy_prio() > new_prio) {
os_put_prio (&os_rdy, os_runtask);
os_runtask->state = READY;
os_dispatch (NULL);
}
tsk_unlock();
return (OS_R_OK);
}
/* Find the task in the "os_active_TCB" array. */
if (task_id > os_maxtaskrun || os_active_TCB[task_id-1] == NULL) {
/* Task with "task_id" not found or not started. */
tsk_unlock ();
return (OS_R_NOK);
}
task_context = os_active_TCB[task_id-1];
task_context->prio = new_prio;
if (task_context == os_runtask) {
goto run_t;
}
if (task_context->state == READY) {
/* Task enqueued in a ready list. */
os_rmv_list (task_context);
/* Check which task continues */
if (new_prio > os_runtask->prio) {
os_put_rdy_first (os_runtask);
os_runtask->state = READY;
os_switch_tasks (task_context);
}
else {
os_put_prio (&os_rdy, task_context);
}
}
tsk_unlock ();
return (OS_R_OK);
} /* end of os_tsk_prio */
/*--------------------------- os_tsk_create_user ----------------------------*/
OS_TID os_tsk_create_user (FUNCP task, U8 priority, void *stk, U16 size) {
/* Start a new task declared with "task". */
P_TCB task_context;
U32 i;
tsk_lock();
/* Priority 0 is reserved for idle task! */
if (priority == 0) {
priority = 1;
}
task_context = os_alloc_TCB ();
if (task_context == NULL) {
tsk_unlock();
return (0);
}
/* If "size != 0" use a private user provided stack. */
task_context->stack = stk;
task_context->priv_stack = size & ~3;
/* For 'size == 0' system allocates the user stack from the memory pool. */
os_init_context (task_context, priority, task, __TRUE);
/* Find a free entry in 'os_active_TCB' table. */
i = os_get_TID (NULL);
os_active_TCB[i-1] = task_context;
os_dispatch (task_context);
tsk_unlock();
return ((OS_TID)i);
} /* end of os_tsk_create_user */
/*--------------------------- os_tsk_create_user_ex -------------------------*/
OS_TID os_tsk_create_user_ex (FUNCPP task, U8 priority,
void *stk, U16 size, void *argv) {
/* Start a new task declared with "task". */
P_TCB task_context;
U32 i;
tsk_lock();
/* Priority 0 is reserved for idle task! */
if (priority == 0) {
priority = 1;
}
task_context = os_alloc_TCB ();
if (task_context == NULL) {
tsk_unlock();
return (0);
}
/* Use a private user provided stack. */
task_context->stack = stk;
task_context->priv_stack = size & ~3;
/* Pass parameter 'argv' to 'os_init_context' */
task_context->p_msg = argv;
/* For 'size == 0' system allocates the user stack from the memory pool. */
os_init_context (task_context, priority, (FUNCP)task, __TRUE);
/* Find a free entry in 'os_active_TCB' table. */
i = os_get_TID (NULL);
os_active_TCB[i-1] = task_context;
os_dispatch (task_context);
tsk_unlock();
return ((OS_TID)i);
} /* end of os_tsk_create_user_ex */
/*--------------------------- os_tsk_delete ---------------------------------*/
OS_RESULT os_tsk_delete (OS_TID task_id) {
/* Terminate the task identified with "task_id". */
P_TCB task_context;
tsk_lock();
if (task_id == 0) {
/* Terminate itself. */
task_context = os_runtask;
task_context->state = INACTIVE;
os_active_TCB[os_get_TID(os_runtask)-1] = NULL;
os_free_TCB (task_context);
os_dispatch (NULL);
/* The program should never come to this point. */
}
else {
/* Find the task in the "os_active_TCB" array. */
if (task_id > os_maxtaskrun || os_active_TCB[task_id-1] == NULL) {
/* Task with "task_id" not found or not started. */
tsk_unlock ();
return (OS_R_NOK);
}
task_context = os_active_TCB[task_id-1];
os_rmv_list (task_context);
os_rmv_dly (task_context);
os_active_TCB[task_id-1] = NULL;
os_free_TCB (task_context);
tsk_unlock ();
}
return (OS_R_OK);
} /* end of os_tsk_delete */
/*--------------------------- os_sys_init_user ------------------------------*/
void os_sys_init_user (FUNCP first_task, U8 priority, void *stk, U16 size) {
/* Initialize system and start up task declared with "first_task". */
tsk_lock();
/* Initialize dynamic memory and task TCB pointers to NULL. */
os_init_mem ();
/* Set up TCB of clock demon: will be activated on clock interrupt */
os_clock_TCB.priv_stack = 0;
os_init_context (&os_clock_TCB, 255, os_clock_demon, __FALSE);
/* Set up TCB of idle demon */
os_idle_TCB.priv_stack = 0;
os_init_context (&os_idle_TCB, 0, os_idle_demon, __FALSE);
/* Set up ready list: initially empty */
os_rdy.cb_type = HCB;
os_rdy.p_lnk = NULL;
/* Set up delay list: initially empty */
os_dly.cb_type = HCB;
os_dly.p_dlnk = NULL;
os_dly.p_blnk = NULL;
os_dly.delta_time = 0;
/* Fix SP and systemvariables to assume idle task is running */
/* Transform main program into idle task by assuming idle TCB */
os_set_env (&os_idle_TCB);
os_runtask = &os_idle_TCB;
os_runtask->state = RUNNING;
/* Initialize ps queue */
os_psq_first = 0;
os_psq_last = 0;
/* Intitialize system clock timer */
os_tmr_init ();
/* Start up first user task before entering the endless loop */
tsk_unlock();
os_tsk_create_user (first_task, priority, stk, size);
/* Call body of idle task: contains an endless loop */
tsk_unlock();
os_idle_demon();
/* This point never reached if idle task contains endless loop */
for (;;);
} /* end of os_sys_init */
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -