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" /> <FileVersion major="1" minor="6" />
<Project> <Project>
<Option title="rx_fsm" /> <Option title="rx_fsm" />
<Option makefile="makefile" />
<Option pch_mode="2" /> <Option pch_mode="2" />
<Option compiler="gcc" /> <Option compiler="gcc" />
<Build> <Build>
<Target title="Debug"> <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 object_output="obj\Debug\" />
<Option type="1" /> <Option type="1" />
<Option compiler="gcc" /> <Option compiler="gcc" />
@@ -18,7 +19,7 @@
</Compiler> </Compiler>
</Target> </Target>
<Target title="Release"> <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 object_output="obj\Release\" />
<Option type="1" /> <Option type="1" />
<Option compiler="gcc" /> <Option compiler="gcc" />
@@ -33,28 +34,17 @@
<Compiler> <Compiler>
<Add option="-Wall" /> <Add option="-Wall" />
<Add option="-fexceptions" /> <Add option="-fexceptions" />
<Add option="-DBIG_ENDIAN=0" />
<Add option="-DBACDL_MSTP=1" /> <Add option="-DBACDL_MSTP=1" />
<Add option="-DBACAPP_ALL" />
<Add option="-DPRINT_ENABLED=1" />
<Add directory="." /> <Add directory="." />
<Add directory="..\..\..\bacnet-stack" /> <Add directory="..\..\include" />
</Compiler> </Compiler>
<Unit filename="..\..\crc.c"> <Unit filename="..\..\include\crc.h" />
<Option compilerVar="CC" /> <Unit filename="..\..\include\debug.h" />
</Unit> <Unit filename="..\..\include\indtext.h" />
<Unit filename="..\..\crc.h" /> <Unit filename="..\..\include\mstp.h" />
<Unit filename="..\..\indtext.c"> <Unit filename="..\..\include\mstptext.h" />
<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="rs485.c"> <Unit filename="rs485.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
@@ -63,9 +53,25 @@
</Unit> </Unit>
<Unit filename="stdbool.h" /> <Unit filename="stdbool.h" />
<Unit filename="stdint.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> <Extensions>
<code_completion /> <code_completion />
<envvars /> <envvars />
<debugger />
</Extensions> </Extensions>
</Project> </Project>
</CodeBlocks_project_file> </CodeBlocks_project_file>
+251 -197
View File
@@ -52,24 +52,41 @@
#include "mstp.h" #include "mstp.h"
#include "crc.h" #include "crc.h"
#include "rs485.h" #include "rs485.h"
#if PRINT_ENABLED
#include "mstptext.h" #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 #endif
#if !defined(PRINT_ENABLED_RECEIVE) #if defined(PRINT_ENABLED_RECEIVE)
#define PRINT_ENABLED_RECEIVE 0 #define printf_receive debug_printf
#else
#define printf_receive (void)
#endif #endif
#if !defined(PRINT_ENABLED_RECEIVE_DATA) #if defined(PRINT_ENABLED_RECEIVE_DATA)
#define PRINT_ENABLED_RECEIVE_DATA 0 #define printf_receive_data debug_printf
#else
#define printf_receive_data (void)
#endif #endif
#if !defined(PRINT_ENABLED_RECEIVE_ERRORS) #if defined(PRINT_ENABLED_RECEIVE_ERRORS)
#define PRINT_ENABLED_RECEIVE_ERRORS 0 #define printf_receive_error debug_printf
#else
#define printf_receive_error (void)
#endif #endif
#if !defined(PRINT_ENABLED_MASTER) #if defined(PRINT_ENABLED_MASTER)
#define PRINT_ENABLED_MASTER 0 #define printf_master debug_printf
#else
#define printf_master (void)
#endif #endif
/* MS/TP Frame Format */ /* MS/TP Frame Format */
@@ -220,17 +237,13 @@ void MSTP_Create_And_Send_Frame(
void MSTP_Receive_Frame_FSM( void MSTP_Receive_Frame_FSM(
volatile struct mstp_port_struct_t *mstp_port) volatile struct mstp_port_struct_t *mstp_port)
{ {
#if PRINT_ENABLED_RECEIVE_DATA
static MSTP_RECEIVE_STATE receive_state = MSTP_RECEIVE_STATE_IDLE; static MSTP_RECEIVE_STATE receive_state = MSTP_RECEIVE_STATE_IDLE;
#endif printf_receive(
#if PRINT_ENABLED_RECEIVE
fprintf(stderr,
"MSTP Rx: State=%s Data=%02X hCRC=%02X Index=%u EC=%u DateLen=%u Silence=%u\n", "MSTP Rx: State=%s Data=%02X hCRC=%02X Index=%u EC=%u DateLen=%u Silence=%u\n",
mstptext_receive_state(mstp_port->receive_state), mstptext_receive_state(mstp_port->receive_state),
mstp_port->DataRegister, mstp_port->HeaderCRC, mstp_port->Index, mstp_port->DataRegister, mstp_port->HeaderCRC, mstp_port->Index,
mstp_port->EventCount, mstp_port->DataLength, mstp_port->EventCount, mstp_port->DataLength,
mstp_port->SilenceTimer(); mstp_port->SilenceTimer());
#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. */
case MSTP_RECEIVE_STATE_IDLE: case MSTP_RECEIVE_STATE_IDLE:
@@ -243,14 +256,12 @@ case MSTP_RECEIVE_STATE_IDLE:
} }
else else
if (mstp_port->DataAvailable == true) { if (mstp_port->DataAvailable == true) {
#if PRINT_ENABLED_RECEIVE_DATA
#if (defined(_WIN32) && defined(TEST_DLMSTP)) #if (defined(_WIN32) && defined(TEST_DLMSTP))
extern uint32_t timestamp_ms(void); 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); mstp_port->DataRegister);
#else #else
fprintf(stderr, "MSTP Rx: %02X ", mstp_port->DataRegister); printf_receive_data("MSTP Rx: %02X ", mstp_port->DataRegister);
#endif
#endif #endif
/* Preamble1 */ /* Preamble1 */
if (mstp_port->DataRegister == 0x55) { if (mstp_port->DataRegister == 0x55) {
@@ -258,9 +269,7 @@ case MSTP_RECEIVE_STATE_IDLE:
mstp_port->receive_state = MSTP_RECEIVE_STATE_PREAMBLE;} mstp_port->receive_state = MSTP_RECEIVE_STATE_PREAMBLE;}
/* EatAnOctet */ /* EatAnOctet */
else { else {
#if PRINT_ENABLED_RECEIVE_DATA printf_receive_data("\n");
fprintf(stderr, "\n");
#endif
/* wait for the start of a frame. */ /* wait for the start of a frame. */
} }
mstp_port->DataAvailable = false; mstp_port->SilenceTimerReset(); mstp_port->DataAvailable = false; mstp_port->SilenceTimerReset();
@@ -282,9 +291,7 @@ case MSTP_RECEIVE_STATE_PREAMBLE:
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;} mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;}
else else
if (mstp_port->DataAvailable == true) { if (mstp_port->DataAvailable == true) {
#if PRINT_ENABLED_RECEIVE_DATA printf_receive_data("%02X ", mstp_port->DataRegister);
fprintf(stderr, "%02X ", mstp_port->DataRegister);
#endif
/* Preamble2 */ /* Preamble2 */
if (mstp_port->DataRegister == 0xFF) { if (mstp_port->DataRegister == 0xFF) {
mstp_port->Index = 0; mstp_port->HeaderCRC = 0xFF; mstp_port->Index = 0; mstp_port->HeaderCRC = 0xFF;
@@ -310,10 +317,8 @@ case MSTP_RECEIVE_STATE_HEADER:
mstp_port->ReceivedInvalidFrame = true; mstp_port->ReceivedInvalidFrame = true;
/* wait for the start of a frame. */ /* wait for the start of a frame. */
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE; mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
#if PRINT_ENABLED_RECEIVE_ERRORS printf_receive_error("MSTP: Rx Header: SilenceTimer %d > %d\n",
fprintf(stderr, "MSTP: Rx Header: SilenceTimer %d > %d\n",
mstp_port->SilenceTimer(), Tframe_abort); mstp_port->SilenceTimer(), Tframe_abort);
#endif
} }
/* Error */ /* Error */
else else
@@ -322,16 +327,12 @@ case MSTP_RECEIVE_STATE_HEADER:
INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount); 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; mstp_port->ReceivedInvalidFrame = true;
#if PRINT_ENABLED_RECEIVE_ERRORS printf_receive_error("MSTP: Rx Header: ReceiveError\n");
fprintf(stderr, "MSTP: Rx Header: ReceiveError\n");
#endif
/* wait for the start of a frame. */ /* wait for the start of a frame. */
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;} mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;}
else else
if (mstp_port->DataAvailable == true) { if (mstp_port->DataAvailable == true) {
#if PRINT_ENABLED_RECEIVE_DATA printf_receive_data("%02X ", mstp_port->DataRegister);
fprintf(stderr, "%02X ", mstp_port->DataRegister);
#endif
/* FrameType */ /* FrameType */
if (mstp_port->Index == 0) { if (mstp_port->Index == 0) {
mstp_port->HeaderCRC = mstp_port->HeaderCRC =
@@ -380,10 +381,8 @@ case MSTP_RECEIVE_STATE_HEADER:
/* indicate that an error has occurred during /* indicate that an error has occurred during
the reception of a frame */ the reception of a frame */
mstp_port->ReceivedInvalidFrame = true; mstp_port->ReceivedInvalidFrame = true;
#if PRINT_ENABLED_RECEIVE_ERRORS printf_receive_error("MSTP: Rx Header: BadCRC [%02X]\n",
fprintf(stderr, "MSTP: Rx Header: BadCRC [%02X]\n",
mstp_port->DataRegister); 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;} mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;}
else { else {
@@ -401,20 +400,16 @@ case MSTP_RECEIVE_STATE_HEADER:
else { else {
/* FrameTooLong */ /* FrameTooLong */
if (mstp_port->DataLength) { if (mstp_port->DataLength) {
#if PRINT_ENABLED_RECEIVE_ERRORS printf_receive_error("MSTP: Rx Header: FrameTooLong %d\n",
fprintf(stderr, "MSTP: Rx Header: FrameTooLong %d\n",
mstp_port->DataLength); mstp_port->DataLength);
#endif
/* indicate that a frame with an illegal or */ /* indicate that a frame with an illegal or */
/* unacceptable data length has been received */ /* unacceptable data length has been received */
mstp_port->ReceivedInvalidFrame = true;} mstp_port->ReceivedInvalidFrame = true;}
/* NoData */ /* NoData */
else else
if (mstp_port->DataLength == 0) { if (mstp_port->DataLength == 0) {
#if PRINT_ENABLED_RECEIVE_DATA printf_receive_data("%s",
fprintf(stderr, "%s",
mstptext_frame_type(mstp_port->FrameType)); mstptext_frame_type(mstp_port->FrameType));
#endif
if ((mstp_port->DestinationAddress == if ((mstp_port->DestinationAddress ==
mstp_port->This_Station) mstp_port->This_Station)
|| (mstp_port->DestinationAddress == || (mstp_port->DestinationAddress ==
@@ -437,74 +432,62 @@ case MSTP_RECEIVE_STATE_HEADER:
/* indicate that an error has occurred during */ /* indicate that an error has occurred during */
/* the reception of a frame */ /* the reception of a frame */
mstp_port->ReceivedInvalidFrame = true; mstp_port->ReceivedInvalidFrame = true;
#if PRINT_ENABLED_RECEIVE_ERRORS printf_receive_error("MSTP: Rx Data: BadIndex %d\n",
fprintf(stderr, "MSTP: Rx Data: BadIndex %d\n",
mstp_port->Index); mstp_port->Index);
#endif
/* wait for the start of a frame. */ /* wait for the start of a frame. */
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;} mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;}
mstp_port->SilenceTimerReset(); mstp_port->SilenceTimerReset();
INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount); INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount);
mstp_port->DataAvailable = false;} mstp_port->DataAvailable = false;
}
break; break;
/* In the HEADER_CRC state, the node validates the CRC on the fixed */ /* In the HEADER_CRC state, the node validates the CRC on the fixed */
/* message header. */ /* message header. */
case MSTP_RECEIVE_STATE_HEADER_CRC: case MSTP_RECEIVE_STATE_HEADER_CRC:
/* note: we should never get to this state since we shortcut /* note: we should never get to this state since we shortcut
it earlier in the state machine, and never set this state */ 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. */ /* In the DATA state, the node waits for the data portion of a frame. */
case MSTP_RECEIVE_STATE_DATA: case MSTP_RECEIVE_STATE_DATA:
/* Timeout */ /* Timeout */
if (mstp_port->SilenceTimer() > Tframe_abort) { if (mstp_port->SilenceTimer() > Tframe_abort) {
/* 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; mstp_port->ReceivedInvalidFrame = true;
#if PRINT_ENABLED_RECEIVE_ERRORS printf_receive_error("MSTP: Rx Data: SilenceTimer %d > %d\n",
fprintf(stderr, "MSTP: Rx Data: SilenceTimer %d > %d\n",
mstp_port->SilenceTimer(), Tframe_abort); 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;} mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;}
/* Error */ /* Error */
else else if (mstp_port->ReceiveError == true) {
if (mstp_port->ReceiveError == true) {
mstp_port->ReceiveError = false; mstp_port->SilenceTimerReset(); mstp_port->ReceiveError = false; mstp_port->SilenceTimerReset();
/* 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; mstp_port->ReceivedInvalidFrame = true;
#if PRINT_ENABLED_RECEIVE_ERRORS printf_receive_error("MSTP: Rx Data: ReceiveError\n");
fprintf(stderr, "MSTP: Rx Data: ReceiveError\n");
#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;} mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
else } else if (mstp_port->DataAvailable == true) {
if (mstp_port->DataAvailable == true) { printf_receive_data("%02X ", mstp_port->DataRegister);
#if PRINT_ENABLED_RECEIVE_DATA
fprintf(stderr, "%02X ", mstp_port->DataRegister);
#endif
/* DataOctet */
if (mstp_port->Index < mstp_port->DataLength) { if (mstp_port->Index < mstp_port->DataLength) {
/* DataOctet */
mstp_port->DataCRC = mstp_port->DataCRC =
CRC_Calc_Data(mstp_port->DataRegister, mstp_port->DataCRC); CRC_Calc_Data(mstp_port->DataRegister, mstp_port->DataCRC);
mstp_port->InputBuffer[mstp_port->Index] = mstp_port->InputBuffer[mstp_port->Index] =
mstp_port->DataRegister; 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 */ /* CRC1 */
else
if (mstp_port->Index == mstp_port->DataLength) {
mstp_port->DataCRC = mstp_port->DataCRC =
CRC_Calc_Data(mstp_port->DataRegister, mstp_port->DataCRC); CRC_Calc_Data(mstp_port->DataRegister, mstp_port->DataCRC);
mstp_port->DataCRCActualMSB = mstp_port->DataRegister; mstp_port->DataCRCActualMSB = mstp_port->DataRegister;
mstp_port->Index++; 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 */ /* CRC2 */
else
if (mstp_port->Index == (mstp_port->DataLength + 1)) {
mstp_port->DataCRC = mstp_port->DataCRC =
CRC_Calc_Data(mstp_port->DataRegister, mstp_port->DataCRC); CRC_Calc_Data(mstp_port->DataRegister, mstp_port->DataCRC);
mstp_port->DataCRCActualLSB = mstp_port->DataRegister; mstp_port->DataCRCActualLSB = mstp_port->DataRegister;
#if PRINT_ENABLED_RECEIVE_DATA printf_receive_data("%s", mstptext_frame_type(mstp_port->FrameType));
fprintf(stderr, "%s", mstptext_frame_type(mstp_port->FrameType));
#endif
/* STATE DATA CRC - no need for new state */ /* STATE DATA CRC - no need for new state */
/* indicate the complete reception of a valid frame */ /* indicate the complete reception of a valid frame */
if (mstp_port->DataCRC == 0xF0B8) { if (mstp_port->DataCRC == 0xF0B8) {
@@ -514,41 +497,46 @@ case MSTP_RECEIVE_STATE_DATA:
|| (mstp_port->Lurking)) { || (mstp_port->Lurking)) {
/* ForUs */ /* ForUs */
/* indicate that a frame with no data has been received */ /* indicate that a frame with no data has been received */
mstp_port->ReceivedValidFrame = true;} mstp_port->ReceivedValidFrame = true;
else { } else {
/* NotForUs - drop */ /* NotForUs - drop */
} }
} } else {
else {
mstp_port->ReceivedInvalidFrame = true; mstp_port->ReceivedInvalidFrame = true;
#if PRINT_ENABLED_RECEIVE_ERRORS printf_receive_error("MSTP: Rx Data: BadCRC [%02X]\n",
fprintf(stderr, "MSTP: Rx Data: BadCRC [%02X]\n",
mstp_port->DataRegister); mstp_port->DataRegister);
#endif
} }
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;} mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
mstp_port->DataAvailable = false; mstp_port->SilenceTimerReset();} }
break; default: mstp_port->DataAvailable = false;
mstp_port->SilenceTimerReset();
}
break;
default:
/* shouldn't get here - but if we do... */ /* shouldn't get here - but if we do... */
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE; break;} mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
#if PRINT_ENABLED_RECEIVE_DATA break;
}
if ((receive_state != MSTP_RECEIVE_STATE_IDLE) && if ((receive_state != MSTP_RECEIVE_STATE_IDLE) &&
(mstp_port->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; receive_state = mstp_port->receive_state;
#endif return;
return;} }
/* returns true if we need to transition immediately */ /* returns true if we need to transition immediately */
bool MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t * mstp_port) { bool MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t * mstp_port) {
unsigned length = 0; uint8_t next_poll_station = 0; unsigned length = 0;
uint8_t next_this_station = 0; uint8_t next_next_station = 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; uint16_t my_timeout = 10, ns_timeout = 0;
/* transition immediately to the next state */ /* transition immediately to the next state */
bool transition_now = false; bool transition_now = false;
#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 */
next_poll_station = next_poll_station =
(mstp_port->Poll_Station + 1) % (mstp_port->Nmax_master + 1); (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); (mstp_port->This_Station + 1) % (mstp_port->Nmax_master + 1);
next_next_station = next_next_station =
(mstp_port->Next_Station + 1) % (mstp_port->Nmax_master + 1); (mstp_port->Next_Station + 1) % (mstp_port->Nmax_master + 1);
#if PRINT_ENABLED_MASTER
if (mstp_port->master_state != master_state) { if (mstp_port->master_state != master_state) {
master_state = mstp_port->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: 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->This_Station, next_this_station,
mstp_port->Next_Station, next_next_station, mstp_port->Next_Station, next_next_station,
mstp_port->Poll_Station, next_poll_station, mstp_port->Poll_Station, next_poll_station,
mstp_port->EventCount, mstp_port->TokenCount, mstp_port->EventCount, mstp_port->TokenCount,
mstp_port->SilenceTimer(), mstp_port->SilenceTimer(),
mstptext_master_state(mstp_port->master_state));} mstptext_master_state(mstp_port->master_state));
#endif }
switch (mstp_port->master_state) { switch (mstp_port->master_state) {
case MSTP_MASTER_STATE_INITIALIZE: case MSTP_MASTER_STATE_INITIALIZE:
/* DoneInitializing */ /* DoneInitializing */
@@ -579,50 +565,62 @@ case MSTP_MASTER_STATE_INITIALIZE:
/* receives the token */ /* receives the token */
mstp_port->TokenCount = Npoll; mstp_port->SoleMaster = false; mstp_port->TokenCount = Npoll; mstp_port->SoleMaster = false;
mstp_port->master_state = MSTP_MASTER_STATE_IDLE; mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
transition_now = true; break; transition_now = true;
/* In the IDLE state, the node waits for a frame. */ break;
case MSTP_MASTER_STATE_IDLE: case MSTP_MASTER_STATE_IDLE:
/* In the IDLE state, the node waits for a frame. */
/* LostToken */ /* LostToken */
if (mstp_port->SilenceTimer() >= Tno_token) { if (mstp_port->SilenceTimer() >= Tno_token) {
/* assume that the token has been lost */ /* assume that the token has been lost */
mstp_port->EventCount = 0; /* Addendum 135-2004d-8 */ mstp_port->EventCount = 0; /* Addendum 135-2004d-8 */
mstp_port->master_state = MSTP_MASTER_STATE_NO_TOKEN; mstp_port->master_state = MSTP_MASTER_STATE_NO_TOKEN;
transition_now = true;} transition_now = true;
} else if (mstp_port->ReceivedInvalidFrame == true) {
/* ReceivedInvalidFrame */ /* ReceivedInvalidFrame */
else
if (mstp_port->ReceivedInvalidFrame == true) {
/* invalid frame was received */ /* invalid frame was received */
mstp_port->ReceivedInvalidFrame = false; mstp_port->ReceivedInvalidFrame = false;
} else if (mstp_port->ReceivedValidFrame == true) {
/* wait for the next frame - remain in IDLE */ /* wait for the next frame - remain in IDLE */
} printf_master(
else "MSTP: ReceivedValidFrame "
if (mstp_port->ReceivedValidFrame == true) { "Src=%02X Dest=%02X DataLen=%u "
#if PRINT_ENABLED_MASTER "FC=%u ST=%u Type=%s\n",
fprintf(stderr, mstp_port->SourceAddress,
"MSTP: ReceivedValidFrame Src=%02X Dest=%02X DataLen=%u FC=%u ST=%u Type=%s\n", mstp_port->DestinationAddress,
mstp_port->SourceAddress, mstp_port->DestinationAddress,
mstp_port->DataLength, mstp_port->FrameCount, mstp_port->DataLength, mstp_port->FrameCount,
mstp_port->SilenceTimer(), mstp_port->SilenceTimer(),
mstptext_frame_type(mstp_port->FrameType)); mstptext_frame_type(mstp_port->FrameType));
#endif
/* destined for me! */ /* destined for me! */
if ((mstp_port->DestinationAddress == mstp_port->This_Station) || if ((mstp_port->DestinationAddress == mstp_port->This_Station) ||
(mstp_port->DestinationAddress == MSTP_BROADCAST_ADDRESS)) { (mstp_port->DestinationAddress == MSTP_BROADCAST_ADDRESS)) {
switch (mstp_port->FrameType) { switch (mstp_port->FrameType) {
/* ReceivedToken */
case FRAME_TYPE_TOKEN: case FRAME_TYPE_TOKEN:
/* ReceivedToken */
/* tokens can't be broadcast */ /* tokens can't be broadcast */
if (mstp_port->DestinationAddress == if (mstp_port->DestinationAddress ==
MSTP_BROADCAST_ADDRESS) MSTP_BROADCAST_ADDRESS) {
break; mstp_port->ReceivedValidFrame = false; break;
mstp_port->FrameCount = 0; mstp_port->SoleMaster = false; }
mstp_port->ReceivedValidFrame = false;
mstp_port->FrameCount = 0;
mstp_port->SoleMaster = false;
mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN; mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN;
transition_now = true; break; transition_now = true;
/* ReceivedPFM */ break;
case FRAME_TYPE_POLL_FOR_MASTER: 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 */ /* 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; */ /*mstp_port->ReplyPostponedTimer = 0; */
/* indicate successful reception to the higher layers */ /* indicate successful reception to the higher layers */
MSTP_Put_Receive(mstp_port); 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 != if (mstp_port->DestinationAddress !=
MSTP_BROADCAST_ADDRESS) { MSTP_BROADCAST_ADDRESS) {
mstp_port->master_state = mstp_port->master_state =
MSTP_MASTER_STATE_ANSWER_DATA_REQUEST;} 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: 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: default:
break;} break;
}
} }
/* For DATA_EXPECTING_REPLY, we will keep the Rx Frame for /* For DATA_EXPECTING_REPLY, we will keep the Rx Frame for
reference, and the flag will be cleared in the next state */ reference, and the flag will be cleared in the next state */
if (mstp_port->master_state != if (mstp_port->master_state !=
MSTP_MASTER_STATE_ANSWER_DATA_REQUEST) { MSTP_MASTER_STATE_ANSWER_DATA_REQUEST) {
mstp_port->ReceivedValidFrame = false;} mstp_port->ReceivedValidFrame = false;
}
} }
break; break;
case MSTP_MASTER_STATE_USE_TOKEN:
/* In the USE_TOKEN state, the node is allowed to send one or */ /* In the USE_TOKEN state, the node is allowed to send one or */
/* more data frames. These may be BACnet Data frames or */ /* more data frames. These may be BACnet Data frames or */
/* proprietary frames. */ /* proprietary frames. */
case MSTP_MASTER_STATE_USE_TOKEN:
/* FIXME: We could wait for up to Tusage_delay */ /* 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 */ /* NothingToSend */
mstp_port->FrameCount = mstp_port->Nmax_info_frames; mstp_port->FrameCount = mstp_port->Nmax_info_frames;
mstp_port->master_state = mstp_port->master_state =
MSTP_MASTER_STATE_DONE_WITH_TOKEN; transition_now = true;} MSTP_MASTER_STATE_DONE_WITH_TOKEN;
else { transition_now = true;
} else {
uint8_t frame_type = mstp_port->OutputBuffer[2]; uint8_t frame_type = mstp_port->OutputBuffer[2];
uint8_t destination = mstp_port->OutputBuffer[3]; uint8_t destination = mstp_port->OutputBuffer[3];
RS485_Send_Frame(mstp_port, RS485_Send_Frame(mstp_port,
(uint8_t *) & mstp_port->OutputBuffer[0], length); (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: case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY:
/* SendAndWait */ /* SendAndWait */
if (destination == MSTP_BROADCAST_ADDRESS) if (destination == MSTP_BROADCAST_ADDRESS) {
mstp_port->master_state = mstp_port->master_state =
MSTP_MASTER_STATE_DONE_WITH_TOKEN; MSTP_MASTER_STATE_DONE_WITH_TOKEN;
else } else {
mstp_port->master_state = MSTP_MASTER_STATE_WAIT_FOR_REPLY; break; case FRAME_TYPE_TEST_REQUEST: mstp_port->master_state =
mstp_port->master_state = MSTP_MASTER_STATE_WAIT_FOR_REPLY; break; case FRAME_TYPE_TEST_RESPONSE: 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: case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY:
default: default:
/* SendNoWait */ /* SendNoWait */
mstp_port->master_state = mstp_port->master_state =
MSTP_MASTER_STATE_DONE_WITH_TOKEN; break;} MSTP_MASTER_STATE_DONE_WITH_TOKEN;
break;
}
} }
break; break;
case MSTP_MASTER_STATE_WAIT_FOR_REPLY:
/* 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:
if (mstp_port->SilenceTimer() >= Treply_timeout) { if (mstp_port->SilenceTimer() >= Treply_timeout) {
/* ReplyTimeout */ /* ReplyTimeout */
/* assume that the request has failed */ /* 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, */ /* 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.) */
transition_now = true;} transition_now = true;
else { } else {
if (mstp_port->ReceivedInvalidFrame == true) { if (mstp_port->ReceivedInvalidFrame == true) {
/* InvalidFrame */ /* InvalidFrame */
/* error in frame reception */ /* error in frame reception */
mstp_port->ReceivedInvalidFrame = false; mstp_port->ReceivedInvalidFrame = false;
mstp_port->master_state = mstp_port->master_state =
MSTP_MASTER_STATE_DONE_WITH_TOKEN; transition_now = true;} MSTP_MASTER_STATE_DONE_WITH_TOKEN;
else transition_now = true;
if (mstp_port->ReceivedValidFrame == true) { } else if (mstp_port->ReceivedValidFrame == true) {
if (mstp_port->DestinationAddress == mstp_port->This_Station) { if (mstp_port->DestinationAddress == mstp_port->This_Station) {
switch (mstp_port->FrameType) { switch (mstp_port->FrameType) {
case FRAME_TYPE_REPLY_POSTPONED: case FRAME_TYPE_REPLY_POSTPONED:
/* ReceivedReplyPostponed */ /* ReceivedReplyPostponed */
mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN; break; case FRAME_TYPE_TEST_RESPONSE: mstp_port->master_state =
mstp_port->master_state = MSTP_MASTER_STATE_IDLE; break; case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: 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 */ /* ReceivedReply */
/* or a proprietary type that indicates a reply */ /* or a proprietary type that indicates a reply */
/* indicate successful reception to the higher layers */ /* 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 /* if proprietary frame was expected, you might
need to transition to DONE WITH TOKEN */ need to transition to DONE WITH TOKEN */
mstp_port->master_state = MSTP_MASTER_STATE_IDLE; mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
break;} break;
} }
else { } else {
/* ReceivedUnexpectedFrame */ /* ReceivedUnexpectedFrame */
/* an unexpected frame was received */ /* an unexpected frame was received */
/* This may indicate the presence of multiple tokens. */ /* This may indicate the presence of multiple tokens. */
/* Synchronize with the network. */ /* Synchronize with the network. */
/* This action drops the token. */ /* This action drops the token. */
mstp_port->master_state = MSTP_MASTER_STATE_IDLE;} mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
mstp_port->ReceivedValidFrame = false; transition_now = true;} }
mstp_port->ReceivedValidFrame = false;
transition_now = true;
}
} }
break; break;
case MSTP_MASTER_STATE_DONE_WITH_TOKEN:
/* The DONE_WITH_TOKEN state either sends another data frame, */ /* The DONE_WITH_TOKEN state either sends another data frame, */
/* passes the token, or initiates a Poll For Master cycle. */ /* passes the token, or initiates a Poll For Master cycle. */
case MSTP_MASTER_STATE_DONE_WITH_TOKEN:
/* SendAnotherFrame */ /* SendAnotherFrame */
if (mstp_port->FrameCount < mstp_port->Nmax_info_frames) { if (mstp_port->FrameCount < mstp_port->Nmax_info_frames) {
/* then this node may send another information frame */ /* then this node may send another information frame */
/* before passing the token. */ /* before passing the token. */
mstp_port->master_state = MSTP_MASTER_STATE_USE_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 */ /* Npoll changed in Errata SSPC-135-2004 */
else
if (mstp_port->TokenCount < (Npoll - 1)) {
if ((mstp_port->SoleMaster == true) && if ((mstp_port->SoleMaster == true) &&
(mstp_port->Next_Station != next_this_station)) { (mstp_port->Next_Station != next_this_station)) {
/* SoleMaster */ /* SoleMaster */
/* there are no other known master nodes to */ /* there are no other known master nodes to */
/* which the token may be sent (true master-slave operation). */ /* 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; mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN;
transition_now = true;} transition_now = true;
else { } else {
/* SendToken */ /* SendToken */
/* Npoll changed in Errata SSPC-135-2004 */ /* Npoll changed in Errata SSPC-135-2004 */
/* The comparison of NS and TS+1 eliminates the Poll For Master */ /* 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 */ /* 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, 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->EventCount = 0;
mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN;} mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN;
} }
else } else if (next_poll_station == mstp_port->Next_Station) {
if (next_poll_station == mstp_port->Next_Station) {
if (mstp_port->SoleMaster == true) { if (mstp_port->SoleMaster == true) {
/* SoleMasterRestartMaintenancePFM */ /* SoleMasterRestartMaintenancePFM */
mstp_port->Poll_Station = next_next_station; 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, FRAME_TYPE_POLL_FOR_MASTER, mstp_port->Poll_Station,
mstp_port->This_Station, NULL, 0); mstp_port->This_Station, NULL, 0);
/* no known successor node */ /* 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 */ /* mstp_port->EventCount = 0; removed in Addendum 135-2004d-8 */
/* find a new successor to TS */ /* 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;
else { } else {
/* ResetMaintenancePFM */ /* ResetMaintenancePFM */
mstp_port->Poll_Station = mstp_port->This_Station; mstp_port->Poll_Station = mstp_port->This_Station;
/* transmit a Token frame to NS */ /* 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->EventCount = 0;
mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN;} mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN;
} }
else { } else {
/* SendMaintenancePFM */ /* SendMaintenancePFM */
mstp_port->Poll_Station = next_poll_station; mstp_port->Poll_Station = next_poll_station;
MSTP_Create_And_Send_Frame(mstp_port, MSTP_Create_And_Send_Frame(mstp_port,
FRAME_TYPE_POLL_FOR_MASTER, mstp_port->Poll_Station, FRAME_TYPE_POLL_FOR_MASTER, mstp_port->Poll_Station,
mstp_port->This_Station, NULL, 0); mstp_port->This_Station, NULL, 0);
mstp_port->RetryCount = 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; break;
case MSTP_MASTER_STATE_PASS_TOKEN:
/* 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:
if (mstp_port->SilenceTimer() <= Tusage_timeout) { if (mstp_port->SilenceTimer() <= Tusage_timeout) {
if (mstp_port->EventCount > Nmin_octets) { if (mstp_port->EventCount > Nmin_octets) {
/* SawTokenUser */ /* 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;
transition_now = true;} transition_now = true;
} }
else { } else {
if (mstp_port->RetryCount < Nretry_token) { if (mstp_port->RetryCount < Nretry_token) {
/* RetrySendToken */ /* 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, FRAME_TYPE_TOKEN, MSTP_Create_And_Send_Frame(mstp_port, FRAME_TYPE_TOKEN,
mstp_port->Next_Station, mstp_port->This_Station, NULL, 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 */ /* re-enter the current state to listen for NS */
/* to begin using the token. */ /* to begin using the token. */
} } else {
else {
/* FindNewSuccessor */ /* FindNewSuccessor */
/* Assume that NS has failed. */ /* Assume that NS has failed. */
mstp_port->Poll_Station = next_next_station; mstp_port->Poll_Station = next_next_station;
@@ -824,11 +867,11 @@ case MSTP_MASTER_STATE_PASS_TOKEN:
MSTP_MASTER_STATE_POLL_FOR_MASTER;} MSTP_MASTER_STATE_POLL_FOR_MASTER;}
} }
break; break;
case MSTP_MASTER_STATE_NO_TOKEN:
/* The NO_TOKEN state is entered if mstp_port->SilenceTimer() becomes greater */ /* The NO_TOKEN state is entered if mstp_port->SilenceTimer() becomes greater */
/* than Tno_token, indicating that there has been no network activity */ /* than Tno_token, indicating that there has been no network activity */
/* for that period of time. The timeout is continued to determine */ /* for that period of time. The timeout is continued to determine */
/* whether or not this node may create a token. */ /* whether or not this node may create a 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);
if (mstp_port->SilenceTimer() < my_timeout) { if (mstp_port->SilenceTimer() < my_timeout) {
if (mstp_port->EventCount > Nmin_octets) { if (mstp_port->EventCount > Nmin_octets) {
@@ -836,9 +879,9 @@ case MSTP_MASTER_STATE_NO_TOKEN:
/* 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;
transition_now = true;} transition_now = true;
} }
else { } else {
ns_timeout = ns_timeout =
Tno_token + (Tslot * (mstp_port->This_Station + 1)); Tno_token + (Tslot * (mstp_port->This_Station + 1));
if (mstp_port->SilenceTimer() < ns_timeout) { 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 */ /* mstp_port->EventCount = 0; removed Addendum 135-2004d-8 */
/* enter the POLL_FOR_MASTER state to find a new successor to TS. */ /* enter the POLL_FOR_MASTER state to find a new successor to TS. */
mstp_port->master_state = mstp_port->master_state =
MSTP_MASTER_STATE_POLL_FOR_MASTER;} MSTP_MASTER_STATE_POLL_FOR_MASTER;
}
} }
break; break;
case MSTP_MASTER_STATE_POLL_FOR_MASTER:
/* 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:
if (mstp_port->ReceivedValidFrame == true) { if (mstp_port->ReceivedValidFrame == true) {
if ((mstp_port->DestinationAddress == mstp_port->This_Station) if ((mstp_port->DestinationAddress == mstp_port->This_Station)
&& (mstp_port->FrameType == && (mstp_port->FrameType ==
@@ -877,18 +921,18 @@ case MSTP_MASTER_STATE_POLL_FOR_MASTER:
NULL, 0); NULL, 0);
mstp_port->Poll_Station = mstp_port->This_Station; mstp_port->Poll_Station = mstp_port->This_Station;
mstp_port->TokenCount = 0; mstp_port->RetryCount = 0; mstp_port->TokenCount = 0; mstp_port->RetryCount = 0;
mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN;} mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN;
else { } else {
/* ReceivedUnexpectedFrame */ /* ReceivedUnexpectedFrame */
/* An unexpected frame was received. */ /* An unexpected frame was received. */
/* This may indicate the presence of multiple tokens. */ /* This may indicate the presence of multiple tokens. */
/* enter the IDLE state to synchronize with the network. */ /* enter the IDLE state to synchronize with the network. */
/* This action drops the token. */ /* This action drops the token. */
mstp_port->master_state = MSTP_MASTER_STATE_IDLE; mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
transition_now = true;} transition_now = true;
mstp_port->ReceivedValidFrame = false;} }
else mstp_port->ReceivedValidFrame = false;
if ((mstp_port->SilenceTimer() > Tusage_timeout) || } else if ((mstp_port->SilenceTimer() > Tusage_timeout) ||
(mstp_port->ReceivedInvalidFrame == true)) { (mstp_port->ReceivedInvalidFrame == true)) {
if (mstp_port->SoleMaster == true) { if (mstp_port->SoleMaster == true) {
/* SoleMaster */ /* SoleMaster */
@@ -897,8 +941,8 @@ case MSTP_MASTER_STATE_POLL_FOR_MASTER:
mstp_port->FrameCount = 0; mstp_port->FrameCount = 0;
/* mstp_port->TokenCount++; removed in 2004 */ /* mstp_port->TokenCount++; removed in 2004 */
mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN; mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN;
transition_now = true;} transition_now = true;
else { } else {
if (mstp_port->Next_Station != mstp_port->This_Station) { if (mstp_port->Next_Station != mstp_port->This_Station) {
/* DoneWithPFM */ /* DoneWithPFM */
/* There was no valid reply to the maintenance */ /* 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 */ /* 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, mstp_port->Next_Station, mstp_port->This_Station,
NULL, 0); mstp_port->RetryCount = 0; NULL, 0);
mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN;} mstp_port->RetryCount = 0;
else { mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN;
} else {
if (next_poll_station != mstp_port->This_Station) { if (next_poll_station != mstp_port->This_Station) {
/* SendNextPFM */ /* SendNextPFM */
mstp_port->Poll_Station = next_poll_station; 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, MSTP_Create_And_Send_Frame(mstp_port,
FRAME_TYPE_POLL_FOR_MASTER, FRAME_TYPE_POLL_FOR_MASTER,
mstp_port->Poll_Station, mstp_port->This_Station, 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. */ /* Re-enter the current state. */
} } else {
else {
/* DeclareSoleMaster */ /* DeclareSoleMaster */
/* to indicate that this station is the only master */ /* to indicate that this station is the only master */
mstp_port->SoleMaster = true; mstp_port->SoleMaster = true;
mstp_port->FrameCount = 0; mstp_port->FrameCount = 0;
mstp_port->master_state = 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; break;
case MSTP_MASTER_STATE_ANSWER_DATA_REQUEST:
/* The ANSWER_DATA_REQUEST state is entered when a */ /* The ANSWER_DATA_REQUEST state is entered when a */
/* BACnet Data Expecting Reply, a Test_Request, or */ /* BACnet Data Expecting Reply, a Test_Request, or */
/* a proprietary frame that expects a reply is received. */ /* 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 */ /* FIXME: we could wait for up to Treply_delay */
length = MSTP_Get_Reply(mstp_port, 0); if (length > 0) { length = MSTP_Get_Reply(mstp_port, 0); if (length > 0) {
/* Reply */ /* Reply */
@@ -946,8 +994,8 @@ case MSTP_MASTER_STATE_ANSWER_DATA_REQUEST:
/* and enter the IDLE state to wait for the next 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); (uint8_t *) & mstp_port->OutputBuffer[0], length);
mstp_port->master_state = MSTP_MASTER_STATE_IDLE;} mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
else { } else {
/* DeferredReply */ /* DeferredReply */
/* If no reply will be available from the higher layers */ /* If no reply will be available from the higher layers */
/* within Treply_delay after the reception of the */ /* 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, MSTP_Create_And_Send_Frame(mstp_port,
FRAME_TYPE_REPLY_POSTPONED, mstp_port->SourceAddress, FRAME_TYPE_REPLY_POSTPONED, mstp_port->SourceAddress,
mstp_port->This_Station, NULL, 0); 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 */ /* clear our flag we were holding for comparison */
mstp_port->ReceivedValidFrame = false; break; default: mstp_port->ReceivedValidFrame = false;
mstp_port->master_state = MSTP_MASTER_STATE_IDLE; break;} 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: This_Station assumed to be set with the MAC address */
/* note: Nmax_info_frames assumed to be set (default=1) */ /* note: Nmax_info_frames assumed to be set (default=1) */