struct plc_state
{
Uint8 cur_state;
Uint8 next_state;
Uint8 (*action) (uint8 init, void *args);//How does this structure work?
};
void plc_machine_opt (void *args)
{
struct Plc_state *pstate = plc_state.pstate;//The key is to see who changed the Plc_state.pstate, found who changed it, is the upstream data to get through.
Uint8 Init;
init = Plc_state.init;
if (init) plc_state.wait_t=0;
Plc_state.init = 0;
if (NULL! = pstate)
{
Pstate->action (init, args); Call the code where he called again ....
}
}
After searching in the code we can clearly see that the void Chg_state (Uint8 cur_state) changed the value of the PLC _state.pstate. The part of the change is shown in the red code below.
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);
}
We will unwittingly consider who called the Void Chg_state (Uint8 cur_state)
The code for the above function is called as shown in red
void Sys_init (void)
{
/* Initialize state machine parameters */
Memset_my (&plc_state, 0x00, sizeof (plc_state));
Memset_my (®, 0x00, sizeof (REG));
Reg.type = password_reg;//Power-on password registration
Chg_state (RST_PLC);//This is a reset operation
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 hours without communication, reset the carrier chip
{
rst_plc_t = 0;
Chg_state (RST_PLC);
}
else if (rst_plc_t) | | (+ = rst_plc_t))
{//Read carrier Eid
GET_ID (Cmd_get_eid, G_frame_buffer);
}
}
/**********************************************
Equipment Registration: 1, the first time registration does not use the password;
2, the second time after registration, and the original record of the same gateway number does not use the password
3, the second time after registration, the new network Kwanhla equipment needs to use the device password
***********************************************/
Static uint8 Get_reg (struct shs_frame *pframe)
{
Uint8 need_wr=1;
if (Password_reg = = Reg.type)
{
if (Unvalid_data = = Eep_param.panid_flag)
{//Registration for the first time, do not award paragraph password
}
else if ((Valid_data = = Eep_param.panid_flag)
&& (0x00 = = Memcmp_my (Eep_param.panid, &pframe->infor[1], Panid_len)))
{//After successful registration is completed, start the registration again, only Judge 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)))
{//Determine if the Panid has been registered successfully
Reg.last_status = Password_err;
Chg_state (Pwd_err);
return (0);
}
}
Successful, set password registration successful
Reg.type = Password_reg;
Chg_state (G_GWID);//Read Gateway 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)
{//Registration for the first time, do not award paragraph password
}
else if ((Valid_data = = Eep_param.panid_flag)
&& (0x00 = = Memcmp_my (Eep_param.panid, &pframe->infor[1], Panid_len)))
{//After successful registration is completed, start the registration again, only Judge 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)))
{//Determine if the Panid has been registered successfully
Reg.last_status = Password_err;
Chg_state (Pwd_err);
return (0);
}
}
Successful, set password registration successful
Reg.type = Password_reg;
Chg_state (G_GWID);//Read Gateway 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) This function is called by the function, by void local_frame_opt (struct shs_frame *pframe)
/****************************************************************
Local communication Protocol resolution
****************************************************************/
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);//carrier active access AID, indicating that the carrier chip may be reset.
}
else if (Cmd_unlink = = Pframe->infor[0])
{//Gateway disconnected, carrier chip escalated disconnect, start carrier registration Panid settings ....
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));
// }
}
Our question comes again, the function called void local_frame_opt (struct shs_frame *pframe) The answer is Uint8 frame_handle (uint8 init, void *args) protocol parsing function
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 communication
Local_frame_opt (pframe);
return (1);
}
Else
{//Offsite communication
ret = remote_frame_opt (pframe);
if (Ret > 1) {
Len = Set_ret_frame (pframe, ret);
Uart_write ((uint8 *) pframe, Len);
}
}
return (0);
}
That function called the function uint8 frame_handle (uint8 init, void *args) .... The answer is the following structure
struct plc_state
{
Uint8 cur_state;
Uint8 next_state;
Uint8 (*action) (uint8 init, void *args);//How does this structure work?
};
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
Password Registration
{pwd_err, UNLINK2, Set_register},
{UNLINK2, S_panid, Set_unlink},
Registration successful
{g_gwid, S_reg, Rd_gw_aid},
{S_reg, G_sid, set_register},//set the registration properties, wait for the carrier chip to escalate Panid
{g_sid, _end, Rd_gw_sid},
{_end, _end, Frame_handle},
};
The following function re-invokes the plc_state_slot[]
/****************************************
Carrier initialization State transitions
****************************************/
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); Calling this function is equivalent to mobilizing the struct const struct Plc_state plc_state_slot[]= ...
}
}
The analysis of the code to this end, some do not understand the place to go back to the company to ask a master, or let me ask my Master buddies. Analysis Endless, I will insist, code is to break the sand pot ask the end. Find out the real side of the code.