赞
踩
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;
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。