{
uint8 cur_state;
uint8 next_state;
uint8 (*action)(uint8 init, void *args);//这个结构体是怎么用的
};
void plc_machine_opt(void *args)
{
struct PLC_STATE *pstate = plc_state.pstate;//关键是看看谁改变了 plc_state.pstate,找到了谁改变了它,就是把上游的数据打通了。
uint8 init;
init = plc_state.init;
if(init) plc_state.wait_t=0;
plc_state.init = 0;
if(NULL != pstate)
{
pstate->action(init, args);调用完这个他又调用的哪里的代码????
}
}
经过在代码中的查找我们可以清楚的看到,是void chg_state(uint8 cur_state)改变了plc _state.pstate的值。改变的部分如下红色代码所示。
void chg_state(uint8 cur_state)
{
uint8 i;
static uint8 last_state=INVALID;
plc_state.wait_t = 0;
plc_state.init=1;
for(i = 0; i < PLC_SLOT_SZ; i++)
{
if(plc_state_slot[i].cur_state == cur_state)
{
plc_state.pstate = (struct PLC_STATE *)&plc_state_slot[i];
break;
}
}
if(i >= PLC_SLOT_SZ)
{
plc_state.pstate = (struct PLC_STATE *)&plc_state_slot[0];
}
if(last_state != plc_state.pstate->cur_state)
{
plc_state.trycnt = 0;
}
last_state = plc_state.pstate->cur_state;
notify(EV_STATE);
}
我们会不知不觉的考虑到谁调用了void chg_state(uint8 cur_state)
调用的上述函数的代码如下红色所示
void sys_init(void)
{
/*初始化状态机参数*/
memset_my(&plc_state, 0x00, sizeof(plc_state));
memset_my(®, 0x00, sizeof(reg));
reg.type = PASSWORD_REG;//上电密码注册
chg_state(RST_PLC);//这是一个复位操作
//chg_state(_END);//noly for debug
memset_my(g_frame_buffer, 0x00, sizeof(g_frame_buffer));
ir_eng.g_ir_state = IR_IDLE;
}
static void chk_plc_alive(void)
{
if(rst_plc_t > 120)//2小时没有通信,复位载波芯片
{
rst_plc_t = 0;
chg_state(RST_PLC);
}
else if((60 == rst_plc_t) || (120 == rst_plc_t))
{//读取载波EID
get_ID(CMD_GET_EID, g_frame_buffer);
}
}
/**********************************************
设备注册:1、第一次注册不使用密码;
2、第二次以后注册,与原记录的网关号相同不使用密码
3、第二次以后注册,新网关拉取设备需要使用设备密码
***********************************************/
static uint8 get_reg(struct SHS_frame *pframe)
{
uint8 need_wr=1;
if(PASSWORD_REG == reg.type)
{
if(UNVALID_DATA == eep_param.panid_flag)
{//第一次注册,不判段密码
}
else if((VALID_DATA == eep_param.panid_flag)
&& (0x00 == memcmp_my(eep_param.panid, &pframe->infor[1], PANID_LEN)))
{//成功注册完成后,再次启动注册,只判断panid
need_wr = 0;
}
else if((eep_param.pwd_magic == VALID_DATA)
&& (0x00 != memcmp_my(eep_param.password, &pframe->infor[PANID_LEN+1], PWD_LEN)))
{//判断是否是已经注册成功的panid
reg.last_status = PASSWORD_ERR;
chg_state(PWD_ERR);
return(0);
}
}
//成功,设置密码注册成功
reg.type = PASSWORD_REG;
chg_state(G_GWID);//读取网关aid
if(need_wr)
{
mymemcpy(eep_param.panid, &pframe->infor[1], PANID_LEN);
eep_param.panid_flag = VALID_DATA;
EEP_Write(OF_PLC_PARAM, (uint8 *)&eep_param, sizeof(eep_param));
}
return(0);
}
#if 0
{
uint8 need_wr=1;
if(PASSWORD_REG == reg.type)
{
if(INVALID_DATA == eep_param.panid_flag)
{//第一次注册,不判段密码
}
else if((VALID_DATA == eep_param.panid_flag)
&& (0x00 == memcmp_my(eep_param.panid, &pframe->infor[1], PANID_LEN)))
{//成功注册完成后,再次启动注册,只判断panid
need_wr = 0;
}
else if((eep_param.pwd_magic == VALID_DATA)
&& (0x00 != memcmp_my(eep_param.password, &pframe->infor[PANID_LEN+1], PWD_LEN)))
{//判断是否是已经注册成功的panid
reg.last_status = PASSWORD_ERR;
chg_state(PWD_ERR);
return(0);
}
}
//成功,设置密码注册成功
reg.type = PASSWORD_REG;
chg_state(G_GWID);//读取网关aid
if(need_wr)
{
mymemcpy(eep_param.panid, &pframe->infor[1], PANID_LEN);
eep_param.panid_flag = VALID_DATA;
EEP_Write(OF_PLC_PARAM, (uint8 *)&eep_param, sizeof(eep_param));
}
return(0);
}
#endif
static uint8 get_reg(struct SHS_frame *pframe)这个函数由那个函数来调用,由void local_frame_opt(struct SHS_frame *pframe)
本地通信协议解析
****************************************************************/
void local_frame_opt(struct SHS_frame *pframe)
{
if(CMD_REGINFOR == pframe->infor[0])
{
get_reg(pframe);
}
else if(CMD_REQ_AID == pframe->infor[0])
{
chg_state(S_AID);//载波出现主动获取aid,说明载波芯片可能复位!!
}
else if(CMD_UNLINK == pframe->infor[0])
{//网关断开连接,载波芯片上报断开连接,启动载波注册panid设置????
chg_state(S_PWDREG);
}
// else if(CMD_GET_GWAID == pframe->infor[0])
// {
// mymemcpy(eep_param.gateway_id, &pframe->infor[1], ID_LEN);
// EEP_Write(OF_PLC_PARAM, (uint8 *)&eep_param, sizeof(eep_param));
// }
}
我们的疑问又来了,那个函数调用的void local_frame_opt(struct SHS_frame *pframe)答案是uint8 frame_handle(uint8 init, void *args) 协议解析函数
uint8 frame_handle(uint8 init, void *args)
{
uint8 len,ret;
struct SHS_frame *pframe = (struct SHS_frame *)args;
if(pframe == NULL) return(0);
if(is_all_xx(pframe->said, 0x00, ID_LEN))
{//本地通信
local_frame_opt(pframe);
return(1);
}
else
{//异地通信
ret = remote_frame_opt(pframe);
if (ret > 1) {
len = set_ret_frame(pframe, ret);
uart_write((uint8 *)pframe, len);
}
}
return(0);
}
那个函数调用了这个函数uint8 frame_handle(uint8 init, void *args)呢????答案是下面的这个结构体
struct PLC_STATE
{
uint8 cur_state;
uint8 next_state;
uint8 (*action)(uint8 init, void *args);//这个结构体是怎么用的
};
const struct PLC_STATE plc_state_slot[]=
{
//init plc
{RST_PLC, R_EID, reset_plc},
//{R_EID, S_BPS, rd_plc_eid},
{R_EID, S_AID, rd_plc_eid},
{S_BPS, S_AID, wr_plc_bps},
{S_AID, S_PWDREG,wr_plc_aid},
{S_PWDREG, S_PANID, set_register},
{S_PANID, _END, wr_plc_panid},
#if KEY_REG
//key reg
{UNLINK1, S_REG, set_unlink},
#endif
//密码注册
{PWD_ERR, UNLINK2, set_register},
{UNLINK2, S_PANID, set_unlink},
//注册成功
{G_GWID, S_REG, rd_gw_aid},
{S_REG, G_SID, set_register},//设置注册属性,等待载波芯片上报panid
{G_SID, _END, rd_gw_sid},
{_END, _END, frame_handle},
};
下面的函数又重新调用了 plc_state_slot[]
/****************************************
载波初始化状态转换
****************************************/
void chg_state(uint8 cur_state)
{
uint8 i;
static uint8 last_state=INVALID;
plc_state.wait_t = 0;
plc_state.init=1;
for(i = 0; i < PLC_SLOT_SZ; i++)
{
if(plc_state_slot[i].cur_state == cur_state)
{
plc_state.pstate = (struct PLC_STATE *)&plc_state_slot[i];
break;
}
}
if(i >= PLC_SLOT_SZ)
{
plc_state.pstate = (struct PLC_STATE *)&plc_state_slot[0];
}
if(last_state != plc_state.pstate->cur_state)
{
plc_state.trycnt = 0;
}
last_state = plc_state.pstate->cur_state;
notify(EV_STATE);
}
void plc_machine_opt(void *args)
{
struct PLC_STATE *pstate = plc_state.pstate;
uint8 init;
init = plc_state.init;
if(init) plc_state.wait_t=0;
plc_state.init = 0;
if(NULL != pstate)
{
pstate->action(init, args);调用这个函数是不是就相当于调动了那个结构体const struct PLC_STATE plc_state_slot[]=????????
}
}
代码的分析到此为止,有些不理解的地方还要回公司问问高手,或者让问问我的高手哥们。分析无止境,我会坚持,代码就是打破砂锅问到底。找出代码最真实的一面。