📄 core.c
字号:
/******************************************************************************
Copyright (c) 2006 by RockOS.
All rights reserved.
This software is supported by the Rock Software Workroom only.
Any bugs please contact the author with e-mail or QQ:
E-mail : baobaoba520@yahoo.com.cn
QQ : 59681888
*******************************************************************************
File name : core.c
Description : This file contains the main sheduler function for RockOS.
:
:
Auther : sunxinqiu
History :
2006-3-15 first release.
******************************************************************************/
#include "os.h"
/******************************************************************************
Global var : HQUEUE g_readyTaskQueue;
Description : indicate the ready task queue.
: Ready task queue is a priority based queue, other priority based
: queues are pend tasks queue, on msg queue or on semaphore.
******************************************************************************/
HQUEUE g_readyTaskQueue;
/******************************************************************************
Global var : HTASK g_runningTask;
: TCB * g_runningTcb;
Description : These two global variables indicate the current running task
: and its control block.
******************************************************************************/
HTASK g_runningTask;
TCB * g_runningTcb;
/******************************************************************************
Global var : HTASK g_newTask;
: TCB * g_newTcb;
Description : Before executing a task switch action, these two global variables
: save the new task and its TCB.
******************************************************************************/
HTASK g_newTask;
TCB * g_newTcb;
/******************************************************************************
Global var : TCB g_sysTcb[];
Description : This global variable is the task's control block of RockOS. All
: tasks are management by TCB seperately.
******************************************************************************/
TCB g_sysTcb[MAX_SYS_TASK];
/******************************************************************************
Global var : HFSM g_taskFsm;
Description : The FSM handle for task state machine.
******************************************************************************/
HFSM g_taskFsm;
/******************************************************************************
Global var : FSM_MAP g_taskFsmMap[]
Description : The task fsm's fsm map.
:
******************************************************************************/
FSM_MAP g_taskFsmMap[] = {
{OS_TASK_READY, T_TRIG_RESUME, NULL},
{OS_TASK_RUNNING, T_TRIG_DEPRIVED, OntaskDeprived},
{OS_TASK_RUNNING, T_TRIG_SEMA_GIVE, OnSemGive},
{OS_TASK_RUNNING, T_TRIG_TAKE_SEMA_DONE, OnSemTakeDone},
{OS_TASK_RUNNING, T_TRIG_TAKE_SEMA_PEND, OnSemTakePending},
{OS_TASK_RUNNING, T_TRIG_RECV_MSGQ_PEND, OnMsgQRecvPending},
{OS_TASK_RUNNING, T_TRIG_SEND_MSGQ_PEND, OnMsgQSendPending},
{OS_TASK_RUNNING, T_TRIG_DELAY, OnTaskDelay},
{OS_TASK_PEND_ON_SEMA, T_TRIG_TAKE_SEMA_DONE, OnSemTakeDone},
{OS_TASK_PEND_ON_SEMA, T_TRIG_DELAY_TMO, OnSemTakeTimeout},
{OS_TASK_PEND_ON_MSGQ_S, T_TRIG_SEND_MSGQ_DONE, OnMsgQSendDone},
{OS_TASK_PEND_ON_MSGQ_S, T_TRIG_DELAY_TMO, OnMsgQSendTimeout},
{OS_TASK_PEND_ON_MSGQ_R, T_TRIG_RECV_MSGQ_DONE, OnMsgQRecvDone},
{OS_TASK_PEND_ON_MSGQ_R, T_TRIG_DELAY_TMO, OnMsgQRecvTimeout},
{OS_TASK_DELAY, T_TRIG_DELAY_TMO, OnTaskDelayTimeout},
{OS_TASK_SUSPEND, T_TRIG_TAKE_SEMA_DONE, OnSemTakeDone},
{OS_TASK_SUSPEND, T_TRIG_RECV_MSGQ_DONE, OnMsgQRecvDone},
{OS_TASK_SUSPEND, T_TRIG_DELAY_TMO, OnTaskDelayTimeout}
};
/******************************************************************************
Global var : const FSM_NAME_TBL g_taskState[]
Description : state name for task fsm.
: This table must be sorted by the task state manually.
******************************************************************************/
FSM_NAME_TBL g_taskState[] = {
{OS_TASK_FREE, "OS_TASK_FREE"},
{OS_TASK_READY, "OS_TASK_READY"},
{OS_TASK_RUNNING, "OS_TASK_RUNNING"},
{OS_TASK_PEND_ON_SEMA, "OS_TASK_PEND_SEMA"},
{OS_TASK_PEND_ON_MSGQ_R, "OS_TASK_PEND_ON_MSGQ_R"},
{OS_TASK_PEND_ON_MSGQ_S, "OS_TASK_PEND_ON_MSGQ_S"},
{OS_TASK_DELAY, "OS_TASK_DELAY"},
{OS_TASK_SUSPEND, "OS_TASK_SUSPEND"},
{OS_TASK_FAULT, "OS_TASK_FAULT"},
{OS_TASK_REMOVING, "OS_TASK_REMOVING"},
{OS_TASK_STATE_MAX, "OS_TASK_STATE_MAX"}
};
/******************************************************************************
Global var : const FSM_NAME_TBL g_taskEvent[]
Description : event name for task fsm.
: This table must be sorted by the event id manually.
******************************************************************************/
FSM_NAME_TBL g_taskEvent[] = {
{T_TRIG_FIRST_RUN, "T_TRIG_FIRST_RUN"},
{T_TRIG_DEPRIVED, "T_TRIG_DEPRIVED"},
{T_TRIG_RESUME, "T_TRIG_RESUME"},
{T_TRIG_SEMA_GIVE, "T_TRIG_SEMA_GIVE"},
{T_TRIG_TAKE_SEMA_PEND, "T_TRIG_TAKE_SEMA_PEND"},
{T_TRIG_TAKE_SEMA_DONE, "T_TRIG_TAKE_SEMA_DONE"},
{T_TRIG_RECV_MSGQ_PEND, "T_TRIG_RECV_MSGQ_PEND"},
{T_TRIG_RECV_MSGQ_DONE, "T_TRIG_RECV_MSGQ_DONE"},
{T_TRIG_SEND_MSGQ_PEND, "T_TRIG_SEND_MSGQ_PEND"},
{T_TRIG_SEND_MSGQ_DONE, "T_TRIG_SEND_MSGQ_DONE"},
{T_TRIG_DELAY, "T_TRIG_DELAY"},
{T_TRIG_DELAY_TMO, "T_TRIG_DELAY_TMO"},
{T_TRIG_CREATE, "T_TRIG_CREATE"},
{T_TRIG_REMOVE, "T_TRIG_REMOVE"},
{T_TRIG_RESTART, "T_TRIG_RESTART"},
{T_TRIG_SUSPEND, "T_TRIG_SUSPEND"},
{T_TRIG_WAKEUP, "T_TRIG_WAKEUP"},
{T_TRIG_PRIO_CHANGE_MAN, "T_TRIG_PRIO_CHANGE_M"},
{T_TRIG_PRIO_CHANGE_AUTO, "T_TRIG_PRIO_CHANGE_A"},
{T_TRIG_INTERRUPT, "T_TRIG_INTERRUPT"},
{T_TRIG_FAULT, "T_TRIG_FAULT"},
{T_TRIG_MAX, "T_TRIG_MAX"}
};
/******************************************************************************
Global var : const FSM_NAME_TBL g_taskAction[]
Description : action name for task fsm.
:
******************************************************************************/
FSM_NAME_TBL g_taskAction[] = {
{(U32)NULL, "(null action)"},
{(U32)OntaskDeprived, "OntaskDeprived"},
{(U32)OnMsgQRecvPending, "OnmsgQRecvPending"},
{(U32)OnMsgQSendPending, "OnmsgQSendPending"},
{(U32)OnTaskDelay, "OnTaskDelay"},
{(U32)OnSemGive, "OnSemGive"},
{(U32)OnSemTakePending, "OnSemTakePending"},
{(U32)OnSemTakeDone, "OnSemTakeDone"},
{(U32)OnSemTakeTimeout, "OnSemTakeTimeout"},
{(U32)OnMsgQSendDone, "OnMsgQSendDone"},
{(U32)OnMsgQSendTimeout, "OnMsgQSendTimeout"},
{(U32)OnMsgQRecvDone, "OnMsgQRecvDone"},
{(U32)OnMsgQRecvTimeout, "OnMsgQRecvTimeout"},
{(U32)OnTaskDelayTimeout, "OnDelayTimeout"},
{(U32)taskCreate, "taskCreate"},
{(U32)taskDelete, "taskDelete"},
{(U32)taskDeleteSelf, "taskDeleteSelf"},
{(U32)taskRestart, "taskRestart"},
{(U32)taskDelay, "taskDelay"},
{(U32)taskSuspend, "taskSuspend"},
{(U32)taskWakeup, "taskWakeup"},
{(U32)taskSetPriority, "taskSetPriority"},
{(U32)taskSetPriorityAuto,"taskSetPriorityAuto"}
};
/******************************************************************************
Function : STATUS core_init()
Params : N/A
:
:
:
Return : OS_SUCCESS always.
Description : This function should only be called during system starting up.
:
******************************************************************************/
STATUS core_init()
{
HANDLE handle;
U32 i, j;
FSM_NAME_TBL tmpFsmNameTbl;
if (g_OSRunning != OS_PHASE_INIT)
{
OS_error("core_init(): this function can't be called after system in scheduling!!!\n");
return OS_FAIL;
}
/* init TCBs. */
for (handle = 0; handle < MAX_SYS_TASK; handle++)
{
memset (&g_sysTcb[handle], 0, sizeof(TCB));
g_sysTcb[handle].state = OS_TASK_FREE;
}
/* create ready task queue. */
g_readyTaskQueue = q_create(OS_QUEUE_PRIO, MAX_SYS_TASK, NULL_TASK, "ready tasks queue");
/* create task fsm. */
g_taskFsm = fsmCreate(&g_taskFsmMap[0], sizeof(g_taskFsmMap)/sizeof(FSM_MAP), NULL_TASK, "task fsm");
fsmReg(g_taskFsm, getTaskState, taskFsmDump);
/* sort the g_taskAction. */
for (i = sizeof(g_taskAction)/sizeof(FSM_NAME_TBL); i > 0; i--)
{
for (j = 0; j < i-1; j++)
{
if (g_taskAction[j].value > g_taskAction[j+1].value)
{
/* swap element. */
memcpy (&tmpFsmNameTbl, &g_taskAction[j], sizeof(FSM_NAME_TBL));
memcpy (&g_taskAction[j], &g_taskAction[j+1], sizeof(FSM_NAME_TBL));
memcpy (&g_taskAction[j+1], &tmpFsmNameTbl, sizeof(FSM_NAME_TBL));
}
}
}
return OS_SUCCESS;
}
/******************************************************************************
Function : U32 OSEnterISR()
Params : N/A
:
:
:
Return : N/A
Description : this function should be called when the CPU enter a trap(ISR).
:
******************************************************************************/
U32 OSEnterISR()
{
g_cpuIntDepth++;
if (g_cpuIntDepth == 1)
{
taskFsmDump(g_taskFsm, g_runningTask, g_runningTcb->state, T_TRIG_INTERRUPT, NULL);
}
return g_cpuIntDepth;
}
/******************************************************************************
Function : void OSLeaveISR()
Params : N/A
:
:
:
Return : N/A
Description : this function should be called when the CPU leave a trap(ISR).
:
******************************************************************************/
void OSLeaveISR()
{
HTASK newTask;
if (g_cpuIntDepth != 0)
{
return;
}
/* if the current task can be deprived. */
if ((g_runningTcb->lockDepth == 0)
&&((g_runningTcb->option&OPT_TASK_LOCK)==0))
{
if (q_head(g_readyTaskQueue, (HANDLE *)&newTask)==OS_SUCCESS)
{
if (g_sysTcb[newTask].runningPriority < g_runningTcb->runningPriority)
{
/* delete this task from ready queue. */
q_enum(g_readyTaskQueue, NULL);
/* the old running task (before interrupt occurs) is deprived. */
g_runningTcb->state = OS_TASK_READY;
q_add(g_readyTaskQueue, (HANDLE)g_runningTask, g_sysTcb[g_runningTask].runningPriority);
g_runningTcb->bDeprived = OS_TRUE;
taskFsmDump(g_taskFsm, g_runningTask, OS_TASK_RUNNING, T_TRIG_DEPRIVED, NULL);
g_newTask = newTask;
g_newTcb = &g_sysTcb[newTask];
g_newTcb->state = OS_TASK_RUNNING;
OSIntSwTask();
enable_watchdog();
while(1);
}
}
else
{
fatalError("OSLeaveISR(): no ready task in ready task queue!!!\n");
}
}
taskFsmDump(g_taskFsm, g_runningTask, OS_TASK_RUNNING, T_TRIG_RESUME, NULL);
OSRunTask();
enable_watchdog();
while(1);
}
/******************************************************************************
Function : void OSLeaveException()
Params : N/A
:
:
:
Return : N/A
Description : this function should be called when the CPU leave an exception.
:
******************************************************************************/
void OSLeaveException()
{
HTASK newTask;
if (g_cpuIntDepth != 0)
{
/* ISR error. */
OS_puterror("OSLeaveException(): error in ISRs, system failure, rebooting....\n");
enable_watchdog();
while(1);
}
g_runningTcb->state = OS_TASK_FAULT;
if (q_head(g_readyTaskQueue, (HANDLE *)&newTask)==OS_SUCCESS)
{
g_runningTask = newTask;
g_runningTcb = &g_sysTcb[newTask];
g_runningTcb->state = OS_TASK_RUNNING;
OSRunTask();
}
else
{
OS_puterror("OSLeaveException(): no ready task in system.....\n");
}
enable_watchdog();
while(1);
}
/******************************************************************************
Function : void disable_irq()
Params : N/A
:
Return : N/A
Description : This function is used to disable all IRQs in OS level.
:
******************************************************************************/
void OS_ENTER_CRITICAL()
{
if ((g_cpuIntDepth == 0)&&(g_OSRunning == OS_PHASE_SCHEDULING))
{
disable_irq();
}
}
/******************************************************************************
Function : void OS_LEAVE_CRITICAL()
Params : N/A
:
Return : N/A
Description : This function is used to enable all IRQs in OS level.
:
******************************************************************************/
void OS_LEAVE_CRITICAL()
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -