Added reset of SilenceTimer in the SendFrame part of MS/TP that had been missing. Refactored more master state machine states.

This commit is contained in:
skarg
2006-08-28 21:13:37 +00:00
parent 011536b9c5
commit 23a8636b90
5 changed files with 230 additions and 245 deletions
+205 -230
View File
@@ -56,7 +56,8 @@
/* debug print statements */ /* debug print statements */
#define PRINT_ENABLED_RECEIVE 0 #define PRINT_ENABLED_RECEIVE 0
#define PRINT_ENABLED_MASTER 0 #define PRINT_ENABLED_RECEIVE_DATA 0
#define PRINT_ENABLED_MASTER 1
/* MS/TP Frame Format */ /* MS/TP Frame Format */
/* All frames are of the following format: */ /* All frames are of the following format: */
@@ -249,9 +250,6 @@ char *mstp_receive_state_text(int state)
case MSTP_RECEIVE_STATE_DATA: case MSTP_RECEIVE_STATE_DATA:
text = "DATA"; text = "DATA";
break; break;
case MSTP_RECEIVE_STATE_DATA_CRC:
text = "CRC";
break;
default: default:
break; break;
} }
@@ -262,6 +260,10 @@ char *mstp_receive_state_text(int state)
void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port) void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port)
{ {
#if PRINT_ENABLED_MASTER
static MSTP_RECEIVE_STATE receive_state = MSTP_RECEIVE_STATE_IDLE;
#endif
#if PRINT_ENABLED_RECEIVE #if PRINT_ENABLED_RECEIVE
fprintf(stderr,"MSTP Rx: State=%s Data=%02X hCRC=%02X Index=%u EC=%u DateLen=%u Silence=%u\r\n", fprintf(stderr,"MSTP Rx: State=%s Data=%02X hCRC=%02X Index=%u EC=%u DateLen=%u Silence=%u\r\n",
mstp_receive_state_text(mstp_port->receive_state), mstp_receive_state_text(mstp_port->receive_state),
@@ -272,6 +274,16 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port)
mstp_port->DataLength, mstp_port->DataLength,
mstp_port->SilenceTimer); mstp_port->SilenceTimer);
#endif #endif
#if PRINT_ENABLED_RECEIVE_DATA
if (mstp_port->DataAvailable == true)
{
if ((mstp_port->receive_state == MSTP_RECEIVE_STATE_IDLE) &&
(receive_state != MSTP_RECEIVE_STATE_IDLE))
fprintf(stderr,"MSTP Rx: ");
fprintf(stderr,"%02X ", mstp_port->DataRegister);
}
receive_state = mstp_port->receive_state;
#endif
switch (mstp_port->receive_state) { switch (mstp_port->receive_state) {
/* In the IDLE state, the node waits for the beginning of a frame. */ /* In the IDLE state, the node waits for the beginning of a frame. */
@@ -515,51 +527,34 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port)
} else if (mstp_port->DataAvailable == true) { } else if (mstp_port->DataAvailable == true) {
/* DataOctet */ /* DataOctet */
if (mstp_port->Index < mstp_port->DataLength) { if (mstp_port->Index < mstp_port->DataLength) {
mstp_port->SilenceTimer = 0;
mstp_port->DataCRC = CRC_Calc_Data(mstp_port->DataRegister, mstp_port->DataCRC = CRC_Calc_Data(mstp_port->DataRegister,
mstp_port->DataCRC); mstp_port->DataCRC);
mstp_port->InputBuffer[mstp_port->Index] = mstp_port->InputBuffer[mstp_port->Index] =
mstp_port->DataRegister; mstp_port->DataRegister;
mstp_port->DataAvailable = false;
mstp_port->Index++; mstp_port->Index++;
mstp_port->receive_state = MSTP_RECEIVE_STATE_DATA; mstp_port->receive_state = MSTP_RECEIVE_STATE_DATA;
} }
/* CRC1 */ /* CRC1 */
else if (mstp_port->Index == mstp_port->DataLength) { else if (mstp_port->Index == mstp_port->DataLength) {
mstp_port->SilenceTimer = 0;
mstp_port->DataCRC = CRC_Calc_Data(mstp_port->DataRegister, mstp_port->DataCRC = CRC_Calc_Data(mstp_port->DataRegister,
mstp_port->DataCRC); mstp_port->DataCRC);
mstp_port->DataAvailable = false;
mstp_port->Index++; mstp_port->Index++;
mstp_port->receive_state = MSTP_RECEIVE_STATE_DATA; mstp_port->receive_state = MSTP_RECEIVE_STATE_DATA;
} }
/* CRC2 */ /* CRC2 */
else if (mstp_port->Index == (mstp_port->DataLength + 1)) { else if (mstp_port->Index == (mstp_port->DataLength + 1)) {
mstp_port->SilenceTimer = 0;
mstp_port->DataCRC = CRC_Calc_Data(mstp_port->DataRegister, mstp_port->DataCRC = CRC_Calc_Data(mstp_port->DataRegister,
mstp_port->DataCRC); mstp_port->DataCRC);
mstp_port->DataAvailable = false; /* STATE DATA CRC - no need for new state */
mstp_port->receive_state = MSTP_RECEIVE_STATE_DATA_CRC; /* indicate the complete reception of a valid frame */
if (mstp_port->DataCRC == 0xF0B8)
mstp_port->ReceivedValidFrame = true;
else
mstp_port->ReceivedInvalidFrame = true;
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
} }
} mstp_port->DataAvailable = false;
break; mstp_port->SilenceTimer = 0;
/* In the DATA_CRC state, the node validates the CRC of the message data. */
case MSTP_RECEIVE_STATE_DATA_CRC:
/* GoodCRC */
if (mstp_port->DataCRC == 0xF0B8) {
/* indicate the complete reception of a valid frame */
mstp_port->ReceivedValidFrame = true;
/* the master node state machine will receive
and validate the message */
/* wait for the start of the next frame. */
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
}
/* BadCRC */
else {
/* to indicate that an error has occurred during the reception of a frame */
mstp_port->ReceivedInvalidFrame = true;
/* wait for the start of the next frame. */
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
} }
break; break;
default: default:
@@ -567,6 +562,13 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port)
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE; mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
break; break;
} }
#if PRINT_ENABLED_RECEIVE_DATA
if ((receive_state != MSTP_RECEIVE_STATE_IDLE) &&
(mstp_port->receive_state == MSTP_RECEIVE_STATE_IDLE))
{
fprintf(stderr,"\r\n");
}
#endif
return; return;
} }
@@ -663,7 +665,9 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port)
uint8_t next_this_station = 0; uint8_t next_this_station = 0;
uint8_t next_next_station = 0; uint8_t next_next_station = 0;
uint16_t my_timeout = 10, ns_timeout = 0; uint16_t my_timeout = 10, ns_timeout = 0;
#if PRINT_ENABLED_MASTER
static MSTP_MASTER_STATE master_state = MSTP_MASTER_STATE_INITIALIZE; static MSTP_MASTER_STATE master_state = MSTP_MASTER_STATE_INITIALIZE;
#endif
/* some calculations that several states need */ /* some calculations that several states need */
@@ -723,11 +727,12 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port)
else if (mstp_port->ReceivedValidFrame == true) { else if (mstp_port->ReceivedValidFrame == true) {
#if PRINT_ENABLED_MASTER #if PRINT_ENABLED_MASTER
fprintf(stderr, fprintf(stderr,
"MSTP: ReceivedValidFrame Src=%02X Dest=%02X DataLen=%u FC=%u Type=%s\r\n", "MSTP: ReceivedValidFrame Src=%02X Dest=%02X DataLen=%u FC=%u ST=%u Type=%s\r\n",
mstp_port->SourceAddress, mstp_port->SourceAddress,
mstp_port->DestinationAddress, mstp_port->DestinationAddress,
mstp_port->DataLength, mstp_port->DataLength,
mstp_port->FrameCount, mstp_port->FrameCount,
mstp_port->SilenceTimer,
mstp_frame_type_text(mstp_port->FrameType)); mstp_frame_type_text(mstp_port->FrameType));
#endif #endif
/* destined for me! */ /* destined for me! */
@@ -832,8 +837,8 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port)
/* In the WAIT_FOR_REPLY state, the node waits for */ /* In the WAIT_FOR_REPLY state, the node waits for */
/* a reply from another node. */ /* a reply from another node. */
case MSTP_MASTER_STATE_WAIT_FOR_REPLY: case MSTP_MASTER_STATE_WAIT_FOR_REPLY:
/* ReplyTimeout */
if (mstp_port->SilenceTimer >= Treply_timeout) { if (mstp_port->SilenceTimer >= Treply_timeout) {
/* ReplyTimeout */
/* assume that the request has failed */ /* assume that the request has failed */
mstp_port->FrameCount = mstp_port->Nmax_info_frames; mstp_port->FrameCount = mstp_port->Nmax_info_frames;
mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN; mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
@@ -841,67 +846,49 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port)
/* to the USE_TOKEN state. (Because of the length of the timeout, */ /* to the USE_TOKEN state. (Because of the length of the timeout, */
/* this transition will cause the token to be passed regardless */ /* this transition will cause the token to be passed regardless */
/* of the initial value of FrameCount.) */ /* of the initial value of FrameCount.) */
} } else {
/* InvalidFrame */ if (mstp_port->ReceivedInvalidFrame == true) {
else if ((mstp_port->SilenceTimer < Treply_timeout) && /* InvalidFrame */
(mstp_port->ReceivedInvalidFrame == true)) { /* error in frame reception */
/* error in frame reception */ mstp_port->ReceivedInvalidFrame = false;
mstp_port->ReceivedInvalidFrame = false; mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN; } else if (mstp_port->ReceivedValidFrame == true) {
} if (mstp_port->DestinationAddress == mstp_port->This_Station) {
/* ReceivedReply */ switch (mstp_port->TxFrameType)
/* or a proprietary type that indicates a reply */ {
else if ((mstp_port->SilenceTimer < Treply_timeout) && case FRAME_TYPE_REPLY_POSTPONED:
(mstp_port->ReceivedValidFrame == true) && /* ReceivedReplyPostponed */
(mstp_port->DestinationAddress == mstp_port->This_Station) && mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
((mstp_port->FrameType == FRAME_TYPE_TEST_RESPONSE) || break;
/*(mstp_port->FrameType == FRAME_TYPE_PROPRIETARY_0) || */ case FRAME_TYPE_TEST_RESPONSE:
(mstp_port->FrameType == mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY))) { break;
/* indicate successful reception to the higher layers */ case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY:
dlmstp_put_receive( /* ReceivedReply */
mstp_port->SourceAddress, /* source MS/TP address */ /* or a proprietary type that indicates a reply */
(uint8_t *) & mstp_port->InputBuffer[0], /* indicate successful reception to the higher layers */
mstp_port->DataLength); dlmstp_put_receive(
mstp_port->ReceivedValidFrame = false; mstp_port->SourceAddress, /* source MS/TP address */
mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN; (uint8_t *) & mstp_port->InputBuffer[0],
} mstp_port->DataLength);
/* ReceivedPostpone */ mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
else if ((mstp_port->SilenceTimer < Treply_timeout) && break;
(mstp_port->ReceivedValidFrame == true) && default:
(mstp_port->DestinationAddress == mstp_port->This_Station) && /* if proprietary frame was expected, you might
(mstp_port->FrameType == FRAME_TYPE_REPLY_POSTPONED)) { need to transition to DONE WITH TOKEN */
/* FIXME: then the reply to the message has been postponed until a later time. */ mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
/* So, what does this really mean? */ break;
mstp_port->ReceivedValidFrame = false; }
mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN; } else {
} /* ReceivedUnexpectedFrame */
/* ReceivedUnexpectedFrame */ /* an unexpected frame was received */
else if ((mstp_port->SilenceTimer < Treply_timeout) && /* This may indicate the presence of multiple tokens. */
(mstp_port->ReceivedValidFrame == true) && /* Synchronize with the network. */
(mstp_port->DestinationAddress != mstp_port->This_Station)) /* This action drops the token. */
/*the expected reply should not be broadcast) */ mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
{ }
/* an unexpected frame was received */ mstp_port->ReceivedValidFrame = false;
/* This may indicate the presence of multiple tokens. */ }
mstp_port->ReceivedValidFrame = false;
/* Synchronize with the network. */
/* This action drops the token. */
mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
}
/* ReceivedUnexpectedFrame */
else if ((mstp_port->SilenceTimer < Treply_timeout) &&
(mstp_port->ReceivedValidFrame == true) &&
((mstp_port->FrameType == FRAME_TYPE_TEST_RESPONSE) ||
/*(mstp_port->FrameType == FRAME_TYPE_PROPRIETARY_0) || */
(mstp_port->FrameType ==
FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY))) {
/* An unexpected frame was received. */
/* This may indicate the presence of multiple tokens. */
mstp_port->ReceivedValidFrame = false;
/* Synchronize with the network. */
/* This action drops the token. */
mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
} }
break; break;
/* The DONE_WITH_TOKEN state either sends another data frame, */ /* The DONE_WITH_TOKEN state either sends another data frame, */
@@ -985,41 +972,40 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port)
/* The PASS_TOKEN state listens for a successor to begin using */ /* The PASS_TOKEN state listens for a successor to begin using */
/* the token that this node has just attempted to pass. */ /* the token that this node has just attempted to pass. */
case MSTP_MASTER_STATE_PASS_TOKEN: case MSTP_MASTER_STATE_PASS_TOKEN:
/* SawTokenUser */ if (mstp_port->SilenceTimer < Tusage_timeout) {
if ((mstp_port->SilenceTimer < Tusage_timeout) && if (mstp_port->EventCount > Nmin_octets) {
(mstp_port->EventCount > Nmin_octets)) { /* SawTokenUser */
/* Assume that a frame has been sent by the new token user. */ /* Assume that a frame has been sent by the new token user. */
/* Enter the IDLE state to process the frame. */ /* Enter the IDLE state to process the frame. */
mstp_port->master_state = MSTP_MASTER_STATE_IDLE; mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
} }
/* RetrySendToken */ } else {
else if ((mstp_port->SilenceTimer >= Tusage_timeout) && if (mstp_port->RetryCount < Nretry_token) {
(mstp_port->RetryCount < Nretry_token)) { /* RetrySendToken */
mstp_port->RetryCount++; mstp_port->RetryCount++;
/* Transmit a Token frame to NS */ /* Transmit a Token frame to NS */
MSTP_Create_And_Send_Frame(mstp_port, MSTP_Create_And_Send_Frame(mstp_port,
FRAME_TYPE_TOKEN, FRAME_TYPE_TOKEN,
mstp_port->Next_Station, mstp_port->This_Station, NULL, 0); mstp_port->Next_Station, mstp_port->This_Station, NULL, 0);
mstp_port->EventCount = 0; mstp_port->EventCount = 0;
/* re-enter the current state to listen for NS */ /* re-enter the current state to listen for NS */
/* to begin using the token. */ /* to begin using the token. */
} } else {
/* FindNewSuccessor */ /* FindNewSuccessor */
else if ((mstp_port->SilenceTimer >= Tusage_timeout) && /* Assume that NS has failed. */
(mstp_port->RetryCount >= Nretry_token)) { mstp_port->Poll_Station = next_next_station;
/* Assume that NS has failed. */ /* Transmit a Poll For Master frame to PS. */
mstp_port->Poll_Station = next_next_station; MSTP_Create_And_Send_Frame(mstp_port,
/* Transmit a Poll For Master frame to PS. */ FRAME_TYPE_POLL_FOR_MASTER,
MSTP_Create_And_Send_Frame(mstp_port, mstp_port->Poll_Station, mstp_port->This_Station, NULL, 0);
FRAME_TYPE_POLL_FOR_MASTER, /* no known successor node */
mstp_port->Poll_Station, mstp_port->This_Station, NULL, 0); mstp_port->Next_Station = mstp_port->This_Station;
/* no known successor node */ mstp_port->RetryCount = 0;
mstp_port->Next_Station = mstp_port->This_Station; mstp_port->TokenCount = 0;
mstp_port->RetryCount = 0; /* mstp_port->EventCount = 0; removed in Addendum 135-2004d-8 */
mstp_port->TokenCount = 0; /* find a new successor to TS */
/* mstp_port->EventCount = 0; removed in Addendum 135-2004d-8 */ mstp_port->master_state = MSTP_MASTER_STATE_POLL_FOR_MASTER;
/* find a new successor to TS */ }
mstp_port->master_state = MSTP_MASTER_STATE_POLL_FOR_MASTER;
} }
break; break;
/* The NO_TOKEN state is entered if mstp_port->SilenceTimer becomes greater */ /* The NO_TOKEN state is entered if mstp_port->SilenceTimer becomes greater */
@@ -1028,119 +1014,108 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port)
/* whether or not this node may create a token. */ /* whether or not this node may create a token. */
case MSTP_MASTER_STATE_NO_TOKEN: case MSTP_MASTER_STATE_NO_TOKEN:
my_timeout = Tno_token + (Tslot * mstp_port->This_Station); my_timeout = Tno_token + (Tslot * mstp_port->This_Station);
ns_timeout = Tno_token + (Tslot * (mstp_port->This_Station + 1)); if (mstp_port->SilenceTimer < my_timeout) {
/* SawFrame */ if (mstp_port->EventCount > Nmin_octets) {
if ((mstp_port->SilenceTimer < my_timeout) && /* SawFrame */
(mstp_port->EventCount > Nmin_octets)) { /* Some other node exists at a lower address. */
/* Some other node exists at a lower address. */ /* Enter the IDLE state to receive and process the incoming frame. */
/* Enter the IDLE state to receive and process the incoming frame. */ mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
mstp_port->master_state = MSTP_MASTER_STATE_IDLE; }
} }
/* GenerateToken */ else {
else if ((mstp_port->SilenceTimer >= my_timeout) && ns_timeout = Tno_token + (Tslot * (mstp_port->This_Station + 1));
(mstp_port->SilenceTimer < ns_timeout)) { if (mstp_port->SilenceTimer < ns_timeout) {
/* Assume that this node is the lowest numerical address */ /* GenerateToken */
/* on the network and is empowered to create a token. */ /* Assume that this node is the lowest numerical address */
mstp_port->Poll_Station = next_this_station; /* on the network and is empowered to create a token. */
/* Transmit a Poll For Master frame to PS. */ mstp_port->Poll_Station = next_this_station;
MSTP_Create_And_Send_Frame(mstp_port, /* Transmit a Poll For Master frame to PS. */
FRAME_TYPE_POLL_FOR_MASTER, MSTP_Create_And_Send_Frame(mstp_port,
mstp_port->Poll_Station, mstp_port->This_Station, NULL, 0); FRAME_TYPE_POLL_FOR_MASTER,
/* indicate that the next station is unknown */ mstp_port->Poll_Station, mstp_port->This_Station, NULL, 0);
mstp_port->Next_Station = mstp_port->This_Station; /* indicate that the next station is unknown */
mstp_port->RetryCount = 0; mstp_port->Next_Station = mstp_port->This_Station;
mstp_port->TokenCount = 0; mstp_port->RetryCount = 0;
/* mstp_port->EventCount = 0; removed Addendum 135-2004d-8 */ mstp_port->TokenCount = 0;
/* enter the POLL_FOR_MASTER state to find a new successor to TS. */ /* mstp_port->EventCount = 0; removed Addendum 135-2004d-8 */
mstp_port->master_state = MSTP_MASTER_STATE_POLL_FOR_MASTER; /* enter the POLL_FOR_MASTER state to find a new successor to TS. */
mstp_port->master_state = MSTP_MASTER_STATE_POLL_FOR_MASTER;
}
} }
break; break;
/* In the POLL_FOR_MASTER state, the node listens for a reply to */ /* In the POLL_FOR_MASTER state, the node listens for a reply to */
/* a previously sent Poll For Master frame in order to find */ /* a previously sent Poll For Master frame in order to find */
/* a successor node. */ /* a successor node. */
case MSTP_MASTER_STATE_POLL_FOR_MASTER: case MSTP_MASTER_STATE_POLL_FOR_MASTER:
/* ReceivedReplyToPFM */ if (mstp_port->ReceivedValidFrame == true)
if ((mstp_port->ReceivedValidFrame == true) &&
(mstp_port->DestinationAddress == mstp_port->This_Station) &&
(mstp_port->FrameType == FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER))
{ {
mstp_port->SoleMaster = false; if ((mstp_port->DestinationAddress == mstp_port->This_Station) &&
mstp_port->Next_Station = mstp_port->SourceAddress; (mstp_port->FrameType == FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER)) {
mstp_port->EventCount = 0; /* ReceivedReplyToPFM */
/* Transmit a Token frame to NS */ mstp_port->SoleMaster = false;
MSTP_Create_And_Send_Frame(mstp_port, mstp_port->Next_Station = mstp_port->SourceAddress;
FRAME_TYPE_TOKEN, mstp_port->EventCount = 0;
mstp_port->Next_Station, mstp_port->This_Station, NULL, 0); /* Transmit a Token frame to NS */
mstp_port->Poll_Station = mstp_port->This_Station; MSTP_Create_And_Send_Frame(mstp_port,
mstp_port->TokenCount = 0; FRAME_TYPE_TOKEN,
mstp_port->RetryCount = 0; mstp_port->Next_Station, mstp_port->This_Station, NULL, 0);
mstp_port->Poll_Station = mstp_port->This_Station;
mstp_port->TokenCount = 0;
mstp_port->RetryCount = 0;
mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN;
}
else {
/* ReceivedUnexpectedFrame */
/* An unexpected frame was received. */
/* This may indicate the presence of multiple tokens. */
/* enter the IDLE state to synchronize with the network. */
/* This action drops the token. */
mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
}
mstp_port->ReceivedValidFrame = false; mstp_port->ReceivedValidFrame = false;
mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN;
} }
/* ReceivedUnexpectedFrame */ else if ((mstp_port->SilenceTimer >= Tusage_timeout) ||
else if ((mstp_port->ReceivedValidFrame == true) && (mstp_port->ReceivedInvalidFrame == true)) {
((mstp_port->DestinationAddress != mstp_port->This_Station) || if (mstp_port->SoleMaster == true) {
(mstp_port->FrameType != /* SoleMaster */
FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER))) { /* There was no valid reply to the periodic poll */
/* An unexpected frame was received. */ /* by the sole known master for other masters. */
/* This may indicate the presence of multiple tokens. */ mstp_port->FrameCount = 0;
mstp_port->ReceivedValidFrame = false; /* mstp_port->TokenCount++; removed in 2004 */
/* enter the IDLE state to synchronize with the network. */ mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN;
/* This action drops the token. */ } else {
mstp_port->master_state = MSTP_MASTER_STATE_IDLE; if (mstp_port->Next_Station != mstp_port->This_Station) {
} /* DoneWithPFM */
/* SoleMaster */ /* There was no valid reply to the maintenance */
else if ((mstp_port->SoleMaster == true) && /* poll for a master at address PS. */
((mstp_port->SilenceTimer >= Tusage_timeout) || mstp_port->EventCount = 0;
(mstp_port->ReceivedInvalidFrame == true))) { /* transmit a Token frame to NS */
/* There was no valid reply to the periodic poll */ MSTP_Create_And_Send_Frame(mstp_port,
/* by the sole known master for other masters. */ FRAME_TYPE_TOKEN,
mstp_port->FrameCount = 0; mstp_port->Next_Station, mstp_port->This_Station, NULL, 0);
/* mstp_port->TokenCount++; removed in 2004 */ mstp_port->RetryCount = 0;
mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN;
} else {
if (next_poll_station != mstp_port->This_Station)
{
/* SendNextPFM */
mstp_port->Poll_Station = next_poll_station;
/* Transmit a Poll For Master frame to PS. */
MSTP_Create_And_Send_Frame(mstp_port,
FRAME_TYPE_POLL_FOR_MASTER,
mstp_port->Poll_Station, mstp_port->This_Station, NULL, 0);
mstp_port->RetryCount = 0;
/* Re-enter the current state. */
} else {
/* DeclareSoleMaster */
/* to indicate that this station is the only master */
mstp_port->SoleMaster = true;
mstp_port->FrameCount = 0;
mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN;
}
}
}
mstp_port->ReceivedInvalidFrame = false; mstp_port->ReceivedInvalidFrame = false;
mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN;
}
/* DoneWithPFM */
else if ((mstp_port->SoleMaster == false) &&
(mstp_port->Next_Station != mstp_port->This_Station) &&
((mstp_port->SilenceTimer >= Tusage_timeout) ||
(mstp_port->ReceivedInvalidFrame == true))) {
/* There was no valid reply to the maintenance */
/* poll for a master at address PS. */
mstp_port->EventCount = 0;
/* transmit a Token frame to NS */
MSTP_Create_And_Send_Frame(mstp_port,
FRAME_TYPE_TOKEN,
mstp_port->Next_Station, mstp_port->This_Station, NULL, 0);
mstp_port->RetryCount = 0;
mstp_port->ReceivedInvalidFrame = false;
mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN;
}
/* SendNextPFM */
else if ((mstp_port->SoleMaster == false) &&
(mstp_port->Next_Station == mstp_port->This_Station) && /* no known successor node */
(next_poll_station != mstp_port->This_Station) &&
((mstp_port->SilenceTimer >= Tusage_timeout)
|| (mstp_port->ReceivedInvalidFrame == true))) {
mstp_port->Poll_Station = next_poll_station;
/* Transmit a Poll For Master frame to PS. */
MSTP_Create_And_Send_Frame(mstp_port,
FRAME_TYPE_POLL_FOR_MASTER,
mstp_port->Poll_Station, mstp_port->This_Station, NULL, 0);
mstp_port->RetryCount = 0;
mstp_port->ReceivedInvalidFrame = false;
/* Re-enter the current state. */
}
/* DeclareSoleMaster */
else if ((mstp_port->SoleMaster == false) && (mstp_port->Next_Station == mstp_port->This_Station) && /* no known successor node */
(next_poll_station == mstp_port->This_Station)
&& ((mstp_port->SilenceTimer >= Tusage_timeout)
|| (mstp_port->ReceivedInvalidFrame == true))) {
/* to indicate that this station is the only master */
mstp_port->SoleMaster = true;
mstp_port->FrameCount = 0;
mstp_port->ReceivedInvalidFrame = false;
mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN;
} }
break; break;
/* The ANSWER_DATA_REQUEST state is entered when a */ /* The ANSWER_DATA_REQUEST state is entered when a */
-1
View File
@@ -75,7 +75,6 @@ typedef enum {
MSTP_RECEIVE_STATE_HEADER, MSTP_RECEIVE_STATE_HEADER,
MSTP_RECEIVE_STATE_HEADER_CRC, MSTP_RECEIVE_STATE_HEADER_CRC,
MSTP_RECEIVE_STATE_DATA, MSTP_RECEIVE_STATE_DATA,
MSTP_RECEIVE_STATE_DATA_CRC
} MSTP_RECEIVE_STATE; } MSTP_RECEIVE_STATE;
/* master node FSM states */ /* master node FSM states */
+8 -2
View File
@@ -109,9 +109,15 @@ int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */
} }
void dlmstp_task(void) void dlmstp_task(void)
{ {
RS485_Check_UART_Data(&MSTP_Port); RS485_Check_UART_Data(&MSTP_Port);
MSTP_Receive_Frame_FSM(&MSTP_Port); /* only do receive state machine while we don't have a frame */
if ((MSTP_Port.ReceivedValidFrame == false) &&
(MSTP_Port.ReceivedInvalidFrame == false))
{
MSTP_Receive_Frame_FSM(&MSTP_Port);
}
/* only do master state machine while rx is idle */
if (MSTP_Port.receive_state == MSTP_RECEIVE_STATE_IDLE) if (MSTP_Port.receive_state == MSTP_RECEIVE_STATE_IDLE)
MSTP_Master_Node_FSM(&MSTP_Port); MSTP_Master_Node_FSM(&MSTP_Port);
} }
+3 -5
View File
@@ -74,16 +74,14 @@ static void Init_Service_Handlers(void)
void millisecond_task(void) void millisecond_task(void)
{ {
Time ticks = 0; /* task cycle */ Time ticks = 0; /* task cycle */
const int UPDATE_CYCLE = 5; /* task cycle in mS */
int i = 0; /* loop counter */ int i = 0; /* loop counter */
ticks = RTKGetTime() + MilliSecsToTicks(UPDATE_CYCLE); ticks = RTKGetTime() + MilliSecsToTicks(1);
while (TRUE) while (TRUE)
{ {
RTKDelayUntil(ticks); RTKDelayUntil(ticks);
for (i = 0; i < UPDATE_CYCLE; i++) dlmstp_millisecond_timer();
dlmstp_millisecond_timer(); ticks += MilliSecsToTicks(1);
ticks += MilliSecsToTicks(UPDATE_CYCLE);
} }
} }
+14 -7
View File
@@ -22,7 +22,7 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* *
*********************************************************************/ *********************************************************************/
#define PRINT_ENABLED_RS485 0 #define PRINT_ENABLED_RS485 1
#include <stdint.h> #include <stdint.h>
#include <rtkernel.h> #include <rtkernel.h>
@@ -132,7 +132,6 @@ void RS485_Send_Frame(volatile struct mstp_port_struct_t *mstp_port, /* port
{ /* number of bytes of data (up to 501) */ { /* number of bytes of data (up to 501) */
bool status = true; /* return value */ bool status = true; /* return value */
(void) mstp_port;
RS485_TRANSMIT_ENABLE(RS485_Port); RS485_TRANSMIT_ENABLE(RS485_Port);
SendBlock(RS485_Port, (char *) buffer, nbytes); SendBlock(RS485_Port, (char *) buffer, nbytes);
/* need to wait at least 9600 baud * 512 bytes = 54mS */ /* need to wait at least 9600 baud * 512 bytes = 54mS */
@@ -140,6 +139,7 @@ void RS485_Send_Frame(volatile struct mstp_port_struct_t *mstp_port, /* port
while (!(LineStatus(RS485_Port) & TX_SHIFT_EMPTY)) while (!(LineStatus(RS485_Port) & TX_SHIFT_EMPTY))
RTKScheduler(); RTKScheduler();
RS485_RECEIVE_ENABLE(RS485_Port); RS485_RECEIVE_ENABLE(RS485_Port);
mstp_port->SilenceTimer = 0;
#if PRINT_ENABLED_RS485 #if PRINT_ENABLED_RS485
{ {
int i = 0; int i = 0;
@@ -162,18 +162,22 @@ void RS485_Send_Frame(volatile struct mstp_port_struct_t *mstp_port, /* port
void RS485_Check_UART_Data(volatile struct mstp_port_struct_t *mstp_port) void RS485_Check_UART_Data(volatile struct mstp_port_struct_t *mstp_port)
{ /* port specific data */ { /* port specific data */
COMData com_data = 0; /* byte from COM driver */ COMData com_data = 0; /* byte from COM driver */
unsigned timeout = 10; /* milliseconds to wait for a character */ unsigned timeout = 1; /* milliseconds to wait for a character */
Duration ticks; /* duration to wait for data */ static Duration ticks = 0; /* duration to wait for data */
if (!ticks)
{
ticks = MilliSecsToTicks(timeout);
if (!ticks)
ticks = 1;
}
if (mstp_port->ReceiveError) { if (mstp_port->ReceiveError) {
/* wait for state machine to clear this */ /* wait for state machine to clear this */
RTKDelay(ticks);
} }
/* wait for state machine to read from the DataRegister */ /* wait for state machine to read from the DataRegister */
else if (!mstp_port->DataAvailable) { else if (!mstp_port->DataAvailable) {
/* check for data */ /* check for data */
ticks = MilliSecsToTicks(timeout);
if (!ticks)
ticks = 1;
if (RTKGetTimed(ReceiveBuffer[RS485_Port], &com_data, ticks)) { if (RTKGetTimed(ReceiveBuffer[RS485_Port], &com_data, ticks)) {
/* if error, */ /* if error, */
if (com_data & (COM_OVERRUN << 8)) if (com_data & (COM_OVERRUN << 8))
@@ -186,4 +190,7 @@ void RS485_Check_UART_Data(volatile struct mstp_port_struct_t *mstp_port)
} }
} }
} }
else
RTKDelay(ticks);
} }