Getting the RTOS-32 port working again. Also getting the MS/TP state machine working. Soon!
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
+295
-116
@@ -46,11 +46,18 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#if PRINT_ENABLED
|
||||
#include <stdio.h>
|
||||
#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);
|
||||
|
||||
+6
-5
@@ -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 */
|
||||
};
|
||||
|
||||
@@ -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=
|
||||
|
||||
Binary file not shown.
@@ -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;
|
||||
}
|
||||
|
||||
@@ -34,18 +34,17 @@
|
||||
|
||||
#include <stdint.h> /* for standard integer types uint8_t etc. */
|
||||
#include <stdbool.h> /* 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);
|
||||
|
||||
@@ -0,0 +1,268 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* 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 <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#if PRINT_ENABLED
|
||||
#include <stdio.h>
|
||||
#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 <MAX_MAC_LEN; i++) {
|
||||
src->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;
|
||||
}
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <windows.h>
|
||||
#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 */
|
||||
}
|
||||
|
||||
@@ -28,35 +28,106 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <conio.h> /* 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 <windows.h>
|
||||
#include <rttarget.h> /* for RTCMOSSetSystemTime */
|
||||
#include <rtfiles.h> /* file system */
|
||||
#include <rtfsys.h> /* file system */
|
||||
#include <Rttbios.h>
|
||||
#endif
|
||||
#include <rtcom.h> /* serial port driver */
|
||||
#include <itimer.h> /* time measurement & timer interrupt rate control */
|
||||
#include <rtkeybrd.h> /* 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 */
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -34,18 +34,47 @@
|
||||
#include <stdlib.h>
|
||||
#include <process.h>
|
||||
|
||||
#ifdef BACDL_BIP
|
||||
#include "bip.h"
|
||||
#ifndef HOST
|
||||
#include <rtipapi.h>
|
||||
#include "netcfg.h"
|
||||
#include <rttarget.h>
|
||||
#include <rtk32.h>
|
||||
#include <clock.h>
|
||||
#include <socket.h>
|
||||
|
||||
/*
|
||||
* 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 <winsock.h>
|
||||
#endif
|
||||
#define close closesocket
|
||||
#endif
|
||||
typedef size_t socklen_t;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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 <dhcpcapi.h>
|
||||
static BYTE TargetIP[] = { 0, 0, 0, 0 }; /* will be filled at run-time */
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
#include <rtkernel.h>
|
||||
#include <rtcom.h>
|
||||
#include <itimer.h>
|
||||
#if PRINT_ENABLED
|
||||
#include <stdio.h>
|
||||
#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 */
|
||||
}
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user