📄 fsm.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 : fsm.c
Description : FSM management module for RockOS.
:
:
Auther : sunxinqiu
History :
2006-3-15 first release.
******************************************************************************/
#include "os.h"
/******************************************************************************
Global var : FSMCB g_fsmCB[];
Description : The FSM control block, it may be free or used by some task, or by
: NULL_TASK if it is the task fsm.
******************************************************************************/
FSMCB g_fsmCB[MAX_FSM_NUM];
/******************************************************************************
Function : STATUS fsm_init(void)
Params : N/A
:
:
:
Return : NO_ERROR always.
Description : This function should only be called when the system is starting
: up.
******************************************************************************/
STATUS fsm_init()
{
HANDLE handle;
if (g_OSRunning != OS_PHASE_INIT)
{
OS_error("fsm_init(): this function can't be called after system in scheduling!!!\n");
return OS_FAIL;
}
for (handle = 0; handle < MAX_FSM_NUM; handle++)
{
memset (&g_fsmCB[handle], 0, sizeof(FSMCB));
g_fsmCB[handle].state = OS_FSM_FREE;
g_fsmCB[handle].owner = NULL_TASK;
}
return OS_SUCCESS;
}
/******************************************************************************
Function : HFSM fsmCreate()
Params : pfsmMap - the FSM MAP table.
: counter - the FSM MAP table element's counter.
: owner - the owner task.
: name - the fsm's name provided by the owner task.
Return : the FSM handle.
Description : To use a FSM, the task should create a FSM first, then register
: the fsm map and some additional actions.
******************************************************************************/
HFSM fsmCreate(FSM_MAP * pfsmMap, U16 counter, HTASK owner, const char * name)
{
HANDLE handle;
HFSM hfsm;
hfsm = NULL_HANDLE;
/* find a free fsm entry. */
OS_ENTER_CRITICAL();
for (handle = 0; handle < MAX_FSM_NUM; handle++)
{
if (g_fsmCB[handle].state == OS_FSM_FREE)
{
hfsm = handle;
g_fsmCB[hfsm].state = OS_FSM_BUSY;
break;
}
}
OS_LEAVE_CRITICAL();
/* config the fsm. */
if (hfsm != NULL_HANDLE)
{
g_fsmCB[hfsm].nIdxCount = counter;
g_fsmCB[hfsm].pIndexMap = fsmCreateIdxMap (hfsm, pfsmMap, counter);
g_fsmCB[hfsm].owner = owner;
strncpy (&g_fsmCB[hfsm].name[0], name, strlen(name));
}
return hfsm;
}
/******************************************************************************
Function : STATUS fsmReg()
Params : hFsm - the FSM handle
: getOldState - FSM scheduler calls this function to get instance's
: old state.
: dumpFsm - the scheduler calls this function to dump the fsm's
: running track.
Return : OS_SUCCESS or OS_FAIL.
Description : This function should be called next the fsmCreate before the
: fsm can be used.
******************************************************************************/
STATUS fsmReg(HFSM hFsm, GET_OLD_STATE getOldState, FSM_DUMP dumpFsm)
{
/* params check. */
if (hFsm >= MAX_FSM_NUM)
{
OS_error("fsmReg(): the fsm instance [%d] is invalid!!!\n", hFsm);
return OS_FAIL;
}
if (g_fsmCB[hFsm].state == OS_FSM_FREE)
{
OS_error("fsmReg(): the fsm instance [%d] is free!!!\n", hFsm);
return OS_FAIL;
}
/* config the fsm. */
if (getOldState != NULL)
{
g_fsmCB[hFsm].getOldState = getOldState;
}
if (dumpFsm != NULL)
{
g_fsmCB[hFsm].dumpFsm = dumpFsm;
}
else
{
g_fsmCB[hFsm].dumpFsm = fsmDumpDefault;
}
return OS_SUCCESS;
}
/******************************************************************************
Function : STATUS fsmRegNameTable()
Params : hFsm - the fsm
: type - type of name table
: size - the name table entries number
: pNameTbl - the name table
:
Return : OS_SUCCESS or OS_FAIL
Description : This function is not mandatory, it is only used to improve the
: readability of the fsm dump information.
******************************************************************************/
STATUS fsmRegNameTable(HFSM hFsm, U32 type, U32 size, const FSM_NAME_TBL * pNameTbl)
{
U32 nsize;
char name[MAX_NAME_LEN+1];
U32 i, j;
FSM_NAME_TBL item;
if (hFsm >= MAX_FSM_NUM)
{
OS_error("fsmRegNameTable(): the fsm instance [%d] is invalid!!!\n", hFsm);
return OS_FAIL;
}
if (g_fsmCB[hFsm].state == OS_FSM_FREE)
{
OS_error("fsmRegNameTable(): the fsm instance [%d] is free!!!\n", hFsm);
return OS_FAIL;
}
switch(type)
{
case FSM_STATE_NAME:
/* copy the name table. */
g_fsmCB[hFsm].stateTblSize = size;
nsize = size * sizeof(FSM_NAME_TBL);
sprintf(&name[0], "fsm %d state name", hFsm);
g_fsmCB[hFsm].pStateTbl = (FSM_NAME_TBL *)memAlloc(nsize, taskIdSelf(), &name[0]);
memcpy (g_fsmCB[hFsm].pStateTbl, pNameTbl, nsize);
/* sort increase. */
for (i = size; i > 0; i--)
{
for (j = 0; j < i-1; j++)
{
if (g_fsmCB[hFsm].pStateTbl[j].value > g_fsmCB[hFsm].pStateTbl[j+1].value)
{
/* swap element. */
memcpy (&item, &g_fsmCB[hFsm].pStateTbl[j], sizeof(FSM_NAME_TBL));
memcpy (&g_fsmCB[hFsm].pStateTbl[j], &g_fsmCB[hFsm].pStateTbl[j+1], sizeof(FSM_NAME_TBL));
memcpy (&g_fsmCB[hFsm].pStateTbl[j+1], &item, sizeof(FSM_NAME_TBL));
}
}
}
break;
case FSM_EVENT_NAME:
g_fsmCB[hFsm].eventTblSize = size;
nsize = size * sizeof(FSM_NAME_TBL);
sprintf(&name[0], "fsm %d evt name", hFsm);
g_fsmCB[hFsm].pEventTbl = (FSM_NAME_TBL *)memAlloc(nsize, taskIdSelf(), &name[0]);
memcpy (g_fsmCB[hFsm].pEventTbl, pNameTbl, nsize);
/* sort increase. */
for (i = size; i > 0; i--)
{
for (j = 0; j < i-1; j++)
{
if (g_fsmCB[hFsm].pStateTbl[j].value > g_fsmCB[hFsm].pStateTbl[j+1].value)
{
/* swap element. */
memcpy (&item, &g_fsmCB[hFsm].pStateTbl[j], sizeof(FSM_NAME_TBL));
memcpy (&g_fsmCB[hFsm].pStateTbl[j], &g_fsmCB[hFsm].pStateTbl[j+1], sizeof(FSM_NAME_TBL));
memcpy (&g_fsmCB[hFsm].pStateTbl[j+1], &item, sizeof(FSM_NAME_TBL));
}
}
}
break;
case FSM_ACTION_NAME:
g_fsmCB[hFsm].actionTblSize = size;
nsize = size * sizeof(FSM_NAME_TBL);
sprintf(&name[0], "fsm %d act name", hFsm);
g_fsmCB[hFsm].pActionTbl = (FSM_NAME_TBL *)memAlloc(nsize, taskIdSelf(), &name[0]);
memcpy (g_fsmCB[hFsm].pActionTbl, pNameTbl, nsize);
/* sort increase. */
for (i = size; i > 0; i--)
{
for (j = 0; j < i-1; j++)
{
if (g_fsmCB[hFsm].pStateTbl[j].value > g_fsmCB[hFsm].pStateTbl[j+1].value)
{
/* swap element. */
memcpy (&item, &g_fsmCB[hFsm].pStateTbl[j], sizeof(FSM_NAME_TBL));
memcpy (&g_fsmCB[hFsm].pStateTbl[j], &g_fsmCB[hFsm].pStateTbl[j+1], sizeof(FSM_NAME_TBL));
memcpy (&g_fsmCB[hFsm].pStateTbl[j+1], &item, sizeof(FSM_NAME_TBL));
}
}
}
break;
default:
OS_error("fsmRegNameTable(): unknown name type [%d].\n", type);
break;
}
return OS_SUCCESS;
}
/******************************************************************************
Function : STATUS fsmSetTrig (HFSM hFsm, HANDLE hInst, U16 event, void * pData)
Params : hFsm - the fsm.
: hInst - the instance in the fsm.
: event - the event raised to the instance
: pData - param for this event.
:
Return : NO_ERROR or other error code.
Description : This function is the main trig function for a fsm.
:
******************************************************************************/
STATUS fsmSetTrig (HFSM hFsm, HANDLE hInst, U16 event, void * pData)
{
U16 oldState;
FSM_ACTION fsm_action;
/* params check. */
if (hFsm >= MAX_FSM_NUM)
{
OS_error("fsmSetTrig(): the fsm instance [%d] is invalid!!!\n", hFsm);
return OS_FAIL;
}
if (g_fsmCB[hFsm].state == OS_FSM_FREE)
{
OS_error("fsmSetTrig(): the fsm instance [%d] is free!!!\n", hFsm);
return OS_FAIL;
}
if (g_fsmCB[hFsm].getOldState == NULL)
{
OS_error("fsmSetTrig(): the fsm [%d:%s] has not been registered!!!\n", hFsm, g_fsmCB[hFsm].name);
return OS_FAIL;
}
oldState = g_fsmCB[hFsm].getOldState(hInst);
fsm_action = fsmGetAction(hFsm, oldState, event);
/* dump the fsm running track. */
taskLock();
g_fsmCB[hFsm].dumpFsm(hFsm, hInst, oldState, event, (void *)fsm_action);
taskUnlock();
/* take action for this state-event combination. */
if (fsm_action != NULL)
{
fsm_action(hInst, pData);
}
return OS_SUCCESS;
}
/******************************************************************************
Function : STATUS fsmDestroy (HFSM hFsm)
Params : hFsm - the fsm to be deleted.
:
:
:
Return : OS_SUCCESS or OS_FAIL.
Description : If a fsm is no use, call this function to delete it.
:
******************************************************************************/
STATUS fsmDestroy (HFSM hFsm)
{
/* params check. */
if (hFsm >= MAX_FSM_NUM)
{
OS_error("fsmDestroy(): the fsm instance [%d] is invalid!!!\n", hFsm);
return OS_FAIL;
}
if (g_fsmCB[hFsm].state == OS_FSM_FREE)
{
OS_error("fsmDestroy(): the fsm instance [%d] is free!!!\n", hFsm);
return OS_SUCCESS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -