From 6f9ba3696754204d6cfb38f9090deeeab0be0bd7 Mon Sep 17 00:00:00 2001 From: skarg Date: Sat, 26 Jun 2010 03:55:20 +0000 Subject: [PATCH] Added extra sub-state for MS/TP from Addendum 135-2008v. --- bacnet-stack/ports/at91sam7s/dlmstp.c | 73 +++++----- bacnet-stack/ports/atmega168/dlmstp.c | 95 ++++++++----- bacnet-stack/ports/bdk-atxx4-mstp/dlmstp.c | 63 +++++---- bacnet-stack/ports/dos/dlmstp.c | 152 +++++++++++---------- bacnet-stack/src/bacapp.c | 2 +- bacnet-stack/src/mstp.c | 45 +++--- 6 files changed, 252 insertions(+), 178 deletions(-) diff --git a/bacnet-stack/ports/at91sam7s/dlmstp.c b/bacnet-stack/ports/at91sam7s/dlmstp.c index f188f090..518f8f6d 100644 --- a/bacnet-stack/ports/at91sam7s/dlmstp.c +++ b/bacnet-stack/ports/at91sam7s/dlmstp.c @@ -1,6 +1,6 @@ /*####COPYRIGHTBEGIN#### ------------------------------------------- - Copyright (C) 2007 Steve Karg + Copyright (C) 2007-2010 Steve Karg This program is free software; you can redistribute it and/or 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 */ /* bandwidth to particular nodes. If Max_Info_Frames is not writable in a */ /* 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 */ /* node's Device object. The value of Max_Master specifies the highest */ /* 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, */ /* 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 */ /* OutputBuffer is indexed from 0 to OutputBufferSize-1. */ /* 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 */ /* a Poll For Master frame: 20 milliseconds. (Implementations may use */ /* 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 */ /* is executed: 50. */ @@ -241,7 +241,7 @@ static uint8_t TransmitPacketDest; bool dlmstp_init( char *ifname) { - (void) ifname; + ifname = ifname; /* initialize hardware */ RS485_Initialize(); @@ -403,8 +403,8 @@ static void MSTP_Send_Frame( uint8_t frame_type, /* type of frame to send - see defines */ uint8_t destination, /* destination address */ uint8_t source, /* source address */ - uint8_t * data, /* any data to be sent - may be null */ - uint16_t data_len) + uint8_t * pdu, /* any data to be sent - may be null */ + uint16_t pdu_len) { /* number of bytes of data (up to 501) */ uint8_t crc8 = 0xFF; /* 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); buffer[4] = source; 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); - buffer[6] = LO_BYTE(data_len); + buffer[6] = LO_BYTE(pdu_len); crc8 = CRC_Calc_Header(buffer[6], crc8); buffer[7] = ~crc8; RS485_Turnaround_Delay(); RS485_Transmitter_Enable(true); RS485_Send_Data(buffer, 8); /* send any data */ - if (data_len) { + if (pdu_len) { /* calculate CRC for any data */ - for (i = 0; i < data_len; i++) { - crc16 = CRC_Calc_Data(data[i], crc16); + for (i = 0; i < pdu_len; i++) { + crc16 = CRC_Calc_Data(pdu[i], crc16); } crc16 = ~crc16; buffer[0] = (crc16 & 0x00FF); buffer[1] = ((crc16 & 0xFF00) >> 8); - RS485_Send_Data(data, data_len); + RS485_Send_Data(pdu, pdu_len); RS485_Send_Data(buffer, 2); } RS485_Transmitter_Enable(false); @@ -704,8 +704,11 @@ static bool MSTP_Master_Node_FSM( bool transition_now = false; /* some calculations that several states need */ + /* (PS+1) modulo (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); + /* (NS +1) modulo (Nmax_master+1) */ next_next_station = (Next_Station + 1) % (Nmax_master + 1); switch (Master_State) { case MSTP_MASTER_STATE_INITIALIZE: @@ -902,8 +905,7 @@ static bool MSTP_Master_Node_FSM( } /* Npoll changed in Errata SSPC-135-2004 */ else if (TokenCount < (Npoll - 1)) { - if ((MSTP_Flag.SoleMaster == true) && - (Next_Station != next_this_station)) { + if (MSTP_Flag.SoleMaster == true) { /* SoleMaster */ /* there are no other known master nodes to */ /* which the token may be sent @@ -913,21 +915,30 @@ static bool MSTP_Master_Node_FSM( Master_State = MSTP_MASTER_STATE_USE_TOKEN; transition_now = true; } else { - /* SendToken */ - /* Npoll changed in Errata SSPC-135-2004 */ - /* The comparison of NS and TS+1 - eliminates the Poll For Master - if there are no addresses between - TS and NS, since there is no - address at which a new master node - may be found in that case. */ - 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; + if (Next_Station == This_Station) { + /* NextStationUnknown - added in Addendum 135-2008v-1 */ + Poll_Station = next_this_station; + MSTP_Send_Frame(FRAME_TYPE_POLL_FOR_MASTER, + Poll_Station, This_Station, NULL, 0); + RetryCount = 0; + Master_State = MSTP_MASTER_STATE_POLL_FOR_MASTER; + } else if (Next_Station == next_this_station) { + /* SendToken */ + /* Npoll changed in Errata SSPC-135-2004 */ + /* The comparison of NS and TS+1 + eliminates the Poll For Master + if there are no addresses between + TS and NS, since there is no + address at which a new master node + may be found in that case. */ + 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) { if (MSTP_Flag.SoleMaster == true) { @@ -1001,7 +1012,7 @@ static bool MSTP_Master_Node_FSM( } } 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 there has been no network activity for that period of time. The timeout is continued to determine diff --git a/bacnet-stack/ports/atmega168/dlmstp.c b/bacnet-stack/ports/atmega168/dlmstp.c index 134276cf..63a222d3 100644 --- a/bacnet-stack/ports/atmega168/dlmstp.c +++ b/bacnet-stack/ports/atmega168/dlmstp.c @@ -162,13 +162,13 @@ static uint8_t This_Station; /* 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 */ /* 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 */ /* node's Device object. The value of Max_Master specifies the highest */ /* 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, */ /* 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 */ /* OutputBuffer is indexed from 0 to OutputBufferSize-1. */ /* 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 */ /* confirmed request: 255 milliseconds. (Implementations may use */ /* 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 */ /* 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 */ /* 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 */ /* is executed: 50. */ @@ -219,6 +219,11 @@ static uint8_t TransmitPacketDest; /* of a frame the node is transmitting: 20 bit times. */ #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 */ /* a reply before sending the first octet of a reply or Reply Postponed */ /* 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 */ /* pass the token. */ static uint8_t FrameCount; - /* "Next Station," the MAC address of the node to which This Station passes */ - /* the token. If the Next_Station is unknown, Next_Station shall be equal to */ - /* This_Station. */ + /* "Next Station," the MAC address of the node to which This Station + passes the token. If the Next_Station is unknown, Next_Station shall + be equal to This_Station. */ static uint8_t Next_Station; /* "Poll Station," the MAC address of the node to which This Station last */ /* 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 */ /* transmission. */ static unsigned RetryCount; - /* The number of tokens received by this node. When this counter reaches the */ - /* value Npoll, the node polls the address range between TS and NS for */ - /* additional master nodes. TokenCount is set to zero at the end of the */ - /* polling process. */ + /* The number of tokens received by this node. When this counter reaches */ + /* the value Npoll, the node polls the address range between TS and NS */ + /* for additional master nodes. TokenCount is set to zero at the end of */ + /* the polling process. */ static unsigned TokenCount; /* next-x-station calculations */ uint8_t next_poll_station = 0; @@ -613,8 +618,11 @@ static bool MSTP_Master_Node_FSM( bool transition_now = false; /* some calculations that several states need */ + /* (PS+1) modulo (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); + /* (NS +1) modulo (Nmax_master+1) */ next_next_station = (Next_Station + 1) % (Nmax_master + 1); switch (Master_State) { case MSTP_MASTER_STATE_INITIALIZE: @@ -669,7 +677,7 @@ static bool MSTP_Master_Node_FSM( MSTP_Flag.ReceivePacketPending = true; break; case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY: - /* indicate successful reception to the higher layers */ + /* indicate successful reception to higher layers */ MSTP_Flag.ReceivePacketPending = true; /* broadcast DER just remains IDLE */ if (DestinationAddress != MSTP_BROADCAST_ADDRESS) { @@ -722,8 +730,10 @@ static bool MSTP_Master_Node_FSM( FrameCount = Nmax_info_frames; Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN; /* Any retry of the data frame shall await the next entry */ - /* to the USE_TOKEN state. (Because of the length of the timeout, */ - /* this transition will cause the token to be passed regardless */ + /* to the USE_TOKEN state. */ + /* (Because of the length of the timeout, */ + /* this transition will cause the token to be */ + /* passed regardless */ /* of the initial value of FrameCount.) */ transition_now = true; } else { @@ -747,8 +757,10 @@ static bool MSTP_Master_Node_FSM( break; case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: /* ReceivedReply */ - /* or a proprietary type that indicates a reply */ - /* indicate successful reception to the higher layers */ + /* or a proprietary type that indicates + a reply */ + /* indicate successful reception to + the higher layers */ MSTP_Flag.ReceivePacketPending = true; Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN; @@ -786,28 +798,40 @@ static bool MSTP_Master_Node_FSM( } /* Npoll changed in Errata SSPC-135-2004 */ else if (TokenCount < (Npoll - 1)) { - if ((MSTP_Flag.SoleMaster == true) && - (Next_Station != next_this_station)) { + if (MSTP_Flag.SoleMaster == true) { /* SoleMaster */ /* 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; TokenCount++; Master_State = MSTP_MASTER_STATE_USE_TOKEN; transition_now = true; } else { - /* SendToken */ - /* Npoll changed in Errata SSPC-135-2004 */ - /* The comparison of NS and TS+1 eliminates the Poll For Master */ - /* if there are no addresses between TS and NS, since there is no */ - /* address at which a new master node may be found in that case. */ - 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; + if (Next_Station == This_Station) { + /* NextStationUnknown - added in Addendum 135-2008v-1 */ + Poll_Station = next_this_station; + MSTP_Send_Frame(FRAME_TYPE_POLL_FOR_MASTER, + Poll_Station, This_Station, NULL, 0); + RetryCount = 0; + Master_State = MSTP_MASTER_STATE_POLL_FOR_MASTER; + } else if (Next_Station == next_this_station) { + /* SendToken */ + /* Npoll changed in Errata SSPC-135-2004 */ + /* The comparison of NS and TS+1 + eliminates the Poll For Master + if there are no addresses between + TS and NS, since there is no + address at which a new master node + may be found in that case. */ + 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) { if (MSTP_Flag.SoleMaster == true) { @@ -880,10 +904,11 @@ static bool MSTP_Master_Node_FSM( } } break; - /* The NO_TOKEN state is entered if Timer_Silence() becomes greater */ - /* than Tno_token, indicating that there has been no network activity */ - /* for that period of time. The timeout is continued to determine */ - /* whether or not this node may create a token. */ + /* The NO_TOKEN state is entered if Silence Timer + becomes greater than Tno_token, indicating that + there has been no network activity for that period + of time. The timeout is continued to determine + whether or not this node may create a token. */ case MSTP_MASTER_STATE_NO_TOKEN: my_timeout = Tno_token + (Tslot * This_Station); if (Timer_Silence() < my_timeout) { diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/dlmstp.c b/bacnet-stack/ports/bdk-atxx4-mstp/dlmstp.c index ad8ace63..d37b263f 100644 --- a/bacnet-stack/ports/bdk-atxx4-mstp/dlmstp.c +++ b/bacnet-stack/ports/bdk-atxx4-mstp/dlmstp.c @@ -1,6 +1,6 @@ /*####COPYRIGHTBEGIN#### ------------------------------------------- - Copyright (C) 2009 Steve Karg + Copyright (C) 2009-2010 Steve Karg This program is free software; you can redistribute it and/or 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 destination, /* destination address */ uint8_t source, /* source address */ - uint8_t * data, /* any data to be sent - may be null */ - uint16_t data_len) + uint8_t * pdu, /* any data to be sent - may be null */ + uint16_t pdu_len) { /* number of bytes of data (up to 501) */ uint8_t crc8 = 0xFF; /* 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); buffer[4] = source; 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); - buffer[6] = LO_BYTE(data_len); + buffer[6] = LO_BYTE(pdu_len); crc8 = CRC_Calc_Header(buffer[6], crc8); buffer[7] = ~crc8; rs485_turnaround_delay(); rs485_rts_enable(true); rs485_bytes_send(buffer, 8); /* send any data */ - if (data_len) { + if (pdu_len) { /* calculate CRC for any data */ - for (i = 0; i < data_len; i++) { - crc16 = CRC_Calc_Data(data[i], crc16); + for (i = 0; i < pdu_len; i++) { + crc16 = CRC_Calc_Data(pdu[i], crc16); } crc16 = ~crc16; buffer[0] = (crc16 & 0x00FF); buffer[1] = ((crc16 & 0xFF00) >> 8); - rs485_bytes_send(data, data_len); + rs485_bytes_send(pdu, pdu_len); rs485_bytes_send(buffer, 2); } rs485_rts_enable(false); @@ -724,8 +724,11 @@ static bool MSTP_Master_Node_FSM( bool transition_now = false; /* some calculations that several states need */ + /* (PS+1) modulo (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); + /* (NS +1) modulo (Nmax_master+1) */ next_next_station = (Next_Station + 1) % (Nmax_master + 1); log_master_state(Master_State); switch (Master_State) { @@ -923,8 +926,7 @@ static bool MSTP_Master_Node_FSM( } /* Npoll changed in Errata SSPC-135-2004 */ else if (TokenCount < (Npoll - 1)) { - if ((MSTP_Flag.SoleMaster == true) && - (Next_Station != next_this_station)) { + if (MSTP_Flag.SoleMaster == true) { /* SoleMaster */ /* there are no other known master nodes to */ /* which the token may be sent @@ -934,21 +936,30 @@ static bool MSTP_Master_Node_FSM( Master_State = MSTP_MASTER_STATE_USE_TOKEN; transition_now = true; } else { - /* SendToken */ - /* Npoll changed in Errata SSPC-135-2004 */ - /* The comparison of NS and TS+1 - eliminates the Poll For Master - if there are no addresses between - TS and NS, since there is no - address at which a new master node - may be found in that case. */ - 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; + if (Next_Station == This_Station) { + /* NextStationUnknown - added in Addendum 135-2008v-1 */ + Poll_Station = next_this_station; + MSTP_Send_Frame(FRAME_TYPE_POLL_FOR_MASTER, + Poll_Station, This_Station, NULL, 0); + RetryCount = 0; + Master_State = MSTP_MASTER_STATE_POLL_FOR_MASTER; + } else if (Next_Station == next_this_station) { + /* SendToken */ + /* Npoll changed in Errata SSPC-135-2004 */ + /* The comparison of NS and TS+1 + eliminates the Poll For Master + if there are no addresses between + TS and NS, since there is no + address at which a new master node + may be found in that case. */ + 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) { if (MSTP_Flag.SoleMaster == true) { diff --git a/bacnet-stack/ports/dos/dlmstp.c b/bacnet-stack/ports/dos/dlmstp.c index 513a7e20..e6a09725 100644 --- a/bacnet-stack/ports/dos/dlmstp.c +++ b/bacnet-stack/ports/dos/dlmstp.c @@ -46,7 +46,7 @@ #include "bacaddr.h" /* This file has been customized for use with small microprocessors */ -/* Assumptions: +/* Assumptions: Only one MS/TP datalink layer */ #include "timer.h" @@ -121,7 +121,7 @@ static struct mstp_flag_t { /* A Boolean flag set TRUE by the datalink transmit if a pending packet is DataExpectingReply */ 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. */ unsigned ReceivePacketPending:1; } MSTP_Flag; @@ -143,7 +143,7 @@ static uint8_t FrameType; and microcontroller architectures have limits as to places to hold contiguous memory. */ static uint8_t *InputBuffer; -static uint8_t InputBufferSize; +static uint16_t InputBufferSize; /* Used to store the Source Address of a received frame. */ static uint8_t SourceAddress; /* "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 */ /* bandwidth to particular nodes. If Max_Info_Frames is not writable in a */ /* 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 */ /* node's Device object. The value of Max_Master specifies the highest */ /* 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, */ /* 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 */ /* OutputBuffer is indexed from 0 to OutputBufferSize-1. */ /* 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 */ /* a Poll For Master frame: 20 milliseconds. (Implementations may use */ /* 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 */ /* is executed: 50. */ @@ -287,8 +287,8 @@ static bool dlmstp_compare_data_expecting_reply( uint8_t dest_address) { uint16_t offset; - /* One way to check the message is to compare NPDU - src, dest, along with the APDU type, invoke id. + /* One way to check the message is to compare NPDU + src, dest, along with the APDU type, invoke id. Seems a bit overkill */ struct DER_compare_t { BACNET_NPDU_DATA npdu_data; @@ -327,7 +327,7 @@ static bool dlmstp_compare_data_expecting_reply( if (reply.npdu_data.network_layer_message) { return false; } - /* reply could be a lot of things: + /* reply could be a lot of things: confirmed, simple ack, abort, reject, error */ reply.pdu_type = reply_pdu[offset] & 0xF0; 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 destination, /* destination address */ uint8_t source, /* source address */ - uint8_t * data, /* any data to be sent - may be null */ - uint16_t data_len) + uint8_t * pdu, /* any data to be sent - may be null */ + uint16_t pdu_len) { /* number of bytes of data (up to 501) */ uint8_t crc8 = 0xFF; /* 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); buffer[4] = source; 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); - buffer[6] = LO_BYTE(data_len); + buffer[6] = LO_BYTE(pdu_len); crc8 = CRC_Calc_Header(buffer[6], crc8); buffer[7] = ~crc8; RS485_Turnaround_Delay(); RS485_Transmitter_Enable(true); RS485_Send_Data(buffer, 8); /* send any data */ - if (data_len) { + if (pdu_len) { /* calculate CRC for any data */ - for (i = 0; i < data_len; i++) { - crc16 = CRC_Calc_Data(data[i], crc16); + for (i = 0; i < pdu_len; i++) { + crc16 = CRC_Calc_Data(pdu[i], crc16); } crc16 = ~crc16; buffer[0] = (crc16 & 0x00FF); buffer[1] = ((crc16 & 0xFF00) >> 8); - RS485_Send_Data(data, data_len); + RS485_Send_Data(pdu, pdu_len); RS485_Send_Data(buffer, 2); } RS485_Transmitter_Enable(false); @@ -453,7 +453,7 @@ static void MSTP_Receive_Frame_FSM( static uint8_t HeaderCRC = 0; /* Used as an index by the Receive State Machine, up to a maximum value of the MPDU */ - static uint8_t Index = 0; + static uint16_t Index = 0; switch (Receive_State) { case MSTP_RECEIVE_STATE_IDLE: @@ -553,7 +553,7 @@ static void MSTP_Receive_Frame_FSM( } else if (Index == 5) { /* 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. */ if (HeaderCRC != 0x55) { /* BadCRC */ @@ -565,7 +565,7 @@ static void MSTP_Receive_Frame_FSM( } else { /* Note: proposed change to BACnet MSTP state machine! 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. */ if ((DataLength) && (DataLength <= InputBufferSize)) { /* Data */ @@ -580,7 +580,7 @@ static void MSTP_Receive_Frame_FSM( (DestinationAddress == MSTP_BROADCAST_ADDRESS)) { /* ForUs */ - /* indicate that a frame with + /* indicate that a frame with no data has been received */ MSTP_Flag.ReceivedValidFrame = true; } 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. */ if (Timer_Silence() > Tframe_abort) { /* 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; /* wait for the start of the next frame. */ Receive_State = MSTP_RECEIVE_STATE_IDLE; @@ -643,7 +644,7 @@ static void MSTP_Receive_Frame_FSM( if ((DestinationAddress == This_Station) || (DestinationAddress == MSTP_BROADCAST_ADDRESS)) { /* ForUs */ - /* indicate that a frame with no data + /* indicate that a frame with no data has been received */ 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 */ /* pass the token. */ static uint8_t FrameCount; - /* "Next Station," the MAC address of the node to which This Station passes */ - /* the token. If the Next_Station is unknown, Next_Station shall be equal to */ - /* This_Station. */ + /* "Next Station," the MAC address of the node to which This Station + passes the token. If the Next_Station is unknown, Next_Station shall + be equal to This_Station. */ static uint8_t Next_Station; /* "Poll Station," the MAC address of the node to which This Station last */ /* 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 */ /* transmission. */ static unsigned RetryCount; - /* The number of tokens received by this node. When this counter reaches the */ - /* value Npoll, the node polls the address range between TS and NS for */ - /* additional master nodes. TokenCount is set to zero at the end of the */ - /* polling process. */ + /* The number of tokens received by this node. When this counter reaches */ + /* the value Npoll, the node polls the address range between TS and NS */ + /* for additional master nodes. TokenCount is set to zero at the end of */ + /* the polling process. */ static unsigned TokenCount; /* next-x-station calculations */ uint8_t next_poll_station = 0; @@ -692,13 +693,16 @@ static bool MSTP_Master_Node_FSM( uint8_t next_next_station = 0; /* timeout values */ uint16_t my_timeout = 10, ns_timeout = 0; - bool matched; + bool matched = false; /* transition immediately to the next state */ bool transition_now = false; /* some calculations that several states need */ + /* (PS+1) modulo (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); + /* (NS +1) modulo (Nmax_master+1) */ next_next_station = (Next_Station + 1) % (Nmax_master + 1); switch (Master_State) { case MSTP_MASTER_STATE_INITIALIZE: @@ -749,7 +753,7 @@ static bool MSTP_Master_Node_FSM( MSTP_Flag.ReceivePacketPending = true; break; case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY: - /* indicate successful reception to the higher layers */ + /* indicate successful reception to higher layers */ MSTP_Flag.ReceivePacketPending = true; /* broadcast DER just remains IDLE */ if (DestinationAddress != MSTP_BROADCAST_ADDRESS) { @@ -766,7 +770,7 @@ static bool MSTP_Master_Node_FSM( default: 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 */ if (Master_State != MSTP_MASTER_STATE_ANSWER_DATA_REQUEST) { MSTP_Flag.ReceivedValidFrame = false; @@ -823,8 +827,10 @@ static bool MSTP_Master_Node_FSM( FrameCount = Nmax_info_frames; Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN; /* Any retry of the data frame shall await the next entry */ - /* to the USE_TOKEN state. (Because of the length of the timeout, */ - /* this transition will cause the token to be passed regardless */ + /* to the USE_TOKEN state. */ + /* (Because of the length of the timeout, */ + /* this transition will cause the token to be */ + /* passed regardless */ /* of the initial value of FrameCount.) */ transition_now = true; } else { @@ -848,8 +854,10 @@ static bool MSTP_Master_Node_FSM( break; case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: /* ReceivedReply */ - /* or a proprietary type that indicates a reply */ - /* indicate successful reception to the higher layers */ + /* or a proprietary type that indicates + a reply */ + /* indicate successful reception to + the higher layers */ MSTP_Flag.ReceivePacketPending = true; Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN; @@ -887,28 +895,40 @@ static bool MSTP_Master_Node_FSM( } /* Npoll changed in Errata SSPC-135-2004 */ else if (TokenCount < (Npoll - 1)) { - if ((MSTP_Flag.SoleMaster == true) && - (Next_Station != next_this_station)) { + if (MSTP_Flag.SoleMaster == true) { /* SoleMaster */ /* 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; TokenCount++; Master_State = MSTP_MASTER_STATE_USE_TOKEN; transition_now = true; } else { - /* SendToken */ - /* Npoll changed in Errata SSPC-135-2004 */ - /* The comparison of NS and TS+1 eliminates the Poll For Master */ - /* if there are no addresses between TS and NS, since there is no */ - /* address at which a new master node may be found in that case. */ - 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; + if (Next_Station == This_Station) { + /* NextStationUnknown - added in Addendum 135-2008v-1 */ + Poll_Station = next_this_station; + MSTP_Send_Frame(FRAME_TYPE_POLL_FOR_MASTER, + Poll_Station, This_Station, NULL, 0); + RetryCount = 0; + Master_State = MSTP_MASTER_STATE_POLL_FOR_MASTER; + } else if (Next_Station == next_this_station) { + /* SendToken */ + /* Npoll changed in Errata SSPC-135-2004 */ + /* The comparison of NS and TS+1 + eliminates the Poll For Master + if there are no addresses between + TS and NS, since there is no + address at which a new master node + may be found in that case. */ + 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) { if (MSTP_Flag.SoleMaster == true) { @@ -981,10 +1001,11 @@ static bool MSTP_Master_Node_FSM( } } break; - /* The NO_TOKEN state is entered if Timer_Silence() becomes greater */ - /* than Tno_token, indicating that there has been no network activity */ - /* for that period of time. The timeout is continued to determine */ - /* whether or not this node may create a token. */ + /* The NO_TOKEN state is entered if Silence Timer + becomes greater than Tno_token, indicating that + there has been no network activity for that period + of time. The timeout is continued to determine + whether or not this node may create a token. */ case MSTP_MASTER_STATE_NO_TOKEN: my_timeout = Tno_token + (Tslot * This_Station); if (Timer_Silence() < my_timeout) { @@ -1075,7 +1096,8 @@ static bool MSTP_Master_Node_FSM( /* Re-enter the current state. */ } else { /* DeclareSoleMaster */ - /* to indicate that this station is the only master */ + /* to indicate that this station + is the only master */ MSTP_Flag.SoleMaster = true; FrameCount = 0; 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 */ if ((MSTP_Flag.ReceivedValidFrame == false) && (MSTP_Flag.ReceivedInvalidFrame == false)) { - for (;;) { - 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; - } + MSTP_Receive_Frame_FSM(); } /* only do master state machine while rx is idle */ if (Receive_State == MSTP_RECEIVE_STATE_IDLE) { @@ -1214,7 +1228,7 @@ void dlmstp_set_mac_address( This_Station = mac_address; /* FIXME: implement your data storage */ /* I2C_Write_Byte( - EEPROM_DEVICE_ADDRESS, + EEPROM_DEVICE_ADDRESS, mac_address, EEPROM_MSTP_MAC_ADDR); */ if (mac_address > Nmax_master) @@ -1243,8 +1257,8 @@ void dlmstp_set_max_info_frames( if (max_info_frames >= 1) { Nmax_info_frames = max_info_frames; /* FIXME: implement your data storage */ - /* I2C_Write_Byte( - EEPROM_DEVICE_ADDRESS, + /* I2C_Write_Byte( + EEPROM_DEVICE_ADDRESS, (uint8_t)max_info_frames, EEPROM_MSTP_MAX_INFO_FRAMES_ADDR); */ } diff --git a/bacnet-stack/src/bacapp.c b/bacnet-stack/src/bacapp.c index 19f007e0..e88ca7f8 100644 --- a/bacnet-stack/src/bacapp.c +++ b/bacnet-stack/src/bacapp.c @@ -957,7 +957,7 @@ bool bacapp_print_value( } else { fprintf(stream, "%u, ", (unsigned) value->type.Date.day); } - if (value->type.Date.year == 255) { + if (value->type.Date.year == 2155) { fprintf(stream, "(unspecified), "); } else { fprintf(stream, "%u", (unsigned) value->type.Date.year); diff --git a/bacnet-stack/src/mstp.c b/bacnet-stack/src/mstp.c index 1ecb45e8..63b87c1b 100644 --- a/bacnet-stack/src/mstp.c +++ b/bacnet-stack/src/mstp.c @@ -1,6 +1,6 @@ /*####COPYRIGHTBEGIN#### ------------------------------------------- - Copyright (C) 2003-2007 Steve Karg + Copyright (C) 2003-2010 Steve Karg This program is free software; you can redistribute it and/or 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; /* some calculations that several states need */ + /* (PS+1) modulo (Nmax_master+1) */ next_poll_station = (mstp_port->Poll_Station + 1) % (mstp_port->Nmax_master + 1); + /* (TS+1) modulo (Nmax_master+1) */ next_this_station = (mstp_port->This_Station + 1) % (mstp_port->Nmax_master + 1); + /* (NS +1) modulo (Nmax_master+1) */ next_next_station = (mstp_port->Next_Station + 1) % (mstp_port->Nmax_master + 1); if (mstp_port->master_state != master_state) { @@ -816,8 +819,7 @@ bool MSTP_Master_Node_FSM( transition_now = true; } else if (mstp_port->TokenCount < (Npoll - 1)) { /* Npoll changed in Errata SSPC-135-2004 */ - if ((mstp_port->SoleMaster == true) && - (mstp_port->Next_Station != next_this_station)) { + if (mstp_port->SoleMaster == true) { /* SoleMaster */ /* there are no other known master nodes to */ /* 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; transition_now = true; } else { - /* SendToken */ - /* Npoll changed in Errata SSPC-135-2004 */ - /* The comparison of NS and TS+1 eliminates the Poll For Master */ - /* if there are no addresses between TS and NS, since there is no */ - /* address at which a new master node may be found in that case. */ - mstp_port->TokenCount++; - /* transmit a Token frame to NS */ - MSTP_Create_And_Send_Frame(mstp_port, FRAME_TYPE_TOKEN, - mstp_port->Next_Station, mstp_port->This_Station, NULL, - 0); - mstp_port->RetryCount = 0; - mstp_port->EventCount = 0; - mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN; + if (mstp_port->Next_Station == mstp_port->This_Station) { + /* NextStationUnknown - added in Addendum 135-2008v-1 */ + mstp_port->Poll_Station = next_this_station; + MSTP_Create_And_Send_Frame(mstp_port, + FRAME_TYPE_POLL_FOR_MASTER, mstp_port->Poll_Station, + mstp_port->This_Station, NULL, 0); + mstp_port->RetryCount = 0; + mstp_port->master_state = + MSTP_MASTER_STATE_POLL_FOR_MASTER; + } else if (mstp_port->Next_Station == next_this_station) { + /* SendToken */ + /* Npoll changed in Errata SSPC-135-2004 */ + /* The comparison of NS and TS+1 eliminates the Poll For Master */ + /* if there are no addresses between TS and NS, since there is no */ + /* address at which a new master node may be found in that case. */ + mstp_port->TokenCount++; + /* transmit a Token frame to NS */ + MSTP_Create_And_Send_Frame(mstp_port, FRAME_TYPE_TOKEN, + mstp_port->Next_Station, mstp_port->This_Station, NULL, + 0); + mstp_port->RetryCount = 0; + mstp_port->EventCount = 0; + mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN; + } } } else if (next_poll_station == mstp_port->Next_Station) { if (mstp_port->SoleMaster == true) {