diff --git a/bacnet-stack/dlmstp.h b/bacnet-stack/dlmstp.h index 2021901e..97b2b622 100644 --- a/bacnet-stack/dlmstp.h +++ b/bacnet-stack/dlmstp.h @@ -45,55 +45,6 @@ #define MAX_HEADER (2+1+1+1+2+1+2+1) #define MAX_MPDU (MAX_HEADER+MAX_PDU) -/* The value 255 is used to denote broadcast when used as a */ -/* destination address but is not allowed as a value for a station. */ -/* Station addresses for master nodes can be 0-127. */ -/* Station addresses for slave nodes can be 127-254. */ -#define MSTP_BROADCAST_ADDRESS 255 - -/* MS/TP Frame Type */ -/* Frame Types 8 through 127 are reserved by ASHRAE. */ -#define FRAME_TYPE_TOKEN 0 -#define FRAME_TYPE_POLL_FOR_MASTER 1 -#define FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER 2 -#define FRAME_TYPE_TEST_REQUEST 3 -#define FRAME_TYPE_TEST_RESPONSE 4 -#define FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY 5 -#define FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY 6 -#define FRAME_TYPE_REPLY_POSTPONED 7 -/* Frame Types 128 through 255: Proprietary Frames */ -/* These frames are available to vendors as proprietary (non-BACnet) frames. */ -/* The first two octets of the Data field shall specify the unique vendor */ -/* identification code, most significant octet first, for the type of */ -/* vendor-proprietary frame to be conveyed. The length of the data portion */ -/* of a Proprietary frame shall be in the range of 2 to 501 octets. */ -#define FRAME_TYPE_PROPRIETARY_MIN 128 -#define FRAME_TYPE_PROPRIETARY_MAX 255 -/* The initial CRC16 checksum value */ -#define CRC16_INITIAL_VALUE (0xFFFF) - -/* receive FSM states */ -typedef enum { - MSTP_RECEIVE_STATE_IDLE = 0, - MSTP_RECEIVE_STATE_PREAMBLE = 1, - MSTP_RECEIVE_STATE_HEADER = 2, - MSTP_RECEIVE_STATE_HEADER_CRC = 3, - MSTP_RECEIVE_STATE_DATA = 4 -} MSTP_RECEIVE_STATE; - -/* master node FSM states */ -typedef enum { - MSTP_MASTER_STATE_INITIALIZE = 0, - MSTP_MASTER_STATE_IDLE = 1, - MSTP_MASTER_STATE_USE_TOKEN = 2, - MSTP_MASTER_STATE_WAIT_FOR_REPLY = 3, - MSTP_MASTER_STATE_DONE_WITH_TOKEN = 4, - MSTP_MASTER_STATE_PASS_TOKEN = 5, - MSTP_MASTER_STATE_NO_TOKEN = 6, - MSTP_MASTER_STATE_POLL_FOR_MASTER = 7, - MSTP_MASTER_STATE_ANSWER_DATA_REQUEST = 8 -} MSTP_MASTER_STATE; - typedef struct dlmstp_packet { bool ready; /* true if ready to be sent or received */ BACNET_ADDRESS address; /* source address */ diff --git a/bacnet-stack/mstp.c b/bacnet-stack/mstp.c index 374f5f3d..65d2003b 100644 --- a/bacnet-stack/mstp.c +++ b/bacnet-stack/mstp.c @@ -105,10 +105,6 @@ /* of a frame the node is transmitting: 20 bit times. */ #define Tframe_gap 20 -/* The time without a DataAvailable or ReceiveError event before declaration */ -/* of loss of token: 500 milliseconds. */ -#define Tno_token 500 - /* 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. */ @@ -121,12 +117,6 @@ the reply may be in the transmit queue */ #define Treply_delay 10 -/* The minimum time without a DataAvailable or ReceiveError event */ -/* 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 255 - /* Repeater turnoff delay. The duration of a continuous logical one state */ /* at the active input port of an MS/TP repeater after which the repeater */ /* will enter the IDLE state: 29 bit times < Troff < 40 bit times. */ @@ -141,12 +131,6 @@ /* 15 milliseconds. */ #define Tusage_delay 15 -/* 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 20 - /* we need to be able to increment without rolling over */ #define INCREMENT_AND_LIMIT_UINT8(x) {if (x < 0xFF) x++;} diff --git a/bacnet-stack/mstp.h b/bacnet-stack/mstp.h index 078bcaa6..b4dd80ed 100644 --- a/bacnet-stack/mstp.h +++ b/bacnet-stack/mstp.h @@ -42,6 +42,72 @@ #include "bacdef.h" #include "dlmstp.h" +/* The value 255 is used to denote broadcast when used as a */ +/* destination address but is not allowed as a value for a station. */ +/* Station addresses for master nodes can be 0-127. */ +/* Station addresses for slave nodes can be 127-254. */ +#define MSTP_BROADCAST_ADDRESS 255 + +/* MS/TP Frame Type */ +/* Frame Types 8 through 127 are reserved by ASHRAE. */ +#define FRAME_TYPE_TOKEN 0 +#define FRAME_TYPE_POLL_FOR_MASTER 1 +#define FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER 2 +#define FRAME_TYPE_TEST_REQUEST 3 +#define FRAME_TYPE_TEST_RESPONSE 4 +#define FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY 5 +#define FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY 6 +#define FRAME_TYPE_REPLY_POSTPONED 7 +/* Frame Types 128 through 255: Proprietary Frames */ +/* These frames are available to vendors as proprietary (non-BACnet) frames. */ +/* The first two octets of the Data field shall specify the unique vendor */ +/* identification code, most significant octet first, for the type of */ +/* vendor-proprietary frame to be conveyed. The length of the data portion */ +/* of a Proprietary frame shall be in the range of 2 to 501 octets. */ +#define FRAME_TYPE_PROPRIETARY_MIN 128 +#define FRAME_TYPE_PROPRIETARY_MAX 255 +/* The initial CRC16 checksum value */ +#define CRC16_INITIAL_VALUE (0xFFFF) + +/* receive FSM states */ +typedef enum { + MSTP_RECEIVE_STATE_IDLE = 0, + MSTP_RECEIVE_STATE_PREAMBLE = 1, + MSTP_RECEIVE_STATE_HEADER = 2, + MSTP_RECEIVE_STATE_HEADER_CRC = 3, + MSTP_RECEIVE_STATE_DATA = 4 +} MSTP_RECEIVE_STATE; + +/* master node FSM states */ +typedef enum { + MSTP_MASTER_STATE_INITIALIZE = 0, + MSTP_MASTER_STATE_IDLE = 1, + MSTP_MASTER_STATE_USE_TOKEN = 2, + MSTP_MASTER_STATE_WAIT_FOR_REPLY = 3, + MSTP_MASTER_STATE_DONE_WITH_TOKEN = 4, + MSTP_MASTER_STATE_PASS_TOKEN = 5, + MSTP_MASTER_STATE_NO_TOKEN = 6, + MSTP_MASTER_STATE_POLL_FOR_MASTER = 7, + MSTP_MASTER_STATE_ANSWER_DATA_REQUEST = 8 +} MSTP_MASTER_STATE; + +/* The time without a DataAvailable or ReceiveError event before declaration */ +/* of loss of token: 500 milliseconds. */ +#define Tno_token 500 + +/* The minimum time without a DataAvailable or ReceiveError event */ +/* 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 255 + +/* 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 20 + + struct mstp_port_struct_t { MSTP_RECEIVE_STATE receive_state; /* When a master node is powered up or reset, */ @@ -93,7 +159,7 @@ struct mstp_port_struct_t { /* InputBuffer is indexed from 0 to InputBufferSize-1. */ /* The maximum size of a frame is 501 octets. */ /* FIXME: assign this to an actual array of bytes! */ - /* Note: the buffer is designed as a pointer since some compilers + /* Note: the buffer is designed as a pointer since some compilers and microcontroller architectures have limits as to places to hold contiguous memory. */ uint8_t *InputBuffer; @@ -158,12 +224,12 @@ struct mstp_port_struct_t { /* less than or equal to 127. If Max_Master is not writable in a node, */ /* its value shall be 127. */ unsigned Nmax_master; - + /* An array of octets, used to store octets for transmitting */ /* OutputBuffer is indexed from 0 to OutputBufferSize-1. */ /* The maximum size of a frame is 501 octets. */ /* FIXME: assign this to an actual array of bytes! */ - /* Note: the buffer is designed as a pointer since some compilers + /* Note: the buffer is designed as a pointer since some compilers and microcontroller architectures have limits as to places to hold contiguous memory. */ uint8_t *OutputBuffer; diff --git a/bacnet-stack/ports/win32/dlmstp.c b/bacnet-stack/ports/win32/dlmstp.c index 205c788e..d353fc12 100644 --- a/bacnet-stack/ports/win32/dlmstp.c +++ b/bacnet-stack/ports/win32/dlmstp.c @@ -25,10 +25,9 @@ #include #include #include +#include #include -#if PRINT_ENABLED #include -#endif #include "bacdef.h" #include "mstp.h" #include "dlmstp.h" @@ -44,6 +43,9 @@ uint16_t MSTP_Packets = 0; /* packet queues */ static DLMSTP_PACKET Receive_Packet; +static HANDLE Receive_Packet_Flag; +/* mechanism to wait for a frame in state machine */ +HANDLE Received_Frame_Flag; static DLMSTP_PACKET Transmit_Packet; /* local MS/TP port data - shared with RS-485 */ volatile struct mstp_port_struct_t MSTP_Port; @@ -69,6 +71,12 @@ void dlmstp_reinit(void) void dlmstp_cleanup(void) { /* nothing to do for static buffers */ + if (Received_Frame_Flag) { + CloseHandle(Received_Frame_Flag); + } + if (Receive_Packet_Flag) { + CloseHandle(Receive_Packet_Flag); + } } /* returns number of bytes sent on success, zero on failure */ @@ -117,25 +125,29 @@ uint16_t dlmstp_receive( unsigned timeout) /* milliseconds to wait for a packet */ { uint16_t pdu_len = 0; + DWORD wait_status = 0; /* see if there is a packet available, and a place to put the reply (if necessary) and process it */ - if (Receive_Packet.ready) { - if (Receive_Packet.pdu_len) { - MSTP_Packets++; - if (src) { - memmove(src, - &Receive_Packet.address, - sizeof(Receive_Packet.address)); + wait_status = WaitForSingleObject(Receive_Packet_Flag,timeout); + if (wait_status == WAIT_OBJECT_0) { + if (Receive_Packet.ready) { + if (Receive_Packet.pdu_len) { + MSTP_Packets++; + if (src) { + memmove(src, + &Receive_Packet.address, + sizeof(Receive_Packet.address)); + } + if (pdu) { + memmove(pdu, + &Receive_Packet.pdu, + sizeof(Receive_Packet.pdu)); + } + pdu_len = Receive_Packet.pdu_len; } - if (pdu) { - memmove(pdu, - &Receive_Packet.pdu, - sizeof(Receive_Packet.pdu)); - } - pdu_len = Receive_Packet.pdu_len; + Receive_Packet.ready = false; } - Receive_Packet.ready = false; } return pdu_len; @@ -145,7 +157,7 @@ static void dlmstp_receive_fsm_task(void *pArg) { bool received_frame; - //(void)SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); + (void)SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); while (TRUE) { /* only do receive state machine while we don't have a frame */ if ((MSTP_Port.ReceivedValidFrame == false) && @@ -155,8 +167,10 @@ static void dlmstp_receive_fsm_task(void *pArg) MSTP_Receive_Frame_FSM(&MSTP_Port); received_frame = MSTP_Port.ReceivedValidFrame || MSTP_Port.ReceivedInvalidFrame; - if (received_frame) + if (received_frame) { + ReleaseSemaphore(Received_Frame_Flag, 1, NULL); break; + } } while (MSTP_Port.DataAvailable); } } @@ -164,14 +178,27 @@ static void dlmstp_receive_fsm_task(void *pArg) static void dlmstp_master_fsm_task(void *pArg) { - //(void)SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); + DWORD dwMilliseconds = 0; + + (void)SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); while (TRUE) { - /* only do master state machine while rx is idle */ - if (MSTP_Port.receive_state == MSTP_RECEIVE_STATE_IDLE) { - while (MSTP_Master_Node_FSM(&MSTP_Port)) { - Sleep(0); - }; + switch (MSTP_Port.master_state) { + case MSTP_MASTER_STATE_IDLE: + dwMilliseconds = Tno_token; + break; + case MSTP_MASTER_STATE_WAIT_FOR_REPLY: + dwMilliseconds = Treply_timeout; + break; + case MSTP_MASTER_STATE_POLL_FOR_MASTER: + dwMilliseconds = Tusage_timeout; + break; + default: + dwMilliseconds = 0; + break; } + if (dwMilliseconds) + WaitForSingleObject(Received_Frame_Flag,dwMilliseconds); + MSTP_Master_Node_FSM(&MSTP_Port); } } @@ -212,6 +239,7 @@ uint16_t MSTP_Put_Receive( volatile struct mstp_port_struct_t *mstp_port) { uint16_t pdu_len = 0; + BOOL rc; if (!Receive_Packet.ready) { /* bounds check - maybe this should send an abort? */ @@ -225,6 +253,7 @@ uint16_t MSTP_Put_Receive( mstp_port->SourceAddress); Receive_Packet.pdu_len = mstp_port->DataLength; Receive_Packet.ready = true; + rc = ReleaseSemaphore(Receive_Packet_Flag, 1, NULL); } return pdu_len; @@ -380,6 +409,14 @@ bool dlmstp_init(char *ifname) /* initialize packet queue */ Receive_Packet.ready = false; Receive_Packet.pdu_len = 0; + Receive_Packet_Flag = CreateSemaphore (NULL,0,1,"dlmstpReceivePacket"); + if (Receive_Packet_Flag == NULL) + exit(1); + Received_Frame_Flag = CreateSemaphore (NULL,0,1,"dlsmtpReceiveFrame"); + if (Received_Frame_Flag == NULL) { + CloseHandle(Receive_Packet_Flag); + exit(1); + } /* initialize hardware */ /* initialize hardware */ if (ifname) { @@ -494,7 +531,7 @@ int main(int argc, char *argv[]) dlmstp_init(Network_Interface); /* forever task */ for (;;) { - pdu_len = dlmstp_receive(NULL,NULL,0,0); + pdu_len = dlmstp_receive(NULL,NULL,0,INFINITE); #if 0 MSTP_Create_And_Send_Frame( &MSTP_Port, @@ -503,7 +540,6 @@ int main(int argc, char *argv[]) MSTP_Port.This_Station, NULL, 0); #endif - Sleep(10); } return 0; diff --git a/bacnet-stack/ports/win32/rs485.c b/bacnet-stack/ports/win32/rs485.c index c8fa0096..16785e09 100644 --- a/bacnet-stack/ports/win32/rs485.c +++ b/bacnet-stack/ports/win32/rs485.c @@ -325,8 +325,7 @@ void RS485_Check_UART_Data(struct mstp_port_struct_t *mstp_port) } } else { if (dwRead) { - mstp_port->DataRegister = lpBuf[0]; /* FIXME: Get this data from UART or buffer */ - /* if data is ready, */ + mstp_port->DataRegister = lpBuf[0]; mstp_port->DataAvailable = TRUE; } }