📄 dlmstp.c
字号:
static bool MSTP_Master_Node_FSM(
void)
{
/* The number of frames sent by this node during a single token hold. */
/* When this counter reaches the value Nmax_info_frames, the node must */
/* pass the token. */
static uint8_t FrameCount;
/* "Next Station," the MAC address of the node to which This Station
passes the token. If the Next_Station is unknown, Next_Station shall
be equal to This_Station. */
static uint8_t Next_Station;
/* "Poll Station," the MAC address of the node to which This Station last */
/* sent a Poll For Master. This is used during token maintenance. */
static uint8_t Poll_Station;
/* A counter of transmission retries used for Token and Poll For Master */
/* transmission. */
static unsigned RetryCount;
/* The number of tokens received by this node. When this counter reaches */
/* the value Npoll, the node polls the address range between TS and NS */
/* for additional master nodes. TokenCount is set to zero at the end of */
/* the polling process. */
static unsigned TokenCount;
/* next-x-station calculations */
uint8_t next_poll_station = 0;
uint8_t next_this_station = 0;
uint8_t next_next_station = 0;
/* timeout values */
uint16_t my_timeout = 10, ns_timeout = 0;
bool matched;
/* transition immediately to the next state */
bool transition_now = false;
/* some calculations that several states need */
next_poll_station = (Poll_Station + 1) % (Nmax_master + 1);
next_this_station = (This_Station + 1) % (Nmax_master + 1);
next_next_station = (Next_Station + 1) % (Nmax_master + 1);
switch (Master_State) {
case MSTP_MASTER_STATE_INITIALIZE:
/* DoneInitializing */
/* indicate that the next station is unknown */
Next_Station = This_Station;
Poll_Station = This_Station;
/* cause a Poll For Master to be sent when this node first */
/* receives the token */
TokenCount = Npoll;
MSTP_Flag.SoleMaster = false;
Master_State = MSTP_MASTER_STATE_IDLE;
transition_now = true;
break;
case MSTP_MASTER_STATE_IDLE:
/* In the IDLE state, the node waits for a frame. */
if (Timer_Silence() >= Tno_token) {
/* LostToken */
/* assume that the token has been lost */
EventCount = 0; /* Addendum 135-2004d-8 */
Master_State = MSTP_MASTER_STATE_NO_TOKEN;
transition_now = true;
} else if (MSTP_Flag.ReceivedInvalidFrame == true) {
/* ReceivedInvalidFrame */
/* invalid frame was received */
MSTP_Flag.ReceivedInvalidFrame = false;
/* wait for the next frame - remain in IDLE */
} else if (MSTP_Flag.ReceivedValidFrame == true) {
switch (FrameType) {
case FRAME_TYPE_TOKEN:
/* ReceivedToken */
/* tokens can't be broadcast */
if (DestinationAddress == MSTP_BROADCAST_ADDRESS)
break;
MSTP_Flag.ReceivedValidFrame = false;
FrameCount = 0;
MSTP_Flag.SoleMaster = false;
Master_State = MSTP_MASTER_STATE_USE_TOKEN;
transition_now = true;
break;
case FRAME_TYPE_POLL_FOR_MASTER:
/* ReceivedPFM */
MSTP_Send_Frame(FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER,
SourceAddress, This_Station, NULL, 0);
break;
case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY:
/* indicate successful reception to the higher layers */
MSTP_Flag.ReceivePacketPending = true;
break;
case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY:
/* indicate successful reception to higher layers */
MSTP_Flag.ReceivePacketPending = true;
/* broadcast DER just remains IDLE */
if (DestinationAddress != MSTP_BROADCAST_ADDRESS) {
Master_State =
MSTP_MASTER_STATE_ANSWER_DATA_REQUEST;
}
break;
case FRAME_TYPE_TEST_REQUEST:
MSTP_Send_Frame(FRAME_TYPE_TEST_RESPONSE,
SourceAddress, This_Station, &InputBuffer[0],
DataLength);
break;
case FRAME_TYPE_TEST_RESPONSE:
default:
break;
}
/* For DATA_EXPECTING_REPLY, we will keep the Rx Frame for
reference, and the flag will be cleared in the next state */
if (Master_State != MSTP_MASTER_STATE_ANSWER_DATA_REQUEST) {
MSTP_Flag.ReceivedValidFrame = false;
}
}
break;
/* In the USE_TOKEN state, the node is allowed to send one or */
/* more data frames. These may be BACnet Data frames or */
/* proprietary frames. */
case MSTP_MASTER_STATE_USE_TOKEN:
/* Note: We could wait for up to Tusage_delay */
if (!MSTP_Flag.TransmitPacketPending) {
/* NothingToSend */
FrameCount = Nmax_info_frames;
Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
transition_now = true;
} else {
uint8_t frame_type;
if (MSTP_Flag.TransmitPacketDER) {
frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY;
} else {
frame_type = FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
}
MSTP_Send_Frame(frame_type, TransmitPacketDest, This_Station,
(uint8_t *) & TransmitPacket[0], TransmitPacketLen);
MSTP_Flag.TransmitPacketPending = false;
FrameCount++;
switch (frame_type) {
case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY:
/* SendAndWait */
if (TransmitPacketDest == MSTP_BROADCAST_ADDRESS)
Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
else
Master_State = MSTP_MASTER_STATE_WAIT_FOR_REPLY;
break;
case FRAME_TYPE_TEST_REQUEST:
Master_State = MSTP_MASTER_STATE_WAIT_FOR_REPLY;
break;
case FRAME_TYPE_TEST_RESPONSE:
case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY:
default:
/* SendNoWait */
Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
break;
}
}
break;
case MSTP_MASTER_STATE_WAIT_FOR_REPLY:
/* In the WAIT_FOR_REPLY state, the node waits for */
/* a reply from another node. */
if (Timer_Silence() >= Treply_timeout) {
/* ReplyTimeout */
/* assume that the request has failed */
FrameCount = Nmax_info_frames;
Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
/* Any retry of the data frame shall await the next entry */
/* to the USE_TOKEN state. */
/* (Because of the length of the timeout, */
/* this transition will cause the token to be */
/* passed regardless */
/* of the initial value of FrameCount.) */
transition_now = true;
} else {
if (MSTP_Flag.ReceivedInvalidFrame == true) {
/* InvalidFrame */
/* error in frame reception */
MSTP_Flag.ReceivedInvalidFrame = false;
Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
transition_now = true;
} else if (MSTP_Flag.ReceivedValidFrame == true) {
if (DestinationAddress == This_Station) {
/* What did we receive? */
switch (FrameType) {
case FRAME_TYPE_REPLY_POSTPONED:
/* ReceivedReplyPostponed */
Master_State =
MSTP_MASTER_STATE_DONE_WITH_TOKEN;
break;
case FRAME_TYPE_TEST_RESPONSE:
Master_State = MSTP_MASTER_STATE_IDLE;
break;
case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY:
/* ReceivedReply */
/* or a proprietary type that indicates
a reply */
/* indicate successful reception to
the higher layers */
MSTP_Flag.ReceivePacketPending = true;
Master_State =
MSTP_MASTER_STATE_DONE_WITH_TOKEN;
break;
default:
/* if proprietary frame was expected, you might
need to transition to DONE WITH TOKEN */
Master_State = MSTP_MASTER_STATE_IDLE;
break;
}
} else {
/* ReceivedUnexpectedFrame */
/* an unexpected frame was received */
/* This may indicate the presence of multiple tokens */
/* or a device that didn't see activity after passing */
/* a token (how lame!). */
/* Synchronize with the network. */
/* This action drops the token. */
Master_State = MSTP_MASTER_STATE_IDLE;
}
MSTP_Flag.ReceivedValidFrame = false;
transition_now = true;
}
}
break;
/* The DONE_WITH_TOKEN state either sends another data frame, */
/* passes the token, or initiates a Poll For Master cycle. */
case MSTP_MASTER_STATE_DONE_WITH_TOKEN:
/* SendAnotherFrame */
if (FrameCount < Nmax_info_frames) {
/* then this node may send another information frame */
/* before passing the token. */
Master_State = MSTP_MASTER_STATE_USE_TOKEN;
transition_now = true;
}
/* Npoll changed in Errata SSPC-135-2004 */
else if (TokenCount < (Npoll - 1)) {
if ((MSTP_Flag.SoleMaster == true) &&
(Next_Station != next_this_station)) {
/* SoleMaster */
/* there are no other known master nodes to */
/* which the token may be sent
(true master-slave operation). */
FrameCount = 0;
TokenCount++;
Master_State = MSTP_MASTER_STATE_USE_TOKEN;
transition_now = true;
} else {
/* SendToken */
/* Npoll changed in Errata SSPC-135-2004 */
/* The comparison of NS and TS+1
eliminates the Poll For Master
if there are no addresses between
TS and NS, since there is no
address at which a new master node
may be found in that case. */
TokenCount++;
/* transmit a Token frame to NS */
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
This_Station, NULL, 0);
RetryCount = 0;
EventCount = 0;
Master_State = MSTP_MASTER_STATE_PASS_TOKEN;
}
} else if (next_poll_station == Next_Station) {
if (MSTP_Flag.SoleMaster == true) {
/* SoleMasterRestartMaintenancePFM */
Poll_Station = next_next_station;
MSTP_Send_Frame(FRAME_TYPE_POLL_FOR_MASTER, Poll_Station,
This_Station, NULL, 0);
/* no known successor node */
Next_Station = This_Station;
RetryCount = 0;
TokenCount = 1; /* changed in Errata SSPC-135-2004 */
/* EventCount = 0; removed in Addendum 135-2004d-8 */
/* find a new successor to TS */
Master_State = MSTP_MASTER_STATE_POLL_FOR_MASTER;
} else {
/* ResetMaintenancePFM */
Poll_Station = This_Station;
/* transmit a Token frame to NS */
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
This_Station, NULL, 0);
RetryCount = 0;
TokenCount = 1; /* changed in Errata SSPC-135-2004 */
EventCount = 0;
Master_State = MSTP_MASTER_STATE_PASS_TOKEN;
}
} else {
/* SendMaintenancePFM */
Poll_Station = next_poll_station;
MSTP_Send_Frame(FRAME_TYPE_POLL_FOR_MASTER, Poll_Station,
This_Station, NULL, 0);
RetryCount = 0;
Master_State = MSTP_MASTER_STATE_POLL_FOR_MASTER;
}
break;
/* The PASS_TOKEN state listens for a successor to begin using */
/* the token that this node has just attempted to pass. */
case MSTP_MASTER_STATE_PASS_TOKEN:
if (Timer_Silence() <= Tusage_timeout) {
if (EventCount > Nmin_octets) {
/* SawTokenUser */
/* Assume that a frame has been sent by
the new token user. */
/* Enter the IDLE state to process the frame. */
Master_State = MSTP_MASTER_STATE_IDLE;
transition_now = true;
}
} else {
if (RetryCount < Nretry_token) {
/* RetrySendToken */
RetryCount++;
/* Transmit a Token frame to NS */
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
This_Station, NULL, 0);
EventCount = 0;
/* re-enter the current state to listen for NS */
/* to begin using the token. */
} else {
/* FindNewSuccessor */
/* Assume that NS has failed. */
Poll_Station = next_next_station;
/* Transmit a Poll For Master frame to PS. */
MSTP_Send_Frame(FRAME_TYPE_POLL_FOR_MASTER, Poll_Station,
This_Station, NULL, 0);
/* no known successor node */
Next_Station = This_Station;
RetryCount = 0;
TokenCount = 0;
/* EventCount = 0; removed in Addendum 135-2004d-8 */
/* find a new successor to TS */
Master_State = MSTP_MASTER_STATE_POLL_FOR_MASTER;
}
}
break;
/* The NO_TOKEN state is entered if Timer_Silence()
becomes greater than Tno_token, indicating that
there has been no network activity for that period
of time. The timeout is continued to determine
whether or not this node may create a token. */
case MSTP_MASTER_STATE_NO_TOKEN:
my_timeout = Tno_token + (Tslot * This_Station);
if (Timer_Silence() < my_timeout) {
if (EventCount > Nmin_octets) {
/* SawFrame */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -