From a8c36762db96218ed3420c3521bbc4836e570668 Mon Sep 17 00:00:00 2001 From: skarg Date: Mon, 21 Jul 2008 16:05:55 +0000 Subject: [PATCH] Converted the MS/TP FSM src module to use the debug printf. --- bacnet-stack/ports/win32/rx_fsm.cbp | 48 +- bacnet-stack/src/mstp.c | 948 +++++++++++++++------------- 2 files changed, 528 insertions(+), 468 deletions(-) diff --git a/bacnet-stack/ports/win32/rx_fsm.cbp b/bacnet-stack/ports/win32/rx_fsm.cbp index 1094a23b..9be05fdc 100644 --- a/bacnet-stack/ports/win32/rx_fsm.cbp +++ b/bacnet-stack/ports/win32/rx_fsm.cbp @@ -3,11 +3,12 @@ diff --git a/bacnet-stack/src/mstp.c b/bacnet-stack/src/mstp.c index 5ea8c02a..550b70de 100644 --- a/bacnet-stack/src/mstp.c +++ b/bacnet-stack/src/mstp.c @@ -52,24 +52,41 @@ #include "mstp.h" #include "crc.h" #include "rs485.h" -#if PRINT_ENABLED #include "mstptext.h" +#if !defined(DEBUG_ENABLED) +#define DEBUG_ENABLED 1 +#endif +#include "debug.h" + +#if PRINT_ENABLED +#undef PRINT_ENABLED_RECEIVE +#define PRINT_ENABLED_RECEIVE_DATA +#define PRINT_ENABLED_RECEIVE_ERRORS +#undef PRINT_ENABLED_MASTER #endif -#if !defined(PRINT_ENABLED_RECEIVE) -#define PRINT_ENABLED_RECEIVE 0 +#if defined(PRINT_ENABLED_RECEIVE) +#define printf_receive debug_printf +#else +#define printf_receive (void) #endif -#if !defined(PRINT_ENABLED_RECEIVE_DATA) -#define PRINT_ENABLED_RECEIVE_DATA 0 +#if defined(PRINT_ENABLED_RECEIVE_DATA) +#define printf_receive_data debug_printf +#else +#define printf_receive_data (void) #endif -#if !defined(PRINT_ENABLED_RECEIVE_ERRORS) -#define PRINT_ENABLED_RECEIVE_ERRORS 0 +#if defined(PRINT_ENABLED_RECEIVE_ERRORS) +#define printf_receive_error debug_printf +#else +#define printf_receive_error (void) #endif -#if !defined(PRINT_ENABLED_MASTER) -#define PRINT_ENABLED_MASTER 0 +#if defined(PRINT_ENABLED_MASTER) +#define printf_master debug_printf +#else +#define printf_master (void) #endif /* MS/TP Frame Format */ @@ -220,20 +237,16 @@ void MSTP_Create_And_Send_Frame( void MSTP_Receive_Frame_FSM( volatile struct mstp_port_struct_t *mstp_port) { -#if PRINT_ENABLED_RECEIVE_DATA static MSTP_RECEIVE_STATE receive_state = MSTP_RECEIVE_STATE_IDLE; -#endif -#if PRINT_ENABLED_RECEIVE - fprintf(stderr, + printf_receive( "MSTP Rx: State=%s Data=%02X hCRC=%02X Index=%u EC=%u DateLen=%u Silence=%u\n", mstptext_receive_state(mstp_port->receive_state), mstp_port->DataRegister, mstp_port->HeaderCRC, mstp_port->Index, mstp_port->EventCount, mstp_port->DataLength, - mstp_port->SilenceTimer(); -#endif - switch (mstp_port->receive_state) { + mstp_port->SilenceTimer()); + switch (mstp_port->receive_state) { /* In the IDLE state, the node waits for the beginning of a frame. */ -case MSTP_RECEIVE_STATE_IDLE: + case MSTP_RECEIVE_STATE_IDLE: /* EatAnError */ if (mstp_port->ReceiveError == true) { mstp_port->ReceiveError = false; @@ -243,14 +256,12 @@ case MSTP_RECEIVE_STATE_IDLE: } else if (mstp_port->DataAvailable == true) { -#if PRINT_ENABLED_RECEIVE_DATA #if (defined(_WIN32) && defined(TEST_DLMSTP)) extern uint32_t timestamp_ms(void); - fprintf(stderr, "MSTP Rx %03u: %02X ", (unsigned) timestamp_ms(), + printf_receive_data("MSTP Rx %03u: %02X ", (unsigned) timestamp_ms(), mstp_port->DataRegister); #else - fprintf(stderr, "MSTP Rx: %02X ", mstp_port->DataRegister); -#endif + printf_receive_data("MSTP Rx: %02X ", mstp_port->DataRegister); #endif /* Preamble1 */ if (mstp_port->DataRegister == 0x55) { @@ -258,16 +269,14 @@ case MSTP_RECEIVE_STATE_IDLE: mstp_port->receive_state = MSTP_RECEIVE_STATE_PREAMBLE;} /* EatAnOctet */ else { -#if PRINT_ENABLED_RECEIVE_DATA - fprintf(stderr, "\n"); -#endif + printf_receive_data("\n"); /* wait for the start of a frame. */ } mstp_port->DataAvailable = false; mstp_port->SilenceTimerReset(); INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount);} break; /* In the PREAMBLE state, the node waits for the second octet of the preamble. */ -case MSTP_RECEIVE_STATE_PREAMBLE: + case MSTP_RECEIVE_STATE_PREAMBLE: /* Timeout */ if (mstp_port->SilenceTimer() > Tframe_abort) { /* a correct preamble has not been received */ @@ -282,9 +291,7 @@ case MSTP_RECEIVE_STATE_PREAMBLE: mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;} else if (mstp_port->DataAvailable == true) { -#if PRINT_ENABLED_RECEIVE_DATA - fprintf(stderr, "%02X ", mstp_port->DataRegister); -#endif + printf_receive_data("%02X ", mstp_port->DataRegister); /* Preamble2 */ if (mstp_port->DataRegister == 0xFF) { mstp_port->Index = 0; mstp_port->HeaderCRC = 0xFF; @@ -302,37 +309,31 @@ case MSTP_RECEIVE_STATE_PREAMBLE: mstp_port->DataAvailable = false; mstp_port->SilenceTimerReset(); INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount);} break; -/* In the HEADER state, the node waits for the fixed message header. */ -case MSTP_RECEIVE_STATE_HEADER: + /* In the HEADER state, the node waits for the fixed message header. */ + case MSTP_RECEIVE_STATE_HEADER: /* Timeout */ if (mstp_port->SilenceTimer() > Tframe_abort) { /* indicate that an error has occurred during the reception of a frame */ mstp_port->ReceivedInvalidFrame = true; /* wait for the start of a frame. */ mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE; -#if PRINT_ENABLED_RECEIVE_ERRORS - fprintf(stderr, "MSTP: Rx Header: SilenceTimer %d > %d\n", + printf_receive_error("MSTP: Rx Header: SilenceTimer %d > %d\n", mstp_port->SilenceTimer(), Tframe_abort); -#endif } /* Error */ else if (mstp_port->ReceiveError == true) { mstp_port->ReceiveError = false; mstp_port->SilenceTimerReset(); INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount); -/* indicate that an error has occurred during the reception of a frame */ + /* indicate that an error has occurred during the reception of a frame */ mstp_port->ReceivedInvalidFrame = true; -#if PRINT_ENABLED_RECEIVE_ERRORS - fprintf(stderr, "MSTP: Rx Header: ReceiveError\n"); -#endif -/* wait for the start of a frame. */ + printf_receive_error("MSTP: Rx Header: ReceiveError\n"); + /* wait for the start of a frame. */ mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;} else if (mstp_port->DataAvailable == true) { -#if PRINT_ENABLED_RECEIVE_DATA - fprintf(stderr, "%02X ", mstp_port->DataRegister); -#endif -/* FrameType */ + printf_receive_data("%02X ", mstp_port->DataRegister); + /* FrameType */ if (mstp_port->Index == 0) { mstp_port->HeaderCRC = CRC_Calc_Header(mstp_port->DataRegister, @@ -373,18 +374,16 @@ case MSTP_RECEIVE_STATE_HEADER: mstp_port->HeaderCRC = CRC_Calc_Header(mstp_port->DataRegister, mstp_port->HeaderCRC); mstp_port->HeaderCRCActual = mstp_port->DataRegister; -/* don't wait for next state - do it here */ -/* MSTP_RECEIVE_STATE_HEADER_CRC */ + /* don't wait for next state - do it here */ + /* MSTP_RECEIVE_STATE_HEADER_CRC */ if (mstp_port->HeaderCRC != 0x55) { /* BadCRC */ /* indicate that an error has occurred during the reception of a frame */ mstp_port->ReceivedInvalidFrame = true; -#if PRINT_ENABLED_RECEIVE_ERRORS - fprintf(stderr, "MSTP: Rx Header: BadCRC [%02X]\n", + printf_receive_error("MSTP: Rx Header: BadCRC [%02X]\n", mstp_port->DataRegister); -#endif -/* wait for the start of the next frame. */ + /* wait for the start of the next frame. */ mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;} else { /* Note: proposed change to BACnet MSTP state machine! @@ -396,25 +395,21 @@ case MSTP_RECEIVE_STATE_HEADER: (mstp_port->DataLength <= mstp_port->InputBufferSize)) { /* Data - decode anyway to keep from false */ mstp_port->Index = 0; mstp_port->DataCRC = 0xFFFF; -/* receive the data portion of the frame. */ + /* receive the data portion of the frame. */ mstp_port->receive_state = MSTP_RECEIVE_STATE_DATA;} else { /* FrameTooLong */ if (mstp_port->DataLength) { -#if PRINT_ENABLED_RECEIVE_ERRORS - fprintf(stderr, "MSTP: Rx Header: FrameTooLong %d\n", + printf_receive_error("MSTP: Rx Header: FrameTooLong %d\n", mstp_port->DataLength); -#endif -/* indicate that a frame with an illegal or */ -/* unacceptable data length has been received */ + /* indicate that a frame with an illegal or */ + /* unacceptable data length has been received */ mstp_port->ReceivedInvalidFrame = true;} /* NoData */ else if (mstp_port->DataLength == 0) { -#if PRINT_ENABLED_RECEIVE_DATA - fprintf(stderr, "%s", + printf_receive_data("%s", mstptext_frame_type(mstp_port->FrameType)); -#endif if ((mstp_port->DestinationAddress == mstp_port->This_Station) || (mstp_port->DestinationAddress == @@ -434,143 +429,134 @@ case MSTP_RECEIVE_STATE_HEADER: /* not per MS/TP standard, but it is a case not covered */ else { mstp_port->ReceiveError = false; -/* indicate that an error has occurred during */ -/* the reception of a frame */ + /* indicate that an error has occurred during */ + /* the reception of a frame */ mstp_port->ReceivedInvalidFrame = true; -#if PRINT_ENABLED_RECEIVE_ERRORS - fprintf(stderr, "MSTP: Rx Data: BadIndex %d\n", + printf_receive_error("MSTP: Rx Data: BadIndex %d\n", mstp_port->Index); -#endif -/* wait for the start of a frame. */ - mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;} - mstp_port->SilenceTimerReset(); - INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount); - mstp_port->DataAvailable = false;} + /* wait for the start of a frame. */ + mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;} + mstp_port->SilenceTimerReset(); + INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount); + mstp_port->DataAvailable = false; + } break; -/* In the HEADER_CRC state, the node validates the CRC on the fixed */ -/* message header. */ -case MSTP_RECEIVE_STATE_HEADER_CRC: + /* In the HEADER_CRC state, the node validates the CRC on the fixed */ + /* message header. */ + case MSTP_RECEIVE_STATE_HEADER_CRC: /* note: we should never get to this state since we shortcut it earlier in the state machine, and never set this state */ - mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE; break; -/* In the DATA state, the node waits for the data portion of a frame. */ -case MSTP_RECEIVE_STATE_DATA: + mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE; + break; + /* In the DATA state, the node waits for the data portion of a frame. */ + case MSTP_RECEIVE_STATE_DATA: /* Timeout */ if (mstp_port->SilenceTimer() > Tframe_abort) { /* indicate that an error has occurred during the reception of a frame */ mstp_port->ReceivedInvalidFrame = true; -#if PRINT_ENABLED_RECEIVE_ERRORS - fprintf(stderr, "MSTP: Rx Data: SilenceTimer %d > %d\n", + printf_receive_error("MSTP: Rx Data: SilenceTimer %d > %d\n", mstp_port->SilenceTimer(), Tframe_abort); -#endif -/* wait for the start of the next frame. */ + /* wait for the start of the next frame. */ mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;} /* Error */ - else - if (mstp_port->ReceiveError == true) { - mstp_port->ReceiveError = false; mstp_port->SilenceTimerReset(); -/* indicate that an error has occurred during the reception of a frame */ - mstp_port->ReceivedInvalidFrame = true; -#if PRINT_ENABLED_RECEIVE_ERRORS - fprintf(stderr, "MSTP: Rx Data: ReceiveError\n"); -#endif -/* wait for the start of the next frame. */ - mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;} - else - if (mstp_port->DataAvailable == true) { -#if PRINT_ENABLED_RECEIVE_DATA - fprintf(stderr, "%02X ", mstp_port->DataRegister); -#endif -/* DataOctet */ - if (mstp_port->Index < mstp_port->DataLength) { - mstp_port->DataCRC = - CRC_Calc_Data(mstp_port->DataRegister, mstp_port->DataCRC); - mstp_port->InputBuffer[mstp_port->Index] = - mstp_port->DataRegister; mstp_port->Index++; - mstp_port->receive_state = MSTP_RECEIVE_STATE_DATA;} - /* CRC1 */ - else - if (mstp_port->Index == mstp_port->DataLength) { - mstp_port->DataCRC = - CRC_Calc_Data(mstp_port->DataRegister, mstp_port->DataCRC); - mstp_port->DataCRCActualMSB = mstp_port->DataRegister; - mstp_port->Index++; - mstp_port->receive_state = MSTP_RECEIVE_STATE_DATA;} - /* CRC2 */ - else - if (mstp_port->Index == (mstp_port->DataLength + 1)) { - mstp_port->DataCRC = - CRC_Calc_Data(mstp_port->DataRegister, mstp_port->DataCRC); - mstp_port->DataCRCActualLSB = mstp_port->DataRegister; -#if PRINT_ENABLED_RECEIVE_DATA - fprintf(stderr, "%s", mstptext_frame_type(mstp_port->FrameType)); -#endif -/* STATE DATA CRC - no need for new state */ -/* indicate the complete reception of a valid frame */ - if (mstp_port->DataCRC == 0xF0B8) { - if ((mstp_port->DestinationAddress == mstp_port->This_Station) - || (mstp_port->DestinationAddress == - MSTP_BROADCAST_ADDRESS) - || (mstp_port->Lurking)) { - /* ForUs */ - /* indicate that a frame with no data has been received */ - mstp_port->ReceivedValidFrame = true;} - else { - /* NotForUs - drop */ - } - } - else { + else if (mstp_port->ReceiveError == true) { + mstp_port->ReceiveError = false; mstp_port->SilenceTimerReset(); + /* indicate that an error has occurred during the reception of a frame */ mstp_port->ReceivedInvalidFrame = true; -#if PRINT_ENABLED_RECEIVE_ERRORS - fprintf(stderr, "MSTP: Rx Data: BadCRC [%02X]\n", - mstp_port->DataRegister); -#endif + printf_receive_error("MSTP: Rx Data: ReceiveError\n"); + /* wait for the start of the next frame. */ + mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE; + } else if (mstp_port->DataAvailable == true) { + printf_receive_data("%02X ", mstp_port->DataRegister); + if (mstp_port->Index < mstp_port->DataLength) { + /* DataOctet */ + mstp_port->DataCRC = + CRC_Calc_Data(mstp_port->DataRegister, mstp_port->DataCRC); + mstp_port->InputBuffer[mstp_port->Index] = + mstp_port->DataRegister; mstp_port->Index++; + mstp_port->receive_state = MSTP_RECEIVE_STATE_DATA; + } else if (mstp_port->Index == mstp_port->DataLength) { + /* CRC1 */ + mstp_port->DataCRC = + CRC_Calc_Data(mstp_port->DataRegister, mstp_port->DataCRC); + mstp_port->DataCRCActualMSB = mstp_port->DataRegister; + mstp_port->Index++; + mstp_port->receive_state = MSTP_RECEIVE_STATE_DATA; + } else if (mstp_port->Index == (mstp_port->DataLength + 1)) { + /* CRC2 */ + mstp_port->DataCRC = + CRC_Calc_Data(mstp_port->DataRegister, mstp_port->DataCRC); + mstp_port->DataCRCActualLSB = mstp_port->DataRegister; + printf_receive_data("%s", mstptext_frame_type(mstp_port->FrameType)); + /* STATE DATA CRC - no need for new state */ + /* indicate the complete reception of a valid frame */ + if (mstp_port->DataCRC == 0xF0B8) { + if ((mstp_port->DestinationAddress == mstp_port->This_Station) + || (mstp_port->DestinationAddress == + MSTP_BROADCAST_ADDRESS) + || (mstp_port->Lurking)) { + /* ForUs */ + /* indicate that a frame with no data has been received */ + mstp_port->ReceivedValidFrame = true; + } else { + /* NotForUs - drop */ + } + } else { + mstp_port->ReceivedInvalidFrame = true; + printf_receive_error("MSTP: Rx Data: BadCRC [%02X]\n", + mstp_port->DataRegister); + } + mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE; + } + mstp_port->DataAvailable = false; + mstp_port->SilenceTimerReset(); } - mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;} - mstp_port->DataAvailable = false; mstp_port->SilenceTimerReset();} -break; default: + break; + default: /* shouldn't get here - but if we do... */ - mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE; break;} -#if PRINT_ENABLED_RECEIVE_DATA - if ((receive_state != MSTP_RECEIVE_STATE_IDLE) && - (mstp_port->receive_state == MSTP_RECEIVE_STATE_IDLE)) { - fprintf(stderr, "\n"); fflush(stderr);} - receive_state = mstp_port->receive_state; -#endif - return;} + mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE; + break; + } + if ((receive_state != MSTP_RECEIVE_STATE_IDLE) && + (mstp_port->receive_state == MSTP_RECEIVE_STATE_IDLE)) { + printf_receive_data("\n"); + fflush(stderr); + } + receive_state = mstp_port->receive_state; + return; +} /* returns true if we need to transition immediately */ - bool MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t * mstp_port) { - unsigned length = 0; uint8_t next_poll_station = 0; - uint8_t next_this_station = 0; uint8_t next_next_station = 0; - uint16_t my_timeout = 10, ns_timeout = 0; - /* transition immediately to the next state */ - bool transition_now = false; -#if PRINT_ENABLED_MASTER - static MSTP_MASTER_STATE master_state = MSTP_MASTER_STATE_INITIALIZE; -#endif - /* some calculations that several states need */ - next_poll_station = - (mstp_port->Poll_Station + 1) % (mstp_port->Nmax_master + 1); - next_this_station = - (mstp_port->This_Station + 1) % (mstp_port->Nmax_master + 1); - next_next_station = - (mstp_port->Next_Station + 1) % (mstp_port->Nmax_master + 1); -#if PRINT_ENABLED_MASTER - if (mstp_port->master_state != master_state) { - master_state = mstp_port->master_state; - fprintf(stderr, - "MSTP: TS=%02X[%02X] NS=%02X[%02X] PS=%02X[%02X] EC=%u TC=%u ST=%u %s\n", - mstp_port->This_Station, next_this_station, - mstp_port->Next_Station, next_next_station, - mstp_port->Poll_Station, next_poll_station, - mstp_port->EventCount, mstp_port->TokenCount, - mstp_port->SilenceTimer(), - mstptext_master_state(mstp_port->master_state));} -#endif +bool MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t * mstp_port) { + unsigned length = 0; + uint8_t next_poll_station = 0; + uint8_t next_this_station = 0; + uint8_t next_next_station = 0; + uint16_t my_timeout = 10, ns_timeout = 0; + /* transition immediately to the next state */ + bool transition_now = false; + static MSTP_MASTER_STATE master_state = MSTP_MASTER_STATE_INITIALIZE; - switch (mstp_port->master_state) { -case MSTP_MASTER_STATE_INITIALIZE: + /* some calculations that several states need */ + next_poll_station = + (mstp_port->Poll_Station + 1) % (mstp_port->Nmax_master + 1); + next_this_station = + (mstp_port->This_Station + 1) % (mstp_port->Nmax_master + 1); + next_next_station = + (mstp_port->Next_Station + 1) % (mstp_port->Nmax_master + 1); + if (mstp_port->master_state != master_state) { + master_state = mstp_port->master_state; + printf_master( + "MSTP: TS=%02X[%02X] NS=%02X[%02X] PS=%02X[%02X] EC=%u TC=%u ST=%u %s\n", + mstp_port->This_Station, next_this_station, + mstp_port->Next_Station, next_next_station, + mstp_port->Poll_Station, next_poll_station, + mstp_port->EventCount, mstp_port->TokenCount, + mstp_port->SilenceTimer(), + mstptext_master_state(mstp_port->master_state)); + } + switch (mstp_port->master_state) { + case MSTP_MASTER_STATE_INITIALIZE: /* DoneInitializing */ /* indicate that the next station is unknown */ mstp_port->Next_Station = mstp_port->This_Station; @@ -579,104 +565,140 @@ case MSTP_MASTER_STATE_INITIALIZE: /* receives the token */ mstp_port->TokenCount = Npoll; mstp_port->SoleMaster = false; mstp_port->master_state = MSTP_MASTER_STATE_IDLE; - transition_now = true; break; + transition_now = true; + break; + case MSTP_MASTER_STATE_IDLE: /* In the IDLE state, the node waits for a frame. */ -case MSTP_MASTER_STATE_IDLE: /* LostToken */ if (mstp_port->SilenceTimer() >= Tno_token) { /* assume that the token has been lost */ mstp_port->EventCount = 0; /* Addendum 135-2004d-8 */ - mstp_port->master_state = MSTP_MASTER_STATE_NO_TOKEN; - transition_now = true;} - /* ReceivedInvalidFrame */ - else - if (mstp_port->ReceivedInvalidFrame == true) { - /* invalid frame was received */ - mstp_port->ReceivedInvalidFrame = false; - /* wait for the next frame - remain in IDLE */ - } - else - if (mstp_port->ReceivedValidFrame == true) { -#if PRINT_ENABLED_MASTER - fprintf(stderr, - "MSTP: ReceivedValidFrame Src=%02X Dest=%02X DataLen=%u FC=%u ST=%u Type=%s\n", - mstp_port->SourceAddress, mstp_port->DestinationAddress, - mstp_port->DataLength, mstp_port->FrameCount, - mstp_port->SilenceTimer(), - mstptext_frame_type(mstp_port->FrameType)); -#endif - /* destined for me! */ - if ((mstp_port->DestinationAddress == mstp_port->This_Station) || - (mstp_port->DestinationAddress == MSTP_BROADCAST_ADDRESS)) { - switch (mstp_port->FrameType) { - /* ReceivedToken */ -case FRAME_TYPE_TOKEN: - /* tokens can't be broadcast */ - if (mstp_port->DestinationAddress == - MSTP_BROADCAST_ADDRESS) - break; mstp_port->ReceivedValidFrame = false; - mstp_port->FrameCount = 0; mstp_port->SoleMaster = false; - mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN; - transition_now = true; break; - /* ReceivedPFM */ -case FRAME_TYPE_POLL_FOR_MASTER: -MSTP_Create_And_Send_Frame(mstp_port, FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER, mstp_port->SourceAddress, mstp_port->This_Station, NULL, 0); break; case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: - /* indicate successful reception to the higher layers */ -MSTP_Put_Receive(mstp_port); break; case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY: - /*mstp_port->ReplyPostponedTimer = 0; */ - /* indicate successful reception to the higher layers */ - MSTP_Put_Receive(mstp_port); - /* broadcast DER just remains IDLE */ - if (mstp_port->DestinationAddress != - MSTP_BROADCAST_ADDRESS) { - mstp_port->master_state = - MSTP_MASTER_STATE_ANSWER_DATA_REQUEST;} -break; case FRAME_TYPE_TEST_REQUEST: -MSTP_Create_And_Send_Frame(mstp_port, FRAME_TYPE_TEST_RESPONSE, mstp_port->SourceAddress, mstp_port->This_Station, mstp_port->InputBuffer, mstp_port->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 (mstp_port->master_state != - MSTP_MASTER_STATE_ANSWER_DATA_REQUEST) { - mstp_port->ReceivedValidFrame = false;} + mstp_port->master_state = MSTP_MASTER_STATE_NO_TOKEN; + transition_now = true; + } else if (mstp_port->ReceivedInvalidFrame == true) { + /* ReceivedInvalidFrame */ + /* invalid frame was received */ + mstp_port->ReceivedInvalidFrame = false; + } else if (mstp_port->ReceivedValidFrame == true) { + /* wait for the next frame - remain in IDLE */ + printf_master( + "MSTP: ReceivedValidFrame " + "Src=%02X Dest=%02X DataLen=%u " + "FC=%u ST=%u Type=%s\n", + mstp_port->SourceAddress, + mstp_port->DestinationAddress, + mstp_port->DataLength, mstp_port->FrameCount, + mstp_port->SilenceTimer(), + mstptext_frame_type(mstp_port->FrameType)); + /* destined for me! */ + if ((mstp_port->DestinationAddress == mstp_port->This_Station) || + (mstp_port->DestinationAddress == MSTP_BROADCAST_ADDRESS)) { + switch (mstp_port->FrameType) { + case FRAME_TYPE_TOKEN: + /* ReceivedToken */ + /* tokens can't be broadcast */ + if (mstp_port->DestinationAddress == + MSTP_BROADCAST_ADDRESS) { + break; + } + mstp_port->ReceivedValidFrame = false; + mstp_port->FrameCount = 0; + mstp_port->SoleMaster = false; + mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN; + transition_now = true; + break; + case FRAME_TYPE_POLL_FOR_MASTER: + /* ReceivedPFM */ + MSTP_Create_And_Send_Frame( + mstp_port, + FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER, + mstp_port->SourceAddress, + mstp_port->This_Station, + NULL, 0); + break; + case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: + /* indicate successful reception to the higher layers */ + MSTP_Put_Receive(mstp_port); + break; + case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY: + /*mstp_port->ReplyPostponedTimer = 0; */ + /* indicate successful reception to the higher layers */ + MSTP_Put_Receive(mstp_port); + /* broadcast DER just remains IDLE */ + if (mstp_port->DestinationAddress != + MSTP_BROADCAST_ADDRESS) { + mstp_port->master_state = + MSTP_MASTER_STATE_ANSWER_DATA_REQUEST; + } + break; + case FRAME_TYPE_TEST_REQUEST: + MSTP_Create_And_Send_Frame( + mstp_port, + FRAME_TYPE_TEST_RESPONSE, + mstp_port->SourceAddress, + mstp_port->This_Station, + mstp_port->InputBuffer, + mstp_port->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 (mstp_port->master_state != + MSTP_MASTER_STATE_ANSWER_DATA_REQUEST) { + mstp_port->ReceivedValidFrame = false; + } } break; + case MSTP_MASTER_STATE_USE_TOKEN: /* 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: /* FIXME: We could wait for up to Tusage_delay */ - length = MSTP_Get_Send(mstp_port, 0); if (length < 1) { + length = MSTP_Get_Send(mstp_port, 0); + if (length < 1) { /* NothingToSend */ - 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; transition_now = true;} - else { + MSTP_MASTER_STATE_DONE_WITH_TOKEN; + transition_now = true; + } else { uint8_t frame_type = mstp_port->OutputBuffer[2]; uint8_t destination = mstp_port->OutputBuffer[3]; RS485_Send_Frame(mstp_port, (uint8_t *) & mstp_port->OutputBuffer[0], length); - mstp_port->FrameCount++; switch (frame_type) { -case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY: - /* SendAndWait */ - if (destination == MSTP_BROADCAST_ADDRESS) - mstp_port->master_state = - MSTP_MASTER_STATE_DONE_WITH_TOKEN; - else -mstp_port->master_state = MSTP_MASTER_STATE_WAIT_FOR_REPLY; break; case FRAME_TYPE_TEST_REQUEST: -mstp_port->master_state = MSTP_MASTER_STATE_WAIT_FOR_REPLY; break; case FRAME_TYPE_TEST_RESPONSE: -case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: -default: - /* SendNoWait */ - mstp_port->master_state = - MSTP_MASTER_STATE_DONE_WITH_TOKEN; break;} + mstp_port->FrameCount++; + switch (frame_type) { + case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY: + /* SendAndWait */ + if (destination == MSTP_BROADCAST_ADDRESS) { + mstp_port->master_state = + MSTP_MASTER_STATE_DONE_WITH_TOKEN; + } else { + mstp_port->master_state = + MSTP_MASTER_STATE_WAIT_FOR_REPLY; + } + break; + case FRAME_TYPE_TEST_REQUEST: + mstp_port->master_state = + MSTP_MASTER_STATE_WAIT_FOR_REPLY; + break; + case FRAME_TYPE_TEST_RESPONSE: + case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: + default: + /* SendNoWait */ + mstp_port->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. */ -case MSTP_MASTER_STATE_WAIT_FOR_REPLY: if (mstp_port->SilenceTimer() >= Treply_timeout) { /* ReplyTimeout */ /* assume that the request has failed */ @@ -686,128 +708,149 @@ case MSTP_MASTER_STATE_WAIT_FOR_REPLY: /* 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 { + transition_now = true; + } else { if (mstp_port->ReceivedInvalidFrame == true) { /* InvalidFrame */ /* error in frame reception */ - mstp_port->ReceivedInvalidFrame = false; + mstp_port->ReceivedInvalidFrame = false; mstp_port->master_state = - MSTP_MASTER_STATE_DONE_WITH_TOKEN; transition_now = true;} - else - if (mstp_port->ReceivedValidFrame == true) { - if (mstp_port->DestinationAddress == mstp_port->This_Station) { - switch (mstp_port->FrameType) { -case FRAME_TYPE_REPLY_POSTPONED: - /* ReceivedReplyPostponed */ -mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN; break; case FRAME_TYPE_TEST_RESPONSE: -mstp_port->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_Put_Receive(mstp_port); mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN; break; default: - /* if proprietary frame was expected, you might - need to transition to DONE WITH TOKEN */ - mstp_port->master_state = MSTP_MASTER_STATE_IDLE; - break;} + MSTP_MASTER_STATE_DONE_WITH_TOKEN; + transition_now = true; + } else if (mstp_port->ReceivedValidFrame == true) { + if (mstp_port->DestinationAddress == mstp_port->This_Station) { + switch (mstp_port->FrameType) { + case FRAME_TYPE_REPLY_POSTPONED: + /* ReceivedReplyPostponed */ + mstp_port->master_state = + MSTP_MASTER_STATE_DONE_WITH_TOKEN; + break; + case FRAME_TYPE_TEST_RESPONSE: + mstp_port->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_Put_Receive(mstp_port); + mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN; + break; + default: + /* if proprietary frame was expected, you might + need to transition to DONE WITH TOKEN */ + mstp_port->master_state = MSTP_MASTER_STATE_IDLE; + break; + } + } else { + /* ReceivedUnexpectedFrame */ + /* an unexpected frame was received */ + /* This may indicate the presence of multiple tokens. */ + /* Synchronize with the network. */ + /* This action drops the token. */ + mstp_port->master_state = MSTP_MASTER_STATE_IDLE; + } + mstp_port->ReceivedValidFrame = false; + transition_now = true; } - else { - /* ReceivedUnexpectedFrame */ - /* an unexpected frame was received */ - /* This may indicate the presence of multiple tokens. */ - /* Synchronize with the network. */ - /* This action drops the token. */ - mstp_port->master_state = MSTP_MASTER_STATE_IDLE;} - mstp_port->ReceivedValidFrame = false; transition_now = true;} } break; + case MSTP_MASTER_STATE_DONE_WITH_TOKEN: /* 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 (mstp_port->FrameCount < mstp_port->Nmax_info_frames) { /* then this node may send another information frame */ /* before passing the token. */ - mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN; - transition_now = true;} - /* Npoll changed in Errata SSPC-135-2004 */ - else - if (mstp_port->TokenCount < (Npoll - 1)) { - if ((mstp_port->SoleMaster == true) && - (mstp_port->Next_Station != next_this_station)) { - /* SoleMaster */ - /* there are no other known master nodes to */ - /* which the token may be sent (true master-slave operation). */ - mstp_port->FrameCount = 0; mstp_port->TokenCount++; mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN; - transition_now = true;} - else { - /* SendToken */ + transition_now = true; + } + else if (mstp_port->TokenCount < (Npoll - 1)) { /* 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. */ - mstp_port->TokenCount++; - /* 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->EventCount = 0; - mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN;} - } - else - if (next_poll_station == mstp_port->Next_Station) { - if (mstp_port->SoleMaster == true) { - /* SoleMasterRestartMaintenancePFM */ - mstp_port->Poll_Station = next_next_station; - MSTP_Create_And_Send_Frame(mstp_port, - FRAME_TYPE_POLL_FOR_MASTER, mstp_port->Poll_Station, - mstp_port->This_Station, NULL, 0); - /* no known successor node */ - mstp_port->Next_Station = mstp_port->This_Station; mstp_port->RetryCount = 0; mstp_port->TokenCount = 1; /* changed in Errata SSPC-135-2004 */ - /* mstp_port->EventCount = 0; removed in Addendum 135-2004d-8 */ - /* find a new successor to TS */ - mstp_port->master_state = MSTP_MASTER_STATE_POLL_FOR_MASTER;} - else { - /* ResetMaintenancePFM */ - mstp_port->Poll_Station = mstp_port->This_Station; - /* 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->TokenCount = 1; /* changed in Errata SSPC-135-2004 */ - mstp_port->EventCount = 0; - mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN;} - } - else { + if ((mstp_port->SoleMaster == true) && + (mstp_port->Next_Station != next_this_station)) { + /* SoleMaster */ + /* there are no other known master nodes to */ + /* which the token may be sent (true master-slave operation). */ + mstp_port->FrameCount = 0; + mstp_port->TokenCount++; + mstp_port->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. */ + mstp_port->TokenCount++; + /* 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->EventCount = 0; + mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN; + } + } else if (next_poll_station == mstp_port->Next_Station) { + if (mstp_port->SoleMaster == true) { + /* SoleMasterRestartMaintenancePFM */ + mstp_port->Poll_Station = next_next_station; + MSTP_Create_And_Send_Frame(mstp_port, + FRAME_TYPE_POLL_FOR_MASTER, mstp_port->Poll_Station, + mstp_port->This_Station, NULL, 0); + /* no known successor node */ + mstp_port->Next_Station = mstp_port->This_Station; + mstp_port->RetryCount = 0; + /* changed in Errata SSPC-135-2004 */ + mstp_port->TokenCount = 1; + /* mstp_port->EventCount = 0; removed in Addendum 135-2004d-8 */ + /* find a new successor to TS */ + mstp_port->master_state = MSTP_MASTER_STATE_POLL_FOR_MASTER; + } else { + /* ResetMaintenancePFM */ + mstp_port->Poll_Station = mstp_port->This_Station; + /* 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; + /* changed in Errata SSPC-135-2004 */ + mstp_port->TokenCount = 1; + mstp_port->EventCount = 0; + mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN; + } + } else { /* SendMaintenancePFM */ - mstp_port->Poll_Station = next_poll_station; + mstp_port->Poll_Station = next_poll_station; 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->master_state = MSTP_MASTER_STATE_POLL_FOR_MASTER;} + mstp_port->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: + case MSTP_MASTER_STATE_PASS_TOKEN: + /* The PASS_TOKEN state listens for a successor to begin using */ + /* the token that this node has just attempted to pass. */ if (mstp_port->SilenceTimer() <= Tusage_timeout) { if (mstp_port->EventCount > Nmin_octets) { /* SawTokenUser */ /* Assume that a frame has been sent by the new token user. */ /* Enter the IDLE state to process the frame. */ - mstp_port->master_state = MSTP_MASTER_STATE_IDLE; - transition_now = true;} - } - else { + mstp_port->master_state = MSTP_MASTER_STATE_IDLE; + transition_now = true; + } + } else { if (mstp_port->RetryCount < Nretry_token) { /* RetrySendToken */ mstp_port->RetryCount++; /* 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->EventCount = 0; + 0); + mstp_port->EventCount = 0; /* re-enter the current state to listen for NS */ /* to begin using the token. */ - } - else { + } else { /* FindNewSuccessor */ /* Assume that NS has failed. */ mstp_port->Poll_Station = next_next_station; @@ -824,23 +867,23 @@ case MSTP_MASTER_STATE_PASS_TOKEN: MSTP_MASTER_STATE_POLL_FOR_MASTER;} } break; -/* The NO_TOKEN state is entered if mstp_port->SilenceTimer() 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: + case MSTP_MASTER_STATE_NO_TOKEN: + /* The NO_TOKEN state is entered if mstp_port->SilenceTimer() 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. */ my_timeout = Tno_token + (Tslot * mstp_port->This_Station); if (mstp_port->SilenceTimer() < my_timeout) { if (mstp_port->EventCount > Nmin_octets) { /* SawFrame */ /* Some other node exists at a lower address. */ /* Enter the IDLE state to receive and process the incoming frame. */ - mstp_port->master_state = MSTP_MASTER_STATE_IDLE; - transition_now = true;} - } - else { + mstp_port->master_state = MSTP_MASTER_STATE_IDLE; + transition_now = true; + } + } else { ns_timeout = - Tno_token + (Tslot * (mstp_port->This_Station + 1)); + Tno_token + (Tslot * (mstp_port->This_Station + 1)); if (mstp_port->SilenceTimer() < ns_timeout) { /* GenerateToken */ /* Assume that this node is the lowest numerical address */ @@ -855,14 +898,15 @@ case MSTP_MASTER_STATE_NO_TOKEN: mstp_port->RetryCount = 0; mstp_port->TokenCount = 0; /* mstp_port->EventCount = 0; removed Addendum 135-2004d-8 */ /* enter the POLL_FOR_MASTER state to find a new successor to TS. */ - mstp_port->master_state = - MSTP_MASTER_STATE_POLL_FOR_MASTER;} + mstp_port->master_state = + MSTP_MASTER_STATE_POLL_FOR_MASTER; + } } break; -/* 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 successor node. */ -case MSTP_MASTER_STATE_POLL_FOR_MASTER: + case MSTP_MASTER_STATE_POLL_FOR_MASTER: + /* 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 successor node. */ if (mstp_port->ReceivedValidFrame == true) { if ((mstp_port->DestinationAddress == mstp_port->This_Station) && (mstp_port->FrameType == @@ -872,69 +916,73 @@ case MSTP_MASTER_STATE_POLL_FOR_MASTER: mstp_port->Next_Station = mstp_port->SourceAddress; mstp_port->EventCount = 0; /* Transmit a Token frame to NS */ - MSTP_Create_And_Send_Frame(mstp_port, FRAME_TYPE_TOKEN, + MSTP_Create_And_Send_Frame(mstp_port, FRAME_TYPE_TOKEN, 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 { + 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; - transition_now = true;} - mstp_port->ReceivedValidFrame = false;} - else - if ((mstp_port->SilenceTimer() > Tusage_timeout) || - (mstp_port->ReceivedInvalidFrame == true)) { - if (mstp_port->SoleMaster == true) { - /* SoleMaster */ - /* There was no valid reply to the periodic poll */ - /* by the sole known master for other masters. */ - mstp_port->FrameCount = 0; -/* mstp_port->TokenCount++; removed in 2004 */ - mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN; - transition_now = true;} - else { - if (mstp_port->Next_Station != mstp_port->This_Station) { - /* DoneWithPFM */ - /* 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->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; transition_now = true;} + mstp_port->master_state = MSTP_MASTER_STATE_IDLE; + transition_now = true; } + mstp_port->ReceivedValidFrame = false; + } else if ((mstp_port->SilenceTimer() > Tusage_timeout) || + (mstp_port->ReceivedInvalidFrame == true)) { + if (mstp_port->SoleMaster == true) { + /* SoleMaster */ + /* There was no valid reply to the periodic poll */ + /* by the sole known master for other masters. */ + mstp_port->FrameCount = 0; + /* mstp_port->TokenCount++; removed in 2004 */ + mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN; + transition_now = true; + } else { + if (mstp_port->Next_Station != mstp_port->This_Station) { + /* DoneWithPFM */ + /* 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->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; + transition_now = true; + } + } + } + mstp_port->ReceivedInvalidFrame = false; } - mstp_port->ReceivedInvalidFrame = false;} break; -/* The ANSWER_DATA_REQUEST state is entered when a */ -/* BACnet Data Expecting Reply, a Test_Request, or */ -/* a proprietary frame that expects a reply is received. */ -case MSTP_MASTER_STATE_ANSWER_DATA_REQUEST: + case MSTP_MASTER_STATE_ANSWER_DATA_REQUEST: + /* The ANSWER_DATA_REQUEST state is entered when a */ + /* BACnet Data Expecting Reply, a Test_Request, or */ + /* a proprietary frame that expects a reply is received. */ /* FIXME: we could wait for up to Treply_delay */ length = MSTP_Get_Reply(mstp_port, 0); if (length > 0) { /* Reply */ @@ -944,10 +992,10 @@ case MSTP_MASTER_STATE_ANSWER_DATA_REQUEST: /* (the mechanism used to determine this is a local matter), */ /* then call MSTP_Create_And_Send_Frame to transmit the reply frame */ /* and enter the IDLE state to wait for the next frame. */ - RS485_Send_Frame(mstp_port, + RS485_Send_Frame(mstp_port, (uint8_t *) & mstp_port->OutputBuffer[0], length); - mstp_port->master_state = MSTP_MASTER_STATE_IDLE;} - else { + mstp_port->master_state = MSTP_MASTER_STATE_IDLE; + } else { /* DeferredReply */ /* If no reply will be available from the higher layers */ /* within Treply_delay after the reception of the */ @@ -957,15 +1005,21 @@ case MSTP_MASTER_STATE_ANSWER_DATA_REQUEST: /* Any reply shall wait until this node receives the token. */ /* Call MSTP_Create_And_Send_Frame to transmit a Reply Postponed frame, */ /* and enter the IDLE state. */ - MSTP_Create_And_Send_Frame(mstp_port, + MSTP_Create_And_Send_Frame(mstp_port, FRAME_TYPE_REPLY_POSTPONED, mstp_port->SourceAddress, mstp_port->This_Station, NULL, 0); - mstp_port->master_state = MSTP_MASTER_STATE_IDLE;} + mstp_port->master_state = MSTP_MASTER_STATE_IDLE; + } /* clear our flag we were holding for comparison */ -mstp_port->ReceivedValidFrame = false; break; default: - mstp_port->master_state = MSTP_MASTER_STATE_IDLE; break;} + mstp_port->ReceivedValidFrame = false; + break; + default: + mstp_port->master_state = MSTP_MASTER_STATE_IDLE; + break; + } - return transition_now;} + return transition_now; +} /* note: This_Station assumed to be set with the MAC address */ /* note: Nmax_info_frames assumed to be set (default=1) */ @@ -973,40 +1027,40 @@ mstp_port->ReceivedValidFrame = false; break; default: /* note: InputBuffer and InputBufferSize assumed to be set */ /* note: OutputBuffer and OutputBufferSize assumed to be set */ /* note: SilenceTimer and SilenceTimerReset assumed to be set */ - void MSTP_Init(volatile struct mstp_port_struct_t *mstp_port) { - if (mstp_port) { - mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE; - mstp_port->master_state = MSTP_MASTER_STATE_INITIALIZE; - mstp_port->ReceiveError = false; mstp_port->DataAvailable = false; - mstp_port->DataRegister = 0; mstp_port->DataCRC = 0; - mstp_port->DataCRC = 0; mstp_port->DataLength = 0; - mstp_port->DestinationAddress = 0; mstp_port->EventCount = 0; - mstp_port->FrameType = FRAME_TYPE_TOKEN; mstp_port->FrameCount = 0; - mstp_port->HeaderCRC = 0; mstp_port->Index = 0; - mstp_port->Index = 0; - mstp_port->Next_Station = mstp_port->This_Station; - mstp_port->Poll_Station = mstp_port->This_Station; - mstp_port->ReceivedInvalidFrame = false; - mstp_port->ReceivedValidFrame = false; mstp_port->RetryCount = 0; - mstp_port->SilenceTimerReset(); mstp_port->SoleMaster = false; - mstp_port->SourceAddress = 0; mstp_port->TokenCount = 0; - mstp_port->Lurking = false; +void MSTP_Init(volatile struct mstp_port_struct_t *mstp_port) { + if (mstp_port) { + mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE; + mstp_port->master_state = MSTP_MASTER_STATE_INITIALIZE; + mstp_port->ReceiveError = false; mstp_port->DataAvailable = false; + mstp_port->DataRegister = 0; mstp_port->DataCRC = 0; + mstp_port->DataCRC = 0; mstp_port->DataLength = 0; + mstp_port->DestinationAddress = 0; mstp_port->EventCount = 0; + mstp_port->FrameType = FRAME_TYPE_TOKEN; mstp_port->FrameCount = 0; + mstp_port->HeaderCRC = 0; mstp_port->Index = 0; + mstp_port->Index = 0; + mstp_port->Next_Station = mstp_port->This_Station; + mstp_port->Poll_Station = mstp_port->This_Station; + mstp_port->ReceivedInvalidFrame = false; + mstp_port->ReceivedValidFrame = false; mstp_port->RetryCount = 0; + mstp_port->SilenceTimerReset(); mstp_port->SoleMaster = false; + mstp_port->SourceAddress = 0; mstp_port->TokenCount = 0; + mstp_port->Lurking = false; #if 0 - /* FIXME: you must point these buffers to actual byte buckets - in the dlmstp function before or after calling this init. */ - mstp_port->InputBuffer = &InputBuffer[0]; - mstp_port->InputBufferSize = sizeof(InputBuffer); - mstp_port->OutputBuffer = &OutputBuffer[0]; - mstp_port->OutputBufferSize = sizeof(OutputBuffer); - /* FIXME: these are adjustable, so you must set these in dlmstp */ - mstp_port->Nmax_info_frames = DEFAULT_MAX_INFO_FRAMES; - mstp_port->Nmax_master = DEFAULT_MAX_MASTER; - /* FIXME: point to functions */ - mstp_port->SilenceTimer = Timer_Silence; - mstp_port = >SilenceTimerReset = Timer_Silence_Reset; + /* FIXME: you must point these buffers to actual byte buckets + in the dlmstp function before or after calling this init. */ + mstp_port->InputBuffer = &InputBuffer[0]; + mstp_port->InputBufferSize = sizeof(InputBuffer); + mstp_port->OutputBuffer = &OutputBuffer[0]; + mstp_port->OutputBufferSize = sizeof(OutputBuffer); + /* FIXME: these are adjustable, so you must set these in dlmstp */ + mstp_port->Nmax_info_frames = DEFAULT_MAX_INFO_FRAMES; + mstp_port->Nmax_master = DEFAULT_MAX_MASTER; + /* FIXME: point to functions */ + mstp_port->SilenceTimer = Timer_Silence; + mstp_port = >SilenceTimerReset = Timer_Silence_Reset; #endif - } } +} #ifdef TEST #include