Added extra sub-state for MS/TP from Addendum 135-2008v.

This commit is contained in:
skarg
2010-06-26 03:55:20 +00:00
parent 0a02accdb1
commit 6f9ba36967
6 changed files with 252 additions and 178 deletions
+42 -31
View File
@@ -1,6 +1,6 @@
/*####COPYRIGHTBEGIN#### /*####COPYRIGHTBEGIN####
------------------------------------------- -------------------------------------------
Copyright (C) 2007 Steve Karg Copyright (C) 2007-2010 Steve Karg
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
@@ -159,13 +159,13 @@ static uint8_t This_Station;
/* nodes. This may be used to allocate more or less of the available link */ /* nodes. This may be used to allocate more or less of the available link */
/* bandwidth to particular nodes. If Max_Info_Frames is not writable in a */ /* bandwidth to particular nodes. If Max_Info_Frames is not writable in a */
/* node, its value shall be 1. */ /* node, its value shall be 1. */
static uint8_t Nmax_info_frames; static uint8_t Nmax_info_frames = 1;
/* This parameter represents the value of the Max_Master property of the */ /* This parameter represents the value of the Max_Master property of the */
/* node's Device object. The value of Max_Master specifies the highest */ /* node's Device object. The value of Max_Master specifies the highest */
/* allowable address for master nodes. The value of Max_Master shall be */ /* allowable address for master nodes. The value of Max_Master shall be */
/* less than or equal to 127. If Max_Master is not writable in a node, */ /* less than or equal to 127. If Max_Master is not writable in a node, */
/* its value shall be 127. */ /* its value shall be 127. */
static uint8_t Nmax_master; static uint8_t Nmax_master = 127;
/* An array of octets, used to store octets for transmitting */ /* An array of octets, used to store octets for transmitting */
/* OutputBuffer is indexed from 0 to OutputBufferSize-1. */ /* OutputBuffer is indexed from 0 to OutputBufferSize-1. */
/* The MAX_PDU size of a frame is MAX_APDU + MAX_NPDU octets. */ /* The MAX_PDU size of a frame is MAX_APDU + MAX_NPDU octets. */
@@ -191,7 +191,7 @@ static uint8_t TransmitPacketDest;
/* node must wait for a remote node to begin using a token or replying to */ /* node must wait for a remote node to begin using a token or replying to */
/* a Poll For Master frame: 20 milliseconds. (Implementations may use */ /* a Poll For Master frame: 20 milliseconds. (Implementations may use */
/* larger values for this timeout, not to exceed 100 milliseconds.) */ /* larger values for this timeout, not to exceed 100 milliseconds.) */
#define Tusage_timeout 25 #define Tusage_timeout 60
/* The number of tokens received or used before a Poll For Master cycle */ /* The number of tokens received or used before a Poll For Master cycle */
/* is executed: 50. */ /* is executed: 50. */
@@ -241,7 +241,7 @@ static uint8_t TransmitPacketDest;
bool dlmstp_init( bool dlmstp_init(
char *ifname) char *ifname)
{ {
(void) ifname; ifname = ifname;
/* initialize hardware */ /* initialize hardware */
RS485_Initialize(); RS485_Initialize();
@@ -403,8 +403,8 @@ static void MSTP_Send_Frame(
uint8_t frame_type, /* type of frame to send - see defines */ uint8_t frame_type, /* type of frame to send - see defines */
uint8_t destination, /* destination address */ uint8_t destination, /* destination address */
uint8_t source, /* source address */ uint8_t source, /* source address */
uint8_t * data, /* any data to be sent - may be null */ uint8_t * pdu, /* any data to be sent - may be null */
uint16_t data_len) uint16_t pdu_len)
{ /* number of bytes of data (up to 501) */ { /* number of bytes of data (up to 501) */
uint8_t crc8 = 0xFF; /* used to calculate the crc value */ uint8_t crc8 = 0xFF; /* used to calculate the crc value */
uint16_t crc16 = 0xFFFF; /* used to calculate the crc value */ uint16_t crc16 = 0xFFFF; /* used to calculate the crc value */
@@ -420,24 +420,24 @@ static void MSTP_Send_Frame(
crc8 = CRC_Calc_Header(buffer[3], crc8); crc8 = CRC_Calc_Header(buffer[3], crc8);
buffer[4] = source; buffer[4] = source;
crc8 = CRC_Calc_Header(buffer[4], crc8); crc8 = CRC_Calc_Header(buffer[4], crc8);
buffer[5] = HI_BYTE(data_len); buffer[5] = HI_BYTE(pdu_len);
crc8 = CRC_Calc_Header(buffer[5], crc8); crc8 = CRC_Calc_Header(buffer[5], crc8);
buffer[6] = LO_BYTE(data_len); buffer[6] = LO_BYTE(pdu_len);
crc8 = CRC_Calc_Header(buffer[6], crc8); crc8 = CRC_Calc_Header(buffer[6], crc8);
buffer[7] = ~crc8; buffer[7] = ~crc8;
RS485_Turnaround_Delay(); RS485_Turnaround_Delay();
RS485_Transmitter_Enable(true); RS485_Transmitter_Enable(true);
RS485_Send_Data(buffer, 8); RS485_Send_Data(buffer, 8);
/* send any data */ /* send any data */
if (data_len) { if (pdu_len) {
/* calculate CRC for any data */ /* calculate CRC for any data */
for (i = 0; i < data_len; i++) { for (i = 0; i < pdu_len; i++) {
crc16 = CRC_Calc_Data(data[i], crc16); crc16 = CRC_Calc_Data(pdu[i], crc16);
} }
crc16 = ~crc16; crc16 = ~crc16;
buffer[0] = (crc16 & 0x00FF); buffer[0] = (crc16 & 0x00FF);
buffer[1] = ((crc16 & 0xFF00) >> 8); buffer[1] = ((crc16 & 0xFF00) >> 8);
RS485_Send_Data(data, data_len); RS485_Send_Data(pdu, pdu_len);
RS485_Send_Data(buffer, 2); RS485_Send_Data(buffer, 2);
} }
RS485_Transmitter_Enable(false); RS485_Transmitter_Enable(false);
@@ -704,8 +704,11 @@ static bool MSTP_Master_Node_FSM(
bool transition_now = false; bool transition_now = false;
/* some calculations that several states need */ /* some calculations that several states need */
/* (PS+1) modulo (Nmax_master+1) */
next_poll_station = (Poll_Station + 1) % (Nmax_master + 1); next_poll_station = (Poll_Station + 1) % (Nmax_master + 1);
/* (TS+1) modulo (Nmax_master+1) */
next_this_station = (This_Station + 1) % (Nmax_master + 1); next_this_station = (This_Station + 1) % (Nmax_master + 1);
/* (NS +1) modulo (Nmax_master+1) */
next_next_station = (Next_Station + 1) % (Nmax_master + 1); next_next_station = (Next_Station + 1) % (Nmax_master + 1);
switch (Master_State) { switch (Master_State) {
case MSTP_MASTER_STATE_INITIALIZE: case MSTP_MASTER_STATE_INITIALIZE:
@@ -902,8 +905,7 @@ static bool MSTP_Master_Node_FSM(
} }
/* Npoll changed in Errata SSPC-135-2004 */ /* Npoll changed in Errata SSPC-135-2004 */
else if (TokenCount < (Npoll - 1)) { else if (TokenCount < (Npoll - 1)) {
if ((MSTP_Flag.SoleMaster == true) && if (MSTP_Flag.SoleMaster == true) {
(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 /* which the token may be sent
@@ -913,21 +915,30 @@ static bool MSTP_Master_Node_FSM(
Master_State = MSTP_MASTER_STATE_USE_TOKEN; Master_State = MSTP_MASTER_STATE_USE_TOKEN;
transition_now = true; transition_now = true;
} else { } else {
/* SendToken */ if (Next_Station == This_Station) {
/* Npoll changed in Errata SSPC-135-2004 */ /* NextStationUnknown - added in Addendum 135-2008v-1 */
/* The comparison of NS and TS+1 Poll_Station = next_this_station;
eliminates the Poll For Master MSTP_Send_Frame(FRAME_TYPE_POLL_FOR_MASTER,
if there are no addresses between Poll_Station, This_Station, NULL, 0);
TS and NS, since there is no RetryCount = 0;
address at which a new master node Master_State = MSTP_MASTER_STATE_POLL_FOR_MASTER;
may be found in that case. */ } else if (Next_Station == next_this_station) {
TokenCount++; /* SendToken */
/* transmit a Token frame to NS */ /* Npoll changed in Errata SSPC-135-2004 */
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station, /* The comparison of NS and TS+1
This_Station, NULL, 0); eliminates the Poll For Master
RetryCount = 0; if there are no addresses between
EventCount = 0; TS and NS, since there is no
Master_State = MSTP_MASTER_STATE_PASS_TOKEN; address at which a new master node
may be found in that case. */
TokenCount++;
/* transmit a Token frame to NS */
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
This_Station, NULL, 0);
RetryCount = 0;
EventCount = 0;
Master_State = MSTP_MASTER_STATE_PASS_TOKEN;
}
} }
} else if (next_poll_station == Next_Station) { } else if (next_poll_station == Next_Station) {
if (MSTP_Flag.SoleMaster == true) { if (MSTP_Flag.SoleMaster == true) {
@@ -1001,7 +1012,7 @@ static bool MSTP_Master_Node_FSM(
} }
} }
break; break;
/* The NO_TOKEN state is entered if Timer_Silence() /* The NO_TOKEN state is entered if Silence Timer
becomes greater than Tno_token, indicating that becomes greater than Tno_token, indicating that
there has been no network activity for that period there has been no network activity for that period
of time. The timeout is continued to determine of time. The timeout is continued to determine
+60 -35
View File
@@ -162,13 +162,13 @@ static uint8_t This_Station;
/* nodes. This may be used to allocate more or less of the available link */ /* nodes. This may be used to allocate more or less of the available link */
/* bandwidth to particular nodes. If Max_Info_Frames is not writable in a */ /* bandwidth to particular nodes. If Max_Info_Frames is not writable in a */
/* node, its value shall be 1. */ /* node, its value shall be 1. */
static uint8_t Nmax_info_frames; static uint8_t Nmax_info_frames = 1;
/* This parameter represents the value of the Max_Master property of the */ /* This parameter represents the value of the Max_Master property of the */
/* node's Device object. The value of Max_Master specifies the highest */ /* node's Device object. The value of Max_Master specifies the highest */
/* allowable address for master nodes. The value of Max_Master shall be */ /* allowable address for master nodes. The value of Max_Master shall be */
/* less than or equal to 127. If Max_Master is not writable in a node, */ /* less than or equal to 127. If Max_Master is not writable in a node, */
/* its value shall be 127. */ /* its value shall be 127. */
static uint8_t Nmax_master; static uint8_t Nmax_master = 127;
/* An array of octets, used to store octets for transmitting */ /* An array of octets, used to store octets for transmitting */
/* OutputBuffer is indexed from 0 to OutputBufferSize-1. */ /* OutputBuffer is indexed from 0 to OutputBufferSize-1. */
/* The MAX_PDU size of a frame is MAX_APDU + MAX_NPDU octets. */ /* The MAX_PDU size of a frame is MAX_APDU + MAX_NPDU octets. */
@@ -188,13 +188,13 @@ static uint8_t TransmitPacketDest;
/* that a node must wait for a station to begin replying to a */ /* that a node must wait for a station to begin replying to a */
/* confirmed request: 255 milliseconds. (Implementations may use */ /* confirmed request: 255 milliseconds. (Implementations may use */
/* larger values for this timeout, not to exceed 300 milliseconds.) */ /* larger values for this timeout, not to exceed 300 milliseconds.) */
#define Treply_timeout 295 #define Treply_timeout 260
/* The minimum time without a DataAvailable or ReceiveError event that a */ /* The minimum time without a DataAvailable or ReceiveError event that a */
/* node must wait for a remote node to begin using a token or replying to */ /* node must wait for a remote node to begin using a token or replying to */
/* a Poll For Master frame: 20 milliseconds. (Implementations may use */ /* a Poll For Master frame: 20 milliseconds. (Implementations may use */
/* larger values for this timeout, not to exceed 100 milliseconds.) */ /* larger values for this timeout, not to exceed 100 milliseconds.) */
#define Tusage_timeout 95 #define Tusage_timeout 60
/* The number of tokens received or used before a Poll For Master cycle */ /* The number of tokens received or used before a Poll For Master cycle */
/* is executed: 50. */ /* is executed: 50. */
@@ -219,6 +219,11 @@ static uint8_t TransmitPacketDest;
/* of a frame the node is transmitting: 20 bit times. */ /* of a frame the node is transmitting: 20 bit times. */
#define Tframe_gap 20 #define Tframe_gap 20
/* The maximum time after the end of the stop bit of the final */
/* octet of a transmitted frame before a node must disable its */
/* EIA-485 driver: 15 bit times. */
#define Tpostdrive 15
/* The maximum time a node may wait after reception of a frame that expects */ /* The maximum time a node may wait after reception of a frame that expects */
/* a reply before sending the first octet of a reply or Reply Postponed */ /* a reply before sending the first octet of a reply or Reply Postponed */
/* frame: 250 milliseconds. */ /* frame: 250 milliseconds. */
@@ -588,9 +593,9 @@ static bool MSTP_Master_Node_FSM(
/* When this counter reaches the value Nmax_info_frames, the node must */ /* When this counter reaches the value Nmax_info_frames, the node must */
/* pass the token. */ /* pass the token. */
static uint8_t FrameCount; static uint8_t FrameCount;
/* "Next Station," the MAC address of the node to which This Station passes */ /* "Next Station," the MAC address of the node to which This Station
/* the token. If the Next_Station is unknown, Next_Station shall be equal to */ passes the token. If the Next_Station is unknown, Next_Station shall
/* This_Station. */ be equal to This_Station. */
static uint8_t Next_Station; static uint8_t Next_Station;
/* "Poll Station," the MAC address of the node to which This Station last */ /* "Poll Station," the MAC address of the node to which This Station last */
/* sent a Poll For Master. This is used during token maintenance. */ /* sent a Poll For Master. This is used during token maintenance. */
@@ -598,10 +603,10 @@ static bool MSTP_Master_Node_FSM(
/* A counter of transmission retries used for Token and Poll For Master */ /* A counter of transmission retries used for Token and Poll For Master */
/* transmission. */ /* transmission. */
static unsigned RetryCount; static unsigned RetryCount;
/* The number of tokens received by this node. When this counter reaches the */ /* The number of tokens received by this node. When this counter reaches */
/* value Npoll, the node polls the address range between TS and NS for */ /* the value Npoll, the node polls the address range between TS and NS */
/* additional master nodes. TokenCount is set to zero at the end of the */ /* for additional master nodes. TokenCount is set to zero at the end of */
/* polling process. */ /* the polling process. */
static unsigned TokenCount; static unsigned TokenCount;
/* next-x-station calculations */ /* next-x-station calculations */
uint8_t next_poll_station = 0; uint8_t next_poll_station = 0;
@@ -613,8 +618,11 @@ static bool MSTP_Master_Node_FSM(
bool transition_now = false; bool transition_now = false;
/* some calculations that several states need */ /* some calculations that several states need */
/* (PS+1) modulo (Nmax_master+1) */
next_poll_station = (Poll_Station + 1) % (Nmax_master + 1); next_poll_station = (Poll_Station + 1) % (Nmax_master + 1);
/* (TS+1) modulo (Nmax_master+1) */
next_this_station = (This_Station + 1) % (Nmax_master + 1); next_this_station = (This_Station + 1) % (Nmax_master + 1);
/* (NS +1) modulo (Nmax_master+1) */
next_next_station = (Next_Station + 1) % (Nmax_master + 1); next_next_station = (Next_Station + 1) % (Nmax_master + 1);
switch (Master_State) { switch (Master_State) {
case MSTP_MASTER_STATE_INITIALIZE: case MSTP_MASTER_STATE_INITIALIZE:
@@ -669,7 +677,7 @@ static bool MSTP_Master_Node_FSM(
MSTP_Flag.ReceivePacketPending = true; MSTP_Flag.ReceivePacketPending = true;
break; break;
case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY: case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY:
/* indicate successful reception to the higher layers */ /* indicate successful reception to higher layers */
MSTP_Flag.ReceivePacketPending = true; MSTP_Flag.ReceivePacketPending = true;
/* broadcast DER just remains IDLE */ /* broadcast DER just remains IDLE */
if (DestinationAddress != MSTP_BROADCAST_ADDRESS) { if (DestinationAddress != MSTP_BROADCAST_ADDRESS) {
@@ -722,8 +730,10 @@ static bool MSTP_Master_Node_FSM(
FrameCount = Nmax_info_frames; FrameCount = Nmax_info_frames;
Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN; Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
/* Any retry of the data frame shall await the next entry */ /* Any retry of the data frame shall await the next entry */
/* to the USE_TOKEN state. (Because of the length of the timeout, */ /* to the USE_TOKEN state. */
/* this transition will cause the token to be passed regardless */ /* (Because of the length of the timeout, */
/* 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 {
@@ -747,8 +757,10 @@ static bool MSTP_Master_Node_FSM(
break; break;
case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY:
/* ReceivedReply */ /* ReceivedReply */
/* or a proprietary type that indicates a reply */ /* or a proprietary type that indicates
/* indicate successful reception to the higher layers */ a reply */
/* indicate successful reception to
the higher layers */
MSTP_Flag.ReceivePacketPending = true; MSTP_Flag.ReceivePacketPending = true;
Master_State = Master_State =
MSTP_MASTER_STATE_DONE_WITH_TOKEN; MSTP_MASTER_STATE_DONE_WITH_TOKEN;
@@ -786,28 +798,40 @@ static bool MSTP_Master_Node_FSM(
} }
/* Npoll changed in Errata SSPC-135-2004 */ /* Npoll changed in Errata SSPC-135-2004 */
else if (TokenCount < (Npoll - 1)) { else if (TokenCount < (Npoll - 1)) {
if ((MSTP_Flag.SoleMaster == true) && if (MSTP_Flag.SoleMaster == true) {
(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). */
FrameCount = 0; FrameCount = 0;
TokenCount++; TokenCount++;
Master_State = MSTP_MASTER_STATE_USE_TOKEN; Master_State = MSTP_MASTER_STATE_USE_TOKEN;
transition_now = true; transition_now = true;
} else { } else {
/* SendToken */ if (Next_Station == This_Station) {
/* Npoll changed in Errata SSPC-135-2004 */ /* NextStationUnknown - added in Addendum 135-2008v-1 */
/* The comparison of NS and TS+1 eliminates the Poll For Master */ Poll_Station = next_this_station;
/* if there are no addresses between TS and NS, since there is no */ MSTP_Send_Frame(FRAME_TYPE_POLL_FOR_MASTER,
/* address at which a new master node may be found in that case. */ Poll_Station, This_Station, NULL, 0);
TokenCount++; RetryCount = 0;
/* transmit a Token frame to NS */ Master_State = MSTP_MASTER_STATE_POLL_FOR_MASTER;
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station, } else if (Next_Station == next_this_station) {
This_Station, NULL, 0); /* SendToken */
RetryCount = 0; /* Npoll changed in Errata SSPC-135-2004 */
EventCount = 0; /* The comparison of NS and TS+1
Master_State = MSTP_MASTER_STATE_PASS_TOKEN; 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. */
TokenCount++;
/* transmit a Token frame to NS */
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
This_Station, NULL, 0);
RetryCount = 0;
EventCount = 0;
Master_State = MSTP_MASTER_STATE_PASS_TOKEN;
}
} }
} else if (next_poll_station == Next_Station) { } else if (next_poll_station == Next_Station) {
if (MSTP_Flag.SoleMaster == true) { if (MSTP_Flag.SoleMaster == true) {
@@ -880,10 +904,11 @@ static bool MSTP_Master_Node_FSM(
} }
} }
break; break;
/* The NO_TOKEN state is entered if Timer_Silence() becomes greater */ /* The NO_TOKEN state is entered if Silence Timer
/* than Tno_token, indicating that there has been no network activity */ becomes greater than Tno_token, indicating that
/* for that period of time. The timeout is continued to determine */ there has been no network activity for that period
/* whether or not this node may create a token. */ 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:
my_timeout = Tno_token + (Tslot * This_Station); my_timeout = Tno_token + (Tslot * This_Station);
if (Timer_Silence() < my_timeout) { if (Timer_Silence() < my_timeout) {
+37 -26
View File
@@ -1,6 +1,6 @@
/*####COPYRIGHTBEGIN#### /*####COPYRIGHTBEGIN####
------------------------------------------- -------------------------------------------
Copyright (C) 2009 Steve Karg Copyright (C) 2009-2010 Steve Karg
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
@@ -407,8 +407,8 @@ static void MSTP_Send_Frame(
uint8_t frame_type, /* type of frame to send - see defines */ uint8_t frame_type, /* type of frame to send - see defines */
uint8_t destination, /* destination address */ uint8_t destination, /* destination address */
uint8_t source, /* source address */ uint8_t source, /* source address */
uint8_t * data, /* any data to be sent - may be null */ uint8_t * pdu, /* any data to be sent - may be null */
uint16_t data_len) uint16_t pdu_len)
{ /* number of bytes of data (up to 501) */ { /* number of bytes of data (up to 501) */
uint8_t crc8 = 0xFF; /* used to calculate the crc value */ uint8_t crc8 = 0xFF; /* used to calculate the crc value */
uint16_t crc16 = 0xFFFF; /* used to calculate the crc value */ uint16_t crc16 = 0xFFFF; /* used to calculate the crc value */
@@ -424,24 +424,24 @@ static void MSTP_Send_Frame(
crc8 = CRC_Calc_Header(buffer[3], crc8); crc8 = CRC_Calc_Header(buffer[3], crc8);
buffer[4] = source; buffer[4] = source;
crc8 = CRC_Calc_Header(buffer[4], crc8); crc8 = CRC_Calc_Header(buffer[4], crc8);
buffer[5] = HI_BYTE(data_len); buffer[5] = HI_BYTE(pdu_len);
crc8 = CRC_Calc_Header(buffer[5], crc8); crc8 = CRC_Calc_Header(buffer[5], crc8);
buffer[6] = LO_BYTE(data_len); buffer[6] = LO_BYTE(pdu_len);
crc8 = CRC_Calc_Header(buffer[6], crc8); crc8 = CRC_Calc_Header(buffer[6], crc8);
buffer[7] = ~crc8; buffer[7] = ~crc8;
rs485_turnaround_delay(); rs485_turnaround_delay();
rs485_rts_enable(true); rs485_rts_enable(true);
rs485_bytes_send(buffer, 8); rs485_bytes_send(buffer, 8);
/* send any data */ /* send any data */
if (data_len) { if (pdu_len) {
/* calculate CRC for any data */ /* calculate CRC for any data */
for (i = 0; i < data_len; i++) { for (i = 0; i < pdu_len; i++) {
crc16 = CRC_Calc_Data(data[i], crc16); crc16 = CRC_Calc_Data(pdu[i], crc16);
} }
crc16 = ~crc16; crc16 = ~crc16;
buffer[0] = (crc16 & 0x00FF); buffer[0] = (crc16 & 0x00FF);
buffer[1] = ((crc16 & 0xFF00) >> 8); buffer[1] = ((crc16 & 0xFF00) >> 8);
rs485_bytes_send(data, data_len); rs485_bytes_send(pdu, pdu_len);
rs485_bytes_send(buffer, 2); rs485_bytes_send(buffer, 2);
} }
rs485_rts_enable(false); rs485_rts_enable(false);
@@ -724,8 +724,11 @@ static bool MSTP_Master_Node_FSM(
bool transition_now = false; bool transition_now = false;
/* some calculations that several states need */ /* some calculations that several states need */
/* (PS+1) modulo (Nmax_master+1) */
next_poll_station = (Poll_Station + 1) % (Nmax_master + 1); next_poll_station = (Poll_Station + 1) % (Nmax_master + 1);
/* (TS+1) modulo (Nmax_master+1) */
next_this_station = (This_Station + 1) % (Nmax_master + 1); next_this_station = (This_Station + 1) % (Nmax_master + 1);
/* (NS +1) modulo (Nmax_master+1) */
next_next_station = (Next_Station + 1) % (Nmax_master + 1); next_next_station = (Next_Station + 1) % (Nmax_master + 1);
log_master_state(Master_State); log_master_state(Master_State);
switch (Master_State) { switch (Master_State) {
@@ -923,8 +926,7 @@ static bool MSTP_Master_Node_FSM(
} }
/* Npoll changed in Errata SSPC-135-2004 */ /* Npoll changed in Errata SSPC-135-2004 */
else if (TokenCount < (Npoll - 1)) { else if (TokenCount < (Npoll - 1)) {
if ((MSTP_Flag.SoleMaster == true) && if (MSTP_Flag.SoleMaster == true) {
(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 /* which the token may be sent
@@ -934,21 +936,30 @@ static bool MSTP_Master_Node_FSM(
Master_State = MSTP_MASTER_STATE_USE_TOKEN; Master_State = MSTP_MASTER_STATE_USE_TOKEN;
transition_now = true; transition_now = true;
} else { } else {
/* SendToken */ if (Next_Station == This_Station) {
/* Npoll changed in Errata SSPC-135-2004 */ /* NextStationUnknown - added in Addendum 135-2008v-1 */
/* The comparison of NS and TS+1 Poll_Station = next_this_station;
eliminates the Poll For Master MSTP_Send_Frame(FRAME_TYPE_POLL_FOR_MASTER,
if there are no addresses between Poll_Station, This_Station, NULL, 0);
TS and NS, since there is no RetryCount = 0;
address at which a new master node Master_State = MSTP_MASTER_STATE_POLL_FOR_MASTER;
may be found in that case. */ } else if (Next_Station == next_this_station) {
TokenCount++; /* SendToken */
/* transmit a Token frame to NS */ /* Npoll changed in Errata SSPC-135-2004 */
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station, /* The comparison of NS and TS+1
This_Station, NULL, 0); eliminates the Poll For Master
RetryCount = 0; if there are no addresses between
EventCount = 0; TS and NS, since there is no
Master_State = MSTP_MASTER_STATE_PASS_TOKEN; address at which a new master node
may be found in that case. */
TokenCount++;
/* transmit a Token frame to NS */
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
This_Station, NULL, 0);
RetryCount = 0;
EventCount = 0;
Master_State = MSTP_MASTER_STATE_PASS_TOKEN;
}
} }
} else if (next_poll_station == Next_Station) { } else if (next_poll_station == Next_Station) {
if (MSTP_Flag.SoleMaster == true) { if (MSTP_Flag.SoleMaster == true) {
+70 -56
View File
@@ -143,7 +143,7 @@ static uint8_t FrameType;
and microcontroller architectures have limits as to places to and microcontroller architectures have limits as to places to
hold contiguous memory. */ hold contiguous memory. */
static uint8_t *InputBuffer; static uint8_t *InputBuffer;
static uint8_t InputBufferSize; static uint16_t InputBufferSize;
/* Used to store the Source Address of a received frame. */ /* Used to store the Source Address of a received frame. */
static uint8_t SourceAddress; static uint8_t SourceAddress;
/* "This Station," the MAC address of this node. TS is generally read from a */ /* "This Station," the MAC address of this node. TS is generally read from a */
@@ -158,13 +158,13 @@ static uint8_t This_Station;
/* nodes. This may be used to allocate more or less of the available link */ /* nodes. This may be used to allocate more or less of the available link */
/* bandwidth to particular nodes. If Max_Info_Frames is not writable in a */ /* bandwidth to particular nodes. If Max_Info_Frames is not writable in a */
/* node, its value shall be 1. */ /* node, its value shall be 1. */
static uint8_t Nmax_info_frames; static uint8_t Nmax_info_frames = 1;
/* This parameter represents the value of the Max_Master property of the */ /* This parameter represents the value of the Max_Master property of the */
/* node's Device object. The value of Max_Master specifies the highest */ /* node's Device object. The value of Max_Master specifies the highest */
/* allowable address for master nodes. The value of Max_Master shall be */ /* allowable address for master nodes. The value of Max_Master shall be */
/* less than or equal to 127. If Max_Master is not writable in a node, */ /* less than or equal to 127. If Max_Master is not writable in a node, */
/* its value shall be 127. */ /* its value shall be 127. */
static uint8_t Nmax_master; static uint8_t Nmax_master = 127;
/* An array of octets, used to store octets for transmitting */ /* An array of octets, used to store octets for transmitting */
/* OutputBuffer is indexed from 0 to OutputBufferSize-1. */ /* OutputBuffer is indexed from 0 to OutputBufferSize-1. */
/* The MAX_PDU size of a frame is MAX_APDU + MAX_NPDU octets. */ /* The MAX_PDU size of a frame is MAX_APDU + MAX_NPDU octets. */
@@ -190,7 +190,7 @@ static uint8_t TransmitPacketDest;
/* node must wait for a remote node to begin using a token or replying to */ /* node must wait for a remote node to begin using a token or replying to */
/* a Poll For Master frame: 20 milliseconds. (Implementations may use */ /* a Poll For Master frame: 20 milliseconds. (Implementations may use */
/* larger values for this timeout, not to exceed 100 milliseconds.) */ /* larger values for this timeout, not to exceed 100 milliseconds.) */
#define Tusage_timeout 25 #define Tusage_timeout 60
/* The number of tokens received or used before a Poll For Master cycle */ /* The number of tokens received or used before a Poll For Master cycle */
/* is executed: 50. */ /* is executed: 50. */
@@ -402,8 +402,8 @@ static void MSTP_Send_Frame(
uint8_t frame_type, /* type of frame to send - see defines */ uint8_t frame_type, /* type of frame to send - see defines */
uint8_t destination, /* destination address */ uint8_t destination, /* destination address */
uint8_t source, /* source address */ uint8_t source, /* source address */
uint8_t * data, /* any data to be sent - may be null */ uint8_t * pdu, /* any data to be sent - may be null */
uint16_t data_len) uint16_t pdu_len)
{ /* number of bytes of data (up to 501) */ { /* number of bytes of data (up to 501) */
uint8_t crc8 = 0xFF; /* used to calculate the crc value */ uint8_t crc8 = 0xFF; /* used to calculate the crc value */
uint16_t crc16 = 0xFFFF; /* used to calculate the crc value */ uint16_t crc16 = 0xFFFF; /* used to calculate the crc value */
@@ -419,24 +419,24 @@ static void MSTP_Send_Frame(
crc8 = CRC_Calc_Header(buffer[3], crc8); crc8 = CRC_Calc_Header(buffer[3], crc8);
buffer[4] = source; buffer[4] = source;
crc8 = CRC_Calc_Header(buffer[4], crc8); crc8 = CRC_Calc_Header(buffer[4], crc8);
buffer[5] = HI_BYTE(data_len); buffer[5] = HI_BYTE(pdu_len);
crc8 = CRC_Calc_Header(buffer[5], crc8); crc8 = CRC_Calc_Header(buffer[5], crc8);
buffer[6] = LO_BYTE(data_len); buffer[6] = LO_BYTE(pdu_len);
crc8 = CRC_Calc_Header(buffer[6], crc8); crc8 = CRC_Calc_Header(buffer[6], crc8);
buffer[7] = ~crc8; buffer[7] = ~crc8;
RS485_Turnaround_Delay(); RS485_Turnaround_Delay();
RS485_Transmitter_Enable(true); RS485_Transmitter_Enable(true);
RS485_Send_Data(buffer, 8); RS485_Send_Data(buffer, 8);
/* send any data */ /* send any data */
if (data_len) { if (pdu_len) {
/* calculate CRC for any data */ /* calculate CRC for any data */
for (i = 0; i < data_len; i++) { for (i = 0; i < pdu_len; i++) {
crc16 = CRC_Calc_Data(data[i], crc16); crc16 = CRC_Calc_Data(pdu[i], crc16);
} }
crc16 = ~crc16; crc16 = ~crc16;
buffer[0] = (crc16 & 0x00FF); buffer[0] = (crc16 & 0x00FF);
buffer[1] = ((crc16 & 0xFF00) >> 8); buffer[1] = ((crc16 & 0xFF00) >> 8);
RS485_Send_Data(data, data_len); RS485_Send_Data(pdu, pdu_len);
RS485_Send_Data(buffer, 2); RS485_Send_Data(buffer, 2);
} }
RS485_Transmitter_Enable(false); RS485_Transmitter_Enable(false);
@@ -453,7 +453,7 @@ static void MSTP_Receive_Frame_FSM(
static uint8_t HeaderCRC = 0; static uint8_t HeaderCRC = 0;
/* Used as an index by the Receive State Machine, /* Used as an index by the Receive State Machine,
up to a maximum value of the MPDU */ up to a maximum value of the MPDU */
static uint8_t Index = 0; static uint16_t Index = 0;
switch (Receive_State) { switch (Receive_State) {
case MSTP_RECEIVE_STATE_IDLE: case MSTP_RECEIVE_STATE_IDLE:
@@ -609,7 +609,8 @@ static void MSTP_Receive_Frame_FSM(
/* 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. */
if (Timer_Silence() > Tframe_abort) { if (Timer_Silence() > Tframe_abort) {
/* Timeout */ /* Timeout */
/* 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_Flag.ReceivedInvalidFrame = true; MSTP_Flag.ReceivedInvalidFrame = true;
/* wait for the start of the next frame. */ /* wait for the start of the next frame. */
Receive_State = MSTP_RECEIVE_STATE_IDLE; Receive_State = MSTP_RECEIVE_STATE_IDLE;
@@ -671,9 +672,9 @@ static bool MSTP_Master_Node_FSM(
/* When this counter reaches the value Nmax_info_frames, the node must */ /* When this counter reaches the value Nmax_info_frames, the node must */
/* pass the token. */ /* pass the token. */
static uint8_t FrameCount; static uint8_t FrameCount;
/* "Next Station," the MAC address of the node to which This Station passes */ /* "Next Station," the MAC address of the node to which This Station
/* the token. If the Next_Station is unknown, Next_Station shall be equal to */ passes the token. If the Next_Station is unknown, Next_Station shall
/* This_Station. */ be equal to This_Station. */
static uint8_t Next_Station; static uint8_t Next_Station;
/* "Poll Station," the MAC address of the node to which This Station last */ /* "Poll Station," the MAC address of the node to which This Station last */
/* sent a Poll For Master. This is used during token maintenance. */ /* sent a Poll For Master. This is used during token maintenance. */
@@ -681,10 +682,10 @@ static bool MSTP_Master_Node_FSM(
/* A counter of transmission retries used for Token and Poll For Master */ /* A counter of transmission retries used for Token and Poll For Master */
/* transmission. */ /* transmission. */
static unsigned RetryCount; static unsigned RetryCount;
/* The number of tokens received by this node. When this counter reaches the */ /* The number of tokens received by this node. When this counter reaches */
/* value Npoll, the node polls the address range between TS and NS for */ /* the value Npoll, the node polls the address range between TS and NS */
/* additional master nodes. TokenCount is set to zero at the end of the */ /* for additional master nodes. TokenCount is set to zero at the end of */
/* polling process. */ /* the polling process. */
static unsigned TokenCount; static unsigned TokenCount;
/* next-x-station calculations */ /* next-x-station calculations */
uint8_t next_poll_station = 0; uint8_t next_poll_station = 0;
@@ -692,13 +693,16 @@ static bool MSTP_Master_Node_FSM(
uint8_t next_next_station = 0; uint8_t next_next_station = 0;
/* timeout values */ /* timeout values */
uint16_t my_timeout = 10, ns_timeout = 0; uint16_t my_timeout = 10, ns_timeout = 0;
bool matched; bool matched = false;
/* transition immediately to the next state */ /* transition immediately to the next state */
bool transition_now = false; bool transition_now = false;
/* some calculations that several states need */ /* some calculations that several states need */
/* (PS+1) modulo (Nmax_master+1) */
next_poll_station = (Poll_Station + 1) % (Nmax_master + 1); next_poll_station = (Poll_Station + 1) % (Nmax_master + 1);
/* (TS+1) modulo (Nmax_master+1) */
next_this_station = (This_Station + 1) % (Nmax_master + 1); next_this_station = (This_Station + 1) % (Nmax_master + 1);
/* (NS +1) modulo (Nmax_master+1) */
next_next_station = (Next_Station + 1) % (Nmax_master + 1); next_next_station = (Next_Station + 1) % (Nmax_master + 1);
switch (Master_State) { switch (Master_State) {
case MSTP_MASTER_STATE_INITIALIZE: case MSTP_MASTER_STATE_INITIALIZE:
@@ -749,7 +753,7 @@ static bool MSTP_Master_Node_FSM(
MSTP_Flag.ReceivePacketPending = true; MSTP_Flag.ReceivePacketPending = true;
break; break;
case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY: case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY:
/* indicate successful reception to the higher layers */ /* indicate successful reception to higher layers */
MSTP_Flag.ReceivePacketPending = true; MSTP_Flag.ReceivePacketPending = true;
/* broadcast DER just remains IDLE */ /* broadcast DER just remains IDLE */
if (DestinationAddress != MSTP_BROADCAST_ADDRESS) { if (DestinationAddress != MSTP_BROADCAST_ADDRESS) {
@@ -823,8 +827,10 @@ static bool MSTP_Master_Node_FSM(
FrameCount = Nmax_info_frames; FrameCount = Nmax_info_frames;
Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN; Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
/* Any retry of the data frame shall await the next entry */ /* Any retry of the data frame shall await the next entry */
/* to the USE_TOKEN state. (Because of the length of the timeout, */ /* to the USE_TOKEN state. */
/* this transition will cause the token to be passed regardless */ /* (Because of the length of the timeout, */
/* 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 {
@@ -848,8 +854,10 @@ static bool MSTP_Master_Node_FSM(
break; break;
case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY:
/* ReceivedReply */ /* ReceivedReply */
/* or a proprietary type that indicates a reply */ /* or a proprietary type that indicates
/* indicate successful reception to the higher layers */ a reply */
/* indicate successful reception to
the higher layers */
MSTP_Flag.ReceivePacketPending = true; MSTP_Flag.ReceivePacketPending = true;
Master_State = Master_State =
MSTP_MASTER_STATE_DONE_WITH_TOKEN; MSTP_MASTER_STATE_DONE_WITH_TOKEN;
@@ -887,28 +895,40 @@ static bool MSTP_Master_Node_FSM(
} }
/* Npoll changed in Errata SSPC-135-2004 */ /* Npoll changed in Errata SSPC-135-2004 */
else if (TokenCount < (Npoll - 1)) { else if (TokenCount < (Npoll - 1)) {
if ((MSTP_Flag.SoleMaster == true) && if (MSTP_Flag.SoleMaster == true) {
(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). */
FrameCount = 0; FrameCount = 0;
TokenCount++; TokenCount++;
Master_State = MSTP_MASTER_STATE_USE_TOKEN; Master_State = MSTP_MASTER_STATE_USE_TOKEN;
transition_now = true; transition_now = true;
} else { } else {
/* SendToken */ if (Next_Station == This_Station) {
/* Npoll changed in Errata SSPC-135-2004 */ /* NextStationUnknown - added in Addendum 135-2008v-1 */
/* The comparison of NS and TS+1 eliminates the Poll For Master */ Poll_Station = next_this_station;
/* if there are no addresses between TS and NS, since there is no */ MSTP_Send_Frame(FRAME_TYPE_POLL_FOR_MASTER,
/* address at which a new master node may be found in that case. */ Poll_Station, This_Station, NULL, 0);
TokenCount++; RetryCount = 0;
/* transmit a Token frame to NS */ Master_State = MSTP_MASTER_STATE_POLL_FOR_MASTER;
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station, } else if (Next_Station == next_this_station) {
This_Station, NULL, 0); /* SendToken */
RetryCount = 0; /* Npoll changed in Errata SSPC-135-2004 */
EventCount = 0; /* The comparison of NS and TS+1
Master_State = MSTP_MASTER_STATE_PASS_TOKEN; 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. */
TokenCount++;
/* transmit a Token frame to NS */
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
This_Station, NULL, 0);
RetryCount = 0;
EventCount = 0;
Master_State = MSTP_MASTER_STATE_PASS_TOKEN;
}
} }
} else if (next_poll_station == Next_Station) { } else if (next_poll_station == Next_Station) {
if (MSTP_Flag.SoleMaster == true) { if (MSTP_Flag.SoleMaster == true) {
@@ -981,10 +1001,11 @@ static bool MSTP_Master_Node_FSM(
} }
} }
break; break;
/* The NO_TOKEN state is entered if Timer_Silence() becomes greater */ /* The NO_TOKEN state is entered if Silence Timer
/* than Tno_token, indicating that there has been no network activity */ becomes greater than Tno_token, indicating that
/* for that period of time. The timeout is continued to determine */ there has been no network activity for that period
/* whether or not this node may create a token. */ 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:
my_timeout = Tno_token + (Tslot * This_Station); my_timeout = Tno_token + (Tslot * This_Station);
if (Timer_Silence() < my_timeout) { if (Timer_Silence() < my_timeout) {
@@ -1075,7 +1096,8 @@ static bool MSTP_Master_Node_FSM(
/* 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_Flag.SoleMaster = true; MSTP_Flag.SoleMaster = true;
FrameCount = 0; FrameCount = 0;
Master_State = MSTP_MASTER_STATE_USE_TOKEN; Master_State = MSTP_MASTER_STATE_USE_TOKEN;
@@ -1178,15 +1200,7 @@ uint16_t dlmstp_receive(
/* only do receive state machine while we don't have a frame */ /* only do receive state machine while we don't have a frame */
if ((MSTP_Flag.ReceivedValidFrame == false) && if ((MSTP_Flag.ReceivedValidFrame == false) &&
(MSTP_Flag.ReceivedInvalidFrame == false)) { (MSTP_Flag.ReceivedInvalidFrame == false)) {
for (;;) { MSTP_Receive_Frame_FSM();
MSTP_Receive_Frame_FSM();
if (MSTP_Flag.ReceivedValidFrame || MSTP_Flag.ReceivedInvalidFrame)
break;
/* if we are not idle, then we are
receiving a frame or timing out */
if (Receive_State == MSTP_RECEIVE_STATE_IDLE)
break;
}
} }
/* only do master state machine while rx is idle */ /* only do master state machine while rx is idle */
if (Receive_State == MSTP_RECEIVE_STATE_IDLE) { if (Receive_State == MSTP_RECEIVE_STATE_IDLE) {
+1 -1
View File
@@ -957,7 +957,7 @@ bool bacapp_print_value(
} else { } else {
fprintf(stream, "%u, ", (unsigned) value->type.Date.day); fprintf(stream, "%u, ", (unsigned) value->type.Date.day);
} }
if (value->type.Date.year == 255) { if (value->type.Date.year == 2155) {
fprintf(stream, "(unspecified), "); fprintf(stream, "(unspecified), ");
} else { } else {
fprintf(stream, "%u", (unsigned) value->type.Date.year); fprintf(stream, "%u", (unsigned) value->type.Date.year);
+29 -16
View File
@@ -1,6 +1,6 @@
/*####COPYRIGHTBEGIN#### /*####COPYRIGHTBEGIN####
------------------------------------------- -------------------------------------------
Copyright (C) 2003-2007 Steve Karg Copyright (C) 2003-2010 Steve Karg
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
@@ -585,10 +585,13 @@ bool MSTP_Master_Node_FSM(
static MSTP_MASTER_STATE master_state = MSTP_MASTER_STATE_INITIALIZE; static MSTP_MASTER_STATE master_state = MSTP_MASTER_STATE_INITIALIZE;
/* some calculations that several states need */ /* some calculations that several states need */
/* (PS+1) modulo (Nmax_master+1) */
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);
/* (TS+1) modulo (Nmax_master+1) */
next_this_station = next_this_station =
(mstp_port->This_Station + 1) % (mstp_port->Nmax_master + 1); (mstp_port->This_Station + 1) % (mstp_port->Nmax_master + 1);
/* (NS +1) modulo (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 (mstp_port->master_state != master_state) { if (mstp_port->master_state != master_state) {
@@ -816,8 +819,7 @@ bool MSTP_Master_Node_FSM(
transition_now = true; transition_now = true;
} else if (mstp_port->TokenCount < (Npoll - 1)) { } else if (mstp_port->TokenCount < (Npoll - 1)) {
/* Npoll changed in Errata SSPC-135-2004 */ /* Npoll changed in Errata SSPC-135-2004 */
if ((mstp_port->SoleMaster == true) && if (mstp_port->SoleMaster == true) {
(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). */
@@ -826,19 +828,30 @@ bool MSTP_Master_Node_FSM(
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 */ if (mstp_port->Next_Station == mstp_port->This_Station) {
/* Npoll changed in Errata SSPC-135-2004 */ /* NextStationUnknown - added in Addendum 135-2008v-1 */
/* The comparison of NS and TS+1 eliminates the Poll For Master */ mstp_port->Poll_Station = next_this_station;
/* if there are no addresses between TS and NS, since there is no */ MSTP_Create_And_Send_Frame(mstp_port,
/* address at which a new master node may be found in that case. */ FRAME_TYPE_POLL_FOR_MASTER, mstp_port->Poll_Station,
mstp_port->TokenCount++; mstp_port->This_Station, NULL, 0);
/* transmit a Token frame to NS */ mstp_port->RetryCount = 0;
MSTP_Create_And_Send_Frame(mstp_port, FRAME_TYPE_TOKEN, mstp_port->master_state =
mstp_port->Next_Station, mstp_port->This_Station, NULL, MSTP_MASTER_STATE_POLL_FOR_MASTER;
0); } else if (mstp_port->Next_Station == next_this_station) {
mstp_port->RetryCount = 0; /* SendToken */
mstp_port->EventCount = 0; /* Npoll changed in Errata SSPC-135-2004 */
mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN; /* 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) { } else if (next_poll_station == mstp_port->Next_Station) {
if (mstp_port->SoleMaster == true) { if (mstp_port->SoleMaster == true) {