有限状态机(FSM)设计思路

1.有限状态机

有限状态机(Finite State Machine)是软件设计领域中一种重要的工具,在软件实现中或多或少都会用到各种各样的状态机,但是实现方多种多样,效果也是良莠不齐,本文主要介绍下有限状态机表的设计思路。

2.FSM实现方式

2.1 if else 或者 switch case结构

这种方式比较直观,对于小型状态机比较适用,但对于稍大型的状态机,使用这种方式难以维护,往往会发生意想不到的bug。

2.2状态机表

维护一个二维状态表,横坐标为各种状态(state),纵坐标为各种事件(event),表中的每一个元素为存储的处理函数(Action),这种方式易于维护,但运行时间和存储空间较大。

3.状态机表实现实例

下面是我在实际工作中使用状态机表实现的baseband 的各种状态,以及处理函数。

3.1.state of bb_fsm

enum{

AR_BB_STATE_NULL,   

AR_BB_STATE_LOCK,    //LOCK STATUS

AR_BB_STATE_CONNECTED,

};

3.2.event of bb_fsm

enum{

AR_BB_ENENT_PHY_UNLOCK,

AR_BB_EVENT_PHY_LOCK,

AR_BB_ EVENT_AUTO_HOP_MODE,

AR_BB_ EVENT_FIXED_HOP_MODE,

AR_BB_ EVENT_UPDATA_BEST_CHN,

AR_BB_EVENT_PIPELINE_STATUS,

};

3.3.information of bb_fsm

#define MAX_BB_FSM_STATE_NUM    4

#define MAX_BB_FSM_EVENT_NUM   8

typedef  void (*ar_bb_fsm_fun)(void *msg);

typedef struct{

uint8_t state_cnt;

uint8_t event_cnt;

uint32_t fsm_state[MAX_BB_FSM_STATE_NUM];

uint32_t fsm_event[MAX_BB_FSM_EVENT_NUM];

ar_bb_fsm_func ar_bb_fsm_proc[MAX_BB_FSM_STATE_NUM][ MAX_BB_FSM_EVENT_NUM];

ar_bb_fsm_func ar_bb_fsm_err_proc;

}ar_bb_fsm_t;

static ar_bb_fsm_t ar_bb_fsm;

 

3.4.table of bb_fsm

State

Event

AR_BB_STATE_NULL

AR_BB_STATE_LOCK

AR_BB_STATE_CONNECTED

AR_BB_ENENT_PHY_UNLOCK

ar_bb_fsm_null_proc_phy_unlock(void *msg);

ar_bb_fsm_lock_proc_phy_unlock(void *msg)

ar_bb_fsm_connected_proc_phy_unlock(void *msg)

AR_BB_EVENT_PHY_LOCK

ar_bb_fsm_null_proc_phy_lock(void *msg)

ar_bb_fsm_lock_proc_phy_lock(void *msg)

ar_bb_fsm_connected_proc_phy_lock(void *msg)

AR_BB_EVENT_AUTO_HOP_MODE

ar_bb_fsm_null_auto_hop_mode(void *msg)

ar_bb_fsm_lock_auto_hop_mode(void *msg)

ar_bb_fsm_connected_auto_hop_mode(void *msg)

AR_BB_EVENT_FIXED_HOP_MODE

ar_bb_fsm_null_fixed_hop_mode(void *msg)

ar_bb_fsm_lock_fixed_hop_mode(void *msg)

ar_bb_fsm_connected_fixed_hop_mode(void *msg)

AR_BB_EVENT_UPDATA_BEST_CHN

ar_bb_fsm_null_updata_best_chn(void *msg)

ar_bb_fsm_null_updata_best_chn(void *msg)

ar_bb_fsm_connected_updata_best_chn(void *msg)

AR_BB_EVENT_PIPELINE_STATUS

ar_bb_fsm_null_get_pipeline_state(void *msg)

ar_bb_fsm_null_get_pipeline_state(void *msg)

ar_bb_fsm_connected_get_pipeline_state(void *msg)

3.5. infactal function

static ar_bb_fsm_t ar_bb_fsm;

 

int ar_bb_fsm_init(ar_bb_fsm_func err_proc)

{

    ar_bb_fsm.ar_bb_fsm_err_proc = err_proc;

    return 0;

}

 

int ar_bb_fsm_add_proc(uint32_t fsm_state, uint32_t fsm_event, ar_bb_fsm_func fsm_proc)

{

    uint8_t state_index;

    uint8_t event_index;

    uint32_t state_exist = 0;

    uint32_t event_exist =0;

    if(fsm_proc == NULL)

        return -1;

                               

    for(state_index =0;  state_index < ar_bb_fsm.state_cnt; state_index++ ){

        if(fsm_state == ar_bb_fsm.fsm_state[state_index]){

                                    state_exist = 1;

                                                break;

                                }

    }

               

                if(0 == state_exist){

                    if(ar_bb_fsm.state_cnt >= MAX_BB_FSM_STATE_NUM){

                                    return -1;

                                }

                    ar_bb_fsm.fsm_state[ar_bb_fsm.state_cnt] = fsm_state;

                                ar_bb_fsm.state_cnt++;             

    }

               

                for(event_index = 0; event_index < ar_bb_fsm.event_cnt;  event_index++){

                    if(fsm_event == ar_bb_fsm.fsm_event[event_index]){

                                    event_exist = 1;

                                                break;

                                }

                }

 

    if(0 == event_exist){

                    if(ar_bb_fsm.event >= MAX_BB_FSM_EVENT_NUM){

                                    return -1;

                                }

                    ar_bb_fsm.fsm_event[ar_bb_fsm.event_cnt] = fsm_event;

                    ar_bb_fsm.event_cnt++;            

    }         

    ar_bb_fsm.fsm_proc[state_index][event_index] = fsm_proc;

                return 0;

}

 

int ar_bb_fsm_run(uint32_t fsm_state, uint32_t fsm_event, void *msg)

{

    uint8_t state_index;

    uint8_t event_index;

    uint32_t state_exist = 0;

    uint32_t event_exist =0;

               

                if(msg == NULL)

                    return -1;

                               

    for(state_index =0;  state_index < ar_bb_fsm.state_cnt; state_index++ ){

        if(fsm_state == ar_bb_fsm.fsm_state[state_index]){

                                    state_exist = 1;

                                                break;

                                }

    }

               

               

                for(event_index = 0; event_index < ar_bb_fsm.event_cnt; event_index++){

                    if(fsm_event == ar_bb_fsm.fsm_event[event_index]){

                                    event_exist = 1;

                                                break;

                                }

                }

 

                if((event_exist != 1) || (state_exist != 1)){

                    if(NULL != ar_bb_fsm.err_proc){

                                    ar_bb_fsm.err_proc();

                                }

                                return -1;

                }

               

                if(NULL == ar_bb_fsm.fsm_proc[state_index][event_index]){

                    if(NULL != ar_bb_fsm.err_proc){

                                    ar_bb_fsm.err_proc(msg);

                                }

        return -1;                    

                }

               

    ar_bb_fsm.fsm_proc[state_index][event_index](msg);

                return 0;

}

 

void ar_bb_fsm_null_proc_phy_unlock(void *msg)

{

               

                if(dev_role == AP){

                    /*

                    slot_rx_unlock_time++;

                    if (slot_rx_unlock_time > threshold_cnt){

                                    phy_rx_reset();

                    }

                    */

                }

                else{

                                /*

                                phy_scan_next_chn();

                                phy_sys_reset();

                                */                          

                }             

}

 

 

 

void ar_bb_fsm_null_proc_phy_lock(void *msg)

{

    //ar_fsm_event_info_t *event_info = (ar_fsm_event_info_t *)msg;

    if(dev_role == AP){   

    // switch fsm_state

        ar_lock();    

        fsm_state = AR_BB_EVENT_PHY_LOCK;

        ar_unlock;

        notify_pipeline;                       

                }

                else{

                                //parser br packet

                                if(parser_ok){

                                                ar_lock();            

            fsm_state = AR_BB_EVENT_PHY_LOCK;

           

                                                //get and set mcs_value

                                                //get and set slot tx freq

                                                //notify pipeline the bb status

                                                ar_unlock;

 

                    }

                }

}

 

void ar_bb_fsm_null_auto_hop_mode(void *msg)

{

    //set freq_hop_mode as auto                              

}

 

void ar_bb_fsm_null_fixed_hop_mode(void *msg)

{

                uint32_t freq = 0;

                ar_fsm_event_info_t *fsm_event = (ar_fsm_event_info_t *)msg;

               

                freq = fsm_event->data;

                //set freq_hop_mode as fixed

                freq_hop_mode = 1;

                //set freq

               

}

 

void ar_bb_fsm_null_updata_best_chn(void *msg)

{

                if((dev_role == AP) && (0 == freq_hop_mode))    //role is ap, and freq_hop_mode is auto

                {

                                //set best chn

                }

}

 

void ar_bb_fsm_null_get_pipeline_state(void *msg)

{

                //do nothing

}

 

 

void ar_bb_fsm_lock_proc_phy_unlock(void *msg)

{

                if(dev_role == AP){

                    /*

                    slot_rx_unlock_time++;

                    if (slot_rx_unlock_time > threshold_cnt){

                                    phy_user_rx_reset();

                                                fsm_state = AR_BB_STATE_NULL;

                                                notify pipeline the fsm_state

                                                                               

                    }

                    */

                }

                else{

                                /*

                                phy_scan_next_chn();

                                phy_sys_reset();

                                */                          

                }             

}

 

void ar_bb_fsm_lock_proc_phy_lock(void *msg)

{

    //ar_fsm_event_info_t *event_info = (ar_fsm_event_info_t *)msg;

    if(dev_role == AP){   

        //count snr, ldpc err, and harq_cnt 

                }

                else{

                                parser br packet

                                if(parser_ok){           

                                                //get and set mcs_value

                                                //get and set slot tx freq

                    }

                }

}

 

void ar_bb_fsm_lock_auto_hop_mode(void *msg)

{

    //set freq_hop_mode as auto                              

}

 

void ar_bb_fsm_lock_fixed_hop_mode(void *msg)

{

                uint32_t freq = 0;

                ar_fsm_event_info_t *fsm_event = (ar_fsm_event_info_t *)msg;

                freq = fsm_event->data;

                //set freq_hop_mode as fixed

                freq_hop_mode = 1;

                //set freq           

}

void ar_bb_fsm_null_updata_best_chn(void *msg)

{

                if((dev_role == AP) && (0 == freq_hop_mode))    //role is ap, and freq_hop_mode is auto

                {

                                //set best chn

                }             

}

 

void ar_bb_fsm_null_get_pipeline_state(void *msg)

{

                if(pipeline_state == PLAYING)

                {

                    fsm_state = AR_BB_STATE_CONNECTED;        

                 }

}

 

 

void ar_bb_fsm_connected_proc_phy_unlock(void *msg)

{

                if(dev_role == AP){   

                    slot_rx_unlock_time++;

                                if(slot_rx_unlock_time >= 64){

                                                notify pipeline that bb_fsm is  AR_BB_STATE_NULL;

                                                phy_user_rxreset_hold(user_index);

                                                phy_user_rxreset_release(user_index);

                                                slot_rx_unlock_time = 0;

                                }

                }

                else{

                    br_rx_unlock_time++;

                                if(br_rx_unlock_time >= 64){

                                                notify pipeline that bb_fsm is  AR_BB_STATE_NULL;

                                                br_rx_unlock_time = 0;

                }

}

 

 

 

void ar_bb_fsm_connected_proc_phy_lock(void *msg)

{

    //ar_fsm_event_info_t *event_info = (ar_fsm_event_info_t *)msg;

    if(dev_role == AP){   

        //count snr, ldpc err, and harq_cnt 

                }

                else{

                                parser br packet

                                if(parser_ok){           

                                                //get and set mcs_value

                                                //get and set slot tx freq

                    }

                }             

}

void ar_bb_fsm_connected_auto_hop_mode(void *msg)

{

    //set freq_hop_mode as auto                       

}

void ar_bb_fsm_connected_fixed_hop_mode(void *msg)

{

                uint32_t freq = 0;

                ar_fsm_event_info_t *fsm_event = (ar_fsm_event_info_t *)msg;

                freq = fsm_event->data;

                //set freq_hop_mode as fixed

                freq_hop_mode = 1;

                //set freq           

}

void ar_bb_fsm_connected_updata_best_chn(void *msg)

{

                if((dev_role == AP) && (0 == freq_hop_mode))    //role is ap, and freq_hop_mode is auto

                {

                                //set best chn

                }             

}

 

void ar_bb_fsm_connected_get_pipeline_state(void *msg)

{

                if(pipeline_state != PLAYING)

                {

                    fsm_state = AR_BB_STATE_NULL;      

    }

}

你可能感兴趣的:(c语言基础)