Added extra sub-state for MS/TP from Addendum 135-2008v.
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
#include "bacaddr.h"
|
#include "bacaddr.h"
|
||||||
|
|
||||||
/* This file has been customized for use with small microprocessors */
|
/* This file has been customized for use with small microprocessors */
|
||||||
/* Assumptions:
|
/* Assumptions:
|
||||||
Only one MS/TP datalink layer
|
Only one MS/TP datalink layer
|
||||||
*/
|
*/
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
@@ -121,7 +121,7 @@ static struct mstp_flag_t {
|
|||||||
/* A Boolean flag set TRUE by the datalink transmit if a
|
/* A Boolean flag set TRUE by the datalink transmit if a
|
||||||
pending packet is DataExpectingReply */
|
pending packet is DataExpectingReply */
|
||||||
unsigned TransmitPacketDER:1;
|
unsigned TransmitPacketDER:1;
|
||||||
/* A Boolean flag set TRUE by the datalink if a
|
/* A Boolean flag set TRUE by the datalink if a
|
||||||
packet has been received, but not processed. */
|
packet has been received, but not processed. */
|
||||||
unsigned ReceivePacketPending:1;
|
unsigned ReceivePacketPending:1;
|
||||||
} MSTP_Flag;
|
} MSTP_Flag;
|
||||||
@@ -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. */
|
||||||
@@ -287,8 +287,8 @@ static bool dlmstp_compare_data_expecting_reply(
|
|||||||
uint8_t dest_address)
|
uint8_t dest_address)
|
||||||
{
|
{
|
||||||
uint16_t offset;
|
uint16_t offset;
|
||||||
/* One way to check the message is to compare NPDU
|
/* One way to check the message is to compare NPDU
|
||||||
src, dest, along with the APDU type, invoke id.
|
src, dest, along with the APDU type, invoke id.
|
||||||
Seems a bit overkill */
|
Seems a bit overkill */
|
||||||
struct DER_compare_t {
|
struct DER_compare_t {
|
||||||
BACNET_NPDU_DATA npdu_data;
|
BACNET_NPDU_DATA npdu_data;
|
||||||
@@ -327,7 +327,7 @@ static bool dlmstp_compare_data_expecting_reply(
|
|||||||
if (reply.npdu_data.network_layer_message) {
|
if (reply.npdu_data.network_layer_message) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/* reply could be a lot of things:
|
/* reply could be a lot of things:
|
||||||
confirmed, simple ack, abort, reject, error */
|
confirmed, simple ack, abort, reject, error */
|
||||||
reply.pdu_type = reply_pdu[offset] & 0xF0;
|
reply.pdu_type = reply_pdu[offset] & 0xF0;
|
||||||
switch (reply.pdu_type) {
|
switch (reply.pdu_type) {
|
||||||
@@ -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:
|
||||||
@@ -553,7 +553,7 @@ static void MSTP_Receive_Frame_FSM(
|
|||||||
} else if (Index == 5) {
|
} else if (Index == 5) {
|
||||||
/* HeaderCRC */
|
/* HeaderCRC */
|
||||||
HeaderCRC = CRC_Calc_Header(DataRegister, HeaderCRC);
|
HeaderCRC = CRC_Calc_Header(DataRegister, HeaderCRC);
|
||||||
/* In the HEADER_CRC state, the node validates the CRC
|
/* In the HEADER_CRC state, the node validates the CRC
|
||||||
on the fixed message header. */
|
on the fixed message header. */
|
||||||
if (HeaderCRC != 0x55) {
|
if (HeaderCRC != 0x55) {
|
||||||
/* BadCRC */
|
/* BadCRC */
|
||||||
@@ -565,7 +565,7 @@ static void MSTP_Receive_Frame_FSM(
|
|||||||
} else {
|
} else {
|
||||||
/* Note: proposed change to BACnet MSTP state machine!
|
/* Note: proposed change to BACnet MSTP state machine!
|
||||||
If we don't decode data that is not for us, we could
|
If we don't decode data that is not for us, we could
|
||||||
get confused about the start if the Preamble 55 FF
|
get confused about the start if the Preamble 55 FF
|
||||||
is part of the data. */
|
is part of the data. */
|
||||||
if ((DataLength) && (DataLength <= InputBufferSize)) {
|
if ((DataLength) && (DataLength <= InputBufferSize)) {
|
||||||
/* Data */
|
/* Data */
|
||||||
@@ -580,7 +580,7 @@ static void MSTP_Receive_Frame_FSM(
|
|||||||
(DestinationAddress ==
|
(DestinationAddress ==
|
||||||
MSTP_BROADCAST_ADDRESS)) {
|
MSTP_BROADCAST_ADDRESS)) {
|
||||||
/* ForUs */
|
/* ForUs */
|
||||||
/* indicate that a frame with
|
/* indicate that a frame with
|
||||||
no data has been received */
|
no data has been received */
|
||||||
MSTP_Flag.ReceivedValidFrame = true;
|
MSTP_Flag.ReceivedValidFrame = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -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;
|
||||||
@@ -643,7 +644,7 @@ static void MSTP_Receive_Frame_FSM(
|
|||||||
if ((DestinationAddress == This_Station) ||
|
if ((DestinationAddress == This_Station) ||
|
||||||
(DestinationAddress == MSTP_BROADCAST_ADDRESS)) {
|
(DestinationAddress == MSTP_BROADCAST_ADDRESS)) {
|
||||||
/* ForUs */
|
/* ForUs */
|
||||||
/* indicate that a frame with no data
|
/* indicate that a frame with no data
|
||||||
has been received */
|
has been received */
|
||||||
MSTP_Flag.ReceivedValidFrame = true;
|
MSTP_Flag.ReceivedValidFrame = true;
|
||||||
}
|
}
|
||||||
@@ -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) {
|
||||||
@@ -766,7 +770,7 @@ static bool MSTP_Master_Node_FSM(
|
|||||||
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 (Master_State != MSTP_MASTER_STATE_ANSWER_DATA_REQUEST) {
|
if (Master_State != MSTP_MASTER_STATE_ANSWER_DATA_REQUEST) {
|
||||||
MSTP_Flag.ReceivedValidFrame = false;
|
MSTP_Flag.ReceivedValidFrame = false;
|
||||||
@@ -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) {
|
||||||
@@ -1214,7 +1228,7 @@ void dlmstp_set_mac_address(
|
|||||||
This_Station = mac_address;
|
This_Station = mac_address;
|
||||||
/* FIXME: implement your data storage */
|
/* FIXME: implement your data storage */
|
||||||
/* I2C_Write_Byte(
|
/* I2C_Write_Byte(
|
||||||
EEPROM_DEVICE_ADDRESS,
|
EEPROM_DEVICE_ADDRESS,
|
||||||
mac_address,
|
mac_address,
|
||||||
EEPROM_MSTP_MAC_ADDR); */
|
EEPROM_MSTP_MAC_ADDR); */
|
||||||
if (mac_address > Nmax_master)
|
if (mac_address > Nmax_master)
|
||||||
@@ -1243,8 +1257,8 @@ void dlmstp_set_max_info_frames(
|
|||||||
if (max_info_frames >= 1) {
|
if (max_info_frames >= 1) {
|
||||||
Nmax_info_frames = max_info_frames;
|
Nmax_info_frames = max_info_frames;
|
||||||
/* FIXME: implement your data storage */
|
/* FIXME: implement your data storage */
|
||||||
/* I2C_Write_Byte(
|
/* I2C_Write_Byte(
|
||||||
EEPROM_DEVICE_ADDRESS,
|
EEPROM_DEVICE_ADDRESS,
|
||||||
(uint8_t)max_info_frames,
|
(uint8_t)max_info_frames,
|
||||||
EEPROM_MSTP_MAX_INFO_FRAMES_ADDR); */
|
EEPROM_MSTP_MAX_INFO_FRAMES_ADDR); */
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user