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:
+205
-230
@@ -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 */
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -111,7 +111,13 @@ 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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user