Converted the MS/TP FSM src module to use the debug printf.

This commit is contained in:
skarg
2008-07-21 16:05:55 +00:00
parent 241e877d23
commit a8c36762db
2 changed files with 528 additions and 468 deletions
+27 -21
View File
@@ -3,11 +3,12 @@
<FileVersion major="1" minor="6" />
<Project>
<Option title="rx_fsm" />
<Option makefile="makefile" />
<Option pch_mode="2" />
<Option compiler="gcc" />
<Build>
<Target title="Debug">
<Option output="bin\Debug\rx_fsm.exe" prefix_auto="1" extension_auto="1" />
<Option output="bin\Debug\rx_fsm" prefix_auto="1" extension_auto="1" />
<Option object_output="obj\Debug\" />
<Option type="1" />
<Option compiler="gcc" />
@@ -18,7 +19,7 @@
</Compiler>
</Target>
<Target title="Release">
<Option output="bin\Release\rx_fsm.exe" prefix_auto="1" extension_auto="1" />
<Option output="bin\Release\rx_fsm" prefix_auto="1" extension_auto="1" />
<Option object_output="obj\Release\" />
<Option type="1" />
<Option compiler="gcc" />
@@ -33,28 +34,17 @@
<Compiler>
<Add option="-Wall" />
<Add option="-fexceptions" />
<Add option="-DBIG_ENDIAN=0" />
<Add option="-DBACDL_MSTP=1" />
<Add option="-DBACAPP_ALL" />
<Add option="-DPRINT_ENABLED=1" />
<Add directory="." />
<Add directory="..\..\..\bacnet-stack" />
<Add directory="..\..\include" />
</Compiler>
<Unit filename="..\..\crc.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\..\crc.h" />
<Unit filename="..\..\indtext.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\..\indtext.h" />
<Unit filename="..\..\mstp.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\..\mstp.h" />
<Unit filename="..\..\mstptext.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\..\mstptext.h" />
<Unit filename="mstp.h" />
<Unit filename="..\..\include\crc.h" />
<Unit filename="..\..\include\debug.h" />
<Unit filename="..\..\include\indtext.h" />
<Unit filename="..\..\include\mstp.h" />
<Unit filename="..\..\include\mstptext.h" />
<Unit filename="rs485.c">
<Option compilerVar="CC" />
</Unit>
@@ -63,9 +53,25 @@
</Unit>
<Unit filename="stdbool.h" />
<Unit filename="stdint.h" />
<Unit filename="..\..\src\crc.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\..\src\debug.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\..\src\indtext.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\..\src\mstp.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\..\src\mstptext.c">
<Option compilerVar="CC" />
</Unit>
<Extensions>
<code_completion />
<envvars />
<debugger />
</Extensions>
</Project>
</CodeBlocks_project_file>
+251 -197
View File
@@ -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,17 +237,13 @@ 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
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:
@@ -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,9 +269,7 @@ 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();
@@ -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;
@@ -310,10 +317,8 @@ case MSTP_RECEIVE_STATE_HEADER:
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
@@ -322,16 +327,12 @@ case MSTP_RECEIVE_STATE_HEADER:
INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount);
/* 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
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
printf_receive_data("%02X ", mstp_port->DataRegister);
/* FrameType */
if (mstp_port->Index == 0) {
mstp_port->HeaderCRC =
@@ -380,10 +381,8 @@ case MSTP_RECEIVE_STATE_HEADER:
/* 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. */
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;}
else {
@@ -401,20 +400,16 @@ case MSTP_RECEIVE_STATE_HEADER:
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 */
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 ==
@@ -437,74 +432,62 @@ case MSTP_RECEIVE_STATE_HEADER:
/* 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;}
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:
/* 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;
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. */
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;}
/* Error */
else
if (mstp_port->ReceiveError == true) {
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
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) {
#if PRINT_ENABLED_RECEIVE_DATA
fprintf(stderr, "%02X ", mstp_port->DataRegister);
#endif
/* DataOctet */
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;}
mstp_port->receive_state = MSTP_RECEIVE_STATE_DATA;
} else if (mstp_port->Index == mstp_port->DataLength) {
/* 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;}
mstp_port->receive_state = MSTP_RECEIVE_STATE_DATA;
} else if (mstp_port->Index == (mstp_port->DataLength + 1)) {
/* 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
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) {
@@ -514,41 +497,46 @@ case MSTP_RECEIVE_STATE_DATA:
|| (mstp_port->Lurking)) {
/* ForUs */
/* indicate that a frame with no data has been received */
mstp_port->ReceivedValidFrame = true;}
else {
mstp_port->ReceivedValidFrame = true;
} else {
/* NotForUs - drop */
}
}
else {
} else {
mstp_port->ReceivedInvalidFrame = true;
#if PRINT_ENABLED_RECEIVE_ERRORS
fprintf(stderr, "MSTP: Rx Data: BadCRC [%02X]\n",
printf_receive_error("MSTP: Rx Data: BadCRC [%02X]\n",
mstp_port->DataRegister);
#endif
}
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;}
mstp_port->DataAvailable = false; mstp_port->SilenceTimerReset();}
break; default:
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
}
mstp_port->DataAvailable = false;
mstp_port->SilenceTimerReset();
}
break;
default:
/* shouldn't get here - but if we do... */
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE; break;}
#if PRINT_ENABLED_RECEIVE_DATA
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
break;
}
if ((receive_state != MSTP_RECEIVE_STATE_IDLE) &&
(mstp_port->receive_state == MSTP_RECEIVE_STATE_IDLE)) {
fprintf(stderr, "\n"); fflush(stderr);}
printf_receive_data("\n");
fflush(stderr);
}
receive_state = mstp_port->receive_state;
#endif
return;}
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;
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);
@@ -556,19 +544,17 @@ break; default:
(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,
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));}
#endif
mstptext_master_state(mstp_port->master_state));
}
switch (mstp_port->master_state) {
case MSTP_MASTER_STATE_INITIALIZE:
/* DoneInitializing */
@@ -579,50 +565,62 @@ 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;
/* In the IDLE state, the node waits for a frame. */
transition_now = true;
break;
case MSTP_MASTER_STATE_IDLE:
/* In the IDLE state, the node waits for a frame. */
/* 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;}
transition_now = true;
} else if (mstp_port->ReceivedInvalidFrame == true) {
/* ReceivedInvalidFrame */
else
if (mstp_port->ReceivedInvalidFrame == true) {
/* invalid frame was received */
mstp_port->ReceivedInvalidFrame = false;
} else if (mstp_port->ReceivedValidFrame == true) {
/* 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,
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));
#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:
/* 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_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 */
transition_now = true;
break;
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:
/* 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_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);
@@ -630,53 +628,77 @@ MSTP_Put_Receive(mstp_port); break; case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY:
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:
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;}
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->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->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) {
mstp_port->FrameCount++;
switch (frame_type) {
case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY:
/* SendAndWait */
if (destination == MSTP_BROADCAST_ADDRESS)
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:
} 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_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,62 +708,75 @@ 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->master_state =
MSTP_MASTER_STATE_DONE_WITH_TOKEN; transition_now = true;}
else
if (mstp_port->ReceivedValidFrame == true) {
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:
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:
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;}
break;
}
else {
} 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;}
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;}
transition_now = true;
}
else if (mstp_port->TokenCount < (Npoll - 1)) {
/* 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->FrameCount = 0;
mstp_port->TokenCount++;
mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN;
transition_now = true;}
else {
transition_now = true;
} else {
/* SendToken */
/* Npoll changed in Errata SSPC-135-2004 */
/* The comparison of NS and TS+1 eliminates the Poll For Master */
@@ -751,12 +786,12 @@ case MSTP_MASTER_STATE_DONE_WITH_TOKEN:
/* 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;
0);
mstp_port->RetryCount = 0;
mstp_port->EventCount = 0;
mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN;}
mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN;
}
else
if (next_poll_station == mstp_port->Next_Station) {
} else if (next_poll_station == mstp_port->Next_Station) {
if (mstp_port->SoleMaster == true) {
/* SoleMasterRestartMaintenancePFM */
mstp_port->Poll_Station = next_next_station;
@@ -764,50 +799,58 @@ case MSTP_MASTER_STATE_DONE_WITH_TOKEN:
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->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 {
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_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;}
mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN;
}
else {
} else {
/* SendMaintenancePFM */
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;
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. */
case MSTP_MASTER_STATE_PASS_TOKEN:
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;}
transition_now = true;
}
else {
} 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,11 +867,11 @@ case MSTP_MASTER_STATE_PASS_TOKEN:
MSTP_MASTER_STATE_POLL_FOR_MASTER;}
}
break;
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. */
case MSTP_MASTER_STATE_NO_TOKEN:
my_timeout = Tno_token + (Tslot * mstp_port->This_Station);
if (mstp_port->SilenceTimer() < my_timeout) {
if (mstp_port->EventCount > Nmin_octets) {
@@ -836,9 +879,9 @@ case MSTP_MASTER_STATE_NO_TOKEN:
/* 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;}
transition_now = true;
}
else {
} else {
ns_timeout =
Tno_token + (Tslot * (mstp_port->This_Station + 1));
if (mstp_port->SilenceTimer() < ns_timeout) {
@@ -856,13 +899,14 @@ case MSTP_MASTER_STATE_NO_TOKEN:
/* 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_MASTER_STATE_POLL_FOR_MASTER;
}
}
break;
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. */
case MSTP_MASTER_STATE_POLL_FOR_MASTER:
if (mstp_port->ReceivedValidFrame == true) {
if ((mstp_port->DestinationAddress == mstp_port->This_Station)
&& (mstp_port->FrameType ==
@@ -877,18 +921,18 @@ case MSTP_MASTER_STATE_POLL_FOR_MASTER:
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) ||
transition_now = true;
}
mstp_port->ReceivedValidFrame = false;
} else if ((mstp_port->SilenceTimer() > Tusage_timeout) ||
(mstp_port->ReceivedInvalidFrame == true)) {
if (mstp_port->SoleMaster == true) {
/* SoleMaster */
@@ -897,8 +941,8 @@ case MSTP_MASTER_STATE_POLL_FOR_MASTER:
mstp_port->FrameCount = 0;
/* mstp_port->TokenCount++; removed in 2004 */
mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN;
transition_now = true;}
else {
transition_now = true;
} else {
if (mstp_port->Next_Station != mstp_port->This_Station) {
/* DoneWithPFM */
/* There was no valid reply to the maintenance */
@@ -907,9 +951,10 @@ case MSTP_MASTER_STATE_POLL_FOR_MASTER:
/* 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 {
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;
@@ -917,24 +962,27 @@ case MSTP_MASTER_STATE_POLL_FOR_MASTER:
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;
NULL, 0);
mstp_port->RetryCount = 0;
/* Re-enter the current state. */
}
else {
} 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_MASTER_STATE_USE_TOKEN;
transition_now = true;
}
}
mstp_port->ReceivedInvalidFrame = false;}
}
mstp_port->ReceivedInvalidFrame = false;
}
break;
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. */
case MSTP_MASTER_STATE_ANSWER_DATA_REQUEST:
/* FIXME: we could wait for up to Treply_delay */
length = MSTP_Get_Reply(mstp_port, 0); if (length > 0) {
/* Reply */
@@ -946,8 +994,8 @@ case MSTP_MASTER_STATE_ANSWER_DATA_REQUEST:
/* and enter the IDLE state to wait for the next frame. */
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 */
@@ -960,12 +1008,18 @@ case MSTP_MASTER_STATE_ANSWER_DATA_REQUEST:
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) */