From 52ee5a56194769eb7836cb07e7fa5af6e994d8b1 Mon Sep 17 00:00:00 2001 From: skarg Date: Wed, 23 Aug 2006 21:32:16 +0000 Subject: [PATCH] Getting the RTOS-32 port working again. Also getting the MS/TP state machine working. Soon! --- bacnet-stack/bip.c | 30 -- bacnet-stack/bip.h | 5 - bacnet-stack/dlmstp.h | 9 +- bacnet-stack/mstp.c | 411 +++++++++++++++------ bacnet-stack/mstp.h | 11 +- bacnet-stack/ports/pic18/BACnet-Server.mcp | 2 + bacnet-stack/ports/pic18/BACnet-Server.mcw | Bin 32768 -> 22528 bytes bacnet-stack/ports/pic18/main.c | 29 +- bacnet-stack/ports/rtos32/bip-init.c | 78 ++-- bacnet-stack/ports/rtos32/dlmstp.c | 268 ++++++++++++++ bacnet-stack/ports/rtos32/ethernet.c | 15 + bacnet-stack/ports/rtos32/main.c | 120 ++++-- bacnet-stack/ports/rtos32/makefile.mak | 39 +- bacnet-stack/ports/rtos32/net.h | 33 +- bacnet-stack/ports/rtos32/netcfg.h | 8 +- bacnet-stack/ports/rtos32/rs485.c | 44 ++- bacnet-stack/ports/win32/MAKEFILE.MAK | 2 +- bacnet-stack/rs485.h | 5 - 18 files changed, 853 insertions(+), 256 deletions(-) create mode 100644 bacnet-stack/ports/rtos32/dlmstp.c diff --git a/bacnet-stack/bip.c b/bacnet-stack/bip.c index 36d0eb88..0237adea 100644 --- a/bacnet-stack/bip.c +++ b/bacnet-stack/bip.c @@ -70,36 +70,6 @@ void bip_cleanup(void) return; } -static void set_network_address(struct in_addr *net_address, - uint8_t octet1, uint8_t octet2, uint8_t octet3, uint8_t octet4) -{ - union { - uint8_t byte[4]; - uint32_t value; - } long_data = { { - 0}}; - - long_data.byte[0] = octet1; - long_data.byte[1] = octet2; - long_data.byte[2] = octet3; - long_data.byte[3] = octet4; - - net_address->s_addr = long_data.value; -} - -void bip_set_address(uint8_t octet1, - uint8_t octet2, uint8_t octet3, uint8_t octet4) -{ - set_network_address(&BIP_Address, octet1, octet2, octet3, octet4); -} - -void bip_set_broadcast_address(uint8_t octet1, - uint8_t octet2, uint8_t octet3, uint8_t octet4) -{ - set_network_address(&BIP_Broadcast_Address, octet1, octet2, octet3, - octet4); -} - /* set using network byte order */ void bip_set_addr(uint32_t net_address) { diff --git a/bacnet-stack/bip.h b/bacnet-stack/bip.h index b6aea1e5..21e4ac05 100644 --- a/bacnet-stack/bip.h +++ b/bacnet-stack/bip.h @@ -76,11 +76,6 @@ extern "C" { uint16_t max_pdu, /* amount of space available in the PDU */ unsigned timeout); /* milliseconds to wait for a packet */ - void bip_set_address(uint8_t octet1, uint8_t octet2, - uint8_t octet3, uint8_t octet4); - void bip_set_broadcast_address(uint8_t octet1, uint8_t octet2, - uint8_t octet3, uint8_t octet4); - /* use host byte order for setting */ void bip_set_port(uint16_t port); /* returns host byte order */ diff --git a/bacnet-stack/dlmstp.h b/bacnet-stack/dlmstp.h index eb2c4dd1..47907ab1 100644 --- a/bacnet-stack/dlmstp.h +++ b/bacnet-stack/dlmstp.h @@ -47,7 +47,7 @@ typedef struct dlmstp_packet { bool ready; /* true if ready to be sent or received */ - BACNET_ADDRESS address; /* src or dest address */ + BACNET_ADDRESS address; /* source address */ unsigned pdu_len; /* packet length */ uint8_t pdu[MAX_MPDU]; /* packet */ } DLMSTP_PACKET; @@ -94,6 +94,13 @@ extern "C" { void dlmstp_set_my_address(uint8_t my_address); void dlmstp_get_my_address(BACNET_ADDRESS * my_address); void dlmstp_get_broadcast_address(BACNET_ADDRESS * dest); /* destination address */ + + /* MS/TP state machine functions */ + uint16_t dlmstp_put_receive( + uint8_t src, /* source MS/TP address */ + uint8_t * pdu, /* PDU data */ + uint16_t pdu_len); + #ifdef __cplusplus } diff --git a/bacnet-stack/mstp.c b/bacnet-stack/mstp.c index 08392e02..30bfaf09 100644 --- a/bacnet-stack/mstp.c +++ b/bacnet-stack/mstp.c @@ -46,11 +46,18 @@ #include #include +#if PRINT_ENABLED +#include +#endif #include "mstp.h" #include "bytes.h" #include "crc.h" #include "rs485.h" +/* debug print statements */ +#define PRINT_ENABLED_RECEIVE 0 +#define PRINT_ENABLED_MASTER 0 + /* MS/TP Frame Format */ /* All frames are of the following format: */ /* */ @@ -74,14 +81,14 @@ const unsigned Nretry_token = 1; /* The minimum number of DataAvailable or ReceiveError events that must be */ /* seen by a receiving node in order to declare the line "active": 4. */ -const unsigned Nmin_octets = 4; +const uint8_t Nmin_octets = 4; /* The minimum time without a DataAvailable or ReceiveError event within */ /* a frame before a receiving node may discard the frame: 60 bit times. */ /* (Implementations may use larger values for this timeout, */ /* not to exceed 100 milliseconds.) */ /* At 9600 baud, 60 bit times would be about 6.25 milliseconds */ -const unsigned Tframe_abort = 1 + ((1000 * 60) / 9600); +const uint16_t Tframe_abort = 1 + ((1000 * 60) / 9600); /* The maximum idle time a sending node may allow to elapse between octets */ /* of a frame the node is transmitting: 20 bit times. */ @@ -89,7 +96,7 @@ const unsigned Tframe_gap = 20; /* The time without a DataAvailable or ReceiveError event before declaration */ /* of loss of token: 500 milliseconds. */ -const unsigned Tno_token = 500; +const uint16_t 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 */ @@ -99,13 +106,13 @@ const unsigned 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. */ -const unsigned Treply_delay = 225; +const uint16_t Treply_delay = 225; /* 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.) */ -const unsigned Treply_timeout = 255; +const uint16_t 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 */ @@ -114,18 +121,22 @@ const unsigned Troff = 30; /* The width of the time slot within which a node may generate a token: */ /* 10 milliseconds. */ -const unsigned Tslot = 10; +const uint16_t Tslot = 10; /* The maximum time a node may wait after reception of the token or */ /* a Poll For Master frame before sending the first octet of a frame: */ /* 15 milliseconds. */ -const unsigned Tusage_delay = 15; +const uint16_t 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.) */ -const unsigned Tusage_timeout = 20; +const uint16_t Tusage_timeout = 20; + +/* we need to be able to increment without rolling over */ +#define INCREMENT_AND_LIMIT_UINT8(x) {if (x < 0xFF) x++;} +#define INCREMENT_AND_LIMIT_UINT16(x) {if (x < 0xFFFF) x++;} unsigned MSTP_Create_Frame(uint8_t * buffer, /* where frame is loaded */ unsigned buffer_len, /* amount of space available */ @@ -199,23 +210,62 @@ void MSTP_Create_And_Send_Frame(volatile struct mstp_port_struct_t *mstp_port, data_len); /* number of bytes of data (up to 501) */ RS485_Send_Frame(mstp_port, &buffer[0], len); - RS485_Process_Tx_Message(); - while (RS485_Tx_Complete()) {/* FIXME: watchdog? */}; } /* Millisecond Timer - called every millisecond */ void MSTP_Millisecond_Timer(volatile struct mstp_port_struct_t *mstp_port) { - if (mstp_port->SilenceTimer < 255) - mstp_port->SilenceTimer++; - if (mstp_port->ReplyPostponedTimer < 255) - mstp_port->ReplyPostponedTimer++; - + INCREMENT_AND_LIMIT_UINT16(mstp_port->SilenceTimer); + INCREMENT_AND_LIMIT_UINT16(mstp_port->ReplyPostponedTimer); return; } +#if PRINT_ENABLED_RECEIVE +char *mstp_receive_state_text(int state) +{ + char *text = "unknown"; + + switch (state) + { + case MSTP_RECEIVE_STATE_IDLE: + text = "IDLE"; + break; + case MSTP_RECEIVE_STATE_PREAMBLE: + text = "PREAMBLE"; + break; + case MSTP_RECEIVE_STATE_HEADER: + text = "HEADER"; + break; + case MSTP_RECEIVE_STATE_HEADER_CRC: + text = "HEADER_CRC"; + break; + case MSTP_RECEIVE_STATE_DATA: + text = "DATA"; + break; + case MSTP_RECEIVE_STATE_DATA_CRC: + text = "CRC"; + break; + default: + break; + } + + return text; +} +#endif + void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port) { + #if PRINT_ENABLED_RECEIVE + fprintf(stderr,"MSTP Rx: State=%s Data=%02X hCRC=%02X Index=%u EC=%u DateLen=%u Silence=%u\r\n", + mstp_receive_state_text(mstp_port->receive_state), + mstp_port->DataRegister, + mstp_port->HeaderCRC, + mstp_port->Index, + mstp_port->EventCount, + mstp_port->DataLength, + mstp_port->SilenceTimer); + #endif + switch (mstp_port->receive_state) { /* In the IDLE state, the node waits for the beginning of a frame. */ case MSTP_RECEIVE_STATE_IDLE: @@ -223,7 +273,7 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port) if (mstp_port->ReceiveError == true) { mstp_port->ReceiveError = false; mstp_port->SilenceTimer = 0; - mstp_port->EventCount++; + INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount); /* wait for the start of a frame. */ mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE; } else { @@ -232,7 +282,7 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port) if (mstp_port->DataRegister == 0x55) { mstp_port->DataAvailable = false; mstp_port->SilenceTimer = 0; - mstp_port->EventCount++; + INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount); /* receive the remainder of the frame. */ mstp_port->receive_state = MSTP_RECEIVE_STATE_PREAMBLE; } @@ -240,7 +290,7 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port) else { mstp_port->DataAvailable = false; mstp_port->SilenceTimer = 0; - mstp_port->EventCount++; + INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount); /* wait for the start of a frame. */ mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE; } @@ -259,7 +309,7 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port) else if (mstp_port->ReceiveError == true) { mstp_port->ReceiveError = false; mstp_port->SilenceTimer = 0; - mstp_port->EventCount++; + INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount); /* wait for the start of a frame. */ mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE; } else { @@ -268,7 +318,7 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port) if (mstp_port->DataRegister == 0xFF) { mstp_port->DataAvailable = false; mstp_port->SilenceTimer = 0; - mstp_port->EventCount++; + INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount); mstp_port->Index = 0; mstp_port->HeaderCRC = 0xFF; /* receive the remainder of the frame. */ @@ -278,7 +328,7 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port) else if (mstp_port->DataRegister == 0x55) { mstp_port->DataAvailable = false; mstp_port->SilenceTimer = 0; - mstp_port->EventCount++; + INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount); /* wait for the second preamble octet. */ mstp_port->receive_state = MSTP_RECEIVE_STATE_PREAMBLE; } @@ -286,7 +336,7 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port) else { mstp_port->DataAvailable = false; mstp_port->SilenceTimer = 0; - mstp_port->EventCount++; + INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount); /* wait for the start of a frame. */ mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE; } @@ -306,7 +356,7 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port) else if (mstp_port->ReceiveError == true) { mstp_port->ReceiveError = false; mstp_port->SilenceTimer = 0; - mstp_port->EventCount++; + INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount); /* indicate that an error has occurred during the reception of a frame */ mstp_port->ReceivedInvalidFrame = true; /* wait for the start of a frame. */ @@ -315,7 +365,7 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port) /* FrameType */ if (mstp_port->Index == 0) { mstp_port->SilenceTimer = 0; - mstp_port->EventCount++; + INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount); mstp_port->HeaderCRC = CRC_Calc_Header(mstp_port->DataRegister, mstp_port->HeaderCRC); @@ -327,7 +377,7 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port) /* Destination */ else if (mstp_port->Index == 1) { mstp_port->SilenceTimer = 0; - mstp_port->EventCount++; + INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount); mstp_port->HeaderCRC = CRC_Calc_Header(mstp_port->DataRegister, mstp_port->HeaderCRC); @@ -339,7 +389,7 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port) /* Source */ else if (mstp_port->Index == 2) { mstp_port->SilenceTimer = 0; - mstp_port->EventCount++; + INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount); mstp_port->HeaderCRC = CRC_Calc_Header(mstp_port->DataRegister, mstp_port->HeaderCRC); @@ -351,7 +401,7 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port) /* Length1 */ else if (mstp_port->Index == 3) { mstp_port->SilenceTimer = 0; - mstp_port->EventCount++; + INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount); mstp_port->HeaderCRC = CRC_Calc_Header(mstp_port->DataRegister, mstp_port->HeaderCRC); @@ -363,7 +413,7 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port) /* Length2 */ else if (mstp_port->Index == 4) { mstp_port->SilenceTimer = 0; - mstp_port->EventCount++; + INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount); mstp_port->HeaderCRC = CRC_Calc_Header(mstp_port->DataRegister, mstp_port->HeaderCRC); @@ -375,7 +425,7 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port) /* HeaderCRC */ else if (mstp_port->Index == 5) { mstp_port->SilenceTimer = 0; - mstp_port->EventCount++; + INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount); mstp_port->HeaderCRC = CRC_Calc_Header(mstp_port->DataRegister, mstp_port->HeaderCRC); @@ -386,7 +436,7 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port) else { mstp_port->ReceiveError = false; mstp_port->SilenceTimer = 0; - mstp_port->EventCount++; + INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount); /* indicate that an error has occurred during */ /* the reception of a frame */ mstp_port->ReceivedInvalidFrame = true; @@ -516,15 +566,135 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port) return; } +void mstp_put_receive(volatile struct mstp_port_struct_t + *mstp_port) +{ + if (mstp_port) + { + dlmstp_put_receive( + mstp_port->SourceAddress, /* source MS/TP address */ + (uint8_t *) & mstp_port->InputBuffer[0], + mstp_port->Index); + } +} + +#if PRINT_ENABLED_MASTER +char *mstp_master_state_text(int state) +{ + char *text = "unknown"; + + switch (state) + { + case MSTP_MASTER_STATE_INITIALIZE: + text = "INITIALIZE"; + break; + case MSTP_MASTER_STATE_IDLE: + text = "IDLE"; + break; + case MSTP_MASTER_STATE_USE_TOKEN: + text = "USE_TOKEN"; + break; + case MSTP_MASTER_STATE_WAIT_FOR_REPLY: + text = "WAIT_FOR_REPLY"; + break; + case MSTP_MASTER_STATE_DONE_WITH_TOKEN: + text = "IDLE"; + break; + case MSTP_MASTER_STATE_PASS_TOKEN: + text = "DONE_WITH_TOKEN"; + break; + case MSTP_MASTER_STATE_NO_TOKEN: + text = "NO_TOKEN"; + break; + case MSTP_MASTER_STATE_POLL_FOR_MASTER: + text = "POLL_FOR_MASTER"; + break; + case MSTP_MASTER_STATE_ANSWER_DATA_REQUEST: + text = "ANSWER_DATA_REQUEST"; + break; + default: + break; + } + + return text; +} +#endif + +#if PRINT_ENABLED +char *mstp_frame_type_text(int type) +{ + char *text = "unknown"; + + switch (type) + { + case FRAME_TYPE_TOKEN: + text = "TOKEN"; + break; + case FRAME_TYPE_POLL_FOR_MASTER: + text = "POLL_FOR_MASTER"; + break; + case FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER: + text = "REPLY_TO_POLL_FOR_MASTER"; + break; + case FRAME_TYPE_TEST_REQUEST: + text = "TEST_REQUEST"; + break; + case FRAME_TYPE_TEST_RESPONSE: + text = "TEST_RESPONSE"; + break; + case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY: + text = "BACNET_DATA_EXPECTING_REPLY"; + break; + case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: + text = "BACNET_DATA_NOT_EXPECTING_REPLY"; + break; + case FRAME_TYPE_REPLY_POSTPONED: + text = "REPLY_POSTPONED"; + break; + default: + if ((type >= FRAME_TYPE_PROPRIETARY_MIN) && + (type <= FRAME_TYPE_PROPRIETARY_MAX)) + text = "PROPRIETARY"; + break; + } + + return text; +} +#endif + void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) { int mtu_len = 0; int frame_type = 0; + uint8_t next_poll_station = 0; + uint8_t next_poll_neighbor = 0; + uint8_t next_station = 0; + /* some calculations that several states need */ + next_poll_station = (mstp_port->Poll_Station + 1) % + (mstp_port->Nmax_master + 1); + next_poll_neighbor = (mstp_port->This_Station + 1) % + (mstp_port->Nmax_master + 1); + next_station = (mstp_port->Next_Station + 1) % + (mstp_port->Nmax_master + 1); + #if PRINT_ENABLED_MASTER + fprintf(stderr,"MSTP: State=%s TS=%u NS=%u PS=%u EC=%u TC=%u Silence=%u\r\n", + mstp_master_state_text(mstp_port->master_state), + mstp_port->This_Station, + mstp_port->Next_Station, + mstp_port->Poll_Station, + mstp_port->EventCount, + mstp_port->TokenCount, + mstp_port->SilenceTimer); + fprintf(stderr,"MSTP: NextPollStation=%u NextPollNeighbor=%u NextStation=%u\r\n", + next_poll_station, + next_poll_neighbor, + next_station); + #endif + switch (mstp_port->master_state) { case MSTP_MASTER_STATE_INITIALIZE: /* DoneInitializing */ - mstp_port->This_Station = 0; /* FIXME: the node's station address */ /* indicate that the next station is unknown */ mstp_port->Next_Station = mstp_port->This_Station; mstp_port->Poll_Station = mstp_port->This_Station; @@ -541,25 +711,32 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) /* LostToken */ if (mstp_port->SilenceTimer >= Tno_token) { /* assume that the token has been lost */ + mstp_port->EventCount = 0; /* Addendum 135-2004d-8 */ mstp_port->master_state = MSTP_MASTER_STATE_NO_TOKEN; } - /* mstp_port->ReceivedInvalidFrame */ + /* ReceivedInvalidFrame */ else if (mstp_port->ReceivedInvalidFrame == true) { /* invalid frame was received */ mstp_port->ReceivedInvalidFrame = false; /* wait for the next frame */ mstp_port->master_state = MSTP_MASTER_STATE_IDLE; } - /* ReceivedUnwantedFrame */ else if (mstp_port->ReceivedValidFrame == true) { - if ((mstp_port->DestinationAddress != mstp_port->This_Station) - || (mstp_port->DestinationAddress != - MSTP_BROADCAST_ADDRESS)) { + #if PRINT_ENABLED + fprintf(stderr,"MSTP: ReceivedValidFrame Type=%s Dest=%02X\r\n", + mstp_frame_type_text(mstp_port->FrameType), + mstp_port->DestinationAddress); + #endif + /* ReceivedUnwantedFrame - not for me */ + if (!((mstp_port->DestinationAddress == mstp_port->This_Station) + || (mstp_port->DestinationAddress == + MSTP_BROADCAST_ADDRESS))) { /* an unexpected or unwanted frame was received. */ mstp_port->ReceivedValidFrame = false; /* wait for the next frame */ mstp_port->master_state = MSTP_MASTER_STATE_IDLE; } + /* ReceivedUnwantedFrame - broadcast TOKEN or TEST_REQUEST */ /* DestinationAddress is equal to 255 (broadcast) and */ /* FrameType has a value of Token, BACnet Data Expecting Reply, Test_Request, */ /* or a proprietary type known to this node that expects a reply */ @@ -567,14 +744,16 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) else if ((mstp_port->DestinationAddress == MSTP_BROADCAST_ADDRESS) && ((mstp_port->FrameType == FRAME_TYPE_TOKEN) + /* removed in Add-2004-135b-PR1 - see BroadcastDataNeedingReply || (mstp_port->FrameType == - FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY) + FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY) */ || (mstp_port->FrameType == FRAME_TYPE_TEST_REQUEST))) { /* an unexpected or unwanted frame was received. */ mstp_port->ReceivedValidFrame = false; /* wait for the next frame */ mstp_port->master_state = MSTP_MASTER_STATE_IDLE; } + /* ReceivedUnwantedFrame - PROPRIETARY unknown to me */ /* FrameType has a value that indicates a standard or proprietary type */ /* that is not known to this node. */ /* FIXME: change this if you add a proprietary type */ @@ -618,8 +797,8 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY) || /* (mstp_port->FrameType == FRAME_TYPE_PROPRIETARY_0) || */ (mstp_port->FrameType == FRAME_TYPE_TEST_RESPONSE))) { - /* FIXME: indicate successful reception to the higher layers */ - /* i.e. Process this frame! */ + /* indicate successful reception to the higher layers */ + mstp_put_receive(mstp_port); mstp_port->ReceivedValidFrame = false; /* wait for the next frame */ mstp_port->master_state = MSTP_MASTER_STATE_IDLE; @@ -635,10 +814,23 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) mstp_port->ReplyPostponedTimer = 0; /* indicate successful reception to the higher layers */ /* (management entity in the case of Test_Request); */ + mstp_put_receive(mstp_port); mstp_port->ReceivedValidFrame = false; mstp_port->master_state = MSTP_MASTER_STATE_ANSWER_DATA_REQUEST; } + /* BroadcastDataNeedingReply */ + else if ((mstp_port->DestinationAddress == + MSTP_BROADCAST_ADDRESS) + && (mstp_port->FrameType == + FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY)) + { + /* indicate successful reception to the higher layers */ + mstp_put_receive(mstp_port); + mstp_port->ReceivedValidFrame = false; + /* wait for the next frame */ + mstp_port->master_state = MSTP_MASTER_STATE_IDLE; + } } break; /* In the USE_TOKEN state, the node is allowed to send one or */ @@ -653,12 +845,11 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) } else { + uint8_t destination = mstp_port->TxBuffer[3]; RS485_Send_Frame( mstp_port, - &mstp_port->TxBuffer[0], + (uint8_t *) &mstp_port->TxBuffer[0], mstp_port->TxLength); - RS485_Process_Tx_Message(); - while (RS485_Tx_Complete()) {/* FIXME: watchdog? */}; mstp_port->TxReady = false; mstp_port->FrameCount++; /* SendNoWait */ @@ -666,7 +857,9 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) /* is of type Test_Response, BACnet Data Not Expecting Reply, */ /* or a proprietary type that does not expect a reply, */ if ((mstp_port->TxFrameType == FRAME_TYPE_TEST_RESPONSE) || - (mstp_port->TxFrameType == FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY)) + (mstp_port->TxFrameType == FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY) || + ((mstp_port->TxFrameType == FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY) && + (destination == MSTP_BROADCAST_ADDRESS))) { mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN; } @@ -709,7 +902,8 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) /*(mstp_port->FrameType == FRAME_TYPE_PROPRIETARY_0) || */ (mstp_port->FrameType == FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY))) { - /* FIXME: indicate successful reception to the higher layers */ + /* indicate successful reception to the higher layers */ + mstp_put_receive(mstp_port); mstp_port->ReceivedValidFrame = false; mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN; } @@ -760,9 +954,10 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) /* before passing the token. */ mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN; } - /* mstp_port->SoleMaster */ + /* SoleMaster */ else if ((mstp_port->FrameCount >= mstp_port->Nmax_info_frames) && - (mstp_port->TokenCount < Npoll) && + /* Npoll changed in Errata SSPC-135-2004 */ + (mstp_port->TokenCount < (Npoll-1)) && (mstp_port->SoleMaster == true)) { /* there are no other known master nodes to */ /* which the token may be sent (true master-slave operation). */ @@ -772,14 +967,13 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) } /* SendToken */ else if (((mstp_port->FrameCount >= mstp_port->Nmax_info_frames) && - (mstp_port->TokenCount < Npoll) && + /* Npoll changed in Errata SSPC-135-2004 */ + (mstp_port->TokenCount < (Npoll-1)) && (mstp_port->SoleMaster == false)) || /* 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->Next_Station == - (uint8_t) ((mstp_port->This_Station + - 1) % (mstp_port->Nmax_master + 1)))) { + (mstp_port->Next_Station == next_poll_neighbor)) { mstp_port->TokenCount++; /* transmit a Token frame to NS */ MSTP_Create_And_Send_Frame(mstp_port, @@ -791,13 +985,10 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) } /* SendMaintenancePFM */ else if ((mstp_port->FrameCount >= mstp_port->Nmax_info_frames) && - (mstp_port->TokenCount >= Npoll) && - ((uint8_t) ((mstp_port->Poll_Station + - 1) % (mstp_port->Nmax_master + 1)) != - mstp_port->Next_Station)) { - mstp_port->Poll_Station = - (mstp_port->Poll_Station + 1) % (mstp_port->Nmax_master + - 1); + /* Npoll changed in Errata SSPC-135-2004 */ + (mstp_port->TokenCount >= (Npoll-1)) && + (next_poll_station != mstp_port->Next_Station)) { + mstp_port->Poll_Station = next_poll_station; MSTP_Create_And_Send_Frame(mstp_port, FRAME_TYPE_POLL_FOR_MASTER, mstp_port->Poll_Station, mstp_port->This_Station, NULL, 0); @@ -806,10 +997,9 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) } /* ResetMaintenancePFM */ else if ((mstp_port->FrameCount >= mstp_port->Nmax_info_frames) && - (mstp_port->TokenCount >= Npoll) && - ((uint8_t) ((mstp_port->Poll_Station + - 1) % (mstp_port->Nmax_master + 1)) == - mstp_port->Next_Station) + /* Npoll changed in Errata SSPC-135-2004 */ + (mstp_port->TokenCount >= (Npoll-1)) && + (next_poll_station == mstp_port->Next_Station) && (mstp_port->SoleMaster == false)) { mstp_port->Poll_Station = mstp_port->This_Station; /* transmit a Token frame to NS */ @@ -817,28 +1007,25 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) FRAME_TYPE_TOKEN, mstp_port->Next_Station, mstp_port->This_Station, NULL, 0); mstp_port->RetryCount = 0; - mstp_port->TokenCount = 0; + mstp_port->TokenCount = 1; /* changed in Errata SSPC-135-2004 */ mstp_port->EventCount = 0; mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN; } /* SoleMasterRestartMaintenancePFM */ else if ((mstp_port->FrameCount >= mstp_port->Nmax_info_frames) && - (mstp_port->TokenCount >= Npoll) && - ((uint8_t) ((mstp_port->Poll_Station + - 1) % (mstp_port->Nmax_master + 1)) == - mstp_port->Next_Station) + /* Npoll changed in Errata SSPC-135-2004 */ + (mstp_port->TokenCount >= (Npoll-1)) && + (next_poll_station == mstp_port->Next_Station) && (mstp_port->SoleMaster == true)) { - mstp_port->Poll_Station = - (mstp_port->Next_Station + 1) % (mstp_port->Nmax_master + - 1); + mstp_port->Poll_Station = next_poll_station; MSTP_Create_And_Send_Frame(mstp_port, FRAME_TYPE_POLL_FOR_MASTER, mstp_port->Poll_Station, mstp_port->This_Station, NULL, 0); /* no known successor node */ mstp_port->Next_Station = mstp_port->This_Station; mstp_port->RetryCount = 0; - mstp_port->TokenCount = 0; - mstp_port->EventCount = 0; + mstp_port->TokenCount = 1; /* changed in Errata SSPC-135-2004 */ + /* mstp_port->EventCount = 0; removed in Addendum 135-2004d-8 */ /* find a new successor to TS */ mstp_port->master_state = MSTP_MASTER_STATE_POLL_FOR_MASTER; } @@ -868,9 +1055,7 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) else if ((mstp_port->SilenceTimer >= Tusage_timeout) && (mstp_port->RetryCount >= Nretry_token)) { /* Assume that NS has failed. */ - mstp_port->Poll_Station = - (mstp_port->Next_Station + 1) % (mstp_port->Nmax_master + - 1); + mstp_port->Poll_Station = next_station; /* Transmit a Poll For Master frame to PS. */ MSTP_Create_And_Send_Frame(mstp_port, FRAME_TYPE_POLL_FOR_MASTER, @@ -879,7 +1064,7 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) mstp_port->Next_Station = mstp_port->This_Station; mstp_port->RetryCount = 0; mstp_port->TokenCount = 0; - mstp_port->EventCount = 0; + /* mstp_port->EventCount = 0; removed in Addendum 135-2004d-8 */ /* find a new successor to TS */ mstp_port->master_state = MSTP_MASTER_STATE_POLL_FOR_MASTER; } @@ -904,9 +1089,7 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) (Tno_token + (Tslot * (mstp_port->This_Station + 1))))) { /* Assume that this node is the lowest numerical address */ /* on the network and is empowered to create a token. */ - mstp_port->Poll_Station = - (mstp_port->This_Station + 1) % (mstp_port->Nmax_master + - 1); + mstp_port->Poll_Station = next_poll_neighbor; /* Transmit a Poll For Master frame to PS. */ MSTP_Create_And_Send_Frame(mstp_port, FRAME_TYPE_POLL_FOR_MASTER, @@ -915,7 +1098,7 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) mstp_port->Next_Station = mstp_port->This_Station; mstp_port->RetryCount = 0; mstp_port->TokenCount = 0; - mstp_port->EventCount = 0; + /* mstp_port->EventCount = 0; removed Addendum 135-2004d-8 */ /* enter the POLL_FOR_MASTER state to find a new successor to TS. */ mstp_port->master_state = MSTP_MASTER_STATE_POLL_FOR_MASTER; } @@ -954,13 +1137,14 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) /* This action drops the token. */ mstp_port->master_state = MSTP_MASTER_STATE_IDLE; } - /* mstp_port->SoleMaster */ + /* SoleMaster */ else if ((mstp_port->SoleMaster == true) && ((mstp_port->SilenceTimer >= Tusage_timeout) || (mstp_port->ReceivedInvalidFrame == true))) { /* There was no valid reply to the periodic poll */ /* by the sole known master for other masters. */ mstp_port->FrameCount = 0; + /* mstp_port->TokenCount++; removed in 2004 */ mstp_port->ReceivedInvalidFrame = false; mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN; } @@ -981,15 +1165,12 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN; } /* SendNextPFM */ - else if ((mstp_port->SoleMaster == false) && (mstp_port->Next_Station == mstp_port->This_Station) && /* no known successor node */ - ((uint8_t) ((mstp_port->Poll_Station + - 1) % (mstp_port->Nmax_master + 1)) != - mstp_port->This_Station) - && ((mstp_port->SilenceTimer >= Tusage_timeout) + else if ((mstp_port->SoleMaster == false) && + (mstp_port->Next_Station == mstp_port->This_Station) && /* no known successor node */ + (next_poll_station != mstp_port->This_Station) && + ((mstp_port->SilenceTimer >= Tusage_timeout) || (mstp_port->ReceivedInvalidFrame == true))) { - mstp_port->Poll_Station = - (mstp_port->Poll_Station + 1) % (mstp_port->Nmax_master + - 1); + mstp_port->Poll_Station = next_poll_station; /* Transmit a Poll For Master frame to PS. */ MSTP_Create_And_Send_Frame(mstp_port, FRAME_TYPE_POLL_FOR_MASTER, @@ -1000,9 +1181,7 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) } /* DeclareSoleMaster */ else if ((mstp_port->SoleMaster == false) && (mstp_port->Next_Station == mstp_port->This_Station) && /* no known successor node */ - ((uint8_t) ((mstp_port->Poll_Station + 1) % - (mstp_port->Nmax_master + 1)) == - mstp_port->This_Station) + (next_poll_station == mstp_port->This_Station) && ((mstp_port->SilenceTimer >= Tusage_timeout) || (mstp_port->ReceivedInvalidFrame == true))) { /* to indicate that this station is the only master */ @@ -1189,7 +1368,7 @@ void testReceiveNodeFSM(Test * pTest) mstp_port.ReceiveError = true; mstp_port.SilenceTimer = 255; mstp_port.EventCount = 0; - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.EventCount == EventCount); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1199,7 +1378,7 @@ void testReceiveNodeFSM(Test * pTest) /* check for bad packet header */ mstp_port.DataAvailable = true; mstp_port.DataRegister = 0x11; - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.DataAvailable == false); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1209,7 +1388,7 @@ void testReceiveNodeFSM(Test * pTest) /* check for good packet header, but timeout */ mstp_port.DataAvailable = true; mstp_port.DataRegister = 0x55; - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.DataAvailable == false); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1223,7 +1402,7 @@ void testReceiveNodeFSM(Test * pTest) /* check for good packet header preamble, but receive error */ mstp_port.DataAvailable = true; mstp_port.DataRegister = 0x55; - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.DataAvailable == false); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1231,7 +1410,7 @@ void testReceiveNodeFSM(Test * pTest) ct_test(pTest, mstp_port.receive_state == MSTP_RECEIVE_STATE_PREAMBLE); /* force the error */ mstp_port.ReceiveError = true; - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.ReceiveError == false); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1241,7 +1420,7 @@ void testReceiveNodeFSM(Test * pTest) /* check for good packet header preamble1, but bad preamble2 */ mstp_port.DataAvailable = true; mstp_port.DataRegister = 0x55; - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.DataAvailable == false); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1256,7 +1435,7 @@ void testReceiveNodeFSM(Test * pTest) /* repeated preamble1 */ mstp_port.DataAvailable = true; mstp_port.DataRegister = 0x55; - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.DataAvailable == false); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1265,7 +1444,7 @@ void testReceiveNodeFSM(Test * pTest) /* repeated preamble1 */ mstp_port.DataAvailable = true; mstp_port.DataRegister = 0x55; - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.DataAvailable == false); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1274,7 +1453,7 @@ void testReceiveNodeFSM(Test * pTest) /* bad data */ mstp_port.DataAvailable = true; mstp_port.DataRegister = 0x11; - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.ReceiveError == false); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1284,7 +1463,7 @@ void testReceiveNodeFSM(Test * pTest) /* check for good packet header preamble, but timeout in packet */ mstp_port.DataAvailable = true; mstp_port.DataRegister = 0x55; - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.DataAvailable == false); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1294,7 +1473,7 @@ void testReceiveNodeFSM(Test * pTest) /* preamble2 */ mstp_port.DataAvailable = true; mstp_port.DataRegister = 0xFF; - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.DataAvailable == false); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1311,7 +1490,7 @@ void testReceiveNodeFSM(Test * pTest) /* check for good packet header preamble, but error in packet */ mstp_port.DataAvailable = true; mstp_port.DataRegister = 0x55; - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.DataAvailable == false); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1321,7 +1500,7 @@ void testReceiveNodeFSM(Test * pTest) /* preamble2 */ mstp_port.DataAvailable = true; mstp_port.DataRegister = 0xFF; - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.DataAvailable == false); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1331,7 +1510,7 @@ void testReceiveNodeFSM(Test * pTest) ct_test(pTest, mstp_port.receive_state == MSTP_RECEIVE_STATE_HEADER); /* force the error */ mstp_port.ReceiveError = true; - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.ReceiveError == false); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1341,7 +1520,7 @@ void testReceiveNodeFSM(Test * pTest) /* check for good packet header preamble */ mstp_port.DataAvailable = true; mstp_port.DataRegister = 0x55; - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.DataAvailable == false); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1351,7 +1530,7 @@ void testReceiveNodeFSM(Test * pTest) /* preamble2 */ mstp_port.DataAvailable = true; mstp_port.DataRegister = 0xFF; - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.DataAvailable == false); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1370,7 +1549,7 @@ void testReceiveNodeFSM(Test * pTest) mstp_port.DataRegister = FRAME_TYPE_TOKEN; HeaderCRC = 0xFF; HeaderCRC = CRC_Calc_Header(mstp_port.DataRegister, HeaderCRC); - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.DataAvailable == false); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1382,7 +1561,7 @@ void testReceiveNodeFSM(Test * pTest) mstp_port.DataAvailable = true; mstp_port.DataRegister = 0x10; HeaderCRC = CRC_Calc_Header(mstp_port.DataRegister, HeaderCRC); - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.DataAvailable == false); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1394,7 +1573,7 @@ void testReceiveNodeFSM(Test * pTest) mstp_port.DataAvailable = true; mstp_port.DataRegister = my_mac; HeaderCRC = CRC_Calc_Header(mstp_port.DataRegister, HeaderCRC); - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.DataAvailable == false); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1406,7 +1585,7 @@ void testReceiveNodeFSM(Test * pTest) mstp_port.DataAvailable = true; mstp_port.DataRegister = 0; HeaderCRC = CRC_Calc_Header(mstp_port.DataRegister, HeaderCRC); - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.DataAvailable == false); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1418,7 +1597,7 @@ void testReceiveNodeFSM(Test * pTest) mstp_port.DataAvailable = true; mstp_port.DataRegister = 0; HeaderCRC = CRC_Calc_Header(mstp_port.DataRegister, HeaderCRC); - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.DataAvailable == false); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1430,7 +1609,7 @@ void testReceiveNodeFSM(Test * pTest) mstp_port.DataAvailable = true; ct_test(pTest, HeaderCRC == 0x73); /* per Annex G example */ mstp_port.DataRegister = ~HeaderCRC; /* one's compliment of CRC is sent */ - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.DataAvailable == false); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1456,7 +1635,7 @@ void testReceiveNodeFSM(Test * pTest) Load_Input_Buffer(buffer, len); for (i = 0; i < len; i++) { RS485_Check_UART_Data(&mstp_port); - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.DataAvailable == false); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1480,7 +1659,7 @@ void testReceiveNodeFSM(Test * pTest) Load_Input_Buffer(buffer, len); for (i = 0; i < len; i++) { RS485_Check_UART_Data(&mstp_port); - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.DataAvailable == false); ct_test(pTest, mstp_port.SilenceTimer == 0); @@ -1506,7 +1685,7 @@ void testReceiveNodeFSM(Test * pTest) Load_Input_Buffer(buffer, len); for (i = 0; i < len; i++) { RS485_Check_UART_Data(&mstp_port); - EventCount++; + INCREMENT_AND_LIMIT_UINT8(EventCount); MSTP_Receive_Frame_FSM(&mstp_port); ct_test(pTest, mstp_port.DataAvailable == false); ct_test(pTest, mstp_port.SilenceTimer == 0); diff --git a/bacnet-stack/mstp.h b/bacnet-stack/mstp.h index 4b53fd91..7837286c 100644 --- a/bacnet-stack/mstp.h +++ b/bacnet-stack/mstp.h @@ -124,7 +124,8 @@ struct mstp_port_struct_t { uint8_t DestinationAddress; /* Used to count the number of received octets or errors. */ /* This is used in the detection of link activity. */ - unsigned EventCount; + /* Compared to Nmin_octets */ + uint8_t EventCount; /* Used to store the frame type of a received frame. */ uint8_t FrameType; /* The number of frames sent by this node during a single token hold. */ @@ -157,12 +158,12 @@ struct mstp_port_struct_t { /* Since the timer resolution is limited and the timer is not necessarily */ /* synchronized to other machine events, a timer value of N will actually */ /* denote intervals between N-1 and N */ - unsigned SilenceTimer; + uint16_t SilenceTimer; /* A timer used to measure and generate Reply Postponed frames. It is */ /* incremented by a timer process and is cleared by the Master Node State */ /* Machine when a Data Expecting Reply Answer activity is completed. */ - unsigned ReplyPostponedTimer; + uint16_t ReplyPostponedTimer; /* Used to store the Source Address of a received frame. */ uint8_t SourceAddress; @@ -196,9 +197,9 @@ struct mstp_port_struct_t { unsigned Nmax_master; /* An array of octets, used to store PDU octets prior to being transmitted. */ - /* This array is not used for passing token frames */ + /* This array is only used for APDU messages */ uint8_t TxBuffer[MAX_MPDU]; - int TxLength; + unsigned TxLength; bool TxReady; /* true if ready to be sent or received */ uint8_t TxFrameType; /* type of message - needed by MS/TP */ }; diff --git a/bacnet-stack/ports/pic18/BACnet-Server.mcp b/bacnet-stack/ports/pic18/BACnet-Server.mcp index 09d643ec..5c04a9de 100644 --- a/bacnet-stack/ports/pic18/BACnet-Server.mcp +++ b/bacnet-stack/ports/pic18/BACnet-Server.mcp @@ -67,6 +67,7 @@ file_047=no file_048=no file_049=no file_050=no +file_051=no [FILE_INFO] file_000=C:\code\bacnet-stack\abort.c file_001=C:\code\bacnet-stack\apdu.c @@ -119,6 +120,7 @@ file_047=C:\code\bacnet-stack\demo\object\ao.h file_048=C:\code\bacnet-stack\demo\object\device.h file_049=stdbool.h file_050=stdint.h +file_051=hardware.h [SUITE_INFO] suite_guid={5B7D72DD-9861-47BD-9F60-2BE967BF8416} suite_state= diff --git a/bacnet-stack/ports/pic18/BACnet-Server.mcw b/bacnet-stack/ports/pic18/BACnet-Server.mcw index a2b348972fcdfa7427dda4947bec59db03ac62e5..a4e164eb4f63761d193fcbd8be8ea341f707dbcd 100644 GIT binary patch delta 1145 zcmZ8hT}V@57=F)omJ?jriMa#8I0n%mAxo$b&0S3JCM<#wG_WWb_=Akuu{v}{1pN@9 zETRjq%DcKaB8X%~5Jg=CLTe#(Vc?CVHB(81sOLF5$E0j2ZIAjJW0pw4e6>(C4+p0usfgg~ z(n}>Sfk0WWmnyk+G(J2FyW90eWu~Ob?es@8C1-@W%v115KpHq(T-8MVsfqq=*cu3p zSieDiHk9yG(G-cgm4_E~VLb*nz`q224cxZ7MS|WW2VpmXBVdwoJYH73ze!y6iu%{Z ze8%zxI2h>wm@)Qd5jfbq5;A85PUJ8}1N0=Crj~TvSERl*D&5ngQd-ue{Y#BSAE^R7 z_Cu5Vp^Q5so16>c_H#V_mll!Rb=h!lzrL*5ZqYF~>rtS?GVuH&)zGKVfI5r%jdb`) zZ}Do?FJ@&P_DSe^WK{Yf*-(c+0badSu9Zei<&A>5wGPjpqyGEHJx@QgAg8Be2J$O{ zrS!|D{y)`u4sR0@#uIXnqzyRvnyHY;0`x-_Bkl#HA_^3M^W&XIYSVI7`sKXz$_2?F zI&o^$<#n%HSH8J3X7dvJ^q57NUEv&2d3L>EPEHkET(Up6Lzs|u!N1jJ?=nSuOcJYK@&nsE?E^bfV9I zd;%s=h9F4b?#&z&Wg(yIlxvv8b;W(0 zbKid1mj|MehIlLxtqV>p4}>f0>it3L%0jspdOT6eWv)z?DKbe)ky|9bWBF1J zCiOGnw8W|P(-O_zxrtCRzxhR;4yokx%{Cd<(R?X+%x4j;62x~LD6o7e+1P)R`0_?r zW01!*X#?U54tAAOf2TsmVu^cx5WWJ>bQb z&tk=Gh`){g8E2n9gzSs-0rJ~XegYxOn0DkWzQ=3&Ta2;%-eUJ9h!1+AJ>l+$V`96{ zUw!vm_Q|m`U5oHA>dNsms~DfOp*>N8u!DIZ_HoEN-JHGLR~+KmOrl&j-H7xOWNb&c zrQg29K=fy{5&hM^W%o(B-NzPKYe@{{KD0fFIAv~2RG2Zeay;02%Z}T9HlrT~$vyOL2}lq-C(n_9 zRAKiHn*BU36C{Q`o$2K$;XdDhbj-x-kV~x1fp5IOlt3@q zjo{uqiiZtb>sc=yA9ft*n9-Yt7p`v4`fHa|LK~yvhgL#AlEZN3hvB!sr>^<0k@*KF zKMl>pil{W}CM2_Ag~ZVF3gomPmI;lN9AnRMj;Pz2wBZU#nm@4qqQ>r;3)w3W%S>vQ zlHkqOR^oy7mtUSbN%wnNk^+oUc0L0{oNiXbl2&-{2UK$ zG}>yJ;?M6h+JK~4*bl2Q-^(!%5zGNC;NHwZVHWt)KD4C^Y=tsd3wOb8$c~0&A)nu* z&ipUL`$yzqU=TF6e+|;Tp#sc5znR$|zme0CGw-VhziITqU8nEzb3B~)A?P&I`KP|f zO!p|d_V=^xADsqb)c0U&>+Dm!3#hm|5R8PX167qSQ!}(89E(T&wd2P1RKsnICTj=B z_1IrSU42be<1&AcHxX$i+VXfok+wJ(sb5xCcG8bHXHT9!vuYR8J8`yd!A46vV_PyV*y}&U`RCYsDC(qA)Y*Aw zv7_p81oaMqNqhQlwhlC}#HqlYoBO~_*irljrp>enVS_Z8r$1@`m}>e^1QY>9KoL*` z6ahs*5l{pa0YyL&Py`eKML-cy1QY>9KoL*`6ahs*5l{pa0YyL&Py`eKML-cy1QY>9 zKoL*`6ahs*5l{pa0YyL&Py`eKML-cy1QY>9KoL*`6ahs*5l{pa0YyL&Py`eKML-ca z&j_UYA4&B9l!>U3@bE;xBP9BXN=J_0M<;aG>AQT}|A{?Ry&j z+L6sLoA!Ne(--;lDRMu2fzbC@7$NQ0W(PTVF`B0BUzagdYZFVHtj{eS^ zc6-a_7=K@E@K!+?{BhCOn8@3R(^uI-#JBqC{mJ$XJN&0L)=HBSp&a^58=Z4{729q9 zl?Ar1vM6GEA+PY5$M{(~2_Ghh^E_q@^s5%dn1}(#v2j$F+@}yvc?Z|~Q0^Y|x&ECp zD+(VgL&ua^+g_Yv`eD1tg(EEDP@D`Sd9%cMzv1PxIXLsK95a39kQ|+2+C3+X--k@{ zDu8p?APV0x8T+lHZ#&0Js9$Q)|NrebM)l^u(HkxUaxrw~>0av%{UOq$Yye!<>E$W_ zA3yZ;)gnuc=eMS$FFA;j3+-=6_2&HRjqSk+KH%W#$=P?-VJ^w^02sP|r%$Gz95n9Ij` ze!*zIC3)|ax!yDw?Wi&T@oHI8OUm*4jOxwhet+{Mbme>K%}4lsW_40;kW^9x6oD%k Gfqwv5w+sLP diff --git a/bacnet-stack/ports/pic18/main.c b/bacnet-stack/ports/pic18/main.c index 855df1e1..fed5859f 100644 --- a/bacnet-stack/ports/pic18/main.c +++ b/bacnet-stack/ports/pic18/main.c @@ -71,23 +71,17 @@ void My_Read_Property_Handler(uint8_t * service_request, int bytes_sent = 0; BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT; BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT; + BACNET_NPDU_DATA npdu_data; len = rp_decode_service_request(service_request, service_len, &data); - /* prepare a reply */ - datalink_get_my_address(&my_address); - /* encode the NPDU portion of the packet */ - pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], src, &my_address, false, /* true for confirmed messages */ - MESSAGE_PRIORITY_NORMAL); /* bad decoding - send an abort */ - if (len == -1) { - pdu_len += abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + if (len < 0) { + pdu_len = abort_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, ABORT_REASON_OTHER); - send = true; } else if (service_data->segmented_message) { - pdu_len += abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = abort_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED); - send = true; } else { switch (data.object_type) { case OBJECT_DEVICE: @@ -101,10 +95,7 @@ void My_Read_Property_Handler(uint8_t * service_request, data.application_data = &Temp_Buf[0]; data.application_data_len = len; /* FIXME: probably need a length limitation sent with encode */ - pdu_len += - rp_ack_encode_apdu(&Handler_Transmit_Buffer - [pdu_len], service_data->invoke_id, &data); - send = true; + pdu_len = rp_ack_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, &data); } else error = true; } else @@ -116,15 +107,13 @@ void My_Read_Property_Handler(uint8_t * service_request, } } if (error) { - pdu_len += bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + pdu_len = bacerror_encode_apdu(&Handler_Transmit_Buffer[0], service_data->invoke_id, SERVICE_CONFIRMED_READ_PROPERTY, error_class, error_code); - send = true; - } - if (send) { - bytes_sent = datalink_send_pdu(src, /* destination address */ - &Handler_Transmit_Buffer[0], pdu_len); /* number of bytes of data */ } + npdu_encode_confirmed_apdu(&npdu_data, MESSAGE_PRIORITY_NORMAL); + bytes_sent = datalink_send_pdu(src, &npdu_data, + &Handler_Transmit_Buffer[0], pdu_len); /* number of bytes of data */ return; } diff --git a/bacnet-stack/ports/rtos32/bip-init.c b/bacnet-stack/ports/rtos32/bip-init.c index a454fc55..80e9dfcc 100644 --- a/bacnet-stack/ports/rtos32/bip-init.c +++ b/bacnet-stack/ports/rtos32/bip-init.c @@ -34,18 +34,17 @@ #include /* for standard integer types uint8_t etc. */ #include /* for the standard bool type. */ +#include "bacdcode.h" #include "bip.h" -#if (defined(BACDL_ETHERNET) || defined(BACDL_BIP)) static int interface = SOCKET_ERROR; /* SOCKET_ERROR means no open interface */ -#endif void bip_set_interface(char *ifname) { /*dummy function - to make the demos compile easier */ + (void)ifname; } -#if (defined(BACDL_ETHERNET) || defined(BACDL_BIP)) /*-----------------------------------*/ static void Error(const char *Msg) { @@ -70,7 +69,6 @@ void InterfaceCleanup(void) #endif } } -#endif static void NetInitialize(void) /* initialize the TCP/IP stack */ @@ -78,16 +76,9 @@ static void NetInitialize(void) int Result; #ifndef HOST - - RTKernelInit(0); /* get the kernel going */ - if (!RTKDebugVersion()) /* switch of all diagnostics and error messages of RTIP-32 */ xn_callbacks()->cb_wr_screen_string_fnc = NULL; - CLKSetTimerIntVal(10 * 1000); /* 10 millisecond tick */ - RTKDelay(1); - RTCMOSSetSystemTime(); /* get the right time-of-day */ - #ifdef RTUSB_VER RTURegisterCallback(USBAX172); /* ax172 and ax772 drivers */ RTURegisterCallback(USBAX772); @@ -207,30 +198,67 @@ static void NetInitialize(void) } #endif +/****************************************************************** +* DESCRIPTION: Converts the byte stored address to an inet address +* RETURN: none +* ALGORITHM: none +* NOTES: none +******************************************************************/ +static void RTIP_To_Network_Address( + BYTE *octet_address, + struct in_addr *addr) +{ + uint32_t ip_address = 0; /* for decoding the subnet mask */ + + decode_unsigned32(octet_address, &ip_address); + addr->s_addr = htonl(ip_address); + + return; +} + +static void set_broadcast_address(uint32_t net_address) +{ + long broadcast_address = 0; + long mask = 0; + + /* Note: sometimes INADDR_BROADCAST does not let me get + any unicast messages. Not sure why... */ +#if USE_INADDR + (void) net_address; + bip_set_broadcast_addr(INADDR_BROADCAST); +#else + if (IN_CLASSA(ntohl(net_address))) + broadcast_address = + (ntohl(net_address) & ~IN_CLASSA_HOST) | IN_CLASSA_HOST; + else if (IN_CLASSB(ntohl(net_address))) + broadcast_address = + (ntohl(net_address) & ~IN_CLASSB_HOST) | IN_CLASSB_HOST; + else if (IN_CLASSC(ntohl(net_address))) + broadcast_address = + (ntohl(net_address) & ~IN_CLASSC_HOST) | IN_CLASSC_HOST; + else if (IN_CLASSD(ntohl(net_address))) + broadcast_address = + (ntohl(net_address) & ~IN_CLASSD_HOST) | IN_CLASSD_HOST; + else + broadcast_address = INADDR_BROADCAST; + bip_set_broadcast_addr(htonl(broadcast_address)); +#endif +} + bool bip_init(void) { int rv = 0; /* return from socket lib calls */ struct sockaddr_in sin = { -1 }; int value = 1; int sock_fd = -1; + struct in_addr my_addr; NetInitialize(); - bip_set_address(TargetIP[0], TargetIP[1], TargetIP[2], TargetIP[3]); - - /* FIXME: */ -#if 0 - bip_set_address(NetMask[0], NetMask[1], NetMask[2], NetMask[3]); - extern unsigned long bip_get_addr(void); - unsigned long broadcast_address = 0; - unsigned long subnet_mask = 0; - - /* local broadcast address */ - broadcast_address = bip_get_addr(); - broadcast_address |= ~(BIP_Subnet_Mask.s_addr); - /* configure standard BACnet/IP port */ + RTIP_To_Network_Address(TargetIP, &my_addr); + bip_set_addr(my_addr.s_addr); + set_broadcast_address(my_addr.s_addr); bip_set_port(0xBAC0); -#endif /* assumes that the driver has already been initialized */ sock_fd = socket(AF_INET, SOCK_DGRAM, IPROTO_UDP); diff --git a/bacnet-stack/ports/rtos32/dlmstp.c b/bacnet-stack/ports/rtos32/dlmstp.c new file mode 100644 index 00000000..bef4dff1 --- /dev/null +++ b/bacnet-stack/ports/rtos32/dlmstp.c @@ -0,0 +1,268 @@ +/************************************************************************** +* +* Copyright (C) 2006 Steve Karg +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +* +*********************************************************************/ +#include +#include +#include +#include +#if PRINT_ENABLED +#include +#endif +#include "bacdef.h" +#include "mstp.h" +#include "dlmstp.h" +#include "rs485.h" +#include "npdu.h" + +/* receive buffer */ +static DLMSTP_PACKET Receive_Buffer; +/* temp buffer for NPDU insertion */ +static uint8_t PDU_Buffer[MAX_MPDU]; +/* local MS/TP port data */ +static volatile struct mstp_port_struct_t MSTP_Port; + +void dlmstp_init(void) +{ + /* initialize buffer */ + Receive_Buffer.ready = false; + Receive_Buffer.pdu_len = 0; + /* initialize hardware */ + RS485_Initialize(); + MSTP_Init(&MSTP_Port, MSTP_Port.This_Station); +} + +void dlmstp_cleanup(void) +{ + /* nothing to do for static buffers */ +} + +/* returns number of bytes sent on success, zero on failure */ +int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */ + BACNET_NPDU_DATA * npdu_data, /* network information */ + uint8_t * pdu, /* any data to be sent - may be null */ + unsigned pdu_len) +{ /* number of bytes of data */ + int bytes_sent = 0; + unsigned npdu_len = 0; + uint8_t frame_type = 0; + uint8_t destination = 0; /* destination address */ + BACNET_ADDRESS src; + + if (MSTP_Port.TxReady == false) { + if (npdu_data->confirmed_message) + MSTP_Port.TxFrameType = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY; + else + MSTP_Port.TxFrameType = FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY; + + /* load destination MAC address */ + if (dest && dest->mac_len == 1) { + destination = dest->mac[0]; + } else { + #if PRINT_ENABLED + fprintf(stderr, "mstp: invalid destination MAC address!\n"); + #endif + return -2; + } + dlmstp_get_my_address(&src); + npdu_len = npdu_encode_pdu(&PDU_Buffer[0], dest, &src, npdu_data); + if ((8 /* header len */ + npdu_len + pdu_len) > MAX_MPDU) { + #if PRINT_ENABLED + fprintf(stderr, "mstp: PDU is too big to send!\n"); + #endif + return -4; + } + memmove(&PDU_Buffer[npdu_len], pdu, pdu_len); + bytes_sent = MSTP_Create_Frame( + (uint8_t *)&MSTP_Port.TxBuffer[0], + sizeof(MSTP_Port.TxBuffer), + MSTP_Port.TxFrameType, + destination, + MSTP_Port.This_Station, + &PDU_Buffer[0], + npdu_len + pdu_len); + MSTP_Port.TxLength = bytes_sent; + MSTP_Port.TxReady = true; + } + + return bytes_sent; +} + +void dlmstp_task(void) +{ + RS485_Check_UART_Data(&MSTP_Port); + MSTP_Receive_Frame_FSM(&MSTP_Port); + MSTP_Master_Node_FSM(&MSTP_Port); +} + +/* called about once a millisecond */ +void dlmstp_millisecond_timer(void) +{ + MSTP_Millisecond_Timer(&MSTP_Port); +} + +/* returns the number of octets in the PDU, or zero on failure */ +/* This function is expecting to be polled. */ +uint16_t dlmstp_receive(BACNET_ADDRESS * src, /* source address */ + uint8_t * pdu, /* PDU data */ + uint16_t max_pdu, /* amount of space available in the PDU */ + unsigned timeout) +{ + uint16_t pdu_len = 0; + + (void) timeout; + /* see if there is a packet available */ + if (Receive_Buffer.ready) + { + memmove(src, &Receive_Buffer.address, sizeof(Receive_Buffer.address)); + pdu_len = Receive_Buffer.pdu_len; + memmove(&pdu[0], &Receive_Buffer.pdu[0], max_pdu); + Receive_Buffer.ready = false; + } + + return pdu_len; +} + +void dlmstp_fill_bacnet_address(BACNET_ADDRESS * src, uint8_t mstp_address) +{ + int i = 0; + + if (mstp_address == MSTP_BROADCAST_ADDRESS) + { + /* mac_len = 0 if broadcast address */ + src->mac_len = 0; + src->mac[0] = 0; + } + else + { + src->mac_len = 1; + src->mac[0] = mstp_address; + } + /* fill with 0's starting with index 1; index 0 filled above */ + for (i = 1; i mac[i] = 0; + } + src->net = 0; + src->len = 0; + for (i = 0; i < MAX_MAC_LEN; i++) { + src->adr[i] = 0; + } +} + +/* for the MS/TP state machine to use for putting received data */ +uint16_t dlmstp_put_receive( + uint8_t src, /* source MS/TP address */ + uint8_t * pdu, /* PDU data */ + uint16_t pdu_len) +{ + if (Receive_Buffer.ready) + { + /* FIXME: what to do when we miss a message? */ + pdu_len = 0; + } + else + { + dlmstp_fill_bacnet_address(&Receive_Buffer.address, src); + Receive_Buffer.pdu_len = pdu_len; + memmove(Receive_Buffer.pdu, pdu, sizeof(Receive_Buffer.pdu)); + Receive_Buffer.ready = true; + } + + return pdu_len; +} + +void dlmstp_set_my_address(uint8_t mac_address) +{ + /* FIXME: Master Nodes can only have address 1-127 */ + MSTP_Port.This_Station = mac_address; + + return; +} + +/* This parameter represents the value of the Max_Info_Frames property of */ +/* the node's Device object. The value of Max_Info_Frames specifies the */ +/* maximum number of information frames the node may send before it must */ +/* pass the token. Max_Info_Frames may have different values on different */ +/* 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. */ +void dlmstp_set_max_info_frames(unsigned max_info_frames) +{ + MSTP_Port.Nmax_info_frames = max_info_frames; + + return; +} + +unsigned dlmstp_max_info_frames(void) +{ + return MSTP_Port.Nmax_info_frames; +} + +/* 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. */ +void dlmstp_set_max_master(uint8_t max_master) +{ + MSTP_Port.Nmax_master = max_master; + + return; +} + +uint8_t dlmstp_max_master(void) +{ + return MSTP_Port.Nmax_master; +} + +void dlmstp_get_my_address(BACNET_ADDRESS * my_address) +{ + int i = 0; /* counter */ + + my_address->mac_len = 1; + my_address->mac[0] = MSTP_Port.This_Station; + my_address->net = 0; /* local only, no routing */ + my_address->len = 0; + for (i = 0; i < MAX_MAC_LEN; i++) { + my_address->adr[i] = 0; + } + + return; +} + +void dlmstp_get_broadcast_address(BACNET_ADDRESS * dest) +{ /* destination address */ + int i = 0; /* counter */ + + if (dest) { + dest->mac_len = 1; + dest->mac[0] = MSTP_BROADCAST_ADDRESS; + dest->net = BACNET_BROADCAST_NETWORK; + dest->len = 0; /* len=0 denotes broadcast address */ + for (i = 0; i < MAX_MAC_LEN; i++) { + dest->adr[i] = 0; + } + } + + return; +} diff --git a/bacnet-stack/ports/rtos32/ethernet.c b/bacnet-stack/ports/rtos32/ethernet.c index 04e37184..2d6dde7b 100644 --- a/bacnet-stack/ports/rtos32/ethernet.c +++ b/bacnet-stack/ports/rtos32/ethernet.c @@ -34,6 +34,7 @@ #include #include "ethernet.h" #include "bacdcode.h" +#include "npdu.h" /* commonly used comparison address for ethernet */ uint8_t Ethernet_Broadcast[MAX_MAC_LEN] = @@ -86,12 +87,14 @@ bool ethernet_init(char *interface_name) /* returns bytes sent on success, negative number on failure */ int ethernet_send(BACNET_ADDRESS * dest, /* destination address */ BACNET_ADDRESS * src, /* source address */ + BACNET_NPDU_DATA * npdu_data, /* network information */ uint8_t * pdu, /* any data to be sent - may be null */ unsigned pdu_len) { /* number of bytes of data */ int bytes = 0; uint8_t mtu[MAX_MPDU] = { 0 }; int mtu_len = 0; + int npdu_len = 0; int i = 0; /* don't waste time if the socket is not valid */ @@ -131,8 +134,16 @@ int ethernet_send(BACNET_ADDRESS * dest, /* destination address */ mtu[mtu_len++] = 0x82; /* DSAP for BACnet */ mtu[mtu_len++] = 0x82; /* SSAP for BACnet */ mtu[mtu_len++] = 0x03; /* Control byte in header */ + npdu_len = npdu_encode_pdu(&mtu[17], dest, src, npdu_data); + mtu_len = 17 + npdu_len; + if ((mtu_len + pdu_len) > MAX_MPDU) { + fprintf(stderr, "ethernet: PDU is too big to send!\n"); + return -4; + } memcpy(&mtu[mtu_len], pdu, pdu_len); mtu_len += pdu_len; + /* packet length - only the logical portion, not the address */ + encode_unsigned16(&mtu[12], 3 + npdu_len + pdu_len); /* Send the packet */ bytes = send(Ethernet_Socket, (const char *) &mtu, mtu_len, 0); @@ -147,6 +158,7 @@ int ethernet_send(BACNET_ADDRESS * dest, /* destination address */ /* function to send a packet out the 802.2 socket */ /* returns bytes sent on success, negative number on failure */ int ethernet_send_pdu(BACNET_ADDRESS * dest, /* destination address */ + BACNET_NPDU_DATA * npdu_data, /* network information */ uint8_t * pdu, /* any data to be sent - may be null */ unsigned pdu_len) { /* number of bytes of data */ @@ -157,10 +169,13 @@ int ethernet_send_pdu(BACNET_ADDRESS * dest, /* destination address */ src.mac[i] = Ethernet_MAC_Address[i]; src.mac_len++; } + + /* FIXME: npdu_data? */ /* function to send a packet out the 802.2 socket */ /* returns 1 on success, 0 on failure */ return ethernet_send(dest, /* destination address */ &src, /* source address */ + npdu_data, pdu, /* any data to be sent - may be null */ pdu_len); /* number of bytes of data */ } diff --git a/bacnet-stack/ports/rtos32/main.c b/bacnet-stack/ports/rtos32/main.c index ed8bec90..fc2fec1b 100644 --- a/bacnet-stack/ports/rtos32/main.c +++ b/bacnet-stack/ports/rtos32/main.c @@ -28,35 +28,106 @@ #include #include #include +#include /* for kbhit */ #include "config.h" #include "bacdef.h" #include "npdu.h" #include "apdu.h" #include "device.h" #include "handlers.h" -#include "net.h" +#include "datalink.h" +#include "iam.h" +#include "txbuf.h" + +/* RTOS-32 */ +#include "rtkernel.h" +#if defined(RTK32_VER) + #define _USER32_ + #define _KERNEL32_ + #include + #include /* for RTCMOSSetSystemTime */ + #include /* file system */ + #include /* file system */ + #include +#endif +#include /* serial port driver */ +#include /* time measurement & timer interrupt rate control */ +#include /* interrupt handler for the keyboard */ /* buffers used for transmit and receive */ static uint8_t Rx_Buf[MAX_MPDU] = { 0 }; -#ifdef BACDL_MSTP -volatile struct mstp_port_struct_t MSTP_Port; /* port data */ -static uint8_t MSTP_MAC_Address = 0x05; /* local MAC address */ -#endif - static void Init_Service_Handlers(void) { /* we need to handle who-is to support dynamic device binding */ - apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, WhoIsHandler); + apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is); /* set the handler for all the services we don't implement */ /* It is required to send the proper reject message... */ - apdu_set_unrecognized_service_handler_handler - (UnrecognizedServiceHandler); + apdu_set_unrecognized_service_handler_handler(handler_unrecognized_service); /* we must implement read property - it's required! */ apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY, - ReadPropertyHandler); + handler_read_property); apdu_set_confirmed_handler(SERVICE_CONFIRMED_WRITE_PROPERTY, - WritePropertyHandler); + handler_write_property); +} + +void millisecond_task(void) +{ + Time ticks = 0; /* task cycle */ + const int UPDATE_CYCLE = 5; /* task cycle in mS */ + int i = 0; /* loop counter */ + + ticks = RTKGetTime() + MilliSecsToTicks(UPDATE_CYCLE); + while (TRUE) + { + RTKDelayUntil(ticks); + for (i = 0; i < UPDATE_CYCLE; i++) + dlmstp_millisecond_timer(); + ticks += MilliSecsToTicks(UPDATE_CYCLE); + } +} + +void RTOS_Initialize(void) +{ + /* allow OS to setup IRQ 1 by using a dummy call */ + (void)kbhit(); + RTKernelInit(0); /* get the kernel going */ + RTKeybrdInit(); + //(void)CPUMoniInit(); /* not needed - just monitor idle task */ + RTComInit(); + ITimerInit(); + + if (RTCallDebugger(RT_DBG_MONITOR,0,0) != -1) + { + /* Win32 structured exception - if no handler is + installed, TerminateProcess() will be called, + which will reboot - a good thing in our case. */ + RTRaiseCPUException(0); // Divide Error DIV and IDIV instructions. + RTRaiseCPUException(1); // Debug Any code or data reference. + RTRaiseCPUException(2); // NMI + RTRaiseCPUException(3); // Breakpoint INT 3 instruction. + RTRaiseCPUException(4); // Overflow INTO instruction. + RTRaiseCPUException(5); // BOUND Range Exceeded BOUND instruction. + RTRaiseCPUException(6); // Invalid Opcode (Undefined Opcode) + // RTRaiseCPUException(7); // Device Not Available (No Math Coprocessor) + RTRaiseCPUException(8); // Double Fault any exception instruction,NMI,INTR. + RTRaiseCPUException(9); // Co-Processor overrun + RTRaiseCPUException(10); // Invalid TSS Task switch or TSS access. + RTRaiseCPUException(11); // Segment Not Present Loading segment registers + RTRaiseCPUException(12); // Stack Seg Fault Stack ops /SS reg loads. + RTRaiseCPUException(13); // General Protection Any memory reference + RTRaiseCPUException(14); // Page Fault Any memory reference. + RTRaiseCPUException(15); // reserved + RTRaiseCPUException(16); // Floating-Point Error (Math Fault) + } + /* setup 1ms timer tick */ + SetTimerIntVal(1000); + /* per recommendation in manual */ + RTKDelay(1); + RTCMOSSetSystemTime(); /* get the right time-of-day */ + + /* create timer tick task */ + RTKCreateTask(millisecond_task,1,1024*8,"millisec task"); } int main(int argc, char *argv[]) @@ -69,6 +140,7 @@ int main(int argc, char *argv[]) (void) argv; Device_Set_Object_Instance_Number(126); Init_Service_Handlers(); + RTOS_Initialize(); /* init the physical layer */ #ifdef BACDL_BIP if (!bip_init()) @@ -79,39 +151,27 @@ int main(int argc, char *argv[]) return 1; #endif #ifdef BACDL_MSTP - RS485_Initialize(); - MSTP_Init(&MSTP_Port, MSTP_MAC_Address); + dlmstp_set_my_address(0x05); + dlmstp_init(); #endif - - + iam_send(&Handler_Transmit_Buffer[0]); /* loop forever */ for (;;) { /* input */ #ifdef BACDL_MSTP - MSTP_Millisecond_Timer(&MSTP_Port); - /* note: also called by RS-485 Receive ISR */ - RS485_Check_UART_Data(&MSTP_Port); - MSTP_Receive_Frame_FSM(&MSTP_Port); + dlmstp_task(); #endif - #if (defined(BACDL_ETHERNET) || defined(BACDL_BIP)) /* returns 0 bytes on timeout */ - pdu_len = bacdl_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout); + pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout); #endif - /* process */ - if (pdu_len) { npdu_handler(&src, &Rx_Buf[0], pdu_len); } - if (I_Am_Request) { - I_Am_Request = false; - Send_IAm(); - } /* output */ -#ifdef BACDL_MSTP - MSTP_Master_Node_FSM(&MSTP_Port); -#endif + + /* blink LEDs, Turn on or off outputs, etc */ } diff --git a/bacnet-stack/ports/rtos32/makefile.mak b/bacnet-stack/ports/rtos32/makefile.mak index fc64338b..0b8ca2aa 100644 --- a/bacnet-stack/ports/rtos32/makefile.mak +++ b/bacnet-stack/ports/rtos32/makefile.mak @@ -22,19 +22,36 @@ PRODUCT_RTB = $(PRODUCT).rtb PRODUCT_EXE = $(PRODUCT).exe # Choose the Data Link Layer to Enable -DEFINES = -DDOC;BACDL_BIP=1 -#DEFINES = -DDOC;BACDL_ETHERNET=1 -#DEFINES = -DDOC;BACDL_MSTP=1 +#DEFINES = -DDOC;BIG_ENDIAN=0;TSM_ENABLED=1;PRINT_ENABLED=1;BACDL_BIP=1 +#DEFINES = -DDOC;BIG_ENDIAN=0;TSM_ENABLED=1;PRINT_ENABLED=1;BACDL_ETHERNET=1 +#DEFINES = -DDOC;BIG_ENDIAN=0;TSM_ENABLED=1;PRINT_ENABLED=1;BACDL_ARCNET=1 +DEFINES = -DDOC;BIG_ENDIAN=0;TSM_ENABLED=1;PRINT_ENABLED=1;BACDL_MSTP=1 -SRCS = init.c main.c ethernet.c bip-init.c \ - rs485.c \ +SRCS = main.c \ + ethernet.c \ + bip-init.c \ + dlmstp.c \ + rs485.c \ + init.c \ ..\..\bip.c \ ..\..\mstp.c \ ..\..\crc.c \ - ..\..\handlers.c \ + ..\..\demo\handler\h_iam.c \ + ..\..\demo\handler\h_whois.c \ + ..\..\demo\handler\h_wp.c \ + ..\..\demo\handler\h_rp.c \ + ..\..\demo\handler\noserv.c \ + ..\..\demo\handler\txbuf.c \ + ..\..\demo\handler\s_rp.c \ + ..\..\demo\handler\s_whois.c \ ..\..\bacdcode.c \ + ..\..\bacstr.c \ + ..\..\bactext.c \ + ..\..\indtext.c \ + ..\..\bacapp.c \ ..\..\bigend.c \ ..\..\whois.c \ + ..\..\dcc.c \ ..\..\iam.c \ ..\..\rp.c \ ..\..\wp.c \ @@ -44,6 +61,12 @@ SRCS = init.c main.c ethernet.c bip-init.c \ ..\..\demo\object\device.c \ ..\..\demo\object\ai.c \ ..\..\demo\object\ao.c \ + ..\..\demo\object\av.c \ + ..\..\demo\object\bi.c \ + ..\..\demo\object\bo.c \ + ..\..\demo\object\bv.c \ + ..\..\demo\object\lsp.c \ + ..\..\demo\object\mso.c \ ..\..\datalink.c \ ..\..\tsm.c \ ..\..\address.c \ @@ -59,6 +82,7 @@ OBJS = $(SRCS:.c=.obj) # CC = $(BORLAND_DIR)\bin\bcc32 +bcc32.cfg LINK = $(BORLAND_DIR)\bin\tlink32 +#LINK = $(BORLAND_DIR)\bin\ilink32 TLIB = $(BORLAND_DIR)\bin\tlib LOCATE = $(RTOS32_DIR)\bin\rtloc @@ -66,7 +90,7 @@ LOCATE = $(RTOS32_DIR)\bin\rtloc # Include directories # CC_DIR = $(BORLAND_DIR)\BIN -INCL_DIRS = -I$(BORLAND_DIR)\include;$(RTOS32_DIR)\include;..\..\;. +INCL_DIRS = -I$(BORLAND_DIR)\include;$(RTOS32_DIR)\include;..\..\;..\..\demo\handler\;..\..\demo\object\;. CFLAGS = $(INCL_DIRS) $(CS_FLAGS) $(DEFINES) @@ -156,6 +180,7 @@ bcc32.cfg : Copy &&| $(CFLAGS) -c +#-g2 #stop after gN warnings -y #include line numbers in OBJ's -v #include debug info -w+ #turn on all warnings diff --git a/bacnet-stack/ports/rtos32/net.h b/bacnet-stack/ports/rtos32/net.h index b339073f..17c90fca 100644 --- a/bacnet-stack/ports/rtos32/net.h +++ b/bacnet-stack/ports/rtos32/net.h @@ -34,18 +34,47 @@ #include #include -#ifdef BACDL_BIP #include "bip.h" #ifndef HOST +#include #include "netcfg.h" #include #include #include #include + +/* + * Definitions of bits in internet address integers. + * On subnets, the decomposition of addresses to host and net parts + * is done according to subnet mask, not the masks here. + */ +#define IN_CLASSA(i) (((long)(i) & 0x80000000) == 0) +#define IN_CLASSA_NET 0xff000000 +#define IN_CLASSA_NSHIFT 24 +#define IN_CLASSA_HOST 0x00ffffff +#define IN_CLASSA_MAX 128 + +#define IN_CLASSB(i) (((long)(i) & 0xc0000000) == 0x80000000) +#define IN_CLASSB_NET 0xffff0000 +#define IN_CLASSB_NSHIFT 16 +#define IN_CLASSB_HOST 0x0000ffff +#define IN_CLASSB_MAX 65536 + +#define IN_CLASSC(i) (((long)(i) & 0xe0000000) == 0xc0000000) +#define IN_CLASSC_NET 0xffffff00 +#define IN_CLASSC_NSHIFT 8 +#define IN_CLASSC_HOST 0x000000ff + +#define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000) +#define IN_CLASSD_NET 0xf0000000 /* These ones aren't really */ +#define IN_CLASSD_NSHIFT 28 /* net and host fields, but */ +#define IN_CLASSD_HOST 0x0fffffff /* routing needn't know. */ +#define IN_MULTICAST(i) IN_CLASSD(i) + #else #include #endif #define close closesocket -#endif +typedef size_t socklen_t; #endif diff --git a/bacnet-stack/ports/rtos32/netcfg.h b/bacnet-stack/ports/rtos32/netcfg.h index c3e0a73d..48e85000 100644 --- a/bacnet-stack/ports/rtos32/netcfg.h +++ b/bacnet-stack/ports/rtos32/netcfg.h @@ -34,10 +34,10 @@ #if defined(AUTO_IP) /* use xn_autoip() to get an IP address */ static BYTE TargetIP[] = { 0, 0, 0, 0 }; /* will be filled at run-time */ static BYTE NetMask[] = { 255, 255, 255, 0 }; -static BYTE MinIP[] = { 192, 168, 1, 128 }; -static BYTE MaxIP[] = { 192, 168, 1, 255 }; -static BYTE DefaultGateway[] = { 192, 168, 1, 1 }; /* set to zero if not available or required */ -static BYTE DNSServer[] = { 192, 168, 1, 1 }; /* ditto */ +static BYTE MinIP[] = { 192, 168, 0, 128 }; +static BYTE MaxIP[] = { 192, 168, 0, 255 }; +static BYTE DefaultGateway[] = { 192, 168, 0, 1 }; /* set to zero if not available or required */ +static BYTE DNSServer[] = { 192, 168, 0, 1 }; /* ditto */ #elif defined(DHCP) /* use DHCP */ #include static BYTE TargetIP[] = { 0, 0, 0, 0 }; /* will be filled at run-time */ diff --git a/bacnet-stack/ports/rtos32/rs485.c b/bacnet-stack/ports/rtos32/rs485.c index 004a74e4..8cbfcdbd 100644 --- a/bacnet-stack/ports/rtos32/rs485.c +++ b/bacnet-stack/ports/rtos32/rs485.c @@ -27,6 +27,9 @@ #include #include #include +#if PRINT_ENABLED +#include +#endif #include "mstp.h" /* note: use the RTKernel-C API so that it can use this library */ @@ -69,11 +72,29 @@ static void RS485_Standard_Port_Settings(long port, long *pIRQ, } } +static int TestCOMPort( + int Base)/* base address of UART */ +{ + int i; + + for (i=0; i<256; i++) + { + RTOut(Base+7, (BYTE)i); // write scratch register + RTOut(Base+1, RTIn(Base+1)); // read/write IER + if (RTIn(Base+7) != i) // check scratch register + return FALSE; + } + return TRUE; +} + static RS485_Open_Port(int port, /* COM port number - COM1 = 0 */ long baud, /* baud rate */ unsigned base, /* io base address */ int irq) { /* hardware IRQ number */ + if (!TestCOMPort(base)) + return; + /* setup the COM IO */ SetIOBase(port, base); SetIRQ(port, irq); @@ -90,6 +111,9 @@ static RS485_Open_Port(int port, /* COM port number - COM1 = 0 */ /* enable the 485 via the DTR pin */ RS485_IO_ENABLE(port); RS485_RECEIVE_ENABLE(port); + #if PRINT_ENABLED + fprintf(stderr,"RS485: COM%d Enabled\r\n",port+1); + #endif return; } @@ -115,6 +139,21 @@ void RS485_Send_Frame(volatile struct mstp_port_struct_t *mstp_port, /* port while (!(LineStatus(RS485_Port) & TX_SHIFT_EMPTY)) RTKScheduler(); RS485_RECEIVE_ENABLE(RS485_Port); + #if PRINT_ENABLED + { + int i = 0; + fprintf(stderr,"RS485 Tx:"); + for (i = 0; i < nbytes; i++) + { + fprintf(stderr," %02X",buffer[i]); + if ((!(i%20)) && (i != 0)) + { + fprintf(stderr,"\r\n "); + } + } + fprintf(stderr,"\r\n"); + } + #endif return; } @@ -147,8 +186,3 @@ void RS485_Check_UART_Data(volatile struct mstp_port_struct_t *mstp_port) } } } - -void RS485_Process_Tx_Message(void) -{ - /* nothing to do */ -} diff --git a/bacnet-stack/ports/win32/MAKEFILE.MAK b/bacnet-stack/ports/win32/MAKEFILE.MAK index cd10e291..06287917 100644 --- a/bacnet-stack/ports/win32/MAKEFILE.MAK +++ b/bacnet-stack/ports/win32/MAKEFILE.MAK @@ -15,7 +15,7 @@ PRODUCT = bacnet PRODUCT_EXE = $(PRODUCT).exe # Choose the Data Link Layer to Enable -DEFINES = -DBACDL_BIP=1;TSM_ENABLED=1 +DEFINES = -DBACDL_BIP=1;TSM_ENABLED=1;BIG_ENDIAN=0 SRCS = main.c bip-init.c \ ..\..\bip.c \ diff --git a/bacnet-stack/rs485.h b/bacnet-stack/rs485.h index ef9a22ff..1f0c18db 100644 --- a/bacnet-stack/rs485.h +++ b/bacnet-stack/rs485.h @@ -51,11 +51,6 @@ extern "C" { void RS485_Check_UART_Data(volatile struct mstp_port_struct_t *mstp_port); /* port specific data */ - void RS485_Process_Tx_Message(void); - - bool RS485_Tx_Complete(void); - - #ifdef __cplusplus } #endif /* __cplusplus */