📄 task.c
字号:
#define OS_GLOBALS
#if !defined(__EBOS_H)
#include "ebos.h"
#endif
extern jmp_buf jmpb;
/*
*********************************************************************************************************
* TASK COMPOENT Implementation
*********************************************************************************************************
*/
/*
*********************************************************************************************************
该函数是由线程调度函数调用的函数,用来把控制交给特定线程,线程的
调度次数加1,并使KERNAL.current_thread指针指向该线程.
*********************************************************************************************************
*/
static TASK_TCB *HighRdyThread;
static void *reserved;
static TASK_TCB *Priority_Head[LOWEST_PRIORITY]; // 优先级表头指针
static void (* LISR_Pointers[MAX_INT_VECT])(void); // 中断函数指针的列表,该列表由中断向量作为索引,在该表中找到要执行的中断函数
static UCHAR Sub_Priority_Groups[LOWEST_PRIORITY/8]; // 子组优先级指针
static UNSIGNED Priority_Group ; // 优先级组位掩码
static UCHAR DirectSched; //是否直接调度
static UNSIGNED Int_Count; //Interrupt nesting level
// UNSIGNED OSCtxSwCtr; /* Counter of number of context switches
static TASK_TCB *TaskTable[MAX_TASK_NUM]; //任务向量表
static TASK_HCB *HisrTable[MAX_HISR_NUM]; //高级中断处理线程向量表
static void * _InitHISRStack(TASK_HCB *hisr); //高级中断处理线程堆栈初始化
static TASK_TCB *TaskFreeList; //可用任务列表头指针
static TASK_HCB *HisrFreeList; //可用HISR表头指针
/********************************************************************************************
取得一个可用的任务ID号
***************************************************************************************/
static SIGNED _NewTaskId()
{
static UNSIGNED next_task_id;
UNSIGNED id; /* process id to return */
EnLock();
if ((id=next_task_id++) < MAX_TASK_NUM){
if (TaskTable[id] == NULL){
UnLock();
return(id);
}
}
else if(TaskFreeList){
id=TaskFreeList->id;
#if ENABLE_MEM
FreeBuff(TaskFreeList);
#endif
TaskFreeList=TaskFreeList->next;
UnLock();
return(id);
}
UnLock();
return(NO_TASK_SPACE);
}
/********************************************************************************************
取得一个可用的HISR ID号
***************************************************************************************/
static SIGNED _NewHisrId()
{
static UNSIGNED next_hisr_id;
UNSIGNED id; /* process id to return */
UNSIGNED i;
EnLock();
if ( (id=next_hisr_id++)< MAX_HISR_NUM){
if (HisrTable[id] == NULL){
UnLock();
return(id);
}
}
else if(HisrFreeList){
id=HisrFreeList->id;
HisrFreeList=HisrFreeList->next;
UnLock();
return(id);
}
UnLock();
return(NO_HISR_SPACE);
}
/********************************************************************************************
任务切换时保存当前上下文
***************************************************************************************/
void interrupt StackSave()
{
EnLock();
FP_SEG(((TASK_TCB *)KERNAL.current_thread)->stack_pointer)=_SS;
FP_OFF(((TASK_TCB *)KERNAL.current_thread)->stack_pointer)=_SP;
Schedule();
}
/********************************************************************************************
恢复当前具有最高优先级的处于准备好状态的线程的上下文,切换到该线程执行
***************************************************************************************/
void _ControlToThread(void)
{
EnLock();
if (((TASK_HCB *)KERNAL.current_thread)->type==HISR){ //HISR每次调度都是从初始开始执行
((TASK_HCB *)KERNAL.current_thread)->stack_pointer=_InitHISRStack(((TASK_HCB *)KERNAL.current_thread));
}
if(((TASK_TCB *)KERNAL.current_thread)->type==SIG){
_SS=FP_SEG(((TASK_TCB *)KERNAL.current_thread)->saved_stack_ptr);
_SP=FP_OFF(((TASK_TCB *)KERNAL.current_thread)->saved_stack_ptr); //若为信号处理线程
}
else{
_SS=FP_SEG(((TASK_TCB *)KERNAL.current_thread)->stack_pointer);
_SP=FP_OFF(((TASK_TCB *)KERNAL.current_thread)->stack_pointer);
}
asm POPF
asm POP BP // ; Load new task's context
asm POP DI
asm POP SI
asm POP DS
asm POP ES
asm POP DX
asm POP CX
asm POP BX
asm POP AX
asm IRET // ; Return to new task
}
/********************************************************************************************
触发任务切换
***************************************************************************************/
void _ControlToSystem(void)
{
// EnLock();
Ctrl_Task_Save(); //保存当前任务的上下文
//UnProtect(); //open interrupt
}
/*
*********************************************************************************************************
该函数是直接调度函数,直接调度到当前已经知道的处于准备好状态中的最高优先级的任务执行,
并关掉任务时间片和强占标志,使该任务不被强占的执行
*********************************************************************************************************
*/
void ScheduleToLockTask(TASK_TCB *task)
{
task->timer_active=FALSE;//不允许中断
task->preemption=FALSE;
HighRdyThread=task;
DirectSched=TRUE;
_ControlToSystem();
}
/*
*********************************************************************************************************
该函数在下一个运行任务已经确定的情况下使用,或在并不需要回到原来线程情况下使用,如信号线程处理
完成重新执行其对应任务等
*********************************************************************************************************
*/
void _DirectSchedule(TASK_TCB *task)
{
EnLock();
DirectSched=TRUE;
HighRdyThread=task;
_ControlToSystem();
}
/*
*********************************************************************************************************
TaskShell是任务完成时的返回函数入口,
*********************************************************************************************************
*/
static void TaskShell(void)
{
STATUS state;
DoProtect(KERNAL.current_thread);
((TASK_TCB *)KERNAL.current_thread)->status=FINISHED;
UnProtect(KERNAL.current_thread);
state=_SuspendTask(KERNAL.current_thread,FINISHED,NULL,NULL,0);
if(state==TRUE)
_ControlToSystem();
}
/*
*********************************************************************************************************
以下函数用于建立任务的上下文环境
该函数用来建立特定任务运行所需的堆栈环境,包括向入口函数传递的参数等
*********************************************************************************************************
*/
static void * _InitTaskStack(TASK_TCB *task)
{
INT16U *stk;
stk =(INT16U *)task->stack_start; /* Load stack pointer*/
// p=stk;
*stk-- = (INT16U)FP_SEG(TaskShell); //CS /* Put pointer to task on top of stack */
*stk-- = (INT16U)FP_OFF(TaskShell);
if(task->argc){
*stk-- = (INT16U)FP_SEG(task->argv); /* Simulate call to function with argument */
*stk-- = (INT16U)FP_OFF(task->argv);
*stk-- = (INT16U)(task->argc); /* Simulate call to function with argument */
*stk-- = (INT16U)FP_SEG(task->entry); /* Simulate call to function with argument */
*stk-- = (INT16U)FP_OFF(task->entry);
}
*stk-- = (INT16U)0x0202;
*stk-- = (INT16U)FP_SEG(task->entry); //CS /* Put pointer to task on top of stack */
*stk-- = (INT16U)FP_OFF(task->entry); //IP
*stk-- =_AX; /* AX = 0xAAAA */
*stk-- =_BX; /* BX = 0xCCCC */
*stk-- =_CX; /* CX = 0xDDDD */
*stk-- =_DX; /* DX = 0xBBBB */
*stk-- = _ES; /* ES= 0x0000 */
*stk-- = _DS; /* DS = 0x1111 */
*stk-- = _SI; /* SI = 0x2222 */
*stk-- = _DI; /* DI = 0x3333*/
*stk-- = _BP; /* BP = 0x4444 */
*stk = (INT16U)0x0202; //FLAGS
return ((void *)stk);
}
/*
*********************************************************************************************************
* 创建任务函数原型
创建任务分两种方式:1 使用CreateTaskExt函数规定好参数,一次完成任务创建.
2 使用CreateTask函数,规定好部分参数,其它为空或默认,如argc,*argv参数,
任务创建后自动处于准备好状态.根据任务结构在创建前分配与否,提供两种函数形式
*******************************************************************************************************
*/
#if ENABLE_MEM
SIGNED CreateTask(void (*entry)(void),UNSIGNED stack_size,INT8U priority)
#else
SIGNED CreateTask(TASK_TCB *task_ptr,void (*entry)(void),INT8U *stack_address,UNSIGNED stack_size,INT8U priority)
#endif
{
UCHAR prio_group,prio_groupbit;
SIGNED task_id;
STATUS err;
void *pointer;
#if ENABLE_MEM
TASK_TCB *task_ptr;
INT8U *stack_address;
#endif
if (priority >LOWEST_PRIORITY) { /* Make sure priority is within allowable range */
return (ERR_INVALID_PRIORITY);
}
if (entry==NULL) return(ERR_INVALID_ENTRY);
if (stack_size<=SYS_MIN_STACK ) return (ERR_INVALID_SIZE);
/* TASK_TCB init*/
task_id=_NewTaskId();
if(task_id<0)
return (task_id);
#if ENABLE_MEM
err=AllocBuff(KERNAL.task_pool,&(void *)task_ptr,-1);
if(err!=OK)
return (ERR_NO_MEMORY);
err=AllocBuff(KERNAL.stack_pool,&(void *)pointer,-1);
if(err!=OK){
FreeBuff(task_ptr);
return (ERR_NO_MEMORY);
}
#if SYS_STK_GROWTH==1
stack_address=(INT8U *)pointer+stack_size;
#else
stack_address=pointer;
#endif
#else
if(!task_ptr) return ERR_INVALID_TASK;
else if(TaskTable[task_ptr->id]==task_ptr) return (task_ptr->id);
#endif
#if DEBUG
DebugLog(CREATE_TASK_ID,task_ptr->id);//在日志中记录操作,时间等信息
#endif
TaskTable[task_id]=task_ptr;
task_ptr->id=task_id;
task_ptr->type=TASK;
task_ptr->current_protect=NULL;
task_ptr->priority=priority;
task_ptr->time_slice=SYS_TIME_SLICE;
task_ptr->preemption=TRUE;
task_ptr->task_timeout=-1;
task_ptr->timer_active=TRUE;
task_ptr->stack_start=(UNSIGNED *)stack_address;
task_ptr->entry=entry;
task_ptr->argc=0;
task_ptr->argv=NULL;
task_ptr->stack_pointer =(UNSIGNED *) _InitTaskStack(task_ptr); /* TaskInit the task's stack */
#if SYS_STK_GROWTH==1
task_ptr->stack_end=(UNSIGNED *)stack_address-stack_size;
#else
task_ptr->stack_end=(UNSIGNED *)stack_address+stack_size;
#endif
#if STACK_CHECK
stack_address=(INT8U *)(task_ptr->stack_end);
*stack_address=0xAA;
#if SYS_STK_GROWTH == 1
*(stack_address+1)=0X55;
#else
*(stack_address-1)=0X55;
#endif
#endif
task_ptr->scheduled=0;
#if ENABLE_SIGNAL_HANDLE==TRUE
task_ptr->enabled_signals =0;
#endif
InitTaskTimer(&(task_ptr->timer_control),task_ptr);
task_ptr->status=READY;
prio_group=priority/8;
prio_groupbit=priority % 8;
EnLock();
Priority_Group |= 1<<prio_group;
Sub_Priority_Groups[prio_group] |= 1<<prio_groupbit;
AddTaskList(&(Priority_Head[priority]),task_ptr,0);
UnLock();
return (task_id);
}
/*
*********************************************************************************************************
* 创建任务函数原型
创建专门处理信号任务的两种方式:
任务创建后自动处于等待状态.等待接收信号,被发送到该任务的信号激活,执行完后重新回到等待状态
*******************************************************************************************************
*/
#if ENABLE_MEM
SIGNED CreateSigTask(UNSIGNED stack_size,INT8U priority)
#else
SIGNED CreateSigTask(TASK_TCB *task_ptr,INT8U *stack_address,UNSIGNED stack_size,INT8U priority)
#endif
{
UCHAR prio_group,prio_groupbit;
SIGNED task_id;
SIGNED err;
void *pointer;
#if ENABLE_MEM
TASK_TCB *task_ptr;
INT8U *stack_address;
#endif
if (priority >LOWEST_PRIORITY) { /* Make sure priority is within allowable range */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -