狀態(tài)機(jī)在嵌入式軟件中隨處可見,可能你會(huì)說狀態(tài)機(jī)有什么難的,不就是switch 嗎?
switch僅僅是最基礎(chǔ)的一個(gè)點(diǎn),關(guān)于狀態(tài)機(jī)的更多操作,或許你都沒有見過,下面分享幾種實(shí)現(xiàn)方法。
狀態(tài)機(jī)基本術(shù)語
現(xiàn)態(tài):是指當(dāng)前所處的狀態(tài)。
條件:又稱為“事件”,當(dāng)一個(gè)條件被滿足,將會(huì)觸發(fā)一個(gè)動(dòng)作,或者執(zhí)行一次狀態(tài)的遷移。
動(dòng)作:條件滿足后執(zhí)行的動(dòng)作。動(dòng)作執(zhí)行完畢后,可以遷移到新的狀態(tài),也可以仍舊保持原狀態(tài)。動(dòng)作不是必需的,當(dāng)條件滿足后,也可以不執(zhí)行任何動(dòng)作,直接遷移到新狀態(tài)。
次態(tài):條件滿足后要遷往的新狀態(tài)?!按螒B(tài)”是相對于“現(xiàn)態(tài)”而言的,“次態(tài)”一旦被激活,就轉(zhuǎn)變成新的“現(xiàn)態(tài)”了。

傳統(tǒng)有限狀態(tài)機(jī)FSM
如圖,是一個(gè)定時(shí)計(jì)數(shù)器,計(jì)數(shù)器存在兩種狀態(tài),一種為設(shè)置狀態(tài),一種為計(jì)時(shí)狀態(tài)
設(shè)置狀態(tài)
“+” “-” 按鍵對初始倒計(jì)時(shí)進(jìn)行設(shè)置
當(dāng)計(jì)數(shù)值設(shè)置完成,點(diǎn)擊確認(rèn)鍵啟動(dòng)計(jì)時(shí) ,即切換到計(jì)時(shí)狀態(tài)
計(jì)時(shí)狀態(tài)
按下“+” “-” 會(huì)進(jìn)行密碼的輸入“+”表示1 ,“-”表示輸入0 ,密碼共有4位
確認(rèn)鍵:只有輸入的密碼等于默認(rèn)密碼,按確認(rèn)鍵才能停止計(jì)時(shí),否則計(jì)時(shí)直接到零,并執(zhí)行相關(guān)操作

嵌套switch
/***************************************
1.列出所有的狀態(tài)
***************************************/
typedefenum{
SETTING,
TIMING
}STATE_TYPE;
/***************************************
2.列出所有的事件
***************************************/
typedefenum{
UP_EVT,
DOWN_EVT,
ARM_EVT,
TICK_EVT
}EVENT_TYPE;
/***************************************
3.定義和狀態(tài)機(jī)相關(guān)結(jié)構(gòu)
***************************************/
structbomb
{
uint8_tstate;
uint8_ttimeout;
uint8_tcode;
uint8_tdefuse_code;
}bomb1;
/***************************************
4.初始化狀態(tài)機(jī)
***************************************/
voidbomb1_init(void)
{
bomb1.state=SETTING;
bomb1.defuse_code=6;//0110
}
/***************************************
5.狀態(tài)機(jī)事件派發(fā)
***************************************/
voidbomb1_fsm_dispatch(EVENT_TYPEevt,void*param)
{
switch(bomb1.state)
{
caseSETTING:
{
switch(evt)
{
caseUP_EVT://"+"按鍵按下事件
if(bomb1.timeout60)??++bomb1.timeout;
??????????????????bsp_display(bomb1.timeout);
??????????????break;
??????????????case?DOWN_EVT:??//?"-"???按鍵按下事件
??????????????????if(bomb1.timeout?>0)--bomb1.timeout;
bsp_display(bomb1.timeout);
break;
caseARM_EVT://"確認(rèn)"按鍵按下事件
bomb1.state=TIMING;
bomb1.code=0;
break;
}
}break;
caseTIMING:
{
switch(evt)
{
caseUP_EVT://"+"按鍵按下事件
bomb1.code=(bomb1.code<<1)?|0x01;
??????????????break;
??????????????case?DOWN_EVT:??//?"-"???按鍵按下事件
??????????????????bomb1.code?=?(bomb1.code?<<1);?
??????????????break;
??????????????case?ARM_EVT:???//?"確認(rèn)"?按鍵按下事件
??????????????????if(bomb1.code?==?bomb1.defuse_code){
??????????????????????bomb1.state?=?SETTING;
??????????????????}
??????????????????else{
????????????????????bsp_display("bomb!")
??????????????????}
??????????????break;
??????????????case?TICK_EVT:
??????????????????if(bomb1.timeout)
??????????????????{
??????????????????????--bomb1.timeout;
??????????????????????bsp_display(bomb1.timeout);
??????????????????}
??????????????????if(bomb1.timeout?==?0)
??????????????????{
??????????????????????bsp_display("bomb!")
??????????????????}
??????????????break;
??????????}???
??????}break;
??}
}

優(yōu)點(diǎn):簡單,代碼閱讀連貫,容易理解
缺點(diǎn)
當(dāng)狀態(tài)或事件增多時(shí),代碼狀態(tài)函數(shù)需要經(jīng)常改動(dòng),狀態(tài)事件處理函數(shù)會(huì)代碼量會(huì)不斷增加
狀態(tài)機(jī)沒有進(jìn)行封裝,移植性差。
沒有實(shí)現(xiàn)狀態(tài)的進(jìn)入和退出的操作。進(jìn)入和退出在狀態(tài)機(jī)中尤為重要。進(jìn)入事件:只會(huì)在剛進(jìn)入時(shí)觸發(fā)一次,主要作用是對狀態(tài)進(jìn)行必要的初始化。退出事件:只會(huì)在狀態(tài)切換時(shí)觸發(fā)一次 ,主要的作用是清除狀態(tài)產(chǎn)生的中間參數(shù),為下次進(jìn)入提供干凈環(huán)境
狀態(tài)表
二維狀態(tài)轉(zhuǎn)換表
狀態(tài)機(jī)可以分為狀態(tài)和事件 ,狀態(tài)的躍遷都是受事件驅(qū)動(dòng)的,因此可以通過一個(gè)二維表格來表示狀態(tài)的躍遷。

僅當(dāng)(code == defuse_code) 時(shí)才發(fā)生到setting 的轉(zhuǎn)換。
/*1.列出所有的狀態(tài)*/
enum
{
SETTING,
TIMING,
MAX_STATE
};
/*2.列出所有的事件*/
enum
{
UP_EVT,
DOWN_EVT,
ARM_EVT,
TICK_EVT,
MAX_EVT
};
/*3.定義狀態(tài)表*/
typedefvoid(*fp_state)(EVT_TYPEevt,void*param);
staticconstfp_statebomb2_table[MAX_STATE][MAX_EVENT]=
{
{setting_UP,setting_DOWN,setting_ARM,null},
{setting_UP,setting_DOWN,setting_ARM,timing_TICK}
};
structbomb_t
{
constfp_stateconst*state_table;/*theState-Table*/
uint8_tstate;/*thecurrentactivestate*/
uint8_ttimeout;
uint8_tcode;
uint8_tdefuse_code;
};
structbombbomb2=
{
.state_table=bomb2_table;
}
voidbomb2_init(void)
{
bomb2.defuse_code=6;//0110
bomb2.state=SETTING;
}
voidbomb2_dispatch(EVT_TYPEevt,void*param)
{
fp_states=NULL;
if(evt>MAX_EVT)
{
LOG("EVTtypeerror!");
return;
}
s=bomb2.state_table[bomb2.state*MAX_EVT+evt];
if(s!=NULL)
{
s(evt,param);
}
}
/*列出所有的狀態(tài)對應(yīng)的事件處理函數(shù)*/
voidsetting_UP(EVT_TYPEevt,void*param)
{
if(bomb1.timeout60)??++bomb1.timeout;
??bsp_display(bomb1.timeout);
}
缺點(diǎn):函數(shù)粒度太小是最明顯的一個(gè)缺點(diǎn),一個(gè)狀態(tài)和一個(gè)事件就會(huì)產(chǎn)生一個(gè)函數(shù),當(dāng)狀態(tài)和事件較多時(shí),處理函數(shù)將增加很快,在閱讀代碼時(shí),邏輯分散。沒有實(shí)現(xiàn)進(jìn)入退出動(dòng)作。
一維狀態(tài)轉(zhuǎn)換表

實(shí)現(xiàn)原理:
typedefvoid(*fp_action)(EVT_TYPEevt,void*param);
/*轉(zhuǎn)換表基礎(chǔ)結(jié)構(gòu)*/
structtran_evt_t
{
EVT_TYPEevt;
uint8_tnext_state;
};
/*狀態(tài)的描述*/
structfsm_state_t
{
fp_actionenter_action;//進(jìn)入動(dòng)作
fp_actionexit_action;//退出動(dòng)作
fp_actionaction;
tran_evt_t*tran;//轉(zhuǎn)換表
uint8_ttran_nb;//轉(zhuǎn)換表的大小
constchar*name;
}
/*狀態(tài)表本體*/
#defineARRAY(x)x,sizeof(x)/sizeof(x[0])
conststructfsm_state_tstate_table[]=
{
{setting_enter,setting_exit,setting_action,ARRAY(set_tran_evt),"setting"},
{timing_enter,timing_exit,timing_action,ARRAY(time_tran_evt),"timing"}
};
/*構(gòu)建一個(gè)狀態(tài)機(jī)*/
structfsm
{
conststructstate_t*state_table;/*theState-Table*/
uint8_tcur_state;/*thecurrentactivestate*/
uint8_ttimeout;
uint8_tcode;
uint8_tdefuse_code;
}bomb3;
/*初始化狀態(tài)機(jī)*/
voidbomb3_init(void)
{
bomb3.state_table=state_table;//指向狀態(tài)表
bomb3.cur_state=setting;
bomb3.defuse_code=8;//1000
}
/*狀態(tài)機(jī)事件派發(fā)*/
voidfsm_dispatch(EVT_TYPEevt,void*param)
{
tran_evt_t*p_tran=NULL;
/*獲取當(dāng)前狀態(tài)的轉(zhuǎn)換表*/
p_tran=bomb3.state_table[bomb3.cur_state]->tran;
/*判斷所有可能的轉(zhuǎn)換是否與當(dāng)前觸發(fā)的事件匹配*/
for(uint8_ti=0;ievt==evt)//事件會(huì)觸發(fā)轉(zhuǎn)換
{
if(NULL!=bomb3.state_table[bomb3.cur_state].exit_action){
bomb3.state_table[bomb3.cur_state].exit_action(NULL);//執(zhí)行退出動(dòng)作
}
if(bomb3.state_table[_tran[i]->next_state].enter_action){
bomb3.state_table[_tran[i]->next_state].enter_action(NULL);//執(zhí)行進(jìn)入動(dòng)作
}
/*更新當(dāng)前狀態(tài)*/
bomb3.cur_state=p_tran[i]->next_state;
}
else
{
bomb3.state_table[bomb3.cur_state].action(evt,param);
}
}
}
/*************************************************************************
setting狀態(tài)相關(guān)
************************************************************************/
voidsetting_enter(EVT_TYPEevt,void*param)
{
}
voidsetting_exit(EVT_TYPEevt,void*param)
{
}
voidsetting_action(EVT_TYPEevt,void*param)
{
}
tran_evt_tset_tran_evt[]=
{
{ARM,timing},
}
/*timing狀態(tài)相關(guān)*/
優(yōu)點(diǎn)
各個(gè)狀態(tài)面向用戶相對獨(dú)立,增加事件和狀態(tài)不需要去修改先前已存在的狀態(tài)事件函數(shù)。
實(shí)現(xiàn)了狀態(tài)的進(jìn)入和退出
容易根據(jù)狀態(tài)躍遷圖來設(shè)計(jì) (狀態(tài)躍遷圖列出了每個(gè)狀態(tài)的躍遷可能,也就是這里的轉(zhuǎn)換表)
實(shí)現(xiàn)靈活,可實(shí)現(xiàn)復(fù)雜邏輯,如上一次狀態(tài),增加監(jiān)護(hù)條件來減少事件的數(shù)量??蓪?shí)現(xiàn)非完全事件驅(qū)動(dòng)
缺點(diǎn)
函數(shù)粒度較?。ū榷S小且增長慢),可以看到,每一個(gè)狀態(tài)需要至少3個(gè)函數(shù),還需要列出所有的轉(zhuǎn)換關(guān)系。
QP嵌入式實(shí)時(shí)框架
事件驅(qū)動(dòng)型編程
好萊塢原則:和傳統(tǒng)的順序式編程方法例如“超級循環(huán)”,或傳統(tǒng)的RTOS 的任務(wù)不同。絕大多數(shù)的現(xiàn)代事件驅(qū)動(dòng)型系統(tǒng)根據(jù)好萊塢原則被構(gòu)造(Don’t call me; I’ll call you.)
面向?qū)ο?/p>
類和單一繼承

工具
QM :一個(gè)通過UML類圖來描述狀態(tài)機(jī)的軟件,并且可以自動(dòng)生成C代碼

QS軟件追蹤工具


QEP實(shí)現(xiàn)有限狀態(tài)機(jī)Fsm

/*qevent.h----------------------------------------------------------------*/
typedefstructQEventTag
{
QSignalsig;
uint8_tdynamic_;
}QEvent;
/*qep.h-------------------------------------------------------------------*/
typedefuint8_tQState;/*statusreturnedfromastate-handlerfunction*/
typedefQState(*QStateHandler)(void*me,QEventconst*e);/*argumentlist*/
typedefstructQFsmTag/*FiniteStateMachine*/
{
QStateHandlerstate;/*currentactivestate*/
}QFsm;
#defineQFsm_ctor(me_,initial_)((me_)->state=(initial_))
voidQFsm_init(QFsm*me,QEventconst*e);
voidQFsm_dispatch(QFsm*me,QEventconst*e);
#defineQ_RET_HANDLED((QState)0)
#defineQ_RET_IGNORED((QState)1)
#defineQ_RET_TRAN((QState)2)
#defineQ_HANDLED()(Q_RET_HANDLED)
#defineQ_IGNORED()(Q_RET_IGNORED)
#defineQ_TRAN(target_)(((QFsm*)me)->state=(QStateHandler)(target_),Q_RET_TRAN)
enumQReservedSignals
{
Q_ENTRY_SIG=1,
Q_EXIT_SIG,
Q_INIT_SIG,
Q_USER_SIG
};
/*fileqfsm_ini.c---------------------------------------------------------*/
#include"qep_port.h"/*theportoftheQEPeventprocessor*/
#include"qassert.h"/*embeddedsystems-friendlyassertions*/
voidQFsm_init(QFsm*me,QEventconst*e)
{
(*me->state)(me,e);/*executethetop-mostinitialtransition*/
/*enterthetarget*/
(void)(*me->state)(me,&QEP_reservedEvt_[Q_ENTRY_SIG]);
}
/*fileqfsm_dis.c---------------------------------------------------------*/
voidQFsm_dispatch(QFsm*me,QEventconst*e)
{
QStateHandlers=me->state;/*savethecurrentstate*/
QStater=(*s)(me,e);/*calltheeventhandler*/
if(r==Q_RET_TRAN)/*transitiontaken?*/
{
(void)(*s)(me,&QEP_reservedEvt_[Q_EXIT_SIG]);/*exitthesource*/
(void)(*me->state)(me,&QEP_reservedEvt_[Q_ENTRY_SIG]);/*entertarget*/
}
}
實(shí)現(xiàn)上面定時(shí)器例子
#include"qep_port.h"/*theportoftheQEPeventprocessor*/
#include"bsp.h"/*boardsupportpackage*/
enumBombSignals/*allsignalsfortheBombFSM*/
{
UP_SIG=Q_USER_SIG,
DOWN_SIG,
ARM_SIG,
TICK_SIG
};
typedefstructTickEvtTag
{
QEventsuper;/*derivefromtheQEventstructure*/
uint8_tfine_time;/*thefine1/10scounter*/
}TickEvt;
typedefstructBomb4Tag
{
QFsmsuper;/*derivefromQFsm*/
uint8_ttimeout;/*numberofsecondstillexplosion*/
uint8_tcode;/*currentlyenteredcodetodisarmthebomb*/
uint8_tdefuse;/*secretdefusecodetodisarmthebomb*/
}Bomb4;
voidBomb4_ctor(Bomb4*me,uint8_tdefuse);
QStateBomb4_initial(Bomb4*me,QEventconst*e);
QStateBomb4_setting(Bomb4*me,QEventconst*e);
QStateBomb4_timing(Bomb4*me,QEventconst*e);
/*--------------------------------------------------------------------------*/
/*theinitialvalueofthetimeout*/
#defineINIT_TIMEOUT10
/*..........................................................................*/
voidBomb4_ctor(Bomb4*me,uint8_tdefuse){
QFsm_ctor_(&me->super,(QStateHandler)&Bomb4_initial);
me->defuse=defuse;/*thedefusecodeisassignedatinstantiation*/
}
/*..........................................................................*/
QStateBomb4_initial(Bomb4*me,QEventconst*e){
(void)e;
me->timeout=INIT_TIMEOUT;
returnQ_TRAN(&Bomb4_setting);
}
/*..........................................................................*/
QStateBomb4_setting(Bomb4*me,QEventconst*e){
switch(e->sig){
caseUP_SIG:{
if(me->timeout60)?{
????????????????++me->timeout;
BSP_display(me->timeout);
}
returnQ_HANDLED();
}
caseDOWN_SIG:{
if(me->timeout>1){
--me->timeout;
BSP_display(me->timeout);
}
returnQ_HANDLED();
}
caseARM_SIG:{
returnQ_TRAN(&Bomb4_timing);/*transitionto"timing"*/
}
}
returnQ_IGNORED();
}
/*..........................................................................*/
voidBomb4_timing(Bomb4*me,QEventconst*e){
switch(e->sig){
caseQ_ENTRY_SIG:{
me->code=0;/*clearthedefusecode*/
returnQ_HANDLED();
}
caseUP_SIG:{
me->code<<=?1;
????????????me->code|=1;
returnQ_HANDLED();
}
caseDOWN_SIG:{
me->code<<=?1;
????????????return?Q_HANDLED();
????????}
????????case?ARM_SIG:?{
????????????if?(me->code==me->defuse){
returnQ_TRAN(&Bomb4_setting);
}
returnQ_HANDLED();
}
caseTICK_SIG:{
if(((TickEvtconst*)e)->fine_time==0){
--me->timeout;
BSP_display(me->timeout);
if(me->timeout==0){
BSP_boom();/*destroythebomb*/
}
}
returnQ_HANDLED();
}
}
returnQ_IGNORED();
}
優(yōu)點(diǎn)
采用面向?qū)ο蟮脑O(shè)計(jì)方法,很好的移植性
實(shí)現(xiàn)了進(jìn)入退出動(dòng)作
合適的粒度,且事件的粒度可控
狀態(tài)切換時(shí)通過改變指針,效率高
可擴(kuò)展成為層次狀態(tài)機(jī)
缺點(diǎn)
對事件的定義以及事件粒度的控制是設(shè)計(jì)的最大難點(diǎn),如串口接收到一幀數(shù)據(jù),這些變量的更新單獨(dú)作為某個(gè)事件,還是串口收到數(shù)據(jù)作為一個(gè)事件。再或者顯示屏,如果使用此種編程方式,如何設(shè)計(jì)事件。
QP 實(shí)現(xiàn)層次狀態(tài)機(jī)

初始化層次狀態(tài)機(jī)的實(shí)現(xiàn):在初始化時(shí),用戶所選取的狀態(tài)永遠(yuǎn)是最底層的狀態(tài),如上圖,我們在計(jì)算器開機(jī)后,應(yīng)該進(jìn)入的是開始狀態(tài),這就涉及到一個(gè)問題,由最初top(頂狀態(tài))到begin 是有一條狀態(tài)切換路徑的,當(dāng)我們設(shè)置狀態(tài)為begin如何搜索這條路徑成為關(guān)鍵(知道了路徑才能正確的進(jìn)入begin,要執(zhí)行路徑中過渡狀態(tài)的進(jìn)入和退出事件)
voidQHsm_init(QHsm*me,QEventconst*e)
{
Q_ALLEGE((*me->state)(me,e)==Q_RET_TRAN);
t=(QStateHandler)&QHsm_top;/*HSMstartsinthetopstate*/
do{/*drillintothetarget...*/
QStateHandlerpath[QEP_MAX_NEST_DEPTH_];
int8_tip=(int8_t)0;/*transitionentrypathindex*/
path[0]=me->state;/*這里的狀態(tài)為begin*/
/*通過執(zhí)行空信號(hào),從底層狀態(tài)找到頂狀態(tài)的路徑*/
(void)QEP_TRIG_(me->state,QEP_EMPTY_SIG_);
while(me->state!=t){
path[++ip]=me->state;
(void)QEP_TRIG_(me->state,QEP_EMPTY_SIG_);
}
/*切換為begin*/
me->state=path[0];/*restorethetargetoftheinitialtran.*/
/*鉆到最底層的狀態(tài),執(zhí)行路徑中的所有進(jìn)入事件*/
Q_ASSERT(ip(int8_t)QEP_MAX_NEST_DEPTH_);
??????do?{?/*?retrace?the?entry?path?in?reverse?(desired)?order...?*/
??????????QEP_ENTER_(path[ip]);?/*?enter?path[ip]?*/
???????}?while?((--ip)?>=(int8_t)0);
t=path[0];/*currentstatebecomesthenewsource*/
}while(QEP_TRIG_(t,Q_INIT_SIG)==Q_RET_TRAN);
me->state=t;
}
狀態(tài)切換

/*.................................................................*/
QStateresult(Calc*me,QEventconst*e)
{
switch(e->sig)
{you
caseENTER_SIG:{
break;
}
caseEXIT_SIG:{
break;
}
caseC_SIG:
{
printf("clear");
returnQ_HANDLED();
}
caseB_SIG:
{
returnQ_TRAN(&begin);
}
}
returnQ_SUPER(&reday);
}
/*.ready為result和begin的超狀態(tài)................................................*/
QStateready(Calc*me,QEventconst*e)
{
switch(e->sig)
{
caseENTER_SIG:{
break;
}
caseEXIT_SIG:{
break;
}
caseOPER_SIG:
{
returnQ_TRAN(&opEntered);
}
}
returnQ_SUPER(&on);
}
voidQHsm_dispatch(QHsm*me,QEventconst*e)
{
QStateHandlerpath[QEP_MAX_NEST_DEPTH_];
QStateHandlers;
QStateHandlert;
QStater;
t=me->state;/*savethecurrentstate*/
do{/*processtheeventhierarchically...*/
s=me->state;
r=(*s)(me,e);/*invokestatehandlers*/
}while(r==Q_RET_SUPER);//當(dāng)前狀態(tài)不能處理事件,直到找到能處理事件的狀態(tài)
if(r==Q_RET_TRAN){/*transitiontaken?*/
int8_tip=(int8_t)(-1);/*transitionentrypathindex*/
int8_tiq;/*helpertransitionentrypathindex*/
path[0]=me->state;/*savethetargetofthetransition*/
path[1]=t;
while(t!=s){/*exitcurrentstatetotransitionsources...*/
if(QEP_TRIG_(t,Q_EXIT_SIG)==Q_RET_HANDLED){/*exithandled?*/
(void)QEP_TRIG_(t,QEP_EMPTY_SIG_);/*findsuperstateoft*/
}
t=me->state;/*me->stateholdsthesuperstate*/
}
...
}
me->state=t;/*setnewstateorrestorethecurrentstate*/
}

t=path[0];/*targetofthetransition*/
if(s==t){/*(a)checksource==target(transitiontoself)*/
QEP_EXIT_(s)/*exitthesource*/
ip=(int8_t)0;/*enterthetarget*/
}
else{
(void)QEP_TRIG_(t,QEP_EMPTY_SIG_);/*superstateoftarget*/
t=me->state;
if(s==t){/*(b)checksource==target->super*/
ip=(int8_t)0;/*enterthetarget*/
}
else{
(void)QEP_TRIG_(s,QEP_EMPTY_SIG_);/*superstateofsrc*/
/*(c)checksource->super==target->super*/
if(me->state==t){
QEP_EXIT_(s)/*exitthesource*/
ip=(int8_t)0;/*enterthetarget*/
}
else{
/*(d)checksource->super==target*/
if(me->state==path[0]){
QEP_EXIT_(s)/*exitthesource*/
}
else{/*(e)checkrestofsource==target->super->super..
*andstoretheentrypathalongtheway*/
....
QP實(shí)時(shí)框架的組成


內(nèi)存管理
使用內(nèi)存池,對于低性能mcu,內(nèi)存極為有限,引入內(nèi)存管理主要是整個(gè)架構(gòu)中,是以事件作為主要的任務(wù)通信手段,且事件是帶參數(shù)的,可能相同類型的事件會(huì)多次觸發(fā),而事件處理完成后,需要清除事件,無法使用靜態(tài)的事件,因此是有必要為不同事件創(chuàng)建內(nèi)存池的。對于不同塊大小的內(nèi)存池,需要考慮的是每個(gè)塊的起始地址對齊問題。在進(jìn)行內(nèi)存池初始化時(shí),我們是根據(jù)blocksize+header大小來進(jìn)行劃分內(nèi)存池的。假設(shè)一個(gè)2字節(jié)的結(jié)構(gòu),如果以2來進(jìn)行劃分,假設(shè)mcu 4字節(jié)對齊,那么將有一半的結(jié)構(gòu)起始地址無法對齊,這時(shí)需要為每個(gè)塊預(yù)留空間,保證每個(gè)塊的對齊。

事件隊(duì)列
每一個(gè)活動(dòng)對象維護(hù)一個(gè)事件隊(duì)列,事件都是由基礎(chǔ)事件派生的,不同類型的事件只需要將其基礎(chǔ)事件成員添加到活動(dòng)對象的隊(duì)列中即可,最終在取出的時(shí)候通過一個(gè)強(qiáng)制轉(zhuǎn)換便能獲得附加的參數(shù)。

事件派發(fā)
直接事件發(fā)送QActive_postLIFO()
發(fā)行訂閱事件發(fā)送豎軸表示信號(hào)(為事件的基類)活動(dòng)對象支持64個(gè)優(yōu)先級,每一個(gè)活動(dòng)對象要求擁有唯一優(yōu)先級通過優(yōu)先級的bit位來表示某個(gè)事件被哪些活動(dòng)對象訂閱,并在事件觸發(fā)后根據(jù)優(yōu)先級為活動(dòng)對象派發(fā)事件。

代碼風(fēng)格

-
嵌入式
+關(guān)注
關(guān)注
5177文章
20003瀏覽量
325580 -
軟件
+關(guān)注
關(guān)注
69文章
5256瀏覽量
90490 -
計(jì)數(shù)器
+關(guān)注
關(guān)注
32文章
2303瀏覽量
97332
原文標(biāo)題:嵌入式中狀態(tài)機(jī)的幾種騷操作
文章出處:【微信號(hào):strongerHuang,微信公眾號(hào):strongerHuang】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
嵌入式狀態(tài)機(jī)的幾種大牛才懂的操作
嵌入式軟件開發(fā)中常用的狀態(tài)機(jī)編程實(shí)現(xiàn)
嵌入式之狀態(tài)機(jī)編程的概念是什么
LSM6DSOX嵌入式有限狀態(tài)機(jī)的使用和配置的信息
ISM330DHCX嵌入式有限狀態(tài)機(jī)的使用和配置信息
狀態(tài)機(jī)在嵌入式系統(tǒng)中的應(yīng)用
嵌入式軟件中狀態(tài)機(jī)的抽象與實(shí)現(xiàn)
有限狀態(tài)機(jī)在嵌入式系統(tǒng)中的實(shí)現(xiàn)及應(yīng)用
有限狀態(tài)機(jī)在嵌入式軟件中的應(yīng)用
基于事件驅(qū)動(dòng)的有限狀態(tài)機(jī)介紹
嵌入式狀態(tài)機(jī)的編程優(yōu)點(diǎn)分析
嵌入式狀態(tài)機(jī)的設(shè)計(jì)與實(shí)現(xiàn)
C語言實(shí)現(xiàn)嵌入式狀態(tài)機(jī)簡單描述與應(yīng)用
LSM6DSOX嵌入式有限狀態(tài)機(jī)的使用和配置

嵌入式中狀態(tài)機(jī)的設(shè)置
評論